Merge tag 'xilinx-for-v2023.04-rc1' of https://source.denx.de/u-boot/custodians/u-boot-microblaze
Xilinx chnages for v2023.04-rc1
makefile:
- Add multi_dtb_fit dependency
clk:
- Handle error cases
microblaze:
- Disable falcon mode and cleanup code around
xilinx:
- Enable regular expression matching in board_fit_config_name_match()
- Fix FRU handling for 0xC1 format
- Fix Xilinx legacy format eeprom parsing
zynqmp:
- Some DT updates/cleanups
- Fix IDcode for xck24
- Remove empty mini config files
- Add support for k24
versal:
- Remove empty mini config files
versal_net:
- Setup timer when runs in EL3
- Build u-boot.elf for mini configurations
zynq-gem:
- Add support for new compatible strings
- Remove support for Avnet Ultrazedev SOM
- Handle SGMII with PCS phy
spi:
- Add support for gigadevice parts
misc:
- Remove CONFIG_TARGET_VENUS ifdef
- Add missing headers to remove sparse warnings
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 02cd8e4..5673bb7 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -2,7 +2,7 @@
windows_vm: windows-2019
ubuntu_vm: ubuntu-22.04
macos_vm: macOS-12
- ci_runner_image: trini/u-boot-gitlab-ci-runner:jammy-20221101-22Nov2022
+ ci_runner_image: trini/u-boot-gitlab-ci-runner:jammy-20221130-11Jan2023
# Add '-u 0' options for Azure pipelines, otherwise we get "permission
# denied" error when it tries to "useradd -m -u 1001 vsts_azpcontainer",
# since our $(ci_runner_image) user is not root.
@@ -64,7 +64,8 @@
# If grep succeeds and finds a match the test fails as we should
# have no matches.
- script: git grep -E '^#[[:blank:]]*(define|undef)[[:blank:]]*CONFIG_'
- include/configs `find arch -name config.h` && exit 1 || exit 0
+ :^doc/ :^arch/arm/dts/ :^scripts/kconfig/lkc.h
+ :^include/linux/kconfig.h :^tools/ && exit 1 || exit 0
- job: cppcheck
displayName: 'Static code analysis with cppcheck'
@@ -76,8 +77,8 @@
steps:
- script: cppcheck -j$(nproc) --force --quiet --inline-suppr .
- - job: htmldocs
- displayName: 'Build HTML documentation'
+ - job: docs
+ displayName: 'Build documentation'
pool:
vmImage: $(ubuntu_vm)
container:
@@ -89,6 +90,7 @@
. /tmp/venvhtml/bin/activate
pip install -r doc/sphinx/requirements.txt
make htmldocs
+ make infodocs
- job: todo
displayName: 'Search for TODO within source tree'
diff --git a/.gitignore b/.gitignore
index eb769f1..3adf1fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
# Normal rules (sorted alphabetically)
#
.*
+!.checkpatch.conf
*.a
*.asn1.[ch]
*.bin
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index afd8394..aaf9d25 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,7 +2,7 @@
# Grab our configured image. The source for this is found
# in the u-boot tree at tools/docker/Dockerfile
-image: trini/u-boot-gitlab-ci-runner:jammy-20221101-22Nov2022
+image: trini/u-boot-gitlab-ci-runner:jammy-20221130-11Jan2023
# We run some tests in different order, to catch some failures quicker.
stages:
@@ -131,7 +131,8 @@
# If grep succeeds and finds a match the test fails as we should
# have no matches.
- git grep -E '^#[[:blank:]]*(define|undef)[[:blank:]]*CONFIG_'
- include/configs `find arch -name config.h` && exit 1 || exit 0
+ :^doc/ :^arch/arm/dts/ :^scripts/kconfig/lkc.h
+ :^include/linux/kconfig.h :^tools/ && exit 1 || exit 0
# QA jobs for code analytics
# static code analysis with cppcheck (we can add --enable=all later)
@@ -149,14 +150,15 @@
# search for HACK within source tree and ignore HACKKIT board
- grep -r HACK . | grep -v HACKKIT
-# build HTML documentation
-htmldocs:
+# build documentation
+docs:
stage: testsuites
script:
- virtualenv -p /usr/bin/python3 /tmp/venvhtml
- . /tmp/venvhtml/bin/activate
- pip install -r doc/sphinx/requirements.txt
- make htmldocs
+ - make infodocs
# some statistics about the code base
sloccount:
diff --git a/.mailmap b/.mailmap
index 8acce4b..4b3532e 100644
--- a/.mailmap
+++ b/.mailmap
@@ -26,6 +26,7 @@
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@free-electrons.com>
Dirk Behme <dirk.behme@googlemail.com>
+Eugen Hristev <eugen.hristev@collabora.com> <eugen.hristev@microchip.com>
Fabio Estevam <fabio.estevam@nxp.com>
Heinrich Schuchardt <xypron.glpk@gmx.de> <heinrich.schuchardt@canonical.com>
Heinrich Schuchardt <xypron.glpk@gmx.de> xypron.glpk@gmx.de <xypron.glpk@gmx.de>
diff --git a/Kconfig b/Kconfig
index d29519c..a75cce7 100644
--- a/Kconfig
+++ b/Kconfig
@@ -456,11 +456,12 @@
string "Build target special images"
default "u-boot-with-spl.sfp" if TARGET_SOCFPGA_ARRIA10
default "u-boot-with-spl.sfp" if TARGET_SOCFPGA_GEN5
- default "u-boot-with-spl.kwb" if ARCH_MVEBU && SPL
+ default "u-boot-with-spl.kwb" if ARMADA_32BIT && SPL
default "u-boot-elf.srec" if RCAR_GEN3
default "u-boot.itb" if !BINMAN && SPL_LOAD_FIT && (ARCH_ROCKCHIP || \
ARCH_SUNXI || RISCV || ARCH_ZYNQMP)
- default "u-boot.kwb" if ARCH_KIRKWOOD
+ default "u-boot.kwb" if (ARCH_KIRKWOOD || ARMADA_32BIT) && !SPL
+ default "u-boot-with-spl.bin" if MPC85xx && !E500MC && !E5500 && !E6500 && SPL
default "u-boot-with-spl.bin" if ARCH_AT91 && SPL_NAND_SUPPORT
default "u-boot-with-spl.imx" if ARCH_MX6 && SPL
help
diff --git a/MAINTAINERS b/MAINTAINERS
index 237f394..8dcce88 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1198,6 +1198,7 @@
S: Maintained
F: doc/api/nvmem.rst
F: drivers/misc/nvmem.c
+F: drivers/reboot-mode/reboot-mode-nvmem.c
F: include/nvmem.h
NXP C45 TJA11XX PHY DRIVER
@@ -1451,6 +1452,7 @@
TPM DRIVERS
M: Ilias Apalodimas <ilias.apalodimas@linaro.org>
S: Maintained
+T: git https://source.denx.de/u-boot/custodians/u-boot-tpm.git
F: drivers/tpm/
TQ GROUP
@@ -1460,6 +1462,8 @@
TEE
M: Jens Wiklander <jens.wiklander@linaro.org>
+M: Ilias Apalodimas <ilias.apalodimas@linaro.org>
+T: git https://source.denx.de/u-boot/custodians/u-boot-tpm.git
S: Maintained
F: drivers/tee/
F: include/tee.h
diff --git a/Makefile b/Makefile
index b23bdc5..9c38cc2 100644
--- a/Makefile
+++ b/Makefile
@@ -1006,14 +1006,9 @@
INPUTS-y += init_sp_bss_offset_check
endif
-ifeq ($(CONFIG_ARCH_ROCKCHIP)$(CONFIG_SPL),yy)
-# Binman image dependencies
-ifeq ($(CONFIG_ARM64),y)
-INPUTS-y += u-boot.itb
-else
+ifeq ($(CONFIG_ARCH_ROCKCHIP)_$(CONFIG_SPL_FRAMEWORK),y_)
INPUTS-y += u-boot.img
endif
-endif
INPUTS-$(CONFIG_X86) += u-boot-x86-start16.bin u-boot-x86-reset16.bin \
$(if $(CONFIG_SPL_X86_16BIT_INIT),spl/u-boot-spl.bin) \
@@ -1370,9 +1365,6 @@
else
ifneq ($(CONFIG_USE_SPL_FIT_GENERATOR),)
U_BOOT_ITS := u-boot.its
-ifeq ($(CONFIG_SPL_FIT_GENERATOR),"arch/arm/mach-rockchip/make_fit_atf.py")
-U_BOOT_ITS_DEPS += u-boot
-endif
$(U_BOOT_ITS): $(U_BOOT_ITS_DEPS) FORCE
$(srctree)/$(CONFIG_SPL_FIT_GENERATOR) \
$(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) > $@
@@ -1478,7 +1470,6 @@
u-boot-with-spl.bin: $(SPL_IMAGE) $(SPL_PAYLOAD) FORCE
$(call if_changed,pad_cat)
-
ifeq ($(CONFIG_ARCH_LPC32XX)$(CONFIG_SPL),yy)
MKIMAGEFLAGS_lpc32xx-spl.img = -T lpc32xximage -a $(CONFIG_SPL_TEXT_BASE)
diff --git a/README b/README
index fe571f7..40619ee 100644
--- a/README
+++ b/README
@@ -445,12 +445,12 @@
example "env grep" and "setexpr".
- Watchdog:
- CONFIG_SYS_WATCHDOG_FREQ
+ CFG_SYS_WATCHDOG_FREQ
Some platforms automatically call WATCHDOG_RESET()
from the timer interrupt handler every
- CONFIG_SYS_WATCHDOG_FREQ interrupts. If not set by the
+ CFG_SYS_WATCHDOG_FREQ interrupts. If not set by the
board configuration file, a default of CONFIG_SYS_HZ/2
- (i.e. 500) is used. Setting CONFIG_SYS_WATCHDOG_FREQ
+ (i.e. 500) is used. Setting CFG_SYS_WATCHDOG_FREQ
to 0 disables calling WATCHDOG_RESET() from the timer
interrupt.
@@ -523,7 +523,7 @@
CONFIG_LAN91C96_USE_32_BIT
Define this to enable 32 bit addressing
- CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT
+ CFG_SYS_DAVINCI_EMAC_PHY_COUNT
Define this if you have more then 3 PHYs.
CONFIG_FTGMAC100
@@ -653,7 +653,7 @@
To enable the ULPI layer support, define CONFIG_USB_ULPI and
CONFIG_USB_ULPI_VIEWPORT in your board configuration file.
If your ULPI phy needs a different reference clock than the
- standard 24 MHz then you have to define CONFIG_ULPI_REF_CLK to
+ standard 24 MHz then you have to define CFG_ULPI_REF_CLK to
the appropriate value in Hz.
- MMC Support:
@@ -734,7 +734,7 @@
4th and following
BOOTP requests: delay 0 ... 8 sec
- CONFIG_BOOTP_ID_CACHE_SIZE
+ CFG_BOOTP_ID_CACHE_SIZE
BOOTP packets are uniquely identified using a 32-bit ID. The
server will copy the ID from client requests to responses and
@@ -747,7 +747,7 @@
time is too long, U-Boot will retransmit requests. In order
to allow earlier responses to still be accepted after these
retransmissions, U-Boot's BOOTP client keeps a small cache of
- IDs. The CONFIG_BOOTP_ID_CACHE_SIZE controls the size of this
+ IDs. The CFG_BOOTP_ID_CACHE_SIZE controls the size of this
cache. The default is to keep IDs for up to four outstanding
requests. Increasing this will allow U-Boot to accept offers
from a BOOTP client in networks with unusually high latency.
@@ -832,11 +832,11 @@
status LED backend implementation. Define CONFIG_LED_STATUS_GPIO
to include the gpio_led driver in the U-Boot binary.
- CONFIG_GPIO_LED_INVERTED_TABLE
+ CFG_GPIO_LED_INVERTED_TABLE
Some GPIO connected LEDs may have inverted polarity in which
case the GPIO high value corresponds to LED off state and
GPIO low value corresponds to LED on state.
- In such cases CONFIG_GPIO_LED_INVERTED_TABLE may be defined
+ In such cases CFG_GPIO_LED_INVERTED_TABLE may be defined
with a list of GPIO LEDs that have inverted polarity.
- I2C Support:
@@ -993,7 +993,7 @@
SPI EEPROM, also an instance works with Crystal A/D and
D/As on the SACSng board)
- CONFIG_SYS_SPI_MXC_WAIT
+ CFG_SYS_SPI_MXC_WAIT
Timeout for waiting until spi transfer completed.
default: (CONFIG_SYS_HZ/100) /* 10 ms */
@@ -1023,7 +1023,7 @@
If defined, a function that provides delays in the FPGA
configuration driver.
- CONFIG_SYS_FPGA_CHECK_ERROR
+ CFG_SYS_FPGA_CHECK_ERROR
Check for configuration errors during FPGA bitfile
loading. For example, abort during Virtex II
@@ -1319,7 +1319,7 @@
- CONFIG_SYS_LONGHELP: Defined when you want long help messages included;
undefine this when you're short of memory.
-- CONFIG_SYS_HELP_CMD_WIDTH: Defined when you want to override the default
+- CFG_SYS_HELP_CMD_WIDTH: Defined when you want to override the default
width of the commands listed in the 'help' command output.
- CONFIG_SYS_PROMPT: This is what U-Boot prints on the console to
diff --git a/arch/Kconfig b/arch/Kconfig
index 5f2b72f..d30676a 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -93,7 +93,7 @@
bool "Nios II architecture"
select CPU
select DM
- imply DM_EVENT
+ select DM_EVENT
select OF_CONTROL
select SUPPORT_OF_CONTROL
imply CMD_DM
@@ -111,9 +111,9 @@
select SUPPORT_OF_CONTROL
select OF_CONTROL
select DM
+ select DM_EVENT
imply SPL_SEPARATE_BSS if SPL
imply DM_SERIAL
- imply DM_EVENT
imply DM_MMC
imply DM_SPI
imply DM_SPI_FLASH
@@ -136,6 +136,7 @@
select BZIP2
select CMD_POWEROFF
select DM
+ select DM_EVENT
select DM_FUZZING_ENGINE
select DM_GPIO
select DM_I2C
@@ -240,7 +241,6 @@
imply CMD_SF
imply CMD_SF_TEST
imply CMD_ZBOOT
- imply DM_EVENT
imply DM_GPIO
imply DM_KEYBOARD
imply DM_MMC
@@ -384,9 +384,11 @@
bool "U-Boot is loaded in to RAM by a pre-loader"
depends on M68K || NIOS2
-config SKIP_LOWLEVEL_INIT
- bool "Skip the calls to certain low level initialization functions"
+menu "Skipping low level initialization functions"
depends on ARM || MIPS || RISCV
+
+config SKIP_LOWLEVEL_INIT
+ bool "Skip calls to certain low level initialization functions"
help
If enabled, then certain low level initializations (like setting up
the memory controller) are omitted and/or U-Boot does not relocate
@@ -396,8 +398,8 @@
debugger which performs these initializations itself.
config SPL_SKIP_LOWLEVEL_INIT
- bool "Skip the calls to certain low level initialization functions"
- depends on SPL && (ARM || MIPS || RISCV)
+ bool "Skip calls to certain low level initialization functions in SPL"
+ depends on SPL
help
If enabled, then certain low level initializations (like setting up
the memory controller) are omitted and/or U-Boot does not relocate
@@ -407,7 +409,7 @@
debugger which performs these initializations itself.
config TPL_SKIP_LOWLEVEL_INIT
- bool "Skip the calls to certain low level initialization functions"
+ bool "Skip calls to certain low level initialization functions in TPL"
depends on SPL && ARM
help
If enabled, then certain low level initializations (like setting up
@@ -418,7 +420,7 @@
debugger which performs these initializations itself.
config SKIP_LOWLEVEL_INIT_ONLY
- bool "Skip the call to lowlevel_init during early boot ONLY"
+ bool "Skip call to lowlevel_init during early boot ONLY"
depends on ARM
help
This allows just the call to lowlevel_init() to be skipped. The
@@ -426,7 +428,7 @@
performed.
config SPL_SKIP_LOWLEVEL_INIT_ONLY
- bool "Skip the call to lowlevel_init during early boot ONLY"
+ bool "Skip call to lowlevel_init during early SPL boot ONLY"
depends on SPL && ARM
help
This allows just the call to lowlevel_init() to be skipped. The
@@ -434,13 +436,15 @@
performed.
config TPL_SKIP_LOWLEVEL_INIT_ONLY
- bool "Skip the call to lowlevel_init during early boot ONLY"
+ bool "Skip call to lowlevel_init during early TPL boot ONLY"
depends on TPL && ARM
help
This allows just the call to lowlevel_init() to be skipped. The
normal CP15 init (such as enabling the instruction cache) is still
performed.
+endmenu
+
config SYS_HAS_NONCACHED_MEMORY
bool "Enable reserving a non-cached memory area for drivers"
depends on (ARM || MIPS) && (RTL8169 || MEDIATEK_ETH)
diff --git a/arch/Kconfig.nxp b/arch/Kconfig.nxp
index ad61dab..6e1c44b 100644
--- a/arch/Kconfig.nxp
+++ b/arch/Kconfig.nxp
@@ -1,3 +1,5 @@
+menu "Functionality shared between NXP SoCs"
+
config FSL_TRUST_ARCH_v1
bool
@@ -142,8 +144,6 @@
endmenu
-comment "Other functionality shared between NXP SoCs"
-
config DEEP_SLEEP
bool "Enable SoC deep sleep feature"
depends on ARCH_T1024 || ARCH_T1040 || ARCH_T1042 || ARCH_LS1021A
@@ -256,6 +256,20 @@
config SYS_FSL_IFC_BE
bool
+config SYS_FSL_IFC_BANK_COUNT
+ int "Maximum banks of Integrated flash controller"
+ depends on ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A || \
+ ARCH_LS1088A || ARCH_LS1021A || ARCH_B4860 || ARCH_B4420 || \
+ ARCH_T4240 || ARCH_T1040 || ARCH_T1042 || ARCH_T1024 || \
+ ARCH_T2080 || ARCH_C29X || ARCH_P1010 || ARCH_BSC9131 || \
+ ARCH_BSC9132
+ default 3 if ARCH_BSC9131 || ARCH_BSC9132
+ default 4 if ARCH_LS1043A || ARCH_LS1046A || ARCH_B4860 || \
+ ARCH_B4420 || ARCH_P1010
+ default 8 if ARCH_LS2080A || ARCH_LS1088A || ARCH_LS1021A || \
+ ARCH_T4240 || ARCH_T1040 || ARCH_T1042 || \
+ ARCH_T1024 || ARCH_T2080 || ARCH_C29X
+
config FSL_QIXIS
bool "Enable QIXIS support"
depends on PPC || ARCH_LS1021A || FSL_LSCH2 || FSL_LSCH3
@@ -271,3 +285,14 @@
config SYS_DPAA_FMAN
bool
+
+config SYS_FSL_SRDS_1
+ bool
+
+config SYS_FSL_SRDS_2
+ bool
+
+config SYS_HAS_SERDES
+ bool
+
+endmenu
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 1a7c525..6ae66bb 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -102,6 +102,13 @@
endchoice
+config ARC_MMU_VER
+ int
+ default 0 if ARC_MMU_ABSENT
+ default 2 if ARC_MMU_V2
+ default 3 if ARC_MMU_V3
+ default 4 if ARC_MMU_V4
+
config CPU_BIG_ENDIAN
bool "Enable Big Endian Mode"
help
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index a48e1ae..74cff71 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -16,16 +16,6 @@
*/
#define ARCH_DMA_MINALIGN 128
-#if defined(ARC_MMU_ABSENT)
-#define CONFIG_ARC_MMU_VER 0
-#elif defined(CONFIG_ARC_MMU_V2)
-#define CONFIG_ARC_MMU_VER 2
-#elif defined(CONFIG_ARC_MMU_V3)
-#define CONFIG_ARC_MMU_VER 3
-#elif defined(CONFIG_ARC_MMU_V4)
-#define CONFIG_ARC_MMU_VER 4
-#endif
-
#ifndef __ASSEMBLY__
void cache_init(void);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index bbf1d52..c9a44eb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -778,7 +778,6 @@
select SUPPORT_SPL
imply TI_SYSC if DM && OF_CONTROL
imply FIT
- imply DM_EVENT
imply SPL_SEPARATE_BSS
config ARCH_MESON
@@ -823,11 +822,11 @@
select SYS_FSL_SEC_COMPAT_4
select SYS_FSL_SEC_LE
select DM
+ select DM_EVENT
select GPIO_EXTRA_HEADER
select MACH_IMX
select OF_CONTROL
select ENABLE_ARM_SOC_BOOT0_HOOK
- imply DM_EVENT
config ARCH_IMX8M
bool "NXP i.MX8M platform"
@@ -839,14 +838,15 @@
select SYS_FSL_SEC_LE
select SYS_I2C_MXC
select DM
+ select DM_EVENT if CLK
select SUPPORT_SPL
imply CMD_DM
- imply DM_EVENT
config ARCH_IMX8ULP
bool "NXP i.MX8ULP platform"
select ARM64
select DM
+ select DM_EVENT
select MACH_IMX
select OF_CONTROL
select SUPPORT_SPL
@@ -854,19 +854,18 @@
select MISC
select IMX_SENTINEL
imply CMD_DM
- imply DM_EVENT
config ARCH_IMX9
bool "NXP i.MX9 platform"
select ARM64
select DM
+ select DM_EVENT
select MACH_IMX
select SUPPORT_SPL
select GPIO_EXTRA_HEADER
select MISC
select IMX_SENTINEL
imply CMD_DM
- imply DM_EVENT
config ARCH_IMXRT
bool "NXP i.MXRT platform"
diff --git a/arch/arm/cpu/arm1176/start.S b/arch/arm/cpu/arm1176/start.S
index 9e76a4a..78a9cc1 100644
--- a/arch/arm/cpu/arm1176/start.S
+++ b/arch/arm/cpu/arm1176/start.S
@@ -17,10 +17,6 @@
#include <config.h>
#include <linux/linkage.h>
-#ifndef CONFIG_SYS_PHY_UBOOT_BASE
-#define CONFIG_SYS_PHY_UBOOT_BASE CFG_SYS_UBOOT_BASE
-#endif
-
/*
*************************************************************************
*
@@ -88,7 +84,7 @@
/* Prepare to disable the MMU */
adr r2, mmu_disable_phys
- sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_TEXT_BASE)
+ sub r2, r2, #(CFG_SYS_UBOOT_BASE - CONFIG_TEXT_BASE)
b mmu_disable
.align 5
diff --git a/arch/arm/cpu/armv7/ls102xa/Kconfig b/arch/arm/cpu/armv7/ls102xa/Kconfig
index a83eb7e..0edcf4c 100644
--- a/arch/arm/cpu/armv7/ls102xa/Kconfig
+++ b/arch/arm/cpu/armv7/ls102xa/Kconfig
@@ -93,19 +93,6 @@
config SYS_FSL_HAS_CCI400
bool
-config SYS_FSL_SRDS_1
- bool
-
-config SYS_FSL_SRDS_2
- bool
-
-config SYS_HAS_SERDES
- bool
-
-config SYS_FSL_IFC_BANK_COUNT
- int "Maximum banks of Integrated flash controller"
- default 8
-
config SYS_FSL_ERRATUM_A008407
bool
diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c
index f4a045e..9d981cc 100644
--- a/arch/arm/cpu/armv7/s5p-common/timer.c
+++ b/arch/arm/cpu/armv7/s5p-common/timer.c
@@ -82,7 +82,7 @@
return time_ms - base;
}
-unsigned long __attribute__((no_instrument_function)) timer_get_us(void)
+unsigned long notrace timer_get_us(void)
{
static unsigned long base_time_us;
diff --git a/arch/arm/cpu/armv7/sunxi/fel_utils.S b/arch/arm/cpu/armv7/sunxi/fel_utils.S
index b231075..78bb165 100644
--- a/arch/arm/cpu/armv7/sunxi/fel_utils.S
+++ b/arch/arm/cpu/armv7/sunxi/fel_utils.S
@@ -20,8 +20,6 @@
str lr, [r0, #12]
mrc p15, 0, lr, c12, c0, 0 @ Read VBAR
str lr, [r0, #16]
- mrc p15, 0, lr, c1, c0, 0 @ Read CP15 Control Register
- str lr, [r0, #20]
b save_boot_params_ret
ENDPROC(save_boot_params)
@@ -29,8 +27,6 @@
mov sp, r0
mov lr, r1
ldr r0, =fel_stash
- ldr r1, [r0, #20]
- mcr p15, 0, r1, c1, c0, 0 @ Write CP15 Control Register
ldr r1, [r0, #16]
mcr p15, 0, r1, c12, c0, 0 @ Write VBAR
ldr r1, [r0, #12]
diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 5266515..2fe38a1 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -39,15 +39,15 @@
adr x1, fel_stash_addr // to find the fel_stash address in AA32
str w2, [x1]
- ldr x0, =0xfa50392f // CPU hotplug magic
+ ldr w0, =0xfa50392f // CPU hotplug magic
#ifdef CONFIG_MACH_SUN50I_H616
- ldr x2, =(SUNXI_R_CPUCFG_BASE + 0x1c0)
+ ldr w2, =(SUNXI_R_CPUCFG_BASE + 0x1c0)
str w0, [x2], #0x4
#elif CONFIG_MACH_SUN50I_H6
- ldr x2, =(SUNXI_RTC_BASE + 0x1b8) // BOOT_CPU_HP_FLAG_REG
+ ldr w2, =(SUNXI_RTC_BASE + 0x1b8) // BOOT_CPU_HP_FLAG_REG
str w0, [x2], #0x4
#else
- ldr x2, =(SUNXI_CPUCFG_BASE + 0x1a4) // offset for CPU hotplug base
+ ldr w2, =(SUNXI_CPUCFG_BASE + 0x1a4) // offset for CPU hotplug base
str w0, [x2, #0x8]
#endif
adr x0, back_in_32
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
index 9656c52..a8b493e 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
+++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig
@@ -525,13 +525,6 @@
Offset for CCI400 base
CCI400 base addr = CCSRBAR + CCI400_OFFSET
-config SYS_FSL_IFC_BANK_COUNT
- int "Maximum banks of Integrated flash controller"
- depends on ARCH_LS1043A || ARCH_LS1046A || ARCH_LS2080A || ARCH_LS1088A
- default 4 if ARCH_LS1043A
- default 4 if ARCH_LS1046A
- default 8 if ARCH_LS2080A || ARCH_LS1088A
-
config SYS_FSL_HAS_CCI400
bool
@@ -574,18 +567,9 @@
DDR controller uses this value as the base address for binding.
It is mapped to CONFIG_SYS_DP_DDR_BASE for core to access.
-config SYS_FSL_SRDS_1
- bool
-
-config SYS_FSL_SRDS_2
- bool
-
config SYS_NXP_SRDS_3
bool
-config SYS_HAS_SERDES
- bool
-
config FSL_TZASC_1
bool
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 5c45c2a..b0e8678 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -91,8 +91,8 @@
#define EARLY_PGTABLE_SIZE 0x5000
static struct mm_region early_map[] = {
#ifdef CONFIG_FSL_LSCH3
- { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
- CONFIG_SYS_FSL_CCSR_SIZE,
+ { CFG_SYS_FSL_CCSR_BASE, CFG_SYS_FSL_CCSR_BASE,
+ CFG_SYS_FSL_CCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
@@ -101,26 +101,26 @@
PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
},
{ CFG_SYS_FSL_QSPI_BASE1, CFG_SYS_FSL_QSPI_BASE1,
- CONFIG_SYS_FSL_QSPI_SIZE1,
+ CFG_SYS_FSL_QSPI_SIZE1,
PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE},
#ifdef CONFIG_FSL_IFC
/* For IFC Region #1, only the first 4MB is cache-enabled */
- { CONFIG_SYS_FSL_IFC_BASE1, CONFIG_SYS_FSL_IFC_BASE1,
- CONFIG_SYS_FSL_IFC_SIZE1_1,
+ { CFG_SYS_FSL_IFC_BASE1, CFG_SYS_FSL_IFC_BASE1,
+ CFG_SYS_FSL_IFC_SIZE1_1,
PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
},
- { CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
- CONFIG_SYS_FSL_IFC_BASE1 + CONFIG_SYS_FSL_IFC_SIZE1_1,
- CONFIG_SYS_FSL_IFC_SIZE1 - CONFIG_SYS_FSL_IFC_SIZE1_1,
+ { CFG_SYS_FSL_IFC_BASE1 + CFG_SYS_FSL_IFC_SIZE1_1,
+ CFG_SYS_FSL_IFC_BASE1 + CFG_SYS_FSL_IFC_SIZE1_1,
+ CFG_SYS_FSL_IFC_SIZE1 - CFG_SYS_FSL_IFC_SIZE1_1,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
},
- { CFG_SYS_FLASH_BASE, CONFIG_SYS_FSL_IFC_BASE1,
- CONFIG_SYS_FSL_IFC_SIZE1,
+ { CFG_SYS_FLASH_BASE, CFG_SYS_FSL_IFC_BASE1,
+ CFG_SYS_FSL_IFC_SIZE1,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
},
#endif
- { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
- CONFIG_SYS_FSL_DRAM_SIZE1,
+ { CFG_SYS_FSL_DRAM_BASE1, CFG_SYS_FSL_DRAM_BASE1,
+ CFG_SYS_FSL_DRAM_SIZE1,
#if defined(CONFIG_TFABOOT) || \
(defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
@@ -131,31 +131,31 @@
},
#ifdef CONFIG_FSL_IFC
/* Map IFC region #2 up to CFG_SYS_FLASH_BASE for NAND boot */
- { CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
- CFG_SYS_FLASH_BASE - CONFIG_SYS_FSL_IFC_BASE2,
+ { CFG_SYS_FSL_IFC_BASE2, CFG_SYS_FSL_IFC_BASE2,
+ CFG_SYS_FLASH_BASE - CFG_SYS_FSL_IFC_BASE2,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
},
#endif
- { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
- CONFIG_SYS_FSL_DCSR_SIZE,
+ { CFG_SYS_FSL_DCSR_BASE, CFG_SYS_FSL_DCSR_BASE,
+ CFG_SYS_FSL_DCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
- CONFIG_SYS_FSL_DRAM_SIZE2,
+ { CFG_SYS_FSL_DRAM_BASE2, CFG_SYS_FSL_DRAM_BASE2,
+ CFG_SYS_FSL_DRAM_SIZE2,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
-#ifdef CONFIG_SYS_FSL_DRAM_BASE3
- { CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
- CONFIG_SYS_FSL_DRAM_SIZE3,
+#ifdef CFG_SYS_FSL_DRAM_BASE3
+ { CFG_SYS_FSL_DRAM_BASE3, CFG_SYS_FSL_DRAM_BASE3,
+ CFG_SYS_FSL_DRAM_SIZE3,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
#endif
#elif defined(CONFIG_FSL_LSCH2)
- { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
- CONFIG_SYS_FSL_CCSR_SIZE,
+ { CFG_SYS_FSL_CCSR_BASE, CFG_SYS_FSL_CCSR_BASE,
+ CFG_SYS_FSL_CCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
@@ -163,23 +163,23 @@
SYS_FSL_OCRAM_SPACE_SIZE,
PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
},
- { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
- CONFIG_SYS_FSL_DCSR_SIZE,
+ { CFG_SYS_FSL_DCSR_BASE, CFG_SYS_FSL_DCSR_BASE,
+ CFG_SYS_FSL_DCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
{ CFG_SYS_FSL_QSPI_BASE, CFG_SYS_FSL_QSPI_BASE,
- CONFIG_SYS_FSL_QSPI_SIZE,
+ CFG_SYS_FSL_QSPI_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
},
#ifdef CONFIG_FSL_IFC
- { CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
- CONFIG_SYS_FSL_IFC_SIZE,
+ { CFG_SYS_FSL_IFC_BASE, CFG_SYS_FSL_IFC_BASE,
+ CFG_SYS_FSL_IFC_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
},
#endif
- { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
- CONFIG_SYS_FSL_DRAM_SIZE1,
+ { CFG_SYS_FSL_DRAM_BASE1, CFG_SYS_FSL_DRAM_BASE1,
+ CFG_SYS_FSL_DRAM_SIZE1,
#if defined(CONFIG_TFABOOT) || \
(defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD))
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
@@ -188,8 +188,8 @@
#endif
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
- { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
- CONFIG_SYS_FSL_DRAM_SIZE2,
+ { CFG_SYS_FSL_DRAM_BASE2, CFG_SYS_FSL_DRAM_BASE2,
+ CFG_SYS_FSL_DRAM_SIZE2,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_PXN | PTE_BLOCK_UXN |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
@@ -199,8 +199,8 @@
static struct mm_region final_map[] = {
#ifdef CONFIG_FSL_LSCH3
- { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
- CONFIG_SYS_FSL_CCSR_SIZE,
+ { CFG_SYS_FSL_CCSR_BASE, CFG_SYS_FSL_CCSR_BASE,
+ CFG_SYS_FSL_CCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
@@ -208,52 +208,52 @@
SYS_FSL_OCRAM_SPACE_SIZE,
PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
},
- { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
- CONFIG_SYS_FSL_DRAM_SIZE1,
+ { CFG_SYS_FSL_DRAM_BASE1, CFG_SYS_FSL_DRAM_BASE1,
+ CFG_SYS_FSL_DRAM_SIZE1,
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
{ CFG_SYS_FSL_QSPI_BASE1, CFG_SYS_FSL_QSPI_BASE1,
- CONFIG_SYS_FSL_QSPI_SIZE1,
+ CFG_SYS_FSL_QSPI_SIZE1,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
{ CFG_SYS_FSL_QSPI_BASE2, CFG_SYS_FSL_QSPI_BASE2,
- CONFIG_SYS_FSL_QSPI_SIZE2,
+ CFG_SYS_FSL_QSPI_SIZE2,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
#ifdef CONFIG_FSL_IFC
- { CONFIG_SYS_FSL_IFC_BASE2, CONFIG_SYS_FSL_IFC_BASE2,
- CONFIG_SYS_FSL_IFC_SIZE2,
+ { CFG_SYS_FSL_IFC_BASE2, CFG_SYS_FSL_IFC_BASE2,
+ CFG_SYS_FSL_IFC_SIZE2,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
#endif
- { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
- CONFIG_SYS_FSL_DCSR_SIZE,
+ { CFG_SYS_FSL_DCSR_BASE, CFG_SYS_FSL_DCSR_BASE,
+ CFG_SYS_FSL_DCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_MC_BASE, CONFIG_SYS_FSL_MC_BASE,
- CONFIG_SYS_FSL_MC_SIZE,
+ { CFG_SYS_FSL_MC_BASE, CFG_SYS_FSL_MC_BASE,
+ CFG_SYS_FSL_MC_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_NI_BASE, CONFIG_SYS_FSL_NI_BASE,
- CONFIG_SYS_FSL_NI_SIZE,
+ { CFG_SYS_FSL_NI_BASE, CFG_SYS_FSL_NI_BASE,
+ CFG_SYS_FSL_NI_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
/* For QBMAN portal, only the first 64MB is cache-enabled */
- { CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
- CONFIG_SYS_FSL_QBMAN_SIZE_1,
+ { CFG_SYS_FSL_QBMAN_BASE, CFG_SYS_FSL_QBMAN_BASE,
+ CFG_SYS_FSL_QBMAN_SIZE_1,
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_BLOCK_NS
},
- { CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
- CONFIG_SYS_FSL_QBMAN_BASE + CONFIG_SYS_FSL_QBMAN_SIZE_1,
- CONFIG_SYS_FSL_QBMAN_SIZE - CONFIG_SYS_FSL_QBMAN_SIZE_1,
+ { CFG_SYS_FSL_QBMAN_BASE + CFG_SYS_FSL_QBMAN_SIZE_1,
+ CFG_SYS_FSL_QBMAN_BASE + CFG_SYS_FSL_QBMAN_SIZE_1,
+ CFG_SYS_FSL_QBMAN_SIZE - CFG_SYS_FSL_QBMAN_SIZE_1,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
@@ -295,29 +295,29 @@
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
#endif
- { CONFIG_SYS_FSL_WRIOP1_BASE, CONFIG_SYS_FSL_WRIOP1_BASE,
- CONFIG_SYS_FSL_WRIOP1_SIZE,
+ { CFG_SYS_FSL_WRIOP1_BASE, CFG_SYS_FSL_WRIOP1_BASE,
+ CFG_SYS_FSL_WRIOP1_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_AIOP1_BASE, CONFIG_SYS_FSL_AIOP1_BASE,
- CONFIG_SYS_FSL_AIOP1_SIZE,
+ { CFG_SYS_FSL_AIOP1_BASE, CFG_SYS_FSL_AIOP1_BASE,
+ CFG_SYS_FSL_AIOP1_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_PEBUF_BASE, CONFIG_SYS_FSL_PEBUF_BASE,
- CONFIG_SYS_FSL_PEBUF_SIZE,
+ { CFG_SYS_FSL_PEBUF_BASE, CFG_SYS_FSL_PEBUF_BASE,
+ CFG_SYS_FSL_PEBUF_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
- CONFIG_SYS_FSL_DRAM_SIZE2,
+ { CFG_SYS_FSL_DRAM_BASE2, CFG_SYS_FSL_DRAM_BASE2,
+ CFG_SYS_FSL_DRAM_SIZE2,
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
-#ifdef CONFIG_SYS_FSL_DRAM_BASE3
- { CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
- CONFIG_SYS_FSL_DRAM_SIZE3,
+#ifdef CFG_SYS_FSL_DRAM_BASE3
+ { CFG_SYS_FSL_DRAM_BASE3, CFG_SYS_FSL_DRAM_BASE3,
+ CFG_SYS_FSL_DRAM_SIZE3,
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
@@ -328,8 +328,8 @@
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_CCSR_BASE, CONFIG_SYS_FSL_CCSR_BASE,
- CONFIG_SYS_FSL_CCSR_SIZE,
+ { CFG_SYS_FSL_CCSR_BASE, CFG_SYS_FSL_CCSR_BASE,
+ CFG_SYS_FSL_CCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
@@ -337,34 +337,34 @@
SYS_FSL_OCRAM_SPACE_SIZE,
PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_NON_SHARE
},
- { CONFIG_SYS_FSL_DCSR_BASE, CONFIG_SYS_FSL_DCSR_BASE,
- CONFIG_SYS_FSL_DCSR_SIZE,
+ { CFG_SYS_FSL_DCSR_BASE, CFG_SYS_FSL_DCSR_BASE,
+ CFG_SYS_FSL_DCSR_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
{ CFG_SYS_FSL_QSPI_BASE, CFG_SYS_FSL_QSPI_BASE,
- CONFIG_SYS_FSL_QSPI_SIZE,
+ CFG_SYS_FSL_QSPI_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
#ifdef CONFIG_FSL_IFC
- { CONFIG_SYS_FSL_IFC_BASE, CONFIG_SYS_FSL_IFC_BASE,
- CONFIG_SYS_FSL_IFC_SIZE,
+ { CFG_SYS_FSL_IFC_BASE, CFG_SYS_FSL_IFC_BASE,
+ CFG_SYS_FSL_IFC_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE
},
#endif
- { CONFIG_SYS_FSL_DRAM_BASE1, CONFIG_SYS_FSL_DRAM_BASE1,
- CONFIG_SYS_FSL_DRAM_SIZE1,
+ { CFG_SYS_FSL_DRAM_BASE1, CFG_SYS_FSL_DRAM_BASE1,
+ CFG_SYS_FSL_DRAM_SIZE1,
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
- { CONFIG_SYS_FSL_QBMAN_BASE, CONFIG_SYS_FSL_QBMAN_BASE,
- CONFIG_SYS_FSL_QBMAN_SIZE,
+ { CFG_SYS_FSL_QBMAN_BASE, CFG_SYS_FSL_QBMAN_BASE,
+ CFG_SYS_FSL_QBMAN_SIZE,
PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
- { CONFIG_SYS_FSL_DRAM_BASE2, CONFIG_SYS_FSL_DRAM_BASE2,
- CONFIG_SYS_FSL_DRAM_SIZE2,
+ { CFG_SYS_FSL_DRAM_BASE2, CFG_SYS_FSL_DRAM_BASE2,
+ CFG_SYS_FSL_DRAM_SIZE2,
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
@@ -385,8 +385,8 @@
PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN
},
#endif
- { CONFIG_SYS_FSL_DRAM_BASE3, CONFIG_SYS_FSL_DRAM_BASE3,
- CONFIG_SYS_FSL_DRAM_SIZE3,
+ { CFG_SYS_FSL_DRAM_BASE3, CFG_SYS_FSL_DRAM_BASE3,
+ CFG_SYS_FSL_DRAM_SIZE3,
PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_OUTER_SHARE | PTE_BLOCK_NS
},
@@ -536,13 +536,13 @@
* table.
*/
switch (final_map[index].virt) {
- case CONFIG_SYS_FSL_DRAM_BASE1:
+ case CFG_SYS_FSL_DRAM_BASE1:
final_map[index].virt = gd->bd->bi_dram[0].start;
final_map[index].phys = gd->bd->bi_dram[0].start;
final_map[index].size = gd->bd->bi_dram[0].size;
break;
-#ifdef CONFIG_SYS_FSL_DRAM_BASE2
- case CONFIG_SYS_FSL_DRAM_BASE2:
+#ifdef CFG_SYS_FSL_DRAM_BASE2
+ case CFG_SYS_FSL_DRAM_BASE2:
#if (CONFIG_NR_DRAM_BANKS >= 2)
final_map[index].virt = gd->bd->bi_dram[1].start;
final_map[index].phys = gd->bd->bi_dram[1].start;
@@ -552,8 +552,8 @@
#endif
break;
#endif
-#ifdef CONFIG_SYS_FSL_DRAM_BASE3
- case CONFIG_SYS_FSL_DRAM_BASE3:
+#ifdef CFG_SYS_FSL_DRAM_BASE3
+ case CFG_SYS_FSL_DRAM_BASE3:
#if (CONFIG_NR_DRAM_BANKS >= 3)
final_map[index].virt = gd->bd->bi_dram[2].start;
final_map[index].phys = gd->bd->bi_dram[2].start;
@@ -1566,7 +1566,7 @@
if (!gd->arch.tlb_addr)
return;
- if (gd->ram_size <= CONFIG_SYS_FSL_DRAM_SIZE1) {
+ if (gd->ram_size <= CFG_SYS_FSL_DRAM_SIZE1) {
mmu_change_region_attr(
CFG_SYS_SDRAM_BASE,
gd->ram_size,
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
index f18407b..4455eb1 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch2_speed.c
@@ -48,10 +48,11 @@
unsigned long cluster_clk;
sys_info->freq_systembus = sysclk;
-#ifndef CONFIG_CLUSTER_CLK_FREQ
-#define CONFIG_CLUSTER_CLK_FREQ get_board_sys_clk()
-#endif
+#ifdef CONFIG_CLUSTER_CLK_FREQ
cluster_clk = CONFIG_CLUSTER_CLK_FREQ;
+#else
+ cluster_clk = get_board_sys_clk();
+#endif
#if defined(CONFIG_DYNAMIC_DDR_CLK_FREQ) || defined(CONFIG_STATIC_DDR_CLK_FREQ)
sys_info->freq_ddrbus = get_board_ddr_clk();
diff --git a/arch/arm/cpu/armv8/generic_timer.c b/arch/arm/cpu/armv8/generic_timer.c
index f27a74b..8f83372 100644
--- a/arch/arm/cpu/armv8/generic_timer.c
+++ b/arch/arm/cpu/armv8/generic_timer.c
@@ -17,7 +17,7 @@
/*
* Generic timer implementation of get_tbclk()
*/
-unsigned long get_tbclk(void)
+unsigned long notrace get_tbclk(void)
{
unsigned long cntfrq;
asm volatile("mrs %0, cntfrq_el0" : "=r" (cntfrq));
@@ -78,7 +78,7 @@
/*
* timer_read_counter() using the Arm Generic Timer (aka arch timer).
*/
-unsigned long timer_read_counter(void)
+unsigned long notrace timer_read_counter(void)
{
unsigned long cntpct;
@@ -89,7 +89,7 @@
}
#endif
-uint64_t get_ticks(void)
+uint64_t notrace get_ticks(void)
{
unsigned long ticks = timer_read_counter();
diff --git a/arch/arm/cpu/armv8/u-boot.lds b/arch/arm/cpu/armv8/u-boot.lds
index 8fe4682..fb6a30c 100644
--- a/arch/arm/cpu/armv8/u-boot.lds
+++ b/arch/arm/cpu/armv8/u-boot.lds
@@ -51,10 +51,12 @@
}
#ifndef CONFIG_ARMV8_SECURE_BASE
-#define CONFIG_ARMV8_SECURE_BASE
+#define __ARMV8_SECURE_BASE
#define __ARMV8_PSCI_STACK_IN_RAM
+#else
+#define __ARMV8_SECURE_BASE CONFIG_ARMV8_SECURE_BASE
#endif
- .secure_text CONFIG_ARMV8_SECURE_BASE :
+ .secure_text __ARMV8_SECURE_BASE :
AT(ADDR(.__secure_start) + SIZEOF(.__secure_start))
{
*(._secure.text)
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index f25f72b..fc4f63d 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -77,11 +77,13 @@
}
#ifndef CONFIG_ARMV7_SECURE_BASE
-#define CONFIG_ARMV7_SECURE_BASE
+#define __ARMV7_SECURE_BASE
#define __ARMV7_PSCI_STACK_IN_RAM
+#else
+#define __ARMV7_SECURE_BASE CONFIG_ARMV7_SECURE_BASE
#endif
- .secure_text CONFIG_ARMV7_SECURE_BASE :
+ .secure_text __ARMV7_SECURE_BASE :
AT(ADDR(.__secure_start) + SIZEOF(.__secure_start))
{
*(._secure.text)
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 82aa450..8e83194 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -153,6 +153,7 @@
rk3399-nanopi-r4s.dtb \
rk3399-orangepi.dtb \
rk3399-pinebook-pro.dtb \
+ rk3399-pinephone-pro.dtb \
rk3399-puma-haikou.dtb \
rk3399-roc-pc.dtb \
rk3399-roc-pc-mezzanine.dtb \
@@ -170,6 +171,9 @@
rv1108-elgin-r1.dtb \
rv1108-evb.dtb
+dtb-$(CONFIG_ROCKCHIP_RV1126) += \
+ rv1126-edgeble-neu2-io.dtb
+
dtb-$(CONFIG_ARCH_S5P4418) += \
s5p4418-nanopi2.dtb
diff --git a/arch/arm/dts/k3-am625-sk-u-boot.dtsi b/arch/arm/dts/k3-am625-sk-u-boot.dtsi
index 92788ba..f275e3b 100644
--- a/arch/arm/dts/k3-am625-sk-u-boot.dtsi
+++ b/arch/arm/dts/k3-am625-sk-u-boot.dtsi
@@ -126,3 +126,25 @@
};
};
};
+
+&cpsw3g {
+ reg = <0x0 0x8000000 0x0 0x200000>,
+ <0x0 0x43000200 0x0 0x8>;
+ reg-names = "cpsw_nuss", "mac_efuse";
+ /delete-property/ ranges;
+ u-boot,dm-spl;
+
+ cpsw-phy-sel@04044 {
+ compatible = "ti,am64-phy-gmii-sel";
+ reg = <0x0 0x00104044 0x0 0x8>;
+ u-boot,dm-spl;
+ };
+};
+
+&cpsw_port1 {
+ u-boot,dm-spl;
+};
+
+&cpsw_port2 {
+ status = "disabled";
+};
diff --git a/arch/arm/dts/px30-ringneck-haikou-u-boot.dtsi b/arch/arm/dts/px30-ringneck-haikou-u-boot.dtsi
new file mode 100644
index 0000000..1325e0c
--- /dev/null
+++ b/arch/arm/dts/px30-ringneck-haikou-u-boot.dtsi
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "px30-u-boot.dtsi"
+
+/ {
+ config {
+ u-boot,mmc-env-offset = <0x5000>; /* @ 20KB */
+ u-boot,efi-partition-entries-offset = <0x200000>; /* 2MB */
+ u-boot,boot-led = "module_led";
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ u-boot,spl-boot-order = "same-as-spl", &emmc, &sdmmc;
+ };
+};
+
+&binman {
+ simple-bin {
+ fit {
+ offset = <((CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR - 64) * 512)>;
+ };
+ };
+};
+
+&emmc_clk {
+ u-boot,dm-pre-reloc;
+};
+
+&emmc_cmd {
+ u-boot,dm-pre-reloc;
+};
+
+&emmc_bus8 {
+ u-boot,dm-pre-reloc;
+};
+
+&gpio0 {
+ u-boot,dm-pre-reloc;
+};
+
+&gpio1 {
+ u-boot,dm-pre-reloc;
+};
+
+&gpio2 {
+ u-boot,dm-pre-reloc;
+
+ /*
+ * The Qseven BIOS_DISABLE signal on the PX30-µQ7 keeps the on-module
+ * eMMC powered-down initially (in fact it keeps the reset signal
+ * asserted). BIOS_DISABLE_OVERRIDE pin allows to re-enable eMMC after
+ * the SPL has been booted from SD Card.
+ */
+ bios-disable-override-hog {
+ u-boot,dm-pre-reloc;
+ };
+};
+
+&pinctrl {
+ u-boot,dm-pre-reloc;
+};
+
+&pcfg_pull_none_8ma {
+ u-boot,dm-pre-reloc;
+};
+
+&pcfg_pull_up_8ma {
+ u-boot,dm-pre-reloc;
+};
+
+&sdmmc_bus4 {
+ u-boot,dm-pre-reloc;
+};
+
+&sdmmc_clk {
+ u-boot,dm-pre-reloc;
+};
+
+&sdmmc_cmd {
+ u-boot,dm-pre-reloc;
+};
+
+&sdmmc_det {
+ u-boot,dm-pre-reloc;
+};
+
+&uart0 {
+ clock-frequency = <24000000>;
+ u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/px30-ringneck-haikou.dts b/arch/arm/dts/px30-ringneck-haikou.dts
new file mode 100644
index 0000000..08a3ad3
--- /dev/null
+++ b/arch/arm/dts/px30-ringneck-haikou.dts
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Theobroma Systems Design und Consulting GmbH
+ */
+
+/dts-v1/;
+#include "px30-ringneck.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "Theobroma Systems PX30-uQ7 SoM on Haikou devkit";
+ compatible = "tsd,px30-ringneck-haikou", "rockchip,px30";
+
+ aliases {
+ mmc2 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&haikou_keys_pin>;
+ pinctrl-names = "default";
+
+ button-batlow-n {
+ label = "BATLOW#";
+ linux,code = <KEY_BATTERY>;
+ gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>;
+ };
+
+ button-slp-btn-n {
+ label = "SLP_BTN#";
+ linux,code = <KEY_SLEEP>;
+ gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>;
+ };
+
+ button-wake-n {
+ label = "WAKE#";
+ linux,code = <KEY_WAKEUP>;
+ gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+
+ switch-lid-btn-n {
+ label = "LID_BTN#";
+ linux,code = <SW_LID>;
+ linux,input-type = <EV_SW>;
+ gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ leds {
+ pinctrl-0 = <&module_led_pin>, <&sd_card_led_pin>;
+
+ sd_card_led: led-1 {
+ gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc2";
+ function = LED_FUNCTION_SD;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+
+ i2s0-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "Haikou,I2S-codec";
+ simple-audio-card,mclk-fs = <512>;
+
+ simple-audio-card,codec {
+ clocks = <&sgtl5000_clk>;
+ sound-dai = <&sgtl5000>;
+ };
+
+ simple-audio-card,cpu {
+ bitclock-master;
+ frame-master;
+ sound-dai = <&i2s0_8ch>;
+ };
+ };
+
+ sgtl5000_clk: sgtl5000-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24576000>;
+ };
+
+ dc_12v: dc-12v-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_12v";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc3v3_baseboard: vcc3v3-baseboard-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_baseboard";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vcc5v0_baseboard: vcc5v0-baseboard-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_baseboard";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vdda_codec: vdda-codec-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vdda_codec";
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc5v0_baseboard>;
+ };
+
+ vddd_codec: vddd-codec-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vddd_codec";
+ regulator-boot-on;
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <1600000>;
+ vin-supply = <&vcc5v0_baseboard>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ sgtl5000: codec@a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ clocks = <&sgtl5000_clk>;
+ #sound-dai-cells = <0>;
+ VDDA-supply = <&vdda_codec>;
+ VDDIO-supply = <&vcc3v3_baseboard>;
+ VDDD-supply = <&vddd_codec>;
+ };
+};
+
+&i2c3 {
+ eeprom@50 {
+ reg = <0x50>;
+ compatible = "atmel,24c01";
+ pagesize = <8>;
+ size = <128>;
+ vcc-supply = <&vcc3v3_baseboard>;
+ };
+};
+
+&i2s0_8ch {
+ status = "okay";
+};
+
+&gmac {
+ status = "okay";
+};
+
+&pinctrl {
+ haikou {
+ haikou_keys_pin: haikou-keys-pin {
+ rockchip,pins =
+ /* WAKE# */
+ <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* SLP_BTN# */
+ <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* LID_BTN */
+ <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* BATLOW# */
+ <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* BIOS_DISABLE# */
+ <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ leds {
+ sd_card_led_pin: sd-card-led-pin {
+ rockchip,pins =
+ <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&sdmmc {
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ vmmc-supply = <&vcc3v3_baseboard>;
+ status = "okay";
+};
+
+&spi1 {
+ status = "okay";
+};
+
+&u2phy_otg {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart5 {
+ pinctrl-0 = <&uart5_xfer>;
+ status = "okay";
+};
+
+&usb20_otg {
+ status = "okay";
+};
diff --git a/arch/arm/dts/px30-ringneck.dtsi b/arch/arm/dts/px30-ringneck.dtsi
new file mode 100644
index 0000000..1239775
--- /dev/null
+++ b/arch/arm/dts/px30-ringneck.dtsi
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Theobroma Systems Design und Consulting GmbH
+ */
+
+/dts-v1/;
+#include "px30.dtsi"
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ mmc0 = &emmc;
+ mmc1 = &sdio;
+ rtc0 = &rtc_twi;
+ rtc1 = &rk809;
+ };
+
+ emmc_pwrseq: emmc-pwrseq {
+ compatible = "mmc-pwrseq-emmc";
+ pinctrl-0 = <&emmc_reset>;
+ pinctrl-names = "default";
+ reset-gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_HIGH>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&module_led_pin>;
+ status = "okay";
+
+ module_led: led-0 {
+ gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_HEARTBEAT;
+ linux,default-trigger = "heartbeat";
+ color = <LED_COLOR_ID_AMBER>;
+ };
+ };
+
+ vcc5v0_sys: vccsys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&emmc {
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ supports-emmc;
+ mmc-pwrseq = <&emmc_pwrseq>;
+ non-removable;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_emmc>;
+
+ status = "okay";
+};
+
+/* On-module TI DP83825I PHY but no connector, enable in carrierboard */
+&gmac {
+ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 50000 50000>;
+ phy-supply = <&vcc_3v3>;
+ clock_in_out = "output";
+};
+
+&gpio2 {
+ /*
+ * The Qseven BIOS_DISABLE signal on the PX30-µQ7 keeps the on-module
+ * eMMC powered-down initially (in fact it keeps the reset signal
+ * asserted). BIOS_DISABLE_OVERRIDE pin allows to re-enable eMMC after
+ * the SPL has been booted from SD Card.
+ */
+ bios-disable-override-hog {
+ gpios = <RK_PB5 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "bios_disable_override";
+ gpio-hog;
+ };
+
+ /*
+ * The BIOS_DISABLE hog is a feedback pin for the actual status of the
+ * signal, ignoring the BIOS_DISABLE_OVERRIDE logic. This usually
+ * represents the state of a switch on the baseboard.
+ */
+ bios-disable-n-hog {
+ gpios = <RK_PC2 GPIO_ACTIVE_LOW>;
+ line-name = "bios_disable";
+ input;
+ gpio-hog;
+ };
+};
+
+&gpu {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&pmic_int>;
+ pinctrl-names = "default";
+ #clock-cells = <0>;
+ clock-output-names = "xin32k";
+ rockchip,system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc_3v3>;
+ vcc6-supply = <&vcc_3v3>;
+ vcc7-supply = <&vcc_3v3>;
+ vcc9-supply = <&vcc5v0_sys>;
+
+ regulators {
+ vdd_log: DCDC_REG1 {
+ regulator-name = "vdd_log";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <950000>;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <950000>;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_3v0_1v8: vcc_emmc: DCDC_REG4 {
+ regulator-name = "vcc_3v0_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3000000>;
+ };
+ };
+
+ vcc_3v3: DCDC_REG5 {
+ regulator-name = "vcc_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_1v8: LDO_REG2 {
+ regulator-name = "vcc_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_1v0: LDO_REG3 {
+ regulator-name = "vcc_1v0";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_lcd: LDO_REG7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-name = "vcc_lcd";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vcc_1v8_lcd: LDO_REG8 {
+ regulator-name = "vcc_1v8_lcd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcca_1v8: LDO_REG9 {
+ regulator-name = "vcca_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ /* SE05x is limited to Fast Mode */
+ clock-frequency = <400000>;
+
+ fan: fan@18 {
+ compatible = "ti,amc6821";
+ reg = <0x18>;
+ #cooling-cells = <2>;
+ };
+
+ rtc_twi: rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2s0_8ch {
+ rockchip,trcm-sync-tx-only;
+
+ pinctrl-0 = <&i2s0_8ch_sclktx &i2s0_8ch_lrcktx
+ &i2s0_8ch_sdo0 &i2s0_8ch_sdi0>;
+};
+
+&io_domains {
+ vccio1-supply = <&vcc_3v3>;
+ vccio2-supply = <&vccio_sd>;
+ vccio3-supply = <&vcc_3v3>;
+ vccio4-supply = <&vcc_3v3>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_emmc>;
+ vccio-oscgpi-supply = <&vcc_3v3>;
+
+ status = "okay";
+};
+
+&pinctrl {
+ emmc {
+ emmc_reset: emmc-reset {
+ rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ module_led_pin: module-led-pin {
+ rockchip,pins = <1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int: pmic-int {
+ rockchip,pins =
+ <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc {
+ vqmmc-supply = <&vccio_sd>;
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+};
+
+&u2phy_host {
+ status = "okay";
+};
+
+/* Mule UCAN */
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm/dts/px30.dtsi b/arch/arm/dts/px30.dtsi
index 00f50b0..bfa3580 100644
--- a/arch/arm/dts/px30.dtsi
+++ b/arch/arm/dts/px30.dtsi
@@ -365,6 +365,28 @@
status = "disabled";
};
+ i2s0_8ch: i2s@ff060000 {
+ compatible = "rockchip,px30-i2s-tdm";
+ reg = <0x0 0xff060000 0x0 0x1000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru SCLK_I2S0_TX>, <&cru SCLK_I2S0_RX>, <&cru HCLK_I2S0>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ dmas = <&dmac 16>, <&dmac 17>;
+ dma-names = "tx", "rx";
+ rockchip,grf = <&grf>;
+ resets = <&cru SRST_I2S0_TX>, <&cru SRST_I2S0_RX>;
+ reset-names = "tx-m", "rx-m";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_8ch_sclktx &i2s0_8ch_sclkrx
+ &i2s0_8ch_lrcktx &i2s0_8ch_lrckrx
+ &i2s0_8ch_sdo0 &i2s0_8ch_sdi0
+ &i2s0_8ch_sdo1 &i2s0_8ch_sdi1
+ &i2s0_8ch_sdo2 &i2s0_8ch_sdi2
+ &i2s0_8ch_sdo3 &i2s0_8ch_sdi3>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
i2s1_2ch: i2s@ff070000 {
compatible = "rockchip,px30-i2s", "rockchip,rk3066-i2s";
reg = <0x0 0xff070000 0x0 0x1000>;
@@ -528,7 +550,7 @@
i2c0: i2c@ff180000 {
compatible = "rockchip,px30-i2c", "rockchip,rk3399-i2c";
reg = <0x0 0xff180000 0x0 0x1000>;
- clocks = <&cru SCLK_I2C0>, <&cru PCLK_I2C0>;
+ clocks = <&cru SCLK_I2C0>, <&cru PCLK_I2C0>;
clock-names = "i2c", "pclk";
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
@@ -711,7 +733,7 @@
clock-names = "pclk", "timer";
};
- dmac: dmac@ff240000 {
+ dmac: dma-controller@ff240000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x0 0xff240000 0x0 0x4000>;
interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
@@ -1072,7 +1094,7 @@
};
dsi: dsi@ff450000 {
- compatible = "rockchip,px30-mipi-dsi";
+ compatible = "rockchip,px30-mipi-dsi", "snps,dw-mipi-dsi";
reg = <0x0 0xff450000 0x0 0x10000>;
interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_MIPI_DSI>;
diff --git a/arch/arm/dts/r8a77980-condor-u-boot.dts b/arch/arm/dts/r8a77980-condor-u-boot.dts
index 1b22c7f..576a74e 100644
--- a/arch/arm/dts/r8a77980-condor-u-boot.dts
+++ b/arch/arm/dts/r8a77980-condor-u-boot.dts
@@ -25,6 +25,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "s25fs512s", "jedec,spi-nor";
+ m25p,fast-read;
spi-max-frequency = <50000000>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <1>;
diff --git a/arch/arm/dts/r8a77980-condor.dts b/arch/arm/dts/r8a77980-condor.dts
index 3dde028..f0a0a51 100644
--- a/arch/arm/dts/r8a77980-condor.dts
+++ b/arch/arm/dts/r8a77980-condor.dts
@@ -212,7 +212,7 @@
&mmc0 {
pinctrl-0 = <&mmc_pins>;
- pinctrl-1 = <&mmc_pins_uhs>;
+ pinctrl-1 = <&mmc_pins>;
pinctrl-names = "default", "state_uhs";
vmmc-supply = <&d3_3v>;
@@ -255,12 +255,6 @@
mmc_pins: mmc {
groups = "mmc_data8", "mmc_ctrl", "mmc_ds";
function = "mmc";
- power-source = <3300>;
- };
-
- mmc_pins_uhs: mmc_uhs {
- groups = "mmc_data8", "mmc_ctrl", "mmc_ds";
- function = "mmc";
power-source = <1800>;
};
diff --git a/arch/arm/dts/rk3399-pinephone-pro-u-boot.dtsi b/arch/arm/dts/rk3399-pinephone-pro-u-boot.dtsi
new file mode 100644
index 0000000..1dad283
--- /dev/null
+++ b/arch/arm/dts/rk3399-pinephone-pro-u-boot.dtsi
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Peter Robinson <pbrobinson at gmail.com>
+ */
+
+#include "rk3399-u-boot.dtsi"
+#include "rk3399-sdram-lpddr4-100.dtsi"
+
+/ {
+ chosen {
+ u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
+ };
+
+ config {
+ u-boot,spl-payload-offset = <0x60000>; /* @ 384KB */
+ };
+};
+
+&rng {
+ status = "okay";
+};
+
+&sdhci {
+ max-frequency = <25000000>;
+ u-boot,dm-pre-reloc;
+};
+
+&sdmmc {
+ max-frequency = <20000000>;
+ u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3399-pinephone-pro.dts b/arch/arm/dts/rk3399-pinephone-pro.dts
new file mode 100644
index 0000000..04403a7
--- /dev/null
+++ b/arch/arm/dts/rk3399-pinephone-pro.dts
@@ -0,0 +1,474 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Martijn Braam <martijn@brixit.nl>
+ * Copyright (c) 2021 Kamil Trzciński <ayufan@ayufan.eu>
+ */
+
+/*
+ * PinePhone Pro datasheet:
+ * https://files.pine64.org/doc/PinePhonePro/PinephonePro-Schematic-V1.0-20211127.pdf
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/linux-event-codes.h>
+#include "rk3399.dtsi"
+#include "rk3399-opp.dtsi"
+
+/ {
+ model = "Pine64 PinePhonePro";
+ compatible = "pine64,pinephone-pro", "rockchip,rk3399";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &sdio0;
+ mmc1 = &sdmmc;
+ mmc2 = &sdhci;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwrbtn_pin>;
+
+ key-power {
+ debounce-interval = <20>;
+ gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
+ label = "Power";
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
+
+ vcc_sys: vcc-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc3v3_sys: vcc3v3-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc_sys>;
+ };
+
+ vcca1v8_s3: vcc1v8-s3-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcca1v8_s3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc3v3_sys>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vcc1v8_codec: vcc1v8-codec-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio3 RK_PA4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc1v8_codec_en>;
+ regulator-name = "vcc1v8_codec";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ wifi_pwrseq: sdio-wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk818 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h_pin>;
+ /*
+ * Wait between power-on and SDIO access for CYP43455
+ * POR circuit.
+ */
+ post-power-on-delay-ms = <110>;
+ /*
+ * Wait between consecutive toggles for CYP43455 CBUCK
+ * regulator discharge.
+ */
+ power-off-delay-us = <10000>;
+
+ /* WL_REG_ON on module */
+ reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&cpu_l0 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l1 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l2 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_l3 {
+ cpu-supply = <&vdd_cpu_l>;
+};
+
+&cpu_b0 {
+ cpu-supply = <&vdd_cpu_b>;
+};
+
+&cpu_b1 {
+ cpu-supply = <&vdd_cpu_b>;
+};
+
+&emmc_phy {
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ i2c-scl-rising-time-ns = <168>;
+ i2c-scl-falling-time-ns = <4>;
+ status = "okay";
+
+ rk818: pmic@1c {
+ compatible = "rockchip,rk818";
+ reg = <0x1c>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <RK_PC5 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "xin32k", "rk808-clkout2";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>;
+ rockchip,system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc_sys>;
+ vcc2-supply = <&vcc_sys>;
+ vcc3-supply = <&vcc_sys>;
+ vcc4-supply = <&vcc_sys>;
+ vcc6-supply = <&vcc_sys>;
+ vcc7-supply = <&vcc3v3_sys>;
+ vcc8-supply = <&vcc_sys>;
+ vcc9-supply = <&vcc3v3_sys>;
+
+ regulators {
+ vdd_cpu_l: DCDC_REG1 {
+ regulator-name = "vdd_cpu_l";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <975000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_center: DCDC_REG2 {
+ regulator-name = "vdd_center";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_1v8: DCDC_REG4 {
+ regulator-name = "vcc_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcca3v0_codec: LDO_REG1 {
+ regulator-name = "vcca3v0_codec";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ vcc3v0_touch: LDO_REG2 {
+ regulator-name = "vcc3v0_touch";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ vcca1v8_codec: LDO_REG3 {
+ regulator-name = "vcca1v8_codec";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ rk818_pwr_on: LDO_REG4 {
+ regulator-name = "rk818_pwr_on";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_3v0: LDO_REG5 {
+ regulator-name = "vcc_3v0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_1v5: LDO_REG6 {
+ regulator-name = "vcc_1v5";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc1v8_dvp: LDO_REG7 {
+ regulator-name = "vcc1v8_dvp";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vcc3v3_s3: LDO_REG8 {
+ regulator-name = "vcc3v3_s3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG9 {
+ regulator-name = "vccio_sd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vcc3v3_s0: SWITCH_REG {
+ regulator-name = "vcc3v3_s0";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+ };
+ };
+
+ vdd_cpu_b: regulator@40 {
+ compatible = "silergy,syr827";
+ reg = <0x40>;
+ fcs,suspend-voltage-selector = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vsel1_pin>;
+ regulator-name = "vdd_cpu_b";
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-ramp-delay = <1000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_gpu: regulator@41 {
+ compatible = "silergy,syr828";
+ reg = <0x41>;
+ fcs,suspend-voltage-selector = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vsel2_pin>;
+ regulator-name = "vdd_gpu";
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <975000>;
+ regulator-ramp-delay = <1000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+};
+
+&cluster0_opp {
+ opp04 {
+ status = "disabled";
+ };
+
+ opp05 {
+ status = "disabled";
+ };
+};
+
+&cluster1_opp {
+ opp06 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <1100000 1100000 1150000>;
+ };
+
+ opp07 {
+ status = "disabled";
+ };
+};
+
+&io_domains {
+ bt656-supply = <&vcc1v8_dvp>;
+ audio-supply = <&vcca1v8_codec>;
+ sdmmc-supply = <&vccio_sd>;
+ gpio1830-supply = <&vcc_3v0>;
+ status = "okay";
+};
+
+&pmu_io_domains {
+ pmu1830-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&pinctrl {
+ buttons {
+ pwrbtn_pin: pwrbtn-pin {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ vsel1_pin: vsel1-pin {
+ rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ vsel2_pin: vsel2-pin {
+ rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ sdio-pwrseq {
+ wifi_enable_h_pin: wifi-enable-h-pin {
+ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sound {
+ vcc1v8_codec_en: vcc1v8-codec-en {
+ rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ wireless-bluetooth {
+ bt_wake_pin: bt-wake-pin {
+ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_host_wake_pin: bt-host-wake-pin {
+ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_reset_pin: bt-reset-pin {
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&sdio0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ disable-wp;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
+ sd-uhs-sdr104;
+ status = "okay";
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ max-frequency = <150000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+ vmmc-supply = <&vcc3v3_sys>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ mmc-hs200-1_8v;
+ non-removable;
+ status = "okay";
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <1>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4345c5";
+ clocks = <&rk818 1>;
+ clock-names = "lpo";
+ device-wakeup-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
+ max-speed = <1500000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake_pin &bt_wake_pin &bt_reset_pin>;
+ shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
+ vbat-supply = <&vcc3v3_sys>;
+ vddio-supply = <&vcc_1v8>;
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
diff --git a/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi b/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
index d2349ae..088861d 100644
--- a/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-puma-haikou-u-boot.dtsi
@@ -46,14 +46,14 @@
&binman {
simple-bin {
- blob {
+ fit {
offset = <((CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR - 64) * 512)>;
};
};
#ifdef CONFIG_ROCKCHIP_SPI_IMAGE
simple-bin-spi {
- blob {
+ fit {
/* same as u-boot,spl-payload-offset */
offset = <0x80000>;
};
diff --git a/arch/arm/dts/rk3399-puma-haikou.dts b/arch/arm/dts/rk3399-puma-haikou.dts
index 292bb7e..115c14c 100644
--- a/arch/arm/dts/rk3399-puma-haikou.dts
+++ b/arch/arm/dts/rk3399-puma-haikou.dts
@@ -49,7 +49,7 @@
sgtl5000_clk: sgtl5000-oscillator {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <24576000>;
+ clock-frequency = <24576000>;
};
dc_12v: dc-12v {
@@ -207,7 +207,7 @@
cap-sd-highspeed;
cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
disable-wp;
- max-frequency = <150000000>;
+ max-frequency = <40000000>;
pinctrl-names = "default";
pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
vmmc-supply = <&vcc3v3_baseboard>;
@@ -232,6 +232,7 @@
&usbdrd_dwc3_0 {
dr_mode = "otg";
+ extcon = <&extcon_usb3>;
status = "okay";
};
diff --git a/arch/arm/dts/rk3399-puma.dtsi b/arch/arm/dts/rk3399-puma.dtsi
index fb67db4..aa3e21b 100644
--- a/arch/arm/dts/rk3399-puma.dtsi
+++ b/arch/arm/dts/rk3399-puma.dtsi
@@ -25,6 +25,13 @@
};
};
+ extcon_usb3: extcon-usb3 {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb3_id>;
+ };
+
clkin_gmac: external-gmac-clock {
compatible = "fixed-clock";
clock-frequency = <125000000>;
@@ -55,7 +62,6 @@
vcc5v0_host: vcc5v0-host-regulator {
compatible = "regulator-fixed";
gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_LOW>;
- enable-active-low;
pinctrl-names = "default";
pinctrl-0 = <&vcc5v0_host_en>;
regulator-name = "vcc5v0_host";
@@ -71,6 +77,17 @@
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
+
+ vdd_log: vdd-log {
+ compatible = "pwm-regulator";
+ pwms = <&pwm2 0 25000 1>;
+ pwm-supply = <&vcc5v0_sys>;
+ regulator-name = "vdd_log";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
};
&cpu_b0 {
@@ -422,9 +439,22 @@
<4 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
+
+ usb3 {
+ usb3_id: usb3-id {
+ rockchip,pins =
+ <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
};
&sdhci {
+ /*
+ * Signal integrity isn't great at 200MHz but 100MHz has proven stable
+ * enough.
+ */
+ max-frequency = <100000000>;
+
bus-width = <8>;
mmc-hs400-1_8v;
mmc-hs400-enhanced-strobe;
diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi
index 3c1a15f..8a0b180 100644
--- a/arch/arm/dts/rk3399-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-u-boot.dtsi
@@ -62,6 +62,7 @@
#if defined(CONFIG_ROCKCHIP_SPI_IMAGE) && defined(CONFIG_HAS_ROM)
&binman {
+ multiple-images;
rom {
filename = "u-boot.rom";
size = <0x400000>;
@@ -82,7 +83,7 @@
};
};
};
-#endif
+#endif /* CONFIG_ROCKCHIP_SPI_IMAGE && CONFIG_HAS_ROM */
&cru {
u-boot,dm-pre-reloc;
diff --git a/arch/arm/dts/rockchip-u-boot.dtsi b/arch/arm/dts/rockchip-u-boot.dtsi
index fa094b0..f147dc2 100644
--- a/arch/arm/dts/rockchip-u-boot.dtsi
+++ b/arch/arm/dts/rockchip-u-boot.dtsi
@@ -30,14 +30,100 @@
};
};
-#ifdef CONFIG_ARM64
- blob {
+#if defined(CONFIG_SPL_FIT) && defined(CONFIG_ARM64)
+ fit: fit {
+ description = "FIT image for U-Boot with bl31 (TF-A)";
+ #address-cells = <1>;
+ fit,fdt-list = "of-list";
filename = "u-boot.itb";
+ fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+ fit,align = <512>;
+ offset = <CONFIG_SPL_PAD_TO>;
+ images {
+ u-boot {
+ description = "U-Boot (64-bit)";
+ type = "standalone";
+ os = "U-Boot";
+ arch = "arm64";
+ compression = "none";
+ load = <CONFIG_TEXT_BASE>;
+ entry = <CONFIG_TEXT_BASE>;
+ u-boot-nodtb {
+ };
+#ifdef CONFIG_SPL_FIT_SIGNATURE
+ hash {
+ algo = "sha256";
+ };
+#endif
+ };
+
+ @atf-SEQ {
+ fit,operation = "split-elf";
+ description = "ARM Trusted Firmware";
+ type = "firmware";
+ arch = "arm64";
+ os = "arm-trusted-firmware";
+ compression = "none";
+ fit,load;
+ fit,entry;
+ fit,data;
+
+ atf-bl31 {
+ };
+#ifdef CONFIG_SPL_FIT_SIGNATURE
+ hash {
+ algo = "sha256";
+ };
+#endif
+ };
+ @tee-SEQ {
+ fit,operation = "split-elf";
+ description = "TEE";
+ type = "tee";
+ arch = "arm64";
+ os = "tee";
+ compression = "none";
+ fit,load;
+ fit,entry;
+ fit,data;
+
+ tee-os {
+ optional;
+ };
+#ifdef CONFIG_SPL_FIT_SIGNATURE
+ hash {
+ algo = "sha256";
+ };
+#endif
+ };
+
+ @fdt-SEQ {
+ description = "fdt-NAME";
+ compression = "none";
+ type = "flat_dt";
+#ifdef CONFIG_SPL_FIT_SIGNATURE
+ hash {
+ algo = "sha256";
+ };
+#endif
+ };
+ };
+
+ configurations {
+ default = "@config-DEFAULT-SEQ";
+ @config-SEQ {
+ description = "NAME.dtb";
+ fdt = "fdt-SEQ";
+ fit,firmware = "atf-1", "u-boot";
+ fit,loadables;
+ };
+ };
+ };
#else
u-boot-img {
-#endif
offset = <CONFIG_SPL_PAD_TO>;
};
+#endif
};
#ifdef CONFIG_ROCKCHIP_SPI_IMAGE
@@ -59,7 +145,8 @@
};
#ifdef CONFIG_ARM64
- blob {
+ fit {
+ type = "blob";
filename = "u-boot.itb";
#else
u-boot-img {
@@ -68,6 +155,6 @@
offset = <CONFIG_SYS_SPI_U_BOOT_OFFS>;
};
};
-#endif
+#endif /* CONFIG_ROCKCHIP_SPI_IMAGE */
};
-#endif
+#endif /* CONFIG_SPL */
diff --git a/arch/arm/dts/rv1126-edgeble-neu2-io-u-boot.dtsi b/arch/arm/dts/rv1126-edgeble-neu2-io-u-boot.dtsi
new file mode 100644
index 0000000..51a1617
--- /dev/null
+++ b/arch/arm/dts/rv1126-edgeble-neu2-io-u-boot.dtsi
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include "rv1126-u-boot.dtsi"
+
+&sdio {
+ status = "disabled";
+};
diff --git a/arch/arm/dts/rv1126-edgeble-neu2-io.dts b/arch/arm/dts/rv1126-edgeble-neu2-io.dts
new file mode 100644
index 0000000..dded0a1
--- /dev/null
+++ b/arch/arm/dts/rv1126-edgeble-neu2-io.dts
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+/dts-v1/;
+#include "rv1126.dtsi"
+#include "rv1126-edgeble-neu2.dtsi"
+
+/ {
+ model = "Edgeble Neu2 IO Board";
+ compatible = "edgeble,neural-compute-module-2-io",
+ "edgeble,neural-compute-module-2", "rockchip,rv1126";
+
+ aliases {
+ serial2 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+};
+
+&sdmmc {
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_clk &sdmmc0_cmd &sdmmc0_bus4 &sdmmc0_det>;
+ rockchip,default-sample-phase = <90>;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr104;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
diff --git a/arch/arm/dts/rv1126-edgeble-neu2.dtsi b/arch/arm/dts/rv1126-edgeble-neu2.dtsi
new file mode 100644
index 0000000..cc64ba4
--- /dev/null
+++ b/arch/arm/dts/rv1126-edgeble-neu2.dtsi
@@ -0,0 +1,338 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+/ {
+ compatible = "edgeble,neural-compute-module-2", "rockchip,rv1126";
+
+ aliases {
+ mmc0 = &emmc;
+ };
+
+ vcc5v0_sys: vcc5v0-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ vccio_flash: vccio-flash-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PB3 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&flash_vol_sel>;
+ regulator-name = "vccio_flash";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc_3v3>;
+ };
+
+ sdio_pwrseq: pwrseq-sdio {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk809 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h>;
+ reset-gpios = <&gpio1 RK_PD0 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&emmc {
+ bus-width = <8>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_cmd &emmc_clk &emmc_rstnout>;
+ rockchip,default-sample-phase = <90>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vccio_flash>;
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB1 IRQ_TYPE_LEVEL_LOW>;
+ #clock-cells = <1>;
+ clock-output-names = "rk808-clkout1", "rk808-clkout2";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>;
+ rockchip,system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc_buck5>;
+ vcc6-supply = <&vcc_buck5>;
+ vcc7-supply = <&vcc5v0_sys>;
+ vcc8-supply = <&vcc3v3_sys>;
+ vcc9-supply = <&vcc5v0_sys>;
+
+ regulators {
+ vdd_npu_vepu: DCDC_REG1 {
+ regulator-name = "vdd_npu_vepu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <650000>;
+ regulator-max-microvolt = <950000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc3v3_sys: DCDC_REG4 {
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_buck5: DCDC_REG5 {
+ regulator-name = "vcc_buck5";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <2200000>;
+ };
+ };
+
+ vcc_0v8: LDO_REG1 {
+ regulator-name = "vcc_0v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc1v8_pmu: LDO_REG2 {
+ regulator-name = "vcc1v8_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd0v8_pmu: LDO_REG3 {
+ regulator-name = "vcc0v8_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <800000>;
+ };
+ };
+
+ vcc_1v8: LDO_REG4 {
+ regulator-name = "vcc_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_dovdd: LDO_REG5 {
+ regulator-name = "vcc_dovdd";
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_dvdd: LDO_REG6 {
+ regulator-name = "vcc_dvdd";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_avdd: LDO_REG7 {
+ regulator-name = "vcc_avdd";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG8 {
+ regulator-name = "vccio_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc3v3_sd: LDO_REG9 {
+ regulator-name = "vcc3v3_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_5v0: SWITCH_REG1 {
+ regulator-name = "vcc_5v0";
+ };
+
+ vcc_3v3: SWITCH_REG2 {
+ regulator-name = "vcc_3v3";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&pinctrl {
+ bt {
+ bt_enable: bt-enable {
+ rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ flash {
+ flash_vol_sel: flash-vol-sel {
+ rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ wifi {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio0-supply = <&vcc1v8_pmu>;
+ pmuio1-supply = <&vcc3v3_sys>;
+ vccio1-supply = <&vccio_flash>;
+ vccio2-supply = <&vccio_sd>;
+ vccio3-supply = <&vcc_1v8>;
+ vccio4-supply = <&vcc_dovdd>;
+ vccio5-supply = <&vcc_1v8>;
+ vccio6-supply = <&vcc_1v8>;
+ vccio7-supply = <&vcc_dovdd>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdio {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ max-frequency = <100000000>;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_clk &sdmmc1_cmd &sdmmc1_bus4>;
+ rockchip,default-sample-phase = <90>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_sys>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_ctsn &uart0_rtsn>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,qca9377-bt";
+ clocks = <&rk809 1>;
+ enable-gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_HIGH>; /* BT_RST */
+ max-speed = <2000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_enable>;
+ vddxo-supply = <&vcc3v3_sys>;
+ vddio-supply = <&vcc_1v8>;
+ };
+};
diff --git a/arch/arm/dts/rv1126-pinctrl.dtsi b/arch/arm/dts/rv1126-pinctrl.dtsi
new file mode 100644
index 0000000..28d8d29
--- /dev/null
+++ b/arch/arm/dts/rv1126-pinctrl.dtsi
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
+ */
+
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rockchip-pinconf.dtsi"
+
+/*
+ * This file is auto generated by pin2dts tool, please keep these code
+ * by adding changes at end of this file.
+ */
+&pinctrl {
+ emmc {
+ /omit-if-no-ref/
+ emmc_rstnout: emmc-rstnout {
+ rockchip,pins =
+ /* emmc_rstn */
+ <1 RK_PA3 2 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ emmc_bus8: emmc-bus8 {
+ rockchip,pins =
+ /* emmc_d0 */
+ <0 RK_PC4 2 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d1 */
+ <0 RK_PC5 2 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d2 */
+ <0 RK_PC6 2 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d3 */
+ <0 RK_PC7 2 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d4 */
+ <0 RK_PD0 2 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d5 */
+ <0 RK_PD1 2 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d6 */
+ <0 RK_PD2 2 &pcfg_pull_up_drv_level_2>,
+ /* emmc_d7 */
+ <0 RK_PD3 2 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ emmc_clk: emmc-clk {
+ rockchip,pins =
+ /* emmc_clko */
+ <0 RK_PD7 2 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ emmc_cmd: emmc-cmd {
+ rockchip,pins =
+ /* emmc_cmd */
+ <0 RK_PD5 2 &pcfg_pull_up_drv_level_2>;
+ };
+ };
+ i2c0 {
+ /omit-if-no-ref/
+ i2c0_xfer: i2c0-xfer {
+ rockchip,pins =
+ /* i2c0_scl */
+ <0 RK_PB4 1 &pcfg_pull_none_drv_level_0_smt>,
+ /* i2c0_sda */
+ <0 RK_PB5 1 &pcfg_pull_none_drv_level_0_smt>;
+ };
+ };
+ sdmmc0 {
+ /omit-if-no-ref/
+ sdmmc0_bus4: sdmmc0-bus4 {
+ rockchip,pins =
+ /* sdmmc0_d0 */
+ <1 RK_PA4 1 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc0_d1 */
+ <1 RK_PA5 1 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc0_d2 */
+ <1 RK_PA6 1 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc0_d3 */
+ <1 RK_PA7 1 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ sdmmc0_clk: sdmmc0-clk {
+ rockchip,pins =
+ /* sdmmc0_clk */
+ <1 RK_PB0 1 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ sdmmc0_cmd: sdmmc0-cmd {
+ rockchip,pins =
+ /* sdmmc0_cmd */
+ <1 RK_PB1 1 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ sdmmc0_det: sdmmc0-det {
+ rockchip,pins =
+ <0 RK_PA3 1 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sdmmc0_pwr: sdmmc0-pwr {
+ rockchip,pins =
+ <0 RK_PC0 1 &pcfg_pull_none>;
+ };
+ };
+ sdmmc1 {
+ /omit-if-no-ref/
+ sdmmc1_bus4: sdmmc1-bus4 {
+ rockchip,pins =
+ /* sdmmc1_d0 */
+ <1 RK_PB4 1 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d1 */
+ <1 RK_PB5 1 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d2 */
+ <1 RK_PB6 1 &pcfg_pull_up_drv_level_2>,
+ /* sdmmc1_d3 */
+ <1 RK_PB7 1 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ sdmmc1_clk: sdmmc1-clk {
+ rockchip,pins =
+ /* sdmmc1_clk */
+ <1 RK_PB2 1 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ sdmmc1_cmd: sdmmc1-cmd {
+ rockchip,pins =
+ /* sdmmc1_cmd */
+ <1 RK_PB3 1 &pcfg_pull_up_drv_level_2>;
+ };
+ /omit-if-no-ref/
+ sdmmc1_det: sdmmc1-det {
+ rockchip,pins =
+ <1 RK_PD0 2 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ sdmmc1_pwr: sdmmc1-pwr {
+ rockchip,pins =
+ <1 RK_PD1 2 &pcfg_pull_none>;
+ };
+ };
+ uart0 {
+ /omit-if-no-ref/
+ uart0_xfer: uart0-xfer {
+ rockchip,pins =
+ /* uart0_rx */
+ <1 RK_PC2 1 &pcfg_pull_up>,
+ /* uart0_tx */
+ <1 RK_PC3 1 &pcfg_pull_up>;
+ };
+ /omit-if-no-ref/
+ uart0_ctsn: uart0-ctsn {
+ rockchip,pins =
+ <1 RK_PC1 1 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart0_rtsn: uart0-rtsn {
+ rockchip,pins =
+ <1 RK_PC0 1 &pcfg_pull_none>;
+ };
+ /omit-if-no-ref/
+ uart0_rtsn_gpio: uart0-rts-pin {
+ rockchip,pins =
+ <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+ uart1 {
+ /omit-if-no-ref/
+ uart1m0_xfer: uart1m0-xfer {
+ rockchip,pins =
+ /* uart1_rx_m0 */
+ <0 RK_PB7 2 &pcfg_pull_up>,
+ /* uart1_tx_m0 */
+ <0 RK_PB6 2 &pcfg_pull_up>;
+ };
+ };
+ uart2 {
+ /omit-if-no-ref/
+ uart2m1_xfer: uart2m1-xfer {
+ rockchip,pins =
+ /* uart2_rx_m1 */
+ <3 RK_PA3 1 &pcfg_pull_up>,
+ /* uart2_tx_m1 */
+ <3 RK_PA2 1 &pcfg_pull_up>;
+ };
+ };
+ uart3 {
+ /omit-if-no-ref/
+ uart3m0_xfer: uart3m0-xfer {
+ rockchip,pins =
+ /* uart3_rx_m0 */
+ <3 RK_PC7 4 &pcfg_pull_up>,
+ /* uart3_tx_m0 */
+ <3 RK_PC6 4 &pcfg_pull_up>;
+ };
+ };
+ uart4 {
+ /omit-if-no-ref/
+ uart4m0_xfer: uart4m0-xfer {
+ rockchip,pins =
+ /* uart4_rx_m0 */
+ <3 RK_PA5 4 &pcfg_pull_up>,
+ /* uart4_tx_m0 */
+ <3 RK_PA4 4 &pcfg_pull_up>;
+ };
+ };
+ uart5 {
+ /omit-if-no-ref/
+ uart5m0_xfer: uart5m0-xfer {
+ rockchip,pins =
+ /* uart5_rx_m0 */
+ <3 RK_PA7 4 &pcfg_pull_up>,
+ /* uart5_tx_m0 */
+ <3 RK_PA6 4 &pcfg_pull_up>;
+ };
+ };
+};
diff --git a/arch/arm/dts/rv1126-u-boot.dtsi b/arch/arm/dts/rv1126-u-boot.dtsi
new file mode 100644
index 0000000..bc77037
--- /dev/null
+++ b/arch/arm/dts/rv1126-u-boot.dtsi
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include "rockchip-u-boot.dtsi"
+
+/ {
+ chosen {
+ u-boot,spl-boot-order = \
+ "same-as-spl", &emmc, &sdmmc;
+ };
+
+ dmc {
+ compatible = "rockchip,rv1126-dmc";
+ u-boot,dm-pre-reloc;
+ };
+};
+
+&gpio0 {
+ u-boot,dm-spl;
+};
+
+&gpio1 {
+ u-boot,dm-spl;
+};
+
+&grf {
+ u-boot,dm-spl;
+};
+
+&pmu {
+ u-boot,dm-spl;
+};
+
+&pmugrf {
+ u-boot,dm-spl;
+};
+
+&xin24m {
+ u-boot,dm-spl;
+};
+
+&cru {
+ u-boot,dm-spl;
+};
+
+&pmucru {
+ u-boot,dm-spl;
+};
+
+&sdmmc {
+ u-boot,dm-spl;
+};
+
+&emmc {
+ u-boot,dm-spl;
+};
+
+&uart2 {
+ u-boot,dm-spl;
+};
diff --git a/arch/arm/dts/rv1126.dtsi b/arch/arm/dts/rv1126.dtsi
new file mode 100644
index 0000000..1cb4314
--- /dev/null
+++ b/arch/arm/dts/rv1126.dtsi
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd.
+ */
+
+#include <dt-bindings/clock/rockchip,rv1126-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/power/rockchip,rv1126-power.h>
+#include <dt-bindings/soc/rockchip,boot-mode.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ compatible = "rockchip,rv1126";
+
+ interrupt-parent = <&gic>;
+
+ aliases {
+ i2c0 = &i2c0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@f00 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0xf00>;
+ enable-method = "psci";
+ clocks = <&cru ARMCLK>;
+ };
+
+ cpu1: cpu@f01 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0xf01>;
+ enable-method = "psci";
+ clocks = <&cru ARMCLK>;
+ };
+
+ cpu2: cpu@f02 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0xf02>;
+ enable-method = "psci";
+ clocks = <&cru ARMCLK>;
+ };
+
+ cpu3: cpu@f03 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0xf03>;
+ enable-method = "psci";
+ clocks = <&cru ARMCLK>;
+ };
+ };
+
+ arm-pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ clock-frequency = <24000000>;
+ };
+
+ xin24m: oscillator {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "xin24m";
+ #clock-cells = <0>;
+ };
+
+ grf: syscon@fe000000 {
+ compatible = "rockchip,rv1126-grf", "syscon", "simple-mfd";
+ reg = <0xfe000000 0x20000>;
+ };
+
+ pmugrf: syscon@fe020000 {
+ compatible = "rockchip,rv1126-pmugrf", "syscon", "simple-mfd";
+ reg = <0xfe020000 0x1000>;
+
+ pmu_io_domains: io-domains {
+ compatible = "rockchip,rv1126-pmu-io-voltage-domain";
+ status = "disabled";
+ };
+ };
+
+ qos_emmc: qos@fe860000 {
+ compatible = "rockchip,rv1126-qos", "syscon";
+ reg = <0xfe860000 0x20>;
+ };
+
+ qos_nandc: qos@fe860080 {
+ compatible = "rockchip,rv1126-qos", "syscon";
+ reg = <0xfe860080 0x20>;
+ };
+
+ qos_sfc: qos@fe860200 {
+ compatible = "rockchip,rv1126-qos", "syscon";
+ reg = <0xfe860200 0x20>;
+ };
+
+ qos_sdio: qos@fe86c000 {
+ compatible = "rockchip,rv1126-qos", "syscon";
+ reg = <0xfe86c000 0x20>;
+ };
+
+ gic: interrupt-controller@feff0000 {
+ compatible = "arm,gic-400";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+
+ reg = <0xfeff1000 0x1000>,
+ <0xfeff2000 0x2000>,
+ <0xfeff4000 0x2000>,
+ <0xfeff6000 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ pmu: power-management@ff3e0000 {
+ compatible = "rockchip,rv1126-pmu", "syscon", "simple-mfd";
+ reg = <0xff3e0000 0x1000>;
+
+ power: power-controller {
+ compatible = "rockchip,rv1126-power-controller";
+ #power-domain-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ power-domain@RV1126_PD_NVM {
+ reg = <RV1126_PD_NVM>;
+ clocks = <&cru HCLK_EMMC>,
+ <&cru CLK_EMMC>,
+ <&cru HCLK_NANDC>,
+ <&cru CLK_NANDC>,
+ <&cru HCLK_SFC>,
+ <&cru HCLK_SFCXIP>,
+ <&cru SCLK_SFC>;
+ pm_qos = <&qos_emmc>,
+ <&qos_nandc>,
+ <&qos_sfc>;
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@RV1126_PD_SDIO {
+ reg = <RV1126_PD_SDIO>;
+ clocks = <&cru HCLK_SDIO>,
+ <&cru CLK_SDIO>;
+ pm_qos = <&qos_sdio>;
+ #power-domain-cells = <0>;
+ };
+ };
+ };
+
+ i2c0: i2c@ff3f0000 {
+ compatible = "rockchip,rv1126-i2c", "rockchip,rk3399-i2c";
+ reg = <0xff3f0000 0x1000>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ rockchip,grf = <&pmugrf>;
+ clocks = <&pmucru CLK_I2C0>, <&pmucru PCLK_I2C0>;
+ clock-names = "i2c", "pclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_xfer>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ uart1: serial@ff410000 {
+ compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
+ reg = <0xff410000 0x100>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <24000000>;
+ clocks = <&pmucru SCLK_UART1>, <&pmucru PCLK_UART1>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac 7>, <&dmac 6>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1m0_xfer>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ pmucru: clock-controller@ff480000 {
+ compatible = "rockchip,rv1126-pmucru";
+ reg = <0xff480000 0x1000>;
+ rockchip,grf = <&grf>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ cru: clock-controller@ff490000 {
+ compatible = "rockchip,rv1126-cru";
+ reg = <0xff490000 0x1000>;
+ clocks = <&xin24m>;
+ clock-names = "xin24m";
+ rockchip,grf = <&grf>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ dmac: dma-controller@ff4e0000 {
+ compatible = "arm,pl330", "arm,primecell";
+ reg = <0xff4e0000 0x4000>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ #dma-cells = <1>;
+ arm,pl330-periph-burst;
+ clocks = <&cru ACLK_DMAC>;
+ clock-names = "apb_pclk";
+ };
+
+ uart0: serial@ff560000 {
+ compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
+ reg = <0xff560000 0x100>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <24000000>;
+ clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac 5>, <&dmac 4>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart2: serial@ff570000 {
+ compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
+ reg = <0xff570000 0x100>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <24000000>;
+ clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac 9>, <&dmac 8>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2m1_xfer>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart3: serial@ff580000 {
+ compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
+ reg = <0xff580000 0x100>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <24000000>;
+ clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac 11>, <&dmac 10>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3m0_xfer>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart4: serial@ff590000 {
+ compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
+ reg = <0xff590000 0x100>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <24000000>;
+ clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac 13>, <&dmac 12>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4m0_xfer>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ uart5: serial@ff5a0000 {
+ compatible = "rockchip,rv1126-uart", "snps,dw-apb-uart";
+ reg = <0xff5a0000 0x100>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <24000000>;
+ clocks = <&cru SCLK_UART5>, <&cru PCLK_UART5>;
+ clock-names = "baudclk", "apb_pclk";
+ dmas = <&dmac 15>, <&dmac 14>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart5m0_xfer>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
+ saradc: adc@ff5e0000 {
+ compatible = "rockchip,rv1126-saradc", "rockchip,rk3399-saradc";
+ reg = <0xff5e0000 0x100>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ #io-channel-cells = <1>;
+ clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>;
+ clock-names = "saradc", "apb_pclk";
+ resets = <&cru SRST_SARADC_P>;
+ reset-names = "saradc-apb";
+ status = "disabled";
+ };
+
+ timer0: timer@ff660000 {
+ compatible = "rockchip,rv1126-timer", "rockchip,rk3288-timer";
+ reg = <0xff660000 0x20>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_TIMER>, <&cru CLK_TIMER0>;
+ clock-names = "pclk", "timer";
+ };
+
+ emmc: mmc@ffc50000 {
+ compatible = "rockchip,rv1126-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0xffc50000 0x4000>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_EMMC>, <&cru CLK_EMMC>,
+ <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <200000000>;
+ power-domains = <&power RV1126_PD_NVM>;
+ status = "disabled";
+ };
+
+ sdmmc: mmc@ffc60000 {
+ compatible = "rockchip,rv1126-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0xffc60000 0x4000>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_SDMMC>, <&cru CLK_SDMMC>,
+ <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <200000000>;
+ status = "disabled";
+ };
+
+ sdio: mmc@ffc70000 {
+ compatible = "rockchip,rv1126-dw-mshc", "rockchip,rk3288-dw-mshc";
+ reg = <0xffc70000 0x4000>;
+ interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_SDIO>, <&cru CLK_SDIO>,
+ <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+ clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+ fifo-depth = <0x100>;
+ max-frequency = <200000000>;
+ power-domains = <&power RV1126_PD_SDIO>;
+ status = "disabled";
+ };
+
+ pinctrl: pinctrl {
+ compatible = "rockchip,rv1126-pinctrl";
+ rockchip,grf = <&grf>;
+ rockchip,pmu = <&pmugrf>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ gpio0: gpio@ff460000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff460000 0x100>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&pmucru PCLK_GPIO0>, <&pmucru DBCLK_GPIO0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio1: gpio@ff620000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff620000 0x100>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO1>, <&cru DBCLK_GPIO1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio2: gpio@ff630000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff630000 0x100>;
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO2>, <&cru DBCLK_GPIO2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio3: gpio@ff640000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff640000 0x100>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO3>, <&cru DBCLK_GPIO3>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ gpio4: gpio@ff650000 {
+ compatible = "rockchip,gpio-bank";
+ reg = <0xff650000 0x100>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_GPIO4>, <&cru DBCLK_GPIO4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+};
+
+#include "rv1126-pinctrl.dtsi"
diff --git a/arch/arm/dts/stm32mp151.dtsi b/arch/arm/dts/stm32mp151.dtsi
index 8bbb1ae..5d178b5 100644
--- a/arch/arm/dts/stm32mp151.dtsi
+++ b/arch/arm/dts/stm32mp151.dtsi
@@ -145,6 +145,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40000000 0x400>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM2_K>;
clock-names = "int";
dmas = <&dmamux1 18 0x400 0x1>,
@@ -178,6 +180,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40001000 0x400>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM3_K>;
clock-names = "int";
dmas = <&dmamux1 23 0x400 0x1>,
@@ -212,6 +216,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40002000 0x400>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM4_K>;
clock-names = "int";
dmas = <&dmamux1 29 0x400 0x1>,
@@ -244,6 +250,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40003000 0x400>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM5_K>;
clock-names = "int";
dmas = <&dmamux1 55 0x400 0x1>,
@@ -278,6 +286,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40004000 0x400>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM6_K>;
clock-names = "int";
dmas = <&dmamux1 69 0x400 0x1>;
@@ -296,6 +306,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40005000 0x400>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM7_K>;
clock-names = "int";
dmas = <&dmamux1 70 0x400 0x1>;
@@ -314,6 +326,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40006000 0x400>;
+ interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM12_K>;
clock-names = "int";
status = "disabled";
@@ -336,6 +350,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40007000 0x400>;
+ interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM13_K>;
clock-names = "int";
status = "disabled";
@@ -358,6 +374,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x40008000 0x400>;
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM14_K>;
clock-names = "int";
status = "disabled";
@@ -641,6 +659,11 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x44000000 0x400>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "brk", "up", "trg-com", "cc";
clocks = <&rcc TIM1_K>;
clock-names = "int";
dmas = <&dmamux1 11 0x400 0x1>,
@@ -677,6 +700,11 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x44001000 0x400>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "brk", "up", "trg-com", "cc";
clocks = <&rcc TIM8_K>;
clock-names = "int";
dmas = <&dmamux1 47 0x400 0x1>,
@@ -764,6 +792,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x44006000 0x400>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM15_K>;
clock-names = "int";
dmas = <&dmamux1 105 0x400 0x1>,
@@ -791,6 +821,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x44007000 0x400>;
+ interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM16_K>;
clock-names = "int";
dmas = <&dmamux1 109 0x400 0x1>,
@@ -815,6 +847,8 @@
#size-cells = <0>;
compatible = "st,stm32-timers";
reg = <0x44008000 0x400>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "global";
clocks = <&rcc TIM17_K>;
clock-names = "int";
dmas = <&dmamux1 111 0x400 0x1>,
diff --git a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi
index 1209dfe..92fdf09 100644
--- a/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157a-dk1-scmi-u-boot.dtsi
@@ -3,7 +3,6 @@
* Copyright : STMicroelectronics 2022
*/
-#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include "stm32mp15-scmi-u-boot.dtsi"
/ {
diff --git a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi
index c265745..63948ef 100644
--- a/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157c-ed1-scmi-u-boot.dtsi
@@ -3,7 +3,6 @@
* Copyright : STMicroelectronics 2022
*/
-#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include "stm32mp15-scmi-u-boot.dtsi"
/ {
diff --git a/arch/arm/dts/stm32mp157c-ev1.dts b/arch/arm/dts/stm32mp157c-ev1.dts
index d142dd3..2d5db41 100644
--- a/arch/arm/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/dts/stm32mp157c-ev1.dts
@@ -362,6 +362,14 @@
&usbh_ehci {
phys = <&usbphyc_port0>;
status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* onboard HUB */
+ hub@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ vdd-supply = <&v3v3>;
+ };
};
&usbotg_hs {
@@ -385,6 +393,10 @@
st,tune-squelch-level = <3>;
st,tune-hs-rx-offset = <2>;
st,no-lsfs-sc;
+ connector {
+ compatible = "usb-a-connector";
+ vbus-supply = <&vbus_sw>;
+ };
};
&usbphyc_port1 {
diff --git a/arch/arm/dts/stm32mp15xx-dkx.dtsi b/arch/arm/dts/stm32mp15xx-dkx.dtsi
index 5a045d7..34af901 100644
--- a/arch/arm/dts/stm32mp15xx-dkx.dtsi
+++ b/arch/arm/dts/stm32mp15xx-dkx.dtsi
@@ -390,21 +390,21 @@
regulator-always-on;
};
- bst_out: boost {
+ bst_out: boost {
regulator-name = "bst_out";
interrupts = <IT_OCP_BOOST 0>;
- };
+ };
vbus_otg: pwr_sw1 {
regulator-name = "vbus_otg";
interrupts = <IT_OCP_OTG 0>;
- };
+ };
- vbus_sw: pwr_sw2 {
+ vbus_sw: pwr_sw2 {
regulator-name = "vbus_sw";
interrupts = <IT_OCP_SWOUT 0>;
regulator-active-discharge = <1>;
- };
+ };
};
onkey {
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index 2028d5b..e959eb2 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -12,9 +12,7 @@
/ {
aliases {
-#ifndef CONFIG_MACH_SUNIV
mmc0 = &mmc0;
-#endif
#if CONFIG_MMC_SUNXI_SLOT_EXTRA == 2
mmc1 = &mmc2;
#endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
index 20f9671..444b566 100644
--- a/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
+++ b/arch/arm/include/asm/arch-fsl-layerscape/cpu.h
@@ -8,32 +8,32 @@
#define _FSL_LAYERSCAPE_CPU_H
#ifdef CONFIG_FSL_LSCH3
-#define CONFIG_SYS_FSL_CCSR_BASE 0x00000000
-#define CONFIG_SYS_FSL_CCSR_SIZE 0x10000000
+#define CFG_SYS_FSL_CCSR_BASE 0x00000000
+#define CFG_SYS_FSL_CCSR_SIZE 0x10000000
#define CFG_SYS_FSL_QSPI_BASE1 0x20000000
-#define CONFIG_SYS_FSL_QSPI_SIZE1 0x10000000
+#define CFG_SYS_FSL_QSPI_SIZE1 0x10000000
#ifndef CONFIG_NXP_LSCH3_2
-#define CONFIG_SYS_FSL_IFC_BASE1 0x30000000
-#define CONFIG_SYS_FSL_IFC_SIZE1 0x10000000
-#define CONFIG_SYS_FSL_IFC_SIZE1_1 0x400000
+#define CFG_SYS_FSL_IFC_BASE1 0x30000000
+#define CFG_SYS_FSL_IFC_SIZE1 0x10000000
+#define CFG_SYS_FSL_IFC_SIZE1_1 0x400000
#endif
-#define CONFIG_SYS_FSL_DRAM_BASE1 0x80000000
-#define CONFIG_SYS_FSL_DRAM_SIZE1 0x80000000
+#define CFG_SYS_FSL_DRAM_BASE1 0x80000000
+#define CFG_SYS_FSL_DRAM_SIZE1 0x80000000
#define CFG_SYS_FSL_QSPI_BASE2 0x400000000
-#define CONFIG_SYS_FSL_QSPI_SIZE2 0x100000000
+#define CFG_SYS_FSL_QSPI_SIZE2 0x100000000
#ifndef CONFIG_NXP_LSCH3_2
-#define CONFIG_SYS_FSL_IFC_BASE2 0x500000000
-#define CONFIG_SYS_FSL_IFC_SIZE2 0x100000000
+#define CFG_SYS_FSL_IFC_BASE2 0x500000000
+#define CFG_SYS_FSL_IFC_SIZE2 0x100000000
#endif
-#define CONFIG_SYS_FSL_DCSR_BASE 0x700000000
-#define CONFIG_SYS_FSL_DCSR_SIZE 0x40000000
-#define CONFIG_SYS_FSL_MC_BASE 0x80c000000
-#define CONFIG_SYS_FSL_MC_SIZE 0x4000000
-#define CONFIG_SYS_FSL_NI_BASE 0x810000000
-#define CONFIG_SYS_FSL_NI_SIZE 0x8000000
-#define CONFIG_SYS_FSL_QBMAN_BASE 0x818000000
-#define CONFIG_SYS_FSL_QBMAN_SIZE 0x8000000
-#define CONFIG_SYS_FSL_QBMAN_SIZE_1 0x4000000
+#define CFG_SYS_FSL_DCSR_BASE 0x700000000
+#define CFG_SYS_FSL_DCSR_SIZE 0x40000000
+#define CFG_SYS_FSL_MC_BASE 0x80c000000
+#define CFG_SYS_FSL_MC_SIZE 0x4000000
+#define CFG_SYS_FSL_NI_BASE 0x810000000
+#define CFG_SYS_FSL_NI_SIZE 0x8000000
+#define CFG_SYS_FSL_QBMAN_BASE 0x818000000
+#define CFG_SYS_FSL_QBMAN_SIZE 0x8000000
+#define CFG_SYS_FSL_QBMAN_SIZE_1 0x4000000
#ifdef CONFIG_ARCH_LS2080A
#define CFG_SYS_PCIE1_PHYS_SIZE 0x200000000
#define CFG_SYS_PCIE2_PHYS_SIZE 0x200000000
@@ -49,45 +49,45 @@
#define SYS_PCIE5_PHYS_SIZE 0x800000000
#define SYS_PCIE6_PHYS_SIZE 0x800000000
#endif
-#define CONFIG_SYS_FSL_WRIOP1_BASE 0x4300000000
-#define CONFIG_SYS_FSL_WRIOP1_SIZE 0x100000000
-#define CONFIG_SYS_FSL_AIOP1_BASE 0x4b00000000
-#define CONFIG_SYS_FSL_AIOP1_SIZE 0x100000000
+#define CFG_SYS_FSL_WRIOP1_BASE 0x4300000000
+#define CFG_SYS_FSL_WRIOP1_SIZE 0x100000000
+#define CFG_SYS_FSL_AIOP1_BASE 0x4b00000000
+#define CFG_SYS_FSL_AIOP1_SIZE 0x100000000
#if !defined(CONFIG_ARCH_LX2160A) || !defined(CONFIG_ARCH_LX2162)
-#define CONFIG_SYS_FSL_PEBUF_BASE 0x4c00000000
+#define CFG_SYS_FSL_PEBUF_BASE 0x4c00000000
#else
-#define CONFIG_SYS_FSL_PEBUF_BASE 0x1c00000000
+#define CFG_SYS_FSL_PEBUF_BASE 0x1c00000000
#endif
-#define CONFIG_SYS_FSL_PEBUF_SIZE 0x400000000
+#define CFG_SYS_FSL_PEBUF_SIZE 0x400000000
#ifdef CONFIG_NXP_LSCH3_2
-#define CONFIG_SYS_FSL_DRAM_BASE2 0x2080000000
-#define CONFIG_SYS_FSL_DRAM_SIZE2 0x1F80000000
-#define CONFIG_SYS_FSL_DRAM_BASE3 0x6000000000
-#define CONFIG_SYS_FSL_DRAM_SIZE3 0x2000000000
+#define CFG_SYS_FSL_DRAM_BASE2 0x2080000000
+#define CFG_SYS_FSL_DRAM_SIZE2 0x1F80000000
+#define CFG_SYS_FSL_DRAM_BASE3 0x6000000000
+#define CFG_SYS_FSL_DRAM_SIZE3 0x2000000000
#else
-#define CONFIG_SYS_FSL_DRAM_BASE2 0x8080000000
-#define CONFIG_SYS_FSL_DRAM_SIZE2 0x7F80000000
+#define CFG_SYS_FSL_DRAM_BASE2 0x8080000000
+#define CFG_SYS_FSL_DRAM_SIZE2 0x7F80000000
#endif
#elif defined(CONFIG_FSL_LSCH2)
-#define CONFIG_SYS_FSL_CCSR_BASE 0x1000000
-#define CONFIG_SYS_FSL_CCSR_SIZE 0xf000000
-#define CONFIG_SYS_FSL_DCSR_BASE 0x20000000
-#define CONFIG_SYS_FSL_DCSR_SIZE 0x4000000
+#define CFG_SYS_FSL_CCSR_BASE 0x1000000
+#define CFG_SYS_FSL_CCSR_SIZE 0xf000000
+#define CFG_SYS_FSL_DCSR_BASE 0x20000000
+#define CFG_SYS_FSL_DCSR_SIZE 0x4000000
#define CFG_SYS_FSL_QSPI_BASE 0x40000000
-#define CONFIG_SYS_FSL_QSPI_SIZE 0x20000000
-#define CONFIG_SYS_FSL_IFC_BASE 0x60000000
-#define CONFIG_SYS_FSL_IFC_SIZE 0x20000000
-#define CONFIG_SYS_FSL_DRAM_BASE1 0x80000000
-#define CONFIG_SYS_FSL_DRAM_SIZE1 0x80000000
-#define CONFIG_SYS_FSL_QBMAN_BASE 0x500000000
-#define CONFIG_SYS_FSL_QBMAN_SIZE 0x10000000
-#define CONFIG_SYS_FSL_DRAM_BASE2 0x880000000
-#define CONFIG_SYS_FSL_DRAM_SIZE2 0x780000000 /* 30GB */
+#define CFG_SYS_FSL_QSPI_SIZE 0x20000000
+#define CFG_SYS_FSL_IFC_BASE 0x60000000
+#define CFG_SYS_FSL_IFC_SIZE 0x20000000
+#define CFG_SYS_FSL_DRAM_BASE1 0x80000000
+#define CFG_SYS_FSL_DRAM_SIZE1 0x80000000
+#define CFG_SYS_FSL_QBMAN_BASE 0x500000000
+#define CFG_SYS_FSL_QBMAN_SIZE 0x10000000
+#define CFG_SYS_FSL_DRAM_BASE2 0x880000000
+#define CFG_SYS_FSL_DRAM_SIZE2 0x780000000 /* 30GB */
#define CFG_SYS_PCIE1_PHYS_SIZE 0x800000000
#define CFG_SYS_PCIE2_PHYS_SIZE 0x800000000
#define CFG_SYS_PCIE3_PHYS_SIZE 0x800000000
-#define CONFIG_SYS_FSL_DRAM_BASE3 0x8800000000
-#define CONFIG_SYS_FSL_DRAM_SIZE3 0x7800000000 /* 480GB */
+#define CFG_SYS_FSL_DRAM_BASE3 0x8800000000
+#define CFG_SYS_FSL_DRAM_SIZE3 0x7800000000 /* 480GB */
#endif
int fsl_qoriq_core_to_cluster(unsigned int core);
diff --git a/arch/arm/include/asm/arch-npcm8xx/rst.h b/arch/arm/include/asm/arch-npcm8xx/rst.h
index 379e841..09e1485 100644
--- a/arch/arm/include/asm/arch-npcm8xx/rst.h
+++ b/arch/arm/include/asm/arch-npcm8xx/rst.h
@@ -16,7 +16,7 @@
#define SW1RST BIT(28)
#define SW2RST BIT(27)
#define SW3RST BIT(26)
-#define SW4RST BIT(25)
+#define TIPRST BIT(25)
#define WD1RST BIT(24)
#define WD2RST BIT(23)
#define RST_STS_MASK GENMASK(31, 23)
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rv1126.h b/arch/arm/include/asm/arch-rockchip/cru_rv1126.h
new file mode 100644
index 0000000..49a1f76
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/cru_rv1126.h
@@ -0,0 +1,459 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 Rockchip Electronics Co. Ltd.
+ * Author: Finley Xiao <finley.xiao@rock-chips.com>
+ */
+
+#ifndef _ASM_ARCH_CRU_RV1126_H
+#define _ASM_ARCH_CRU_RV1126_H
+
+#define MHz 1000000
+#define KHz 1000
+#define OSC_HZ (24 * MHz)
+
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_KERNEL_BOOT)
+#define APLL_HZ (1008 * MHz)
+#else
+#define APLL_HZ (816 * MHz)
+#endif
+#define GPLL_HZ (1188 * MHz)
+#define CPLL_HZ (500 * MHz)
+#define HPLL_HZ (1400 * MHz)
+#define PCLK_PDPMU_HZ (100 * MHz)
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_KERNEL_BOOT)
+#define ACLK_PDBUS_HZ (396 * MHz)
+#else
+#define ACLK_PDBUS_HZ (500 * MHz)
+#endif
+#define HCLK_PDBUS_HZ (200 * MHz)
+#define PCLK_PDBUS_HZ (100 * MHz)
+#define ACLK_PDPHP_HZ (300 * MHz)
+#define HCLK_PDPHP_HZ (200 * MHz)
+#define HCLK_PDCORE_HZ (200 * MHz)
+#define HCLK_PDAUDIO_HZ (150 * MHz)
+#define CLK_OSC0_DIV_HZ (32768)
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_KERNEL_BOOT)
+#define ACLK_PDVI_HZ (297 * MHz)
+#define CLK_ISP_HZ (297 * MHz)
+#define ACLK_PDISPP_HZ (297 * MHz)
+#define CLK_ISPP_HZ (237 * MHz)
+#define ACLK_VOP_HZ (300 * MHz)
+#define DCLK_VOP_HZ (65 * MHz)
+#endif
+
+/* RV1126 pll id */
+enum rv1126_pll_id {
+ APLL,
+ DPLL,
+ CPLL,
+ HPLL,
+ GPLL,
+ PLL_COUNT,
+};
+
+struct rv1126_clk_info {
+ unsigned long id;
+ char *name;
+ bool is_cru;
+};
+
+/* Private data for the clock driver - used by rockchip_get_cru() */
+struct rv1126_pmuclk_priv {
+ struct rv1126_pmucru *pmucru;
+ ulong gpll_hz;
+};
+
+struct rv1126_clk_priv {
+ struct rv1126_cru *cru;
+ struct rv1126_grf *grf;
+ ulong gpll_hz;
+ ulong cpll_hz;
+ ulong hpll_hz;
+ ulong armclk_hz;
+ ulong armclk_enter_hz;
+ ulong armclk_init_hz;
+ bool sync_kernel;
+ bool set_armclk_rate;
+};
+
+struct rv1126_pll {
+ unsigned int con0;
+ unsigned int con1;
+ unsigned int con2;
+ unsigned int con3;
+ unsigned int con4;
+ unsigned int con5;
+ unsigned int con6;
+ unsigned int reserved0[1];
+};
+
+struct rv1126_pmucru {
+ unsigned int pmu_mode;
+ unsigned int reserved1[3];
+ struct rv1126_pll pll;
+ unsigned int offsetcal_status;
+ unsigned int reserved2[51];
+ unsigned int pmu_clksel_con[14];
+ unsigned int reserved3[18];
+ unsigned int pmu_clkgate_con[3];
+ unsigned int reserved4[29];
+ unsigned int pmu_softrst_con[2];
+ unsigned int reserved5[14];
+ unsigned int pmu_autocs_con[2];
+};
+
+check_member(rv1126_pmucru, pmu_autocs_con[1], 0x244);
+
+struct rv1126_cru {
+ struct rv1126_pll pll[4];
+ unsigned int offsetcal_status[4];
+ unsigned int mode;
+ unsigned int reserved1[27];
+ unsigned int clksel_con[78];
+ unsigned int reserved2[18];
+ unsigned int clkgate_con[25];
+ unsigned int reserved3[7];
+ unsigned int softrst_con[15];
+ unsigned int reserved4[17];
+ unsigned int ssgtbl[32];
+ unsigned int glb_cnt_th;
+ unsigned int glb_rst_st;
+ unsigned int glb_srst_fst;
+ unsigned int glb_srst_snd;
+ unsigned int glb_rst_con;
+ unsigned int reserved5[11];
+ unsigned int sdmmc_con[2];
+ unsigned int sdio_con[2];
+ unsigned int emmc_con[2];
+ unsigned int reserved6[2];
+ unsigned int gmac_con;
+ unsigned int misc[2];
+ unsigned int reserved7[45];
+ unsigned int autocs_con[26];
+};
+
+check_member(rv1126_cru, autocs_con[25], 0x584);
+
+struct pll_rate_table {
+ unsigned long rate;
+ unsigned int fbdiv;
+ unsigned int postdiv1;
+ unsigned int refdiv;
+ unsigned int postdiv2;
+ unsigned int dsmpd;
+ unsigned int frac;
+};
+
+struct cpu_rate_table {
+ unsigned long rate;
+ unsigned int aclk_div;
+ unsigned int pclk_div;
+};
+
+#define RV1126_PMU_MODE 0x0
+#define RV1126_PMU_PLL_CON(x) ((x) * 0x4 + 0x10)
+#define RV1126_PLL_CON(x) ((x) * 0x4)
+#define RV1126_MODE_CON 0x90
+
+enum {
+ /* CRU_PMU_CLK_SEL0_CON */
+ RTC32K_SEL_SHIFT = 7,
+ RTC32K_SEL_MASK = 0x3 << RTC32K_SEL_SHIFT,
+ RTC32K_SEL_PMUPVTM = 0,
+ RTC32K_SEL_OSC1_32K,
+ RTC32K_SEL_OSC0_DIV32K,
+
+ /* CRU_PMU_CLK_SEL1_CON */
+ PCLK_PDPMU_DIV_SHIFT = 0,
+ PCLK_PDPMU_DIV_MASK = 0x1f,
+
+ /* CRU_PMU_CLK_SEL2_CON */
+ CLK_I2C0_DIV_SHIFT = 0,
+ CLK_I2C0_DIV_MASK = 0x7f,
+
+ /* CRU_PMU_CLK_SEL3_CON */
+ CLK_I2C2_DIV_SHIFT = 0,
+ CLK_I2C2_DIV_MASK = 0x7f,
+
+ /* CRU_PMU_CLK_SEL6_CON */
+ CLK_PWM1_SEL_SHIFT = 15,
+ CLK_PWM1_SEL_MASK = 1 << CLK_PWM1_SEL_SHIFT,
+ CLK_PWM1_SEL_XIN24M = 0,
+ CLK_PWM1_SEL_GPLL,
+ CLK_PWM1_DIV_SHIFT = 8,
+ CLK_PWM1_DIV_MASK = 0x7f << CLK_PWM1_DIV_SHIFT,
+ CLK_PWM0_SEL_SHIFT = 7,
+ CLK_PWM0_SEL_MASK = 1 << CLK_PWM0_SEL_SHIFT,
+ CLK_PWM0_SEL_XIN24M = 0,
+ CLK_PWM0_SEL_GPLL,
+ CLK_PWM0_DIV_SHIFT = 0,
+ CLK_PWM0_DIV_MASK = 0x7f,
+
+ /* CRU_PMU_CLK_SEL9_CON */
+ CLK_SPI0_SEL_SHIFT = 7,
+ CLK_SPI0_SEL_MASK = 1 << CLK_SPI0_SEL_SHIFT,
+ CLK_SPI0_SEL_GPLL = 0,
+ CLK_SPI0_SEL_XIN24M,
+ CLK_SPI0_DIV_SHIFT = 0,
+ CLK_SPI0_DIV_MASK = 0x7f,
+
+ /* CRU_PMU_CLK_SEL13_CON */
+ CLK_RTC32K_FRAC_NUMERATOR_SHIFT = 16,
+ CLK_RTC32K_FRAC_NUMERATOR_MASK = 0xffff << 16,
+ CLK_RTC32K_FRAC_DENOMINATOR_SHIFT = 0,
+ CLK_RTC32K_FRAC_DENOMINATOR_MASK = 0xffff,
+
+ /* CRU_CLK_SEL0_CON */
+ CORE_HCLK_DIV_SHIFT = 8,
+ CORE_HCLK_DIV_MASK = 0x1f << CORE_HCLK_DIV_SHIFT,
+
+ /* CRU_CLK_SEL1_CON */
+ CORE_ACLK_DIV_SHIFT = 4,
+ CORE_ACLK_DIV_MASK = 0xf << CORE_ACLK_DIV_SHIFT,
+ CORE_DBG_DIV_SHIFT = 0,
+ CORE_DBG_DIV_MASK = 0x7,
+
+ /* CRU_CLK_SEL2_CON */
+ HCLK_PDBUS_SEL_SHIFT = 15,
+ HCLK_PDBUS_SEL_MASK = 1 << HCLK_PDBUS_SEL_SHIFT,
+ HCLK_PDBUS_SEL_GPLL = 0,
+ HCLK_PDBUS_SEL_CPLL,
+ HCLK_PDBUS_DIV_SHIFT = 8,
+ HCLK_PDBUS_DIV_MASK = 0x1f << HCLK_PDBUS_DIV_SHIFT,
+ ACLK_PDBUS_SEL_SHIFT = 6,
+ ACLK_PDBUS_SEL_MASK = 0x3 << ACLK_PDBUS_SEL_SHIFT,
+ ACLK_PDBUS_SEL_GPLL = 0,
+ ACLK_PDBUS_SEL_CPLL,
+ ACLK_PDBUS_SEL_DPLL,
+ ACLK_PDBUS_DIV_SHIFT = 0,
+ ACLK_PDBUS_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL3_CON */
+ CLK_SCR1_SEL_SHIFT = 15,
+ CLK_SCR1_SEL_MASK = 1 << CLK_SCR1_SEL_SHIFT,
+ CLK_SCR1_SEL_GPLL = 0,
+ CLK_SCR1_SEL_CPLL,
+ CLK_SCR1_DIV_SHIFT = 8,
+ CLK_SCR1_DIV_MASK = 0x1f << CLK_SCR1_DIV_SHIFT,
+ PCLK_PDBUS_SEL_SHIFT = 7,
+ PCLK_PDBUS_SEL_MASK = 1 << PCLK_PDBUS_SEL_SHIFT,
+ PCLK_PDBUS_SEL_GPLL = 0,
+ PCLK_PDBUS_SEL_CPLL,
+ PCLK_PDBUS_DIV_SHIFT = 0,
+ PCLK_PDBUS_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL4_CON */
+ ACLK_CRYPTO_SEL_SHIFT = 7,
+ ACLK_CRYPTO_SEL_MASK = 1 << ACLK_CRYPTO_SEL_SHIFT,
+ ACLK_CRYPTO_SEL_GPLL = 0,
+ ACLK_CRYPTO_SEL_CPLL,
+ ACLK_CRYPTO_DIV_SHIFT = 0,
+ ACLK_CRYPTO_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL5_CON */
+ CLK_I2C3_DIV_SHIFT = 8,
+ CLK_I2C3_DIV_MASK = 0x7f << CLK_I2C3_DIV_SHIFT,
+ CLK_I2C1_DIV_SHIFT = 0,
+ CLK_I2C1_DIV_MASK = 0x7f,
+
+ /* CRU_CLK_SEL6_CON */
+ CLK_I2C5_DIV_SHIFT = 8,
+ CLK_I2C5_DIV_MASK = 0x7f << CLK_I2C5_DIV_SHIFT,
+ CLK_I2C4_DIV_SHIFT = 0,
+ CLK_I2C4_DIV_MASK = 0x7f,
+
+ /* CRU_CLK_SEL7_CON */
+ CLK_CRYPTO_PKA_SEL_SHIFT = 15,
+ CLK_CRYPTO_PKA_SEL_MASK = 1 << CLK_CRYPTO_PKA_SEL_SHIFT,
+ CLK_CRYPTO_PKA_SEL_GPLL = 0,
+ CLK_CRYPTO_PKA_SEL_CPLL,
+ CLK_CRYPTO_PKA_DIV_SHIFT = 8,
+ CLK_CRYPTO_PKA_DIV_MASK = 0x1f << CLK_CRYPTO_PKA_DIV_SHIFT,
+ CLK_CRYPTO_CORE_SEL_SHIFT = 7,
+ CLK_CRYPTO_CORE_SEL_MASK = 1 << CLK_CRYPTO_CORE_SEL_SHIFT,
+ CLK_CRYPTO_CORE_SEL_GPLL = 0,
+ CLK_CRYPTO_CORE_SEL_CPLL,
+ CLK_CRYPTO_CORE_DIV_SHIFT = 0,
+ CLK_CRYPTO_CORE_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL8_CON */
+ CLK_SPI1_SEL_SHIFT = 8,
+ CLK_SPI1_SEL_MASK = 1 << CLK_SPI1_SEL_SHIFT,
+ CLK_SPI1_SEL_GPLL = 0,
+ CLK_SPI1_SEL_XIN24M,
+ CLK_SPI1_DIV_SHIFT = 0,
+ CLK_SPI1_DIV_MASK = 0x7f,
+
+ /* CRU_CLK_SEL9_CON */
+ CLK_PWM2_SEL_SHIFT = 15,
+ CLK_PWM2_SEL_MASK = 1 << CLK_PWM2_SEL_SHIFT,
+ CLK_PWM2_SEL_XIN24M = 0,
+ CLK_PWM2_SEL_GPLL,
+ CLK_PWM2_DIV_SHIFT = 8,
+ CLK_PWM2_DIV_MASK = 0x7f << CLK_PWM2_DIV_SHIFT,
+
+ /* CRU_CLK_SEL20_CON */
+ CLK_SARADC_DIV_SHIFT = 0,
+ CLK_SARADC_DIV_MASK = 0x7ff,
+
+ /* CRU_CLK_SEL25_CON */
+ DCLK_DECOM_SEL_SHIFT = 15,
+ DCLK_DECOM_SEL_MASK = 1 << DCLK_DECOM_SEL_SHIFT,
+ DCLK_DECOM_SEL_GPLL = 0,
+ DCLK_DECOM_SEL_CPLL,
+ DCLK_DECOM_DIV_SHIFT = 8,
+ DCLK_DECOM_DIV_MASK = 0x7f << DCLK_DECOM_DIV_SHIFT,
+
+ /* CRU_CLK_SEL26_CON */
+ HCLK_PDAUDIO_DIV_SHIFT = 0,
+ HCLK_PDAUDIO_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL45_CON */
+ ACLK_PDVO_SEL_SHIFT = 7,
+ ACLK_PDVO_SEL_MASK = 1 << ACLK_PDVO_SEL_SHIFT,
+ ACLK_PDVO_SEL_GPLL = 0,
+ ACLK_PDVO_SEL_CPLL,
+ ACLK_PDVO_DIV_SHIFT = 0,
+ ACLK_PDVO_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL47_CON */
+ DCLK_VOP_SEL_SHIFT = 8,
+ DCLK_VOP_SEL_MASK = 1 << DCLK_VOP_SEL_SHIFT,
+ DCLK_VOP_SEL_GPLL = 0,
+ DCLK_VOP_SEL_CPLL,
+ DCLK_VOP_DIV_SHIFT = 0,
+ DCLK_VOP_DIV_MASK = 0xff,
+
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_KERNEL_BOOT)
+ /* CRU_CLK_SEL49_CON */
+ ACLK_PDVI_SEL_SHIFT = 6,
+ ACLK_PDVI_SEL_MASK = 0x3 << ACLK_PDVI_SEL_SHIFT,
+ ACLK_PDVI_SEL_CPLL = 0,
+ ACLK_PDVI_SEL_GPLL,
+ ACLK_PDVI_SEL_HPLL,
+ ACLK_PDVI_DIV_SHIFT = 0,
+ ACLK_PDVI_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL50_CON */
+ CLK_ISP_SEL_SHIFT = 6,
+ CLK_ISP_SEL_MASK = 0x3 << CLK_ISP_SEL_SHIFT,
+ CLK_ISP_SEL_GPLL = 0,
+ CLK_ISP_SEL_CPLL,
+ CLK_ISP_SEL_HPLL,
+ CLK_ISP_DIV_SHIFT = 0,
+ CLK_ISP_DIV_MASK = 0x1f,
+#endif
+
+ /* CRU_CLK_SEL53_CON */
+ HCLK_PDPHP_DIV_SHIFT = 8,
+ HCLK_PDPHP_DIV_MASK = 0x1f << HCLK_PDPHP_DIV_SHIFT,
+ ACLK_PDPHP_SEL_SHIFT = 7,
+ ACLK_PDPHP_SEL_MASK = 1 << ACLK_PDPHP_SEL_SHIFT,
+ ACLK_PDPHP_SEL_GPLL = 0,
+ ACLK_PDPHP_SEL_CPLL,
+ ACLK_PDPHP_DIV_SHIFT = 0,
+ ACLK_PDPHP_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL57_CON */
+ EMMC_SEL_SHIFT = 14,
+ EMMC_SEL_MASK = 0x3 << EMMC_SEL_SHIFT,
+ EMMC_SEL_GPLL = 0,
+ EMMC_SEL_CPLL,
+ EMMC_SEL_XIN24M,
+ EMMC_DIV_SHIFT = 0,
+ EMMC_DIV_MASK = 0xff,
+
+ /* CRU_CLK_SEL58_CON */
+ SCLK_SFC_SEL_SHIFT = 15,
+ SCLK_SFC_SEL_MASK = 0x1 << SCLK_SFC_SEL_SHIFT,
+ SCLK_SFC_SEL_CPLL = 0,
+ SCLK_SFC_SEL_GPLL,
+ SCLK_SFC_DIV_SHIFT = 0,
+ SCLK_SFC_DIV_MASK = 0xff,
+
+ /* CRU_CLK_SEL59_CON */
+ CLK_NANDC_SEL_SHIFT = 15,
+ CLK_NANDC_SEL_MASK = 0x1 << CLK_NANDC_SEL_SHIFT,
+ CLK_NANDC_SEL_GPLL = 0,
+ CLK_NANDC_SEL_CPLL,
+ CLK_NANDC_DIV_SHIFT = 0,
+ CLK_NANDC_DIV_MASK = 0xff,
+
+ /* CRU_CLK_SEL61_CON */
+ CLK_GMAC_OUT_SEL_SHIFT = 15,
+ CLK_GMAC_OUT_SEL_MASK = 0x1 << CLK_GMAC_OUT_SEL_SHIFT,
+ CLK_GMAC_OUT_SEL_CPLL = 0,
+ CLK_GMAC_OUT_SEL_GPLL,
+ CLK_GMAC_OUT_DIV_SHIFT = 8,
+ CLK_GMAC_OUT_DIV_MASK = 0x1f << CLK_GMAC_OUT_DIV_SHIFT,
+
+ /* CRU_CLK_SEL63_CON */
+ PCLK_GMAC_DIV_SHIFT = 8,
+ PCLK_GMAC_DIV_MASK = 0x1f << PCLK_GMAC_DIV_SHIFT,
+ CLK_GMAC_SRC_SEL_SHIFT = 7,
+ CLK_GMAC_SRC_SEL_MASK = 0x1 << CLK_GMAC_SRC_SEL_SHIFT,
+ CLK_GMAC_SRC_SEL_CPLL = 0,
+ CLK_GMAC_SRC_SEL_GPLL,
+ CLK_GMAC_SRC_DIV_SHIFT = 0,
+ CLK_GMAC_SRC_DIV_MASK = 0x1f << CLK_GMAC_SRC_DIV_SHIFT,
+
+#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_KERNEL_BOOT)
+ /* CRU_CLK_SEL68_CON */
+ ACLK_PDISPP_SEL_SHIFT = 6,
+ ACLK_PDISPP_SEL_MASK = 0x3 << ACLK_PDISPP_SEL_SHIFT,
+ ACLK_PDISPP_SEL_CPLL = 0,
+ ACLK_PDISPP_SEL_GPLL,
+ ACLK_PDISPP_SEL_HPLL,
+ ACLK_PDISPP_DIV_SHIFT = 0,
+ ACLK_PDISPP_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL69_CON */
+ CLK_ISPP_SEL_SHIFT = 6,
+ CLK_ISPP_SEL_MASK = 0x3 << CLK_ISPP_SEL_SHIFT,
+ CLK_ISPP_SEL_CPLL = 0,
+ CLK_ISPP_SEL_GPLL,
+ CLK_ISPP_SEL_HPLL,
+ CLK_ISPP_DIV_SHIFT = 0,
+ CLK_ISPP_DIV_MASK = 0x1f,
+
+ /* CRU_CLK_SEL73_CON */
+ MIPICSI_OUT_SEL_SHIFT = 10,
+ MIPICSI_OUT_SEL_MASK = 0x3 << MIPICSI_OUT_SEL_SHIFT,
+ MIPICSI_OUT_SEL_XIN24M = 0,
+ MIPICSI_OUT_SEL_DIV,
+ MIPICSI_OUT_SEL_FRACDIV,
+ MIPICSI_OUT_DIV_SHIFT = 0,
+ MIPICSI_OUT_DIV_MASK = 0x1f,
+#endif
+
+ /* CRU_GMAC_CON */
+ GMAC_SRC_M1_SEL_SHIFT = 5,
+ GMAC_SRC_M1_SEL_MASK = 0x1 << GMAC_SRC_M1_SEL_SHIFT,
+ GMAC_SRC_M1_SEL_INT = 0,
+ GMAC_SRC_M1_SEL_EXT,
+ GMAC_MODE_SEL_SHIFT = 4,
+ GMAC_MODE_SEL_MASK = 0x1 << GMAC_MODE_SEL_SHIFT,
+ GMAC_RGMII_MODE = 0,
+ GMAC_RMII_MODE,
+ RGMII_CLK_SEL_SHIFT = 2,
+ RGMII_CLK_SEL_MASK = 0x3 << RGMII_CLK_SEL_SHIFT,
+ RGMII_CLK_DIV0 = 0,
+ RGMII_CLK_DIV1,
+ RGMII_CLK_DIV50,
+ RGMII_CLK_DIV5,
+ RMII_CLK_SEL_SHIFT = 1,
+ RMII_CLK_SEL_MASK = 0x1 << RMII_CLK_SEL_SHIFT,
+ RMII_CLK_DIV20 = 0,
+ RMII_CLK_DIV2,
+ GMAC_SRC_M0_SEL_SHIFT = 0,
+ GMAC_SRC_M0_SEL_MASK = 0x1,
+ GMAC_SRC_M0_SEL_INT = 0,
+ GMAC_SRC_M0_SEL_EXT,
+
+ /* GRF_IOFUNC_CON1 */
+ GMAC_SRC_SEL_SHIFT = 12,
+ GMAC_SRC_SEL_MASK = 1 << GMAC_SRC_SEL_SHIFT,
+ GMAC_SRC_SEL_M0 = 0,
+ GMAC_SRC_SEL_M1,
+};
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3288.h b/arch/arm/include/asm/arch-rockchip/ddr_rk3288.h
index 979d547..43ccae1 100644
--- a/arch/arm/include/asm/arch-rockchip/ddr_rk3288.h
+++ b/arch/arm/include/asm/arch-rockchip/ddr_rk3288.h
@@ -360,7 +360,7 @@
#define PCTL_STAT_MSK 7
#define INIT_MEM 0
#define CONFIG 1
-#define CONFIG_REQ 2
+#define CFG_REQ 2
#define ACCESS 3
#define ACCESS_REQ 4
#define LOW_POWER 5
diff --git a/arch/arm/include/asm/arch-rockchip/dram_spec_timing.h b/arch/arm/include/asm/arch-rockchip/dram_spec_timing.h
new file mode 100644
index 0000000..a691e97
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/dram_spec_timing.h
@@ -0,0 +1,452 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ROCKCHIP_DRAM_SPEC_TIMING_H__
+#define __ROCKCHIP_DRAM_SPEC_TIMING_H__
+
+enum ddr3_speed_rate {
+ /* 5-5-5 */
+ DDR3_800D = 0,
+ /* 6-6-6 */
+ DDR3_800E = 1,
+ /* 6-6-6 */
+ DDR3_1066E = 2,
+ /* 7-7-7 */
+ DDR3_1066F = 3,
+ /* 8-8-8 */
+ DDR3_1066G = 4,
+ /* 7-7-7 */
+ DDR3_1333F = 5,
+ /* 8-8-8 */
+ DDR3_1333G = 6,
+ /* 9-9-9 */
+ DDR3_1333H = 7,
+ /* 10-10-10 */
+ DDR3_1333J = 8,
+ /* 8-8-8 */
+ DDR3_1600G = 9,
+ /* 9-9-9 */
+ DDR3_1600H = 10,
+ /* 10-10-10 */
+ DDR3_1600J = 11,
+ /* 11-11-11 */
+ DDR3_1600K = 12,
+ /* 10-10-10 */
+ DDR3_1866J = 13,
+ /* 11-11-11 */
+ DDR3_1866K = 14,
+ /* 12-12-12 */
+ DDR3_1866L = 15,
+ /* 13-13-13 */
+ DDR3_1866M = 16,
+ /* 11-11-11 */
+ DDR3_2133K = 17,
+ /* 12-12-12 */
+ DDR3_2133L = 18,
+ /* 13-13-13 */
+ DDR3_2133M = 19,
+ /* 14-14-14 */
+ DDR3_2133N = 20,
+ DDR3_DEFAULT = 21,
+};
+
+enum ddr4_speed_rate {
+ /* DDR4_1600J (10-10-10) */
+ DDR4_1600J = 0,
+ /* DDR4_1600K (11-11-11) */
+ DDR4_1600K = 1,
+ /* DDR4_1600L (12-12-12) */
+ DDR4_1600L = 2,
+ /* DDR4_1800L (12-12-12) */
+ DDR4_1866L = 3,
+ /* DDR4_1800M (13-13-13) */
+ DDR4_1866M = 4,
+ /* DDR4_1800N (14-14-14) */
+ DDR4_1866N = 5,
+ /* DDR4_2133N (14-14-14) */
+ DDR4_2133N = 6,
+ /* DDR4_2133P (15-15-15) */
+ DDR4_2133P = 7,
+ /* DDR4_2133R (16-16-16) */
+ DDR4_2133R = 8,
+ /* DDR4_2400P (15-15-15) */
+ DDR4_2400P = 9,
+ /* DDR4_2400R (16-16-16) */
+ DDR4_2400R = 10,
+ /* DDR4_2400U (18-18-18) */
+ DDR4_2400U = 11,
+ /* DEFAULT */
+ DDR4_DEFAULT = 12,
+};
+
+/* mr0 for ddr3 */
+#define DDR3_BL8 (0)
+#define DDR3_BC4_8 (1)
+#define DDR3_BC4 (2)
+#define DDR3_CL(n) (((((n) - 4) & 0x7) << 4)\
+ | ((((n) - 4) & 0x8) >> 1))
+#define DDR3_WR(n) (((n) & 0x7) << 9)
+#define DDR3_DLL_RESET (1 << 8)
+#define DDR3_DLL_DERESET (0 << 8)
+
+/* mr1 for ddr3 */
+#define DDR3_DLL_ENABLE (0)
+#define DDR3_DLL_DISABLE (1)
+#define DDR3_MR1_AL(n) (((n) & 0x3) << 3)
+
+#define DDR3_DS_40 (0)
+#define DDR3_DS_34 BIT(1)
+#define DDR3_DS_MASK ((1 << 1) | (1 << 5))
+#define DDR3_RTT_NOM_MASK ((1 << 2) | (1 << 6) | (1 << 9))
+#define DDR3_RTT_NOM_DIS (0)
+#define DDR3_RTT_NOM_60 BIT(2)
+#define DDR3_RTT_NOM_120 BIT(6)
+#define DDR3_RTT_NOM_40 ((1 << 2) | (1 << 6))
+#define DDR3_TDQS BIT(11)
+
+/* mr2 for ddr3 */
+#define DDR3_MR2_CWL(n) ((((n) - 5) & 0x7) << 3)
+#define DDR3_RTT_WR_DIS (0)
+#define DDR3_RTT_WR_60 (1 << 9)
+#define DDR3_RTT_WR_120 (2 << 9)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete, 1:DAI still in progress
+ */
+#define LPDDR2_DAI (0x1)
+/* 0:S2 or S4 SDRAM, 1:NVM */
+#define LPDDR2_DI (0x1 << 1)
+/* 0:DNV not supported, 1:DNV supported */
+#define LPDDR2_DNVI (0x1 << 2)
+#define LPDDR2_RZQI (0x3 << 3)
+
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+
+/* MR1 (Device Feature) */
+#define LPDDR2_BL4 (0x2)
+#define LPDDR2_BL8 (0x3)
+#define LPDDR2_BL16 (0x4)
+#define LPDDR2_N_WR(n) (((n) - 2) << 5)
+
+/* MR2 (Device Feature 2) */
+#define LPDDR2_RL3_WL1 (0x1)
+#define LPDDR2_RL4_WL2 (0x2)
+#define LPDDR2_RL5_WL2 (0x3)
+#define LPDDR2_RL6_WL3 (0x4)
+#define LPDDR2_RL7_WL4 (0x5)
+#define LPDDR2_RL8_WL4 (0x6)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR2_DS_34 (0x1)
+#define LPDDR2_DS_40 (0x2)
+#define LPDDR2_DS_48 (0x3)
+#define LPDDR2_DS_60 (0x4)
+#define LPDDR2_DS_80 (0x6)
+/* optional */
+#define LPDDR2_DS_120 (0x7)
+
+/* MR4 (Device Temperature) */
+#define LPDDR2_TREF_MASK (0x7)
+#define LPDDR2_4_TREF (0x1)
+#define LPDDR2_2_TREF (0x2)
+#define LPDDR2_1_TREF (0x3)
+#define LPDDR2_025_TREF (0x5)
+#define LPDDR2_025_TREF_DERATE (0x6)
+
+#define LPDDR2_TUF (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR2_S4 (0x0)
+#define LPDDR2_S2 (0x1)
+#define LPDDR2_N (0x2)
+/* Unit:MB */
+#define LPDDR2_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR2_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR2_ZQINIT (0xff)
+#define LPDDR2_ZQCL (0xab)
+#define LPDDR2_ZQCS (0x56)
+#define LPDDR2_ZQRESET (0xc3)
+
+/* MR16 (PASR Bank Mask), S2 SDRAM Only */
+#define LPDDR2_PASR_FULL (0x0)
+#define LPDDR2_PASR_1_2 (0x1)
+#define LPDDR2_PASR_1_4 (0x2)
+#define LPDDR2_PASR_1_8 (0x3)
+
+/*
+ * MR0 (Device Information)
+ * 0:DAI complete,
+ * 1:DAI still in progress
+ */
+#define LPDDR3_DAI (0x1)
+/*
+ * 00:RZQ self test not supported,
+ * 01:ZQ-pin may connect to VDDCA or float
+ * 10:ZQ-pin may short to GND.
+ * 11:ZQ-pin self test completed, no error condition detected.
+ */
+#define LPDDR3_RZQI (0x3 << 3)
+/*
+ * 0:DRAM does not support WL(Set B),
+ * 1:DRAM support WL(Set B)
+ */
+#define LPDDR3_WL_SUPOT BIT(6)
+/*
+ * 0:DRAM does not support RL=3,nWR=3,WL=1;
+ * 1:DRAM supports RL=3,nWR=3,WL=1 for frequencies <=166
+ */
+#define LPDDR3_RL3_SUPOT BIT(7)
+
+/* MR1 (Device Feature) */
+#define LPDDR3_BL8 (0x3)
+#define LPDDR3_N_WR(n) ((n) << 5)
+
+/* MR2 (Device Feature 2), WL Set A,default */
+/* <=166MHz,optional*/
+#define LPDDR3_RL3_WL1 (0x1)
+/* <=400MHz*/
+#define LPDDR3_RL6_WL3 (0x4)
+/* <=533MHz*/
+#define LPDDR3_RL8_WL4 (0x6)
+/* <=600MHz*/
+#define LPDDR3_RL9_WL5 (0x7)
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL6 (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL6 (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL6 (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL8 (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL8 (0xe)
+
+/* WL Set B, optional */
+/* <=667MHz,default*/
+#define LPDDR3_RL10_WL8 (0x8)
+/* <=733MHz*/
+#define LPDDR3_RL11_WL9 (0x9)
+/* <=800MHz*/
+#define LPDDR3_RL12_WL9 (0xa)
+/* <=933MHz*/
+#define LPDDR3_RL14_WL11 (0xc)
+/* <=1066MHz*/
+#define LPDDR3_RL16_WL13 (0xe)
+
+/* 1:enable nWR programming > 9(default)*/
+#define LPDDR3_N_WRE BIT(4)
+/* 1:Select WL Set B*/
+#define LPDDR3_WL_S BIT(6)
+/* 1:enable*/
+#define LPDDR3_WR_LEVEL BIT(7)
+
+/* MR3 (IO Configuration 1) */
+#define LPDDR3_DS_34 (0x1)
+#define LPDDR3_DS_40 (0x2)
+#define LPDDR3_DS_48 (0x3)
+#define LPDDR3_DS_60 (0x4)
+#define LPDDR3_DS_80 (0x6)
+#define LPDDR3_DS_34D_40U (0x9)
+#define LPDDR3_DS_40D_48U (0xa)
+#define LPDDR3_DS_34D_48U (0xb)
+
+/* MR4 (Device Temperature) */
+#define LPDDR3_TREF_MASK (0x7)
+/* SDRAM Low temperature operating limit exceeded */
+#define LPDDR3_LT_EXED (0x0)
+#define LPDDR3_4_TREF (0x1)
+#define LPDDR3_2_TREF (0x2)
+#define LPDDR3_1_TREF (0x3)
+#define LPDDR3_05_TREF (0x4)
+#define LPDDR3_025_TREF (0x5)
+#define LPDDR3_025_TREF_DERATE (0x6)
+/* SDRAM High temperature operating limit exceeded */
+#define LPDDR3_HT_EXED (0x7)
+
+/* 1:value has changed since last read of MR4 */
+#define LPDDR3_TUF (0x1 << 7)
+
+/* MR8 (Basic configuration 4) */
+#define LPDDR3_S8 (0x3)
+#define LPDDR3_DENSITY(mr8) (8 << (((mr8) >> 2) & 0xf))
+#define LPDDR3_IO_WIDTH(mr8) (32 >> (((mr8) >> 6) & 0x3))
+
+/* MR10 (Calibration) */
+#define LPDDR3_ZQINIT (0xff)
+#define LPDDR3_ZQCL (0xab)
+#define LPDDR3_ZQCS (0x56)
+#define LPDDR3_ZQRESET (0xc3)
+
+/* MR11 (ODT Control) */
+#define LPDDR3_ODT_60 (1)
+#define LPDDR3_ODT_120 (2)
+#define LPDDR3_ODT_240 (3)
+#define LPDDR3_ODT_DIS (0)
+
+/* MR2 (Device Feature 2) */
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL6_NRTP8 (0x0)
+#define LPDDR4_RL10_NRTP8 (0x1)
+#define LPDDR4_RL14_NRTP8 (0x2)
+#define LPDDR4_RL20_NRTP8 (0x3)
+#define LPDDR4_RL24_NRTP10 (0x4)
+#define LPDDR4_RL28_NRTP12 (0x5)
+#define LPDDR4_RL32_NRTP14 (0x6)
+#define LPDDR4_RL36_NRTP16 (0x7)
+/* RL & nRTP for DBI-RD Disabled */
+#define LPDDR4_RL12_NRTP8 (0x1)
+#define LPDDR4_RL16_NRTP8 (0x2)
+#define LPDDR4_RL22_NRTP8 (0x3)
+#define LPDDR4_RL28_NRTP10 (0x4)
+#define LPDDR4_RL32_NRTP12 (0x5)
+#define LPDDR4_RL36_NRTP14 (0x6)
+#define LPDDR4_RL40_NRTP16 (0x7)
+/* WL Set A,default */
+#define LPDDR4_A_WL4 (0x0 << 3)
+#define LPDDR4_A_WL6 (0x1 << 3)
+#define LPDDR4_A_WL8 (0x2 << 3)
+#define LPDDR4_A_WL10 (0x3 << 3)
+#define LPDDR4_A_WL12 (0x4 << 3)
+#define LPDDR4_A_WL14 (0x5 << 3)
+#define LPDDR4_A_WL16 (0x6 << 3)
+#define LPDDR4_A_WL18 (0x7 << 3)
+/* WL Set B, optional */
+#define LPDDR4_B_WL4 (0x0 << 3)
+#define LPDDR4_B_WL8 (0x1 << 3)
+#define LPDDR4_B_WL12 (0x2 << 3)
+#define LPDDR4_B_WL18 (0x3 << 3)
+#define LPDDR4_B_WL22 (0x4 << 3)
+#define LPDDR4_B_WL26 (0x5 << 3)
+#define LPDDR4_B_WL30 (0x6 << 3)
+#define LPDDR4_B_WL34 (0x7 << 3)
+/* 1:Select WL Set B*/
+#define LPDDR4_WL_B BIT(6)
+/* 1:enable*/
+#define LPDDR4_WR_LEVEL BIT(7)
+
+/* MR3 */
+#define LPDDR4_VDDQ_2_5 (0)
+#define LPDDR4_VDDQ_3 (1)
+#define LPDDR4_PU_CAL_MASK (1)
+#define LPDDR4_WRPST_0_5_TCK (0 << 1)
+#define LPDDR4_WRPST_1_5_TCK (1 << 1)
+#define LPDDR4_PPR_EN (1 << 2)
+/* PDDS */
+#define LPDDR4_PDDS_MASK (0x7 << 3)
+#define LPDDR4_PDDS_SHIFT (3)
+#define LPDDR4_PDDS_240 (0x1 << 3)
+#define LPDDR4_PDDS_120 (0x2 << 3)
+#define LPDDR4_PDDS_80 (0x3 << 3)
+#define LPDDR4_PDDS_60 (0x4 << 3)
+#define LPDDR4_PDDS_48 (0x5 << 3)
+#define LPDDR4_PDDS_40 (0x6 << 3)
+#define LPDDR4_DBI_RD_EN BIT(6)
+#define LPDDR4_DBI_WR_EN BIT(7)
+
+/* MR11 (ODT Control) */
+#define LPDDR4_DQODT_MASK (0x7)
+#define LPDDR4_DQODT_SHIFT (0x0)
+#define LPDDR4_DQODT_240 (1)
+#define LPDDR4_DQODT_120 (2)
+#define LPDDR4_DQODT_80 (3)
+#define LPDDR4_DQODT_60 (4)
+#define LPDDR4_DQODT_48 (5)
+#define LPDDR4_DQODT_40 (6)
+#define LPDDR4_DQODT_DIS (0)
+#define LPDDR4_CAODT_MASK (0x7 << 4)
+#define LPDDR4_CAODT_SHIFT (4)
+#define LPDDR4_CAODT_240 (1 << 4)
+#define LPDDR4_CAODT_120 (2 << 4)
+#define LPDDR4_CAODT_80 (3 << 4)
+#define LPDDR4_CAODT_60 (4 << 4)
+#define LPDDR4_CAODT_48 (5 << 4)
+#define LPDDR4_CAODT_40 (6 << 4)
+#define LPDDR4_CAODT_DIS (0 << 4)
+
+/* MR22 */
+#define LPDDR4_ODTE_CK_SHIFT (3)
+#define LPDDR4_ODTE_CS_SHIFT (4)
+#define LPDDR4_ODTD_CA_SHIFT (5)
+#define LPDDR4_SOC_ODT_MASK (0x7)
+#define LPDDR4_SOC_ODT_SHIFT (0)
+#define LPDDR4_SOC_ODT_240 (1)
+#define LPDDR4_SOC_ODT_120 (2)
+#define LPDDR4_SOC_ODT_80 (3)
+#define LPDDR4_SOC_ODT_60 (4)
+#define LPDDR4_SOC_ODT_48 (5)
+#define LPDDR4_SOC_ODT_40 (6)
+#define LPDDR4_SOC_ODT_DIS (0)
+
+/* LPDDR4x */
+/* MR3 */
+#define LPDDR4X_VDDQ_0_6 (0)
+#define LPDDR4X_VDDQ_0_5 (1)
+
+/* mr0 for ddr4 */
+#define DDR4_BL8 (0)
+#define DDR4_BC4_8 (1)
+#define DDR4_BC4 (2)
+#define DDR4_WR_RTP(n) ((n) << 9)
+#define DDR4_CL(n) ((((n) & 0xe) << 3) | ((n) & 1) << 2)
+#define DDR4_DLL_RESET(n) ((n) << 8)
+#define DDR4_DLL_ON BIT(0)
+#define DDR4_DLL_OFF (0 << 0)
+
+/* mr1 for ddr4 */
+#define DDR4_AL ((n) << 3)
+#define DDR4_DS_34 (0)
+#define DDR4_DS_48 BIT(1)
+#define DDR4_DS_MASK (0x3 << 1)
+#define DDR4_RTT_NOM_MASK (0x7 << 8)
+#define DDR4_RTT_NOM_DIS (0)
+#define DDR4_RTT_NOM_60 BIT(8)
+#define DDR4_RTT_NOM_120 (2 << 8)
+#define DDR4_RTT_NOM_40 (0x3 << 8)
+#define DDR4_RTT_NOM_240 (0x4 << 8)
+#define DDR4_RTT_NOM_48 (0x5 << 8)
+#define DDR4_RTT_NOM_80 (0x6 << 8)
+#define DDR4_RTT_NOM_34 (0x7 << 8)
+
+/* mr2 for ddr4 */
+#define DDR4_MR2_CWL(n) ((n) << 3)
+#define DDR4_RTT_WR_DIS (0)
+#define DDR4_RTT_WR_120 BIT(9)
+#define DDR4_RTT_WR_240 (2 << 9)
+
+/* mr4 for ddr4 */
+#define DDR4_READ_PREAMBLE(n) ((n) << 11)
+#define DDR4_WRITE_PREAMBLE(n) ((n) << 12)
+#define DDR4_READ_PREAMBLE_TRAIN(n) ((n) << 10)
+
+/* mr5 for ddr4 */
+#define DDR4_RD_DBI(n) ((n) << 12)
+#define DDR4_WR_DBI(n) ((n) << 11)
+#define DDR4_DM(n) ((n) << 10)
+#define DDR4_RTT_PARK_DIS (0 << 6)
+#define DDR4_RTT_PARK_60 (1 << 6)
+#define DDR4_RTT_PARK_120 (2 << 6)
+#define DDR4_RTT_PARK_40 (3 << 6)
+#define DDR4_RTT_PARK_240 (4 << 6)
+#define DDR4_RTT_PARK_48 (5 << 6)
+#define DDR4_RTT_PARK_80 (6 << 6)
+#define DDR4_RTT_PARK_34 (7 << 6)
+#define DIS_ODT_PD (1 << 5)
+#define EN_ODT_PD (0 << 5)
+
+/* mr6 for ddr4 */
+#define DDR4_TCCD_L(n) (((n) - 4) << 10)
+
+#define PS_2_CLK(freq, ps) (((uint64_t)(ps) / 100 * (uint64_t)(freq) +\
+ 9999) / 10000)
+
+#endif /* __ROCKCHIP_DRAM_SPEC_TIMING_H__ */
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rv1126.h b/arch/arm/include/asm/arch-rockchip/grf_rv1126.h
new file mode 100644
index 0000000..4e0488b
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/grf_rv1126.h
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd.
+ */
+
+#ifndef _ASM_ARCH_GRF_RV1126_H
+#define _ASM_ARCH_GRF_RV1126_H
+
+struct rv1126_grf {
+ unsigned int soc_con0;
+ unsigned int soc_con1;
+ unsigned int soc_con2;
+ unsigned int reserved0[1];
+ unsigned int soc_status0;
+ unsigned int soc_status1;
+ unsigned int reserved1[2];
+ unsigned int cpu_con0;
+ unsigned int cpu_con1;
+ unsigned int reserved2[2];
+ unsigned int cpu_status0;
+ unsigned int reserved3[3];
+ unsigned int noc_con0;
+ unsigned int noc_con1;
+ unsigned int noc_con2;
+ unsigned int noc_con3;
+ unsigned int usbhost_con0;
+ unsigned int usbhost_con1;
+ unsigned int usbhost_status0;
+ unsigned int usbotg_con0;
+ unsigned int usbotg_con1;
+ unsigned int usbotg_status0;
+ unsigned int usbotg_status1;
+ unsigned int usbotg_status2;
+ unsigned int mac_con0;
+ unsigned int mac_con1;
+ unsigned int mac_con2;
+ unsigned int reserved4[2];
+ unsigned int mac_status0;
+ unsigned int mac_status1;
+ unsigned int mac_status2;
+ unsigned int mem_con0;
+ unsigned int mem_con1;
+ unsigned int mem_con2;
+ unsigned int mem_con3;
+ unsigned int reserved5[(0x100 - 0x09c) / 4 - 1];
+ unsigned int tsadc_con0;
+ unsigned int reserved6[3];
+ unsigned int chip_id;
+ unsigned int reserved7[(0x10000 - 0x110) / 4 - 1];
+ unsigned int gpio0c_iomux_h;
+ unsigned int gpio0d_iomux_l;
+ unsigned int gpio0d_iomux_h;
+ unsigned int reserved8[1];
+ unsigned int gpio1a_iomux_l;
+ unsigned int gpio1a_iomux_h;
+ unsigned int gpio1b_iomux_l;
+ unsigned int gpio1b_iomux_h;
+ unsigned int gpio1c_iomux_l;
+ unsigned int gpio1c_iomux_h;
+ unsigned int gpio1d_iomux_l;
+ unsigned int gpio1d_iomux_h;
+ unsigned int gpio2a_iomux_l;
+ unsigned int gpio2a_iomux_h;
+ unsigned int gpio2b_iomux_l;
+ unsigned int gpio2b_iomux_h;
+ unsigned int gpio2c_iomux_l;
+ unsigned int gpio2c_iomux_h;
+ unsigned int gpio2d_iomux_l;
+ unsigned int gpio2d_iomux_h;
+ unsigned int gpio3a_iomux_l;
+ unsigned int gpio3a_iomux_h;
+ unsigned int gpio3b_iomux_l;
+ unsigned int gpio3b_iomux_h;
+ unsigned int gpio3c_iomux_l;
+ unsigned int gpio3c_iomux_h;
+ unsigned int gpio3d_iomux_l;
+ unsigned int gpio3d_iomux_h;
+ unsigned int gpio4a_iomux_l;
+ unsigned int reserved9[3];
+ unsigned int gpio0c_ds_h;
+ unsigned int gpio0d_ds_l;
+ unsigned int gpio0d_ds_h;
+ unsigned int reserved10[1];
+ unsigned int gpio1a_ds_l;
+ unsigned int gpio1a_ds_h;
+ unsigned int gpio1b_ds_l;
+ unsigned int gpio1b_ds_h;
+ unsigned int gpio1c_ds_l;
+ unsigned int gpio1c_ds_h;
+ unsigned int gpio1d_ds_l;
+ unsigned int gpio1d_ds_h;
+ unsigned int gpio2a_ds_l;
+ unsigned int gpio2a_ds_h;
+ unsigned int gpio2b_ds_l;
+ unsigned int gpio2b_ds_h;
+ unsigned int gpio2c_ds_l;
+ unsigned int gpio2c_ds_h;
+ unsigned int gpio2d_ds_l;
+ unsigned int gpio2d_ds_h;
+ unsigned int gpio3a_ds_l;
+ unsigned int gpio3a_ds_h;
+ unsigned int gpio3b_ds_l;
+ unsigned int gpio3b_ds_h;
+ unsigned int gpio3c_ds_l;
+ unsigned int gpio3c_ds_h;
+ unsigned int gpio3d_ds_l;
+ unsigned int gpio3d_ds_h;
+ unsigned int gpio4a_ds_l;
+ unsigned int reserved12[3];
+ unsigned int gpio0c_p_h;
+ unsigned int gpio0d_p;
+ unsigned int gpio1a_p;
+ unsigned int gpio1b_p;
+ unsigned int gpio1c_p;
+ unsigned int gpio1d_p;
+ unsigned int gpio2a_p;
+ unsigned int gpio2b_p;
+ unsigned int gpio2c_p;
+ unsigned int gpio2d_p;
+ unsigned int gpio3a_p;
+ unsigned int gpio3b_p;
+ unsigned int gpio3c_p;
+ unsigned int gpio3d_p;
+ unsigned int gpio4a_p;
+ unsigned int reserved13[1];
+ unsigned int gpio0c_ie_h;
+ unsigned int gpio0d_ie;
+ unsigned int gpio1a_ie;
+ unsigned int gpio1b_ie;
+ unsigned int gpio1c_ie;
+ unsigned int gpio1d_ie;
+ unsigned int gpio2a_ie;
+ unsigned int gpio2b_ie;
+ unsigned int gpio2c_ie;
+ unsigned int gpio2d_ie;
+ unsigned int gpio3a_ie;
+ unsigned int gpio3b_ie;
+ unsigned int gpio3c_ie;
+ unsigned int gpio3d_ie;
+ unsigned int gpio4a_ie;
+ unsigned int reserved14[1];
+ unsigned int gpio0c_smt_h;
+ unsigned int gpio0d_smt;
+ unsigned int gpio1a_smt;
+ unsigned int gpio1b_smt;
+ unsigned int gpio1c_smt;
+ unsigned int gpio1d_smt;
+ unsigned int gpio2a_smt;
+ unsigned int gpio2b_smt;
+ unsigned int gpio2c_smt;
+ unsigned int gpio2d_smt;
+ unsigned int gpio3a_smt;
+ unsigned int gpio3b_smt;
+ unsigned int gpio3c_smt;
+ unsigned int gpio3d_smt;
+ unsigned int gpio4a_smt;
+ unsigned int reserved15[(0x10200 - 0x101b8) / 4 - 1];
+ unsigned int csiphy0_con;
+ unsigned int reserved16[1];
+ unsigned int csiphy0_status;
+ unsigned int reserved17[1];
+ unsigned int csiphy1_con;
+ unsigned int reserved18[1];
+ unsigned int csiphy1_status;
+ unsigned int reserved19[1];
+ unsigned int dsiphy_con;
+ unsigned int reserved20[3];
+ unsigned int usbphy_con0;
+ unsigned int usbphy_con1;
+ unsigned int usbphy_con2;
+ unsigned int reserved21[3];
+ unsigned int usbphy_status;
+ unsigned int reserved22[1];
+ unsigned int cifio_con;
+ unsigned int sddetflt_con;
+ unsigned int uart2rx_low_con;
+ unsigned int reserved23[1];
+ unsigned int iofunc_con0;
+ unsigned int iofunc_con1;
+ unsigned int iofunc_con2;
+ unsigned int iofunc_con3;
+ unsigned int usbphy0_cfg_con;
+ unsigned int usbphy0_cfg_addrin;
+ unsigned int usbphy0_cfg_addrout;
+ unsigned int usbphy0_cfg_dly_con;
+ unsigned int usbphy1_cfg_con;
+ unsigned int usbphy1_cfg_addrin;
+ unsigned int usbphy1_cfg_addrout;
+ unsigned int usbphy1_cfg_dly_con;
+ unsigned int reserved24[(0x10300 - 0x1028c) / 4 - 1];
+ unsigned int usb_sig_detect_con;
+ unsigned int usb_sig_detect_status;
+ unsigned int usb_sig_detect_clr;
+ unsigned int reserved25[1];
+ unsigned int usb_linestate_con;
+ unsigned int usb_disconnect_con;
+ unsigned int usb_bvalid_con;
+ unsigned int usb_id_con;
+};
+
+check_member(rv1126_grf, usb_id_con, 0x1031c);
+
+struct rv1126_pmugrf {
+ unsigned int gpio0a_iomux_l;
+ unsigned int gpio0a_iomux_h;
+ unsigned int gpio0b_iomux_l;
+ unsigned int gpio0b_iomux_h;
+ unsigned int gpio0c_iomux_l;
+ unsigned int reserved0[3];
+ unsigned int gpio0a_ds_l;
+ unsigned int gpio0a_ds_h;
+ unsigned int gpio0b_ds_l;
+ unsigned int gpio0b_ds_h;
+ unsigned int gpio0c_ds_l;
+ unsigned int osc_ds;
+ unsigned int reserved1[2];
+ unsigned int gpio0a_p;
+ unsigned int gpio0b_p;
+ unsigned int gpio0c_p_l;
+ unsigned int reserved2[1];
+ unsigned int gpio0a_ie;
+ unsigned int gpio0b_ie;
+ unsigned int gpio0c_ie_l;
+ unsigned int reserved3[1];
+ unsigned int gpio0a_smt;
+ unsigned int gpio0b_smt;
+ unsigned int gpio0c_smt_l;
+ unsigned int reserved4[(0x100 - 0x68) / 4 - 1];
+ unsigned int soc_con[7];
+ unsigned int reserved5[(0x140 - 0x118) / 4 - 1];
+ unsigned int io_vsel;
+ unsigned int io_vret;
+ unsigned int reserved6[(0x180 - 0x144) / 4 - 1];
+ unsigned int pmupvtm_clkdiv;
+ unsigned int reserved7[(0x200 - 0x180) / 4 - 1];
+ unsigned int os_reg[12];
+ unsigned int rstfunc_status;
+ unsigned int rstfunc_clr;
+ unsigned int reserved8[(0x380 - 0x234) / 4 - 1];
+ unsigned int sd_detect_con;
+ unsigned int reserved9[3];
+ unsigned int sd_detect_status;
+ unsigned int reserved10[3];
+ unsigned int sd_detect_clr;
+ unsigned int reserved11[3];
+ unsigned int sd_det_count;
+};
+
+check_member(rv1126_pmugrf, sd_det_count, 0x3b0);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_common.h b/arch/arm/include/asm/arch-rockchip/sdram_common.h
index 5efa6e9..e53e5a9 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_common.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_common.h
@@ -15,6 +15,210 @@
#define MIN(a, b) (((a) > (b)) ? (b) : (a))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+/* get head info for initial */
+#define DDR_FREQ_F0_SHIFT (0)
+#define DDR_FREQ_F1_SHIFT (12)
+#define DDR_FREQ_F2_SHIFT (0)
+#define DDR_FREQ_F3_SHIFT (12)
+#define DDR_FREQ_F4_SHIFT (0)
+#define DDR_FREQ_F5_SHIFT (12)
+#define DDR_FREQ_MASK (0xfff)
+
+#define UART_INFO_ID_SHIFT (28)
+#define UART_INFO_IOMUX_SHIFT (24)
+#define UART_INFO_BAUD_SHIFT (0)
+#define UART_INFO_ID(n) (((n) >> 28) & 0xf)
+#define UART_INFO_IOMUX(n) (((n) >> 24) & 0xf)
+#define UART_INFO_BAUD(n) ((n) & 0xffffff)
+
+/* g_ch_info[15:0]: g_stdby_idle */
+#define STANDBY_IDLE(n) ((n) & 0xffff)
+
+#define SR_INFO(n) (((n) >> 16) & 0xffff)
+#define PD_INFO(n) ((n) & 0xffff)
+
+#define FIRST_SCAN_CH(n) (((n) >> 28) & 0xf)
+#define CHANNEL_MASK(n) (((n) >> 24) & 0xf)
+#define STRIDE_TYPE(n) (((n) >> 16) & 0xff)
+
+#define DDR_2T_INFO(n) ((n) & 1)
+#define PLL_SSMOD_SPREAD(n) (((n) >> 1) & 0xff)
+#define PLL_SSMOD_DIV(n) (((n) >> 9) & 0xff)
+#define PLL_SSMOD_DOWNSPREAD(n) (((n) >> 17) & 0x3)
+
+/* sdram_head_info_v2 define */
+/* for *_drv_odten and *_drv_odtoff */
+#define PHY_DQ_DRV_SHIFT 0
+#define PHY_CA_DRV_SHIFT 8
+#define PHY_CLK_DRV_SHIFT 16
+#define DRAM_DQ_DRV_SHIFT 24
+#define DRV_INFO_PHY_DQ_DRV(n) ((n) & 0xff)
+#define DRV_INFO_PHY_CA_DRV(n) (((n) >> PHY_CA_DRV_SHIFT) & 0xff)
+#define DRV_INFO_PHY_CLK_DRV(n) (((n) >> PHY_CLK_DRV_SHIFT) & 0xff)
+#define DRV_INFO_DRAM_DQ_DRV(n) (((n) >> DRAM_DQ_DRV_SHIFT) & 0xff)
+
+/* for *_odt_info */
+#define DRAM_ODT_SHIFT 0
+#define PHY_ODT_SHIFT 8
+#define PHY_ODT_PUUP_EN_SHIFT 18
+#define PHY_ODT_PUDN_EN_SHIFT 19
+#define ODT_INFO_DRAM_ODT(n) (((n) >> DRAM_ODT_SHIFT) & 0xff)
+#define ODT_INFO_PHY_ODT(n) (((n) >> PHY_ODT_SHIFT) & 0x3ff)
+#define ODT_INFO_PULLUP_EN(n) (((n) >> PHY_ODT_PUUP_EN_SHIFT) & 1)
+#define ODT_INFO_PULLDOWN_EN(n) (((n) >> PHY_ODT_PUDN_EN_SHIFT) & 1)
+
+/* for *odt_en_freq; */
+#define DRAM_ODT_EN_FREQ_SHIFT 0
+#define PHY_ODT_EN_FREQ_SHIFT 12
+#define DRAMODT_EN_FREQ(n) (((n) >> DRAM_ODT_EN_FREQ_SHIFT) & \
+ 0xfff)
+#define PHYODT_EN_FREQ(n) (((n) >> PHY_ODT_EN_FREQ_SHIFT) & 0xfff)
+
+#define PHY_DQ_SR_SHIFT 0
+#define PHY_CA_SR_SHIFT 8
+#define PHY_CLK_SR_SHIFT 16
+#define DQ_SR_INFO(n) (((n) >> PHY_DQ_SR_SHIFT) & 0xff)
+#define CA_SR_INFO(n) (((n) >> PHY_CA_SR_SHIFT) & 0xff)
+#define CLK_SR_INFO(n) (((n) >> PHY_CLK_SR_SHIFT) & 0xff)
+
+/* LP4 */
+#define LP4_CA_ODT_SHIFT (18)
+#define LP4_DRV_PU_CAL_ODTEN_SHIFT (26)
+#define LP4_DRV_PU_CAL_ODTOFF_SHIFT (27)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTEN_SHIFT (28)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTOFF_SHIFT (29)
+#define ODT_INFO_LP4_CA_ODT(n) (((n) >> LP4_CA_ODT_SHIFT) & \
+ 0xff)
+#define LP4_DRV_PU_CAL_ODTEN(n) \
+ (((n) >> LP4_DRV_PU_CAL_ODTEN_SHIFT) & 1)
+#define LP4_DRV_PU_CAL_ODTOFF(n) \
+ (((n) >> LP4_DRV_PU_CAL_ODTOFF_SHIFT) & 1)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTEN(n) \
+ (((n) >> PHY_LP4_DRV_PULLDOWN_EN_ODTEN_SHIFT) & 1)
+#define PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(n) \
+ (((n) >> PHY_LP4_DRV_PULLDOWN_EN_ODTOFF_SHIFT) & 1)
+
+#define PHY_LP4_CS_DRV_ODTEN_SHIFT (0)
+#define PHY_LP4_CS_DRV_ODTOFF_SHIFT (8)
+#define LP4_ODTE_CK_SHIFT (16)
+#define LP4_ODTE_CS_EN_SHIFT (17)
+#define LP4_ODTD_CA_EN_SHIFT (18)
+#define PHY_LP4_CS_DRV_ODTEN(n) \
+ (((n) >> PHY_LP4_CS_DRV_ODTEN_SHIFT) & 0xff)
+#define PHY_LP4_CS_DRV_ODTOFF(n) \
+ (((n) >> PHY_LP4_CS_DRV_ODTOFF_SHIFT) & 0xff)
+#define LP4_ODTE_CK_EN(n) (((n) >> LP4_ODTE_CK_SHIFT) & 1)
+#define LP4_ODTE_CS_EN(n) (((n) >> LP4_ODTE_CS_EN_SHIFT) & 1)
+#define LP4_ODTD_CA_EN(n) (((n) >> LP4_ODTD_CA_EN_SHIFT) & 1)
+
+#define PHY_LP4_DQ_VREF_SHIFT (0)
+#define LP4_DQ_VREF_SHIFT (10)
+#define LP4_CA_VREF_SHIFT (20)
+
+#define PHY_LP4_DQ_VREF(n) \
+ (((n) >> PHY_LP4_DQ_VREF_SHIFT) & 0x3ff)
+#define LP4_DQ_VREF(n) (((n) >> LP4_DQ_VREF_SHIFT) & 0x3ff)
+#define LP4_CA_VREF(n) (((n) >> LP4_CA_VREF_SHIFT) & 0x3ff)
+
+#define LP4_DQ_ODT_EN_FREQ_SHIFT (0)
+#define PHY_LP4_ODT_EN_FREQ_SHIFT (12)
+#define LP4_CA_ODT_EN_FREQ_SHIFT (0)
+#define PHY_LP4_ODT_EN_FREQ(n) \
+ (((n) >> PHY_LP4_ODT_EN_FREQ_SHIFT) & 0xfff)
+#define LP4_DQ_ODT_EN_FREQ(n) \
+ (((n) >> LP4_DQ_ODT_EN_FREQ_SHIFT) & 0xfff)
+#define LP4_CA_ODT_EN_FREQ(n) \
+ (((n) >> LP4_CA_ODT_EN_FREQ_SHIFT) & 0xfff)
+
+struct sdram_head_info_v0 {
+ u32 start_tag;
+ u32 version_info;
+ u32 gcpu_gen_freq;
+ u32 g_d2_lp2_freq;
+ u32 g_d3_lp3_freq;
+ u32 g_d4_lp4_freq;
+ u32 g_uart_info;
+ u32 g_sr_pd_idle;
+ u32 g_ch_info;
+ u32 g_2t_info;
+ u32 reserved11;
+ u32 reserved12;
+ u32 reserved13;
+};
+
+struct index_info {
+ u8 offset;
+ u8 size;
+};
+
+struct sdram_head_info_index_v2 {
+ u32 start_tag;
+ u32 version_info;
+ struct index_info cpu_gen_index;
+ struct index_info global_index;
+
+ struct index_info ddr2_index;
+ struct index_info ddr3_index;
+
+ struct index_info ddr4_index;
+ struct index_info ddr5_index;
+
+ struct index_info lp2_index;
+ struct index_info lp3_index;
+
+ struct index_info lp4_index;
+ struct index_info lp5_index;
+
+ struct index_info skew_index;
+ struct index_info dq_map_index;
+
+ struct index_info lp4x_index;
+ struct index_info reserved;
+};
+
+struct global_info {
+ u32 uart_info;
+ u32 sr_pd_info;
+ u32 ch_info;
+ u32 info_2t;
+ u32 reserved[4];
+};
+
+struct ddr2_3_4_lp2_3_info {
+ u32 ddr_freq0_1;
+ u32 ddr_freq2_3;
+ u32 ddr_freq4_5;
+ u32 drv_when_odten;
+ u32 drv_when_odtoff;
+ u32 odt_info;
+ u32 odten_freq;
+ u32 sr_when_odten;
+ u32 sr_when_odtoff;
+};
+
+struct lp4_info {
+ u32 ddr_freq0_1;
+ u32 ddr_freq2_3;
+ u32 ddr_freq4_5;
+ u32 drv_when_odten;
+ u32 drv_when_odtoff;
+ u32 odt_info;
+ u32 dq_odten_freq;
+ u32 sr_when_odten;
+ u32 sr_when_odtoff;
+ u32 ca_odten_freq;
+ u32 cs_drv_ca_odt_info;
+ u32 vref_when_odten;
+ u32 vref_when_odtoff;
+};
+
+struct dq_map_info {
+ u32 byte_map[2];
+ u32 lp3_dq0_7_map;
+ u32 lp2_dq0_7_map;
+ u32 ddr4_dq_map[4];
+};
+
struct sdram_cap_info {
unsigned int rank;
/* dram column number, 0 means this channel is invalid */
@@ -46,6 +250,14 @@
};
#define DDR_SYS_REG_VERSION (0x2)
+/* for modify tRFC and related timing */
+#define DIE_CAP_512MBIT 64
+#define DIE_CAP_1GBIT 128
+#define DIE_CAP_2GBIT 256
+#define DIE_CAP_4GBIT 512
+#define DIE_CAP_8GBIT 1024
+#define DIE_CAP_16GBIT 2048
+#define DIE_CAP_32GBIT 4096
/*
* sys_reg2 bitfield struct
* [31] row_3_4_ch1
@@ -116,7 +328,7 @@
void sdram_print_dram_type(unsigned char dramtype);
void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
- struct sdram_base_params *base);
+ struct sdram_base_params *base, u32 split);
void sdram_print_stride(unsigned int stride);
void sdram_org_config(struct sdram_cap_info *cap_info,
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_msch.h b/arch/arm/include/asm/arch-rockchip/sdram_msch.h
index cfb3d9c..d1926f4 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_msch.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_msch.h
@@ -57,6 +57,18 @@
} b;
};
+union noc_devtodev_rv1126 {
+ u32 d32;
+ struct {
+ unsigned busrdtord : 3;
+ unsigned reserved0 : 1;
+ unsigned busrdtowr : 4;
+ unsigned buswrtord : 4;
+ unsigned buswrtowr : 3;
+ unsigned reserved2 : 17;
+ } b;
+};
+
union noc_ddrmode {
u32 d32;
struct {
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h b/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h
index 3a36577..3780dc6 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_pctl_px30.h
@@ -12,7 +12,7 @@
#endif
struct ddr_pctl_regs {
- u32 pctl[30][2];
+ u32 pctl[35][2];
};
/* ddr pctl registers define */
@@ -25,6 +25,7 @@
#define DDR_PCTL2_MRCTRL2 0x1c
#define DDR_PCTL2_DERATEEN 0x20
#define DDR_PCTL2_DERATEINT 0x24
+#define DDR_PCTL2_MSTR2 0x28
#define DDR_PCTL2_PWRCTL 0x30
#define DDR_PCTL2_PWRTMG 0x34
#define DDR_PCTL2_HWLPCTL 0x38
@@ -122,8 +123,103 @@
#define DDR_PCTL2_PCFGW_n 0x408
#define DDR_PCTL2_PCTRL_n 0x490
+#define UMCTL2_REGS_FREQ(n) \
+ ((0x1000 * (n) + (((n) > 0) ? 0x1000 : 0)))
+
+/* PCTL2_MSTR */
+#define PCTL2_FREQUENCY_MODE_MASK (1)
+#define PCTL2_FREQUENCY_MODE_SHIFT (29)
+#define PCTL2_DLL_OFF_MODE BIT(15)
+/* PCTL2_STAT */
+#define PCTL2_SELFREF_TYPE_MASK (3 << 4)
+#define PCTL2_SELFREF_TYPE_SR_NOT_AUTO (2 << 4)
+#define PCTL2_OPERATING_MODE_MASK (7)
+#define PCTL2_OPERATING_MODE_INIT (0)
+#define PCTL2_OPERATING_MODE_NORMAL (1)
+#define PCTL2_OPERATING_MODE_PD (2)
+#define PCTL2_OPERATING_MODE_SR (3)
+/* PCTL2_MRCTRL0 */
+#define PCTL2_MR_WR BIT(31)
+#define PCTL2_MR_ADDR_SHIFT (12)
+#define PCTL2_MR_RANK_SHIFT (4)
+#define PCTL2_MR_TYPE_WR (0)
+#define PCTL2_MR_TYPE_RD (1)
+/* PCTL2_MRCTRL1 */
+#define PCTL2_MR_ADDRESS_SHIFT (8)
+#define PCTL2_MR_DATA_MASK (0xff)
/* PCTL2_MRSTAT */
-#define MR_WR_BUSY BIT(0)
+#define PCTL2_MR_WR_BUSY BIT(0)
+/* PCTL2_DERATEEN */
+#define PCTL2_DERATE_ENABLE (1)
+/* PCTL2_PWRCTL */
+#define PCTL2_SELFREF_SW BIT(5)
+#define PCTL2_POWERDOWN_EN BIT(1)
+#define PCTL2_SELFREF_EN (1)
+/* PCTL2_PWRTMG */
+#define PCTL2_SELFREF_TO_X32_MASK (0xFF)
+#define PCTL2_SELFREF_TO_X32_SHIFT (16)
+#define PCTL2_POWERDOWN_TO_X32_MASK (0x1F)
+/* PCTL2_INIT3 */
+#define PCTL2_DDR34_MR0_SHIFT (16)
+#define PCTL2_LPDDR234_MR1_SHIFT (16)
+#define PCTL2_DDR34_MR1_SHIFT (0)
+#define PCTL2_LPDDR234_MR2_SHIFT (0)
+/* PCTL2_INIT4 */
+#define PCTL2_DDR34_MR2_SHIFT (16)
+#define PCTL2_LPDDR234_MR3_SHIFT (16)
+#define PCTL2_DDR34_MR3_SHIFT (0)
+#define PCTL2_LPDDR4_MR13_SHIFT (0)
+
+/* PCTL2_INIT6 */
+#define PCTL2_DDR4_MR4_SHIFT (16)
+#define PCTL2_LPDDR4_MR11_SHIFT (16)
+#define PCTL2_DDR4_MR5_SHIFT (0)
+#define PCTL2_LPDDR4_MR12_SHIFT (0)
+
+/* PCTL2_INIT7 */
+#define PCTL2_LPDDR4_MR22_SHIFT (16)
+#define PCTL2_DDR4_MR6_SHIFT (0)
+#define PCTL2_LPDDR4_MR14_SHIFT (0)
+
+#define PCTL2_MR_MASK (0xffff)
+
+/* PCTL2_RFSHCTL3 */
+#define PCTL2_DIS_AUTO_REFRESH (1)
+/* PCTL2_ZQCTL0 */
+#define PCTL2_DIS_AUTO_ZQ BIT(31)
+#define PCTL2_DIS_SRX_ZQCL BIT(30)
+/* PCTL2_DFILPCFG0 */
+#define PCTL2_DFI_LP_EN_SR BIT(8)
+#define PCTL2_DFI_LP_EN_SR_MASK BIT(8)
+#define PCTL2_DFI_LP_EN_SR_SHIFT (8)
+/* PCTL2_DFIMISC */
+#define PCTL2_DFI_INIT_COMPLETE_EN (1)
+/* PCTL2_DFISTAT */
+#define PCTL2_DFI_LP_ACK BIT(1)
+#define PCTL2_DFI_INIT_COMPLETE (1)
+/* PCTL2_DBG1 */
+#define PCTL2_DIS_HIF BIT(1)
+/* PCTL2_DBGCAM */
+#define PCTL2_DBG_WR_Q_EMPTY BIT(26)
+#define PCTL2_DBG_RD_Q_EMPTY BIT(25)
+#define PCTL2_DBG_LPR_Q_DEPTH_MASK (0xffff << 8)
+#define PCTL2_DBG_LPR_Q_DEPTH_EMPTY (0x0 << 8)
+/* PCTL2_DBGCMD */
+#define PCTL2_RANK1_REFRESH BIT(1)
+#define PCTL2_RANK0_REFRESH (1)
+/* PCTL2_DBGSTAT */
+#define PCTL2_RANK1_REFRESH_BUSY BIT(1)
+#define PCTL2_RANK0_REFRESH_BUSY (1)
+/* PCTL2_SWCTL */
+#define PCTL2_SW_DONE (1)
+#define PCTL2_SW_DONE_CLEAR (0)
+/* PCTL2_SWSTAT */
+#define PCTL2_SW_DONE_ACK (1)
+/* PCTL2_PSTAT */
+#define PCTL2_WR_PORT_BUSY_0 BIT(16)
+#define PCTL2_RD_PORT_BUSY_0 (1)
+/* PCTL2_PCTRLn */
+#define PCTL2_PORT_EN (1)
void pctl_read_mr(void __iomem *pctl_base, u32 rank, u32 mr_num);
int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg,
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_phy_rv1126.h b/arch/arm/include/asm/arch-rockchip/sdram_phy_rv1126.h
new file mode 100644
index 0000000..5b64ec3
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_phy_rv1126.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_RK1126_PHY_H
+#define _ASM_ARCH_SDRAM_RK1126_PHY_H
+
+/* PHY_REG0 */
+#define DIGITAL_DERESET BIT(3)
+#define ANALOG_DERESET BIT(2)
+#define DIGITAL_RESET (0 << 3)
+#define ANALOG_RESET (0 << 2)
+
+/* PHY_REG1 */
+#define PHY_DDR2 (0)
+#define PHY_LPDDR2 (1)
+#define PHY_DDR3 (2)
+#define PHY_LPDDR3 (3)
+#define PHY_DDR4 (4)
+#define PHY_DDR5 (5)
+#define PHY_BL_4 (0 << 3)
+#define PHY_BL_8_OR_16 BIT(3)
+
+/* PHY_REG2 */
+#define PHY_DTT_EN BIT(0)
+#define PHY_DTT_DISB (0 << 0)
+#define PHY_WRITE_LEVELING_EN BIT(2)
+#define PHY_WRITE_LEVELING_DISB (0 << 2)
+#define PHY_SELECT_CS0 (2)
+#define PHY_SELECT_CS1 (1)
+#define PHY_SELECT_CS0_1 (0)
+#define PHY_WRITE_LEVELING_SELECTCS(n) ((n) << 6)
+#define PHY_DATA_TRAINING_SELECTCS(n) ((n) << 4)
+
+/* PHY_REGf */
+#define PHY_DQ_WIDTH_MASK (0xf)
+
+/* PHY_REG51 */
+#define PHY_PBDIV_BIT9_MASK BIT(0)
+#define PHY_PBDIV_BIT9_SHIFT (0)
+#define PHY_POSTDIV_EN_MASK BIT(7)
+#define PHY_POSTDIV_EN_SHIFT (7)
+
+/* PHY_REG52 */
+#define PHY_PREDIV_MASK (0x1F)
+#define PHY_PREDIV_SHIFT (0)
+
+/* PHY_REG53*/
+#define PHY_POSTDIV_MASK (0x7)
+#define PHY_POSTDIV_SHIFT (5)
+#define PHY_PD_DISB BIT(3)
+
+/* PHY_REG90 */
+#define PHY_PLL_LOCK BIT(2)
+
+struct ca_skew {
+ u32 a0_a3_a3_cke1_a_de_skew;
+ u32 a1_ba1_null_cke0_b_de_skew;
+ u32 a2_a9_a9_a4_a_de_skew;
+ u32 a3_a15_null_a5_b_de_skew;
+ u32 a4_a6_a6_ck_a_de_skew;
+ u32 a5_a12_null_odt0_b_de_skew;
+ u32 a6_ba2_null_a0_a_de_skew;
+ u32 a7_a4_a4_odt0_a_de_skew;
+ u32 a8_a1_a1_cke0_a_de_skew;
+ u32 a9_a5_a5_a5_a_de_skew;
+ u32 a10_a8_a8_clkb_a_de_skew;
+ u32 a11_a7_a7_ca2_a_de_skew;
+ u32 a12_rasn_null_ca1_a_de_skew;
+ u32 a13_a13_null_ca3_a_de_skew;
+ u32 a14_a14_null_csb1_b_de_skew;
+ u32 a15_a10_null_ca0_b_de_skew;
+ u32 a16_a11_null_csb0_b_de_skew;
+ u32 a17_null_null_null_de_skew;
+ u32 ba0_csb1_csb1_csb0_a_de_skew;
+ u32 ba1_wen_null_cke1_b_de_skew;
+ u32 bg0_odt1_odt1_csb1_a_de_skew;
+ u32 bg1_a2_a2_odt1_a_de_skew;
+ u32 cke0_casb_null_ca1_b_de_skew;
+ u32 ck_ck_ck_ck_b_de_skew;
+ u32 ckb_ckb_ckb_ckb_b_de_skew;
+ u32 csb0_odt0_odt0_ca2_b_de_skew;
+ u32 odt0_csb0_csb0_ca4_b_de_skew;
+ u32 resetn_resetn_null_resetn_de_skew;
+ u32 actn_cke_cke_ca3_b_de_skew;
+ u32 null_null_null_null_de_skew;
+ u32 csb1_ba0_null_null_de_skew;
+ u32 odt1_a0_a0_odt1_b_de_skew;
+};
+
+#define PHY_REG(base, n) ((base) + 4 * (n))
+#endif /* _ASM_ARCH_SDRAM_RK1126_PHY_H */
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
index 6f6c5c9..0d29aef 100644
--- a/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rk322x.h
@@ -415,7 +415,7 @@
#define PCTL_STAT_MASK 7
#define INIT_MEM 0
#define CONFIG 1
-#define CONFIG_REQ 2
+#define CFG_REQ 2
#define ACCESS 3
#define ACCESS_REQ 4
#define LOW_POWER 5
diff --git a/arch/arm/include/asm/arch-rockchip/sdram_rv1126.h b/arch/arm/include/asm/arch-rockchip/sdram_rv1126.h
new file mode 100644
index 0000000..6a07436
--- /dev/null
+++ b/arch/arm/include/asm/arch-rockchip/sdram_rv1126.h
@@ -0,0 +1,420 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef _ASM_ARCH_SDRAM_RK1126_H
+#define _ASM_ARCH_SDRAM_RK1126_H
+
+#include <asm/arch-rockchip/dram_spec_timing.h>
+#include <asm/arch-rockchip/sdram.h>
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_msch.h>
+#include <asm/arch-rockchip/sdram_pctl_px30.h>
+#include <asm/arch-rockchip/sdram_phy_rv1126.h>
+
+#define AGINGX0_VAL (4)
+#define AGING_CPU_VAL (0xff)
+#define AGING_NPU_VAL (0xff)
+#define AGING_OTHER_VAL (0x33)
+
+#define PATTERN (0x5aa5f00f)
+
+#define PHY_DDR3_RON_DISABLE (0)
+#define PHY_DDR3_RON_455ohm (1)
+#define PHY_DDR3_RON_230ohm (2)
+#define PHY_DDR3_RON_153ohm (3)
+#define PHY_DDR3_RON_115ohm (4)
+#define PHY_DDR3_RON_91ohm (5)
+#define PHY_DDR3_RON_76ohm (6)
+#define PHY_DDR3_RON_65ohm (7)
+#define PHY_DDR3_RON_57ohm (16)
+#define PHY_DDR3_RON_51ohm (17)
+#define PHY_DDR3_RON_46ohm (18)
+#define PHY_DDR3_RON_41ohm (19)
+#define PHY_DDR3_RON_38ohm (20)
+#define PHY_DDR3_RON_35ohm (21)
+#define PHY_DDR3_RON_32ohm (22)
+#define PHY_DDR3_RON_30ohm (23)
+#define PHY_DDR3_RON_28ohm (24)
+#define PHY_DDR3_RON_27ohm (25)
+#define PHY_DDR3_RON_25ohm (26)
+#define PHY_DDR3_RON_24ohm (27)
+#define PHY_DDR3_RON_23ohm (28)
+#define PHY_DDR3_RON_22ohm (29)
+#define PHY_DDR3_RON_21ohm (30)
+#define PHY_DDR3_RON_20ohm (31)
+
+#define PHY_DDR3_RTT_DISABLE (0)
+#define PHY_DDR3_RTT_561ohm (1)
+#define PHY_DDR3_RTT_282ohm (2)
+#define PHY_DDR3_RTT_188ohm (3)
+#define PHY_DDR3_RTT_141ohm (4)
+#define PHY_DDR3_RTT_113ohm (5)
+#define PHY_DDR3_RTT_94ohm (6)
+#define PHY_DDR3_RTT_81ohm (7)
+#define PHY_DDR3_RTT_72ohm (16)
+#define PHY_DDR3_RTT_64ohm (17)
+#define PHY_DDR3_RTT_58ohm (18)
+#define PHY_DDR3_RTT_52ohm (19)
+#define PHY_DDR3_RTT_48ohm (20)
+#define PHY_DDR3_RTT_44ohm (21)
+#define PHY_DDR3_RTT_41ohm (22)
+#define PHY_DDR3_RTT_38ohm (23)
+#define PHY_DDR3_RTT_37ohm (24)
+#define PHY_DDR3_RTT_34ohm (25)
+#define PHY_DDR3_RTT_32ohm (26)
+#define PHY_DDR3_RTT_31ohm (27)
+#define PHY_DDR3_RTT_29ohm (28)
+#define PHY_DDR3_RTT_28ohm (29)
+#define PHY_DDR3_RTT_27ohm (30)
+#define PHY_DDR3_RTT_25ohm (31)
+
+#define PHY_DDR4_LPDDR3_RON_DISABLE (0)
+#define PHY_DDR4_LPDDR3_RON_482ohm (1)
+#define PHY_DDR4_LPDDR3_RON_244ohm (2)
+#define PHY_DDR4_LPDDR3_RON_162ohm (3)
+#define PHY_DDR4_LPDDR3_RON_122ohm (4)
+#define PHY_DDR4_LPDDR3_RON_97ohm (5)
+#define PHY_DDR4_LPDDR3_RON_81ohm (6)
+#define PHY_DDR4_LPDDR3_RON_69ohm (7)
+#define PHY_DDR4_LPDDR3_RON_61ohm (16)
+#define PHY_DDR4_LPDDR3_RON_54ohm (17)
+#define PHY_DDR4_LPDDR3_RON_48ohm (18)
+#define PHY_DDR4_LPDDR3_RON_44ohm (19)
+#define PHY_DDR4_LPDDR3_RON_40ohm (20)
+#define PHY_DDR4_LPDDR3_RON_37ohm (21)
+#define PHY_DDR4_LPDDR3_RON_34ohm (22)
+#define PHY_DDR4_LPDDR3_RON_32ohm (23)
+#define PHY_DDR4_LPDDR3_RON_30ohm (24)
+#define PHY_DDR4_LPDDR3_RON_28ohm (25)
+#define PHY_DDR4_LPDDR3_RON_27ohm (26)
+#define PHY_DDR4_LPDDR3_RON_25ohm (27)
+#define PHY_DDR4_LPDDR3_RON_24ohm (28)
+#define PHY_DDR4_LPDDR3_RON_23ohm (29)
+#define PHY_DDR4_LPDDR3_RON_22ohm (30)
+#define PHY_DDR4_LPDDR3_RON_21ohm (31)
+
+#define PHY_DDR4_LPDDR3_RTT_DISABLE (0)
+#define PHY_DDR4_LPDDR3_RTT_586ohm (1)
+#define PHY_DDR4_LPDDR3_RTT_294ohm (2)
+#define PHY_DDR4_LPDDR3_RTT_196ohm (3)
+#define PHY_DDR4_LPDDR3_RTT_148ohm (4)
+#define PHY_DDR4_LPDDR3_RTT_118ohm (5)
+#define PHY_DDR4_LPDDR3_RTT_99ohm (6)
+#define PHY_DDR4_LPDDR3_RTT_85ohm (7)
+#define PHY_DDR4_LPDDR3_RTT_76ohm (16)
+#define PHY_DDR4_LPDDR3_RTT_67ohm (17)
+#define PHY_DDR4_LPDDR3_RTT_60ohm (18)
+#define PHY_DDR4_LPDDR3_RTT_55ohm (19)
+#define PHY_DDR4_LPDDR3_RTT_50ohm (20)
+#define PHY_DDR4_LPDDR3_RTT_46ohm (21)
+#define PHY_DDR4_LPDDR3_RTT_43ohm (22)
+#define PHY_DDR4_LPDDR3_RTT_40ohm (23)
+#define PHY_DDR4_LPDDR3_RTT_38ohm (24)
+#define PHY_DDR4_LPDDR3_RTT_36ohm (25)
+#define PHY_DDR4_LPDDR3_RTT_34ohm (26)
+#define PHY_DDR4_LPDDR3_RTT_32ohm (27)
+#define PHY_DDR4_LPDDR3_RTT_31ohm (28)
+#define PHY_DDR4_LPDDR3_RTT_29ohm (29)
+#define PHY_DDR4_LPDDR3_RTT_28ohm (30)
+#define PHY_DDR4_LPDDR3_RTT_27ohm (31)
+
+#define PHY_LPDDR4_RON_DISABLE (0)
+#define PHY_LPDDR4_RON_501ohm (1)
+#define PHY_LPDDR4_RON_253ohm (2)
+#define PHY_LPDDR4_RON_168ohm (3)
+#define PHY_LPDDR4_RON_126ohm (4)
+#define PHY_LPDDR4_RON_101ohm (5)
+#define PHY_LPDDR4_RON_84ohm (6)
+#define PHY_LPDDR4_RON_72ohm (7)
+#define PHY_LPDDR4_RON_63ohm (16)
+#define PHY_LPDDR4_RON_56ohm (17)
+#define PHY_LPDDR4_RON_50ohm (18)
+#define PHY_LPDDR4_RON_46ohm (19)
+#define PHY_LPDDR4_RON_42ohm (20)
+#define PHY_LPDDR4_RON_38ohm (21)
+#define PHY_LPDDR4_RON_36ohm (22)
+#define PHY_LPDDR4_RON_33ohm (23)
+#define PHY_LPDDR4_RON_31ohm (24)
+#define PHY_LPDDR4_RON_29ohm (25)
+#define PHY_LPDDR4_RON_28ohm (26)
+#define PHY_LPDDR4_RON_26ohm (27)
+#define PHY_LPDDR4_RON_25ohm (28)
+#define PHY_LPDDR4_RON_24ohm (29)
+#define PHY_LPDDR4_RON_23ohm (30)
+#define PHY_LPDDR4_RON_22ohm (31)
+
+#define PHY_LPDDR4_RTT_DISABLE (0)
+#define PHY_LPDDR4_RTT_604ohm (1)
+#define PHY_LPDDR4_RTT_303ohm (2)
+#define PHY_LPDDR4_RTT_202ohm (3)
+#define PHY_LPDDR4_RTT_152ohm (4)
+#define PHY_LPDDR4_RTT_122ohm (5)
+#define PHY_LPDDR4_RTT_101ohm (6)
+#define PHY_LPDDR4_RTT_87ohm (7)
+#define PHY_LPDDR4_RTT_78ohm (16)
+#define PHY_LPDDR4_RTT_69ohm (17)
+#define PHY_LPDDR4_RTT_62ohm (18)
+#define PHY_LPDDR4_RTT_56ohm (19)
+#define PHY_LPDDR4_RTT_52ohm (20)
+#define PHY_LPDDR4_RTT_48ohm (21)
+#define PHY_LPDDR4_RTT_44ohm (22)
+#define PHY_LPDDR4_RTT_41ohm (23)
+#define PHY_LPDDR4_RTT_39ohm (24)
+#define PHY_LPDDR4_RTT_37ohm (25)
+#define PHY_LPDDR4_RTT_35ohm (26)
+#define PHY_LPDDR4_RTT_33ohm (27)
+#define PHY_LPDDR4_RTT_32ohm (28)
+#define PHY_LPDDR4_RTT_30ohm (29)
+#define PHY_LPDDR4_RTT_29ohm (30)
+#define PHY_LPDDR4_RTT_27ohm (31)
+
+#define ADD_CMD_CA (0x150)
+#define ADD_GROUP_CS0_A (0x170)
+#define ADD_GROUP_CS0_B (0x1d0)
+#define ADD_GROUP_CS1_A (0x1a0)
+#define ADD_GROUP_CS1_B (0x200)
+
+/* PMUGRF */
+#define PMUGRF_OS_REG0 (0x200)
+#define PMUGRF_OS_REG(n) (PMUGRF_OS_REG0 + (n) * 4)
+#define PMUGRF_CON_DDRPHY_BUFFEREN_MASK (0x3 << (12 + 16))
+#define PMUGRF_CON_DDRPHY_BUFFEREN_EN (0x1 << 12)
+#define PMUGRF_CON_DDRPHY_BUFFEREN_DIS (0x2 << 12)
+
+/* DDR GRF */
+#define DDR_GRF_CON(n) (0 + (n) * 4)
+#define DDR_GRF_STATUS_BASE (0X100)
+#define DDR_GRF_STATUS(n) (DDR_GRF_STATUS_BASE + (n) * 4)
+#define DDR_GRF_LP_CON (0x20)
+
+#define SPLIT_MODE_32_L16_VALID (0)
+#define SPLIT_MODE_32_H16_VALID (1)
+#define SPLIT_MODE_16_L8_VALID (2)
+#define SPLIT_MODE_16_H8_VALID (3)
+
+#define DDR_GRF_SPLIT_CON (0x10)
+#define SPLIT_MODE_MASK (0x3)
+#define SPLIT_MODE_OFFSET (9)
+#define SPLIT_BYPASS_MASK (1)
+#define SPLIT_BYPASS_OFFSET (8)
+#define SPLIT_SIZE_MASK (0xff)
+#define SPLIT_SIZE_OFFSET (0)
+
+/* SGRF SOC_CON13 */
+#define UPCTL2_ASRSTN_REQ(n) (((0x1 << 0) << 16) | ((n) << 0))
+#define UPCTL2_PSRSTN_REQ(n) (((0x1 << 1) << 16) | ((n) << 1))
+#define UPCTL2_SRSTN_REQ(n) (((0x1 << 2) << 16) | ((n) << 2))
+
+/* CRU define */
+/* CRU_PLL_CON0 */
+#define PB(n) ((0x1 << (15 + 16)) | ((n) << 15))
+#define POSTDIV1(n) ((0x7 << (12 + 16)) | ((n) << 12))
+#define FBDIV(n) ((0xFFF << 16) | (n))
+
+/* CRU_PLL_CON1 */
+#define RSTMODE(n) ((0x1 << (15 + 16)) | ((n) << 15))
+#define RST(n) ((0x1 << (14 + 16)) | ((n) << 14))
+#define PD(n) ((0x1 << (13 + 16)) | ((n) << 13))
+#define DSMPD(n) ((0x1 << (12 + 16)) | ((n) << 12))
+#define LOCK(n) (((n) >> 10) & 0x1)
+#define POSTDIV2(n) ((0x7 << (6 + 16)) | ((n) << 6))
+#define REFDIV(n) ((0x3F << 16) | (n))
+
+/* CRU_PLL_CON3 */
+#define SSMOD_SPREAD(n) ((0x1f << (8 + 16)) | ((n) << 8))
+#define SSMOD_DIVVAL(n) ((0xf << (4 + 16)) | ((n) << 4))
+#define SSMOD_DOWNSPREAD(n) ((0x1 << (3 + 16)) | ((n) << 3))
+#define SSMOD_RESET(n) ((0x1 << (2 + 16)) | ((n) << 2))
+#define SSMOD_DIS_SSCG(n) ((0x1 << (1 + 16)) | ((n) << 1))
+#define SSMOD_BP(n) ((0x1 << (0 + 16)) | ((n) << 0))
+
+/* CRU_MODE */
+#define CLOCK_FROM_XIN_OSC (0)
+#define CLOCK_FROM_PLL (1)
+#define CLOCK_FROM_RTC_32K (2)
+#define DPLL_MODE(n) ((0x3 << (2 + 16)) | ((n) << 2))
+
+/* CRU_SOFTRESET_CON1 */
+#define DDRPHY_PSRSTN_REQ(n) (((0x1 << 14) << 16) | ((n) << 14))
+#define DDRPHY_SRSTN_REQ(n) (((0x1 << 15) << 16) | ((n) << 15))
+/* CRU_CLKGATE_CON2 */
+#define DDR_MSCH_EN_MASK ((0x1 << 10) << 16)
+#define DDR_MSCH_EN_SHIFT (10)
+
+/* CRU register */
+#define CRU_PLL_CON(pll_id, n) ((pll_id) * 0x20 + (n) * 4)
+#define CRU_MODE (0xa0)
+#define CRU_GLB_CNT_TH (0xb0)
+#define CRU_CLKSEL_CON_BASE 0x100
+#define CRU_CLKSELS_CON(i) (CRU_CLKSEL_CON_BASE + ((i) * 4))
+#define CRU_CLKGATE_CON_BASE 0x230
+#define CRU_CLKGATE_CON(i) (CRU_CLKGATE_CON_BASE + ((i) * 4))
+#define CRU_CLKSFTRST_CON_BASE 0x300
+#define CRU_CLKSFTRST_CON(i) (CRU_CLKSFTRST_CON_BASE + ((i) * 4))
+
+/* SGRF_SOC_CON2 */
+#define MSCH_AXI_BYPASS_ALL_MASK (1)
+#define MSCH_AXI_BYPASS_ALL_SHIFT (15)
+
+/* SGRF_SOC_CON12 */
+#define CLK_DDR_UPCTL_EN_MASK ((0x1 << 2) << 16)
+#define CLK_DDR_UPCTL_EN_SHIFT (2)
+#define ACLK_DDR_UPCTL_EN_MASK ((0x1 << 0) << 16)
+#define ACLK_DDR_UPCTL_EN_SHIFT (0)
+
+/* DDRGRF DDR CON2 */
+#define DFI_FREQ_CHANGE_ACK BIT(10)
+/* DDRGRF status8 */
+#define DFI_FREQ_CHANGE_REQ BIT(19)
+
+struct rv1126_ddrgrf {
+ u32 ddr_grf_con[4];
+ u32 grf_ddrsplit_con;
+ u32 reserved1[(0x20 - 0x10) / 4 - 1];
+ u32 ddr_grf_lp_con;
+ u32 reserved2[(0x40 - 0x20) / 4 - 1];
+ u32 grf_ddrphy_con[6];
+ u32 reserved3[(0x100 - 0x54) / 4 - 1];
+ u32 ddr_grf_status[18];
+ u32 reserved4[(0x150 - 0x144) / 4 - 1];
+ u32 grf_ddrhold_status;
+ u32 reserved5[(0x160 - 0x150) / 4 - 1];
+ u32 grf_ddrphy_status[2];
+};
+
+struct rv1126_ddr_phy_regs {
+ u32 phy[8][2];
+};
+
+struct msch_regs {
+ u32 coreid;
+ u32 revisionid;
+ u32 deviceconf;
+ u32 devicesize;
+ u32 ddrtiminga0;
+ u32 ddrtimingb0;
+ u32 ddrtimingc0;
+ u32 devtodev0;
+ u32 reserved1[(0x110 - 0x20) / 4];
+ u32 ddrmode;
+ u32 ddr4timing;
+ u32 reserved2[(0x1000 - 0x118) / 4];
+ u32 agingx0;
+ u32 reserved3[(0x1040 - 0x1004) / 4];
+ u32 aging0;
+ u32 aging1;
+ u32 aging2;
+ u32 aging3;
+};
+
+struct sdram_msch_timings {
+ union noc_ddrtiminga0 ddrtiminga0;
+ union noc_ddrtimingb0 ddrtimingb0;
+ union noc_ddrtimingc0 ddrtimingc0;
+ union noc_devtodev_rv1126 devtodev0;
+ union noc_ddrmode ddrmode;
+ union noc_ddr4timing ddr4timing;
+ u32 agingx0;
+ u32 aging0;
+ u32 aging1;
+ u32 aging2;
+ u32 aging3;
+};
+
+struct rv1126_sdram_channel {
+ struct sdram_cap_info cap_info;
+ struct sdram_msch_timings noc_timings;
+};
+
+struct rv1126_sdram_params {
+ struct rv1126_sdram_channel ch;
+ struct sdram_base_params base;
+ struct ddr_pctl_regs pctl_regs;
+ struct rv1126_ddr_phy_regs phy_regs;
+};
+
+struct rv1126_fsp_param {
+ u32 flag;
+ u32 freq_mhz;
+
+ /* dram size */
+ u32 dq_odt;
+ u32 ca_odt;
+ u32 ds_pdds;
+ u32 vref_ca[2];
+ u32 vref_dq[2];
+
+ /* phy side */
+ u32 wr_dq_drv;
+ u32 wr_ca_drv;
+ u32 wr_ckcs_drv;
+ u32 rd_odt;
+ u32 rd_odt_up_en;
+ u32 rd_odt_down_en;
+ u32 vref_inner;
+ u32 vref_out;
+ u32 lp4_drv_pd_en;
+
+ struct sdram_msch_timings noc_timings;
+};
+
+#define MAX_IDX (4)
+#define FSP_FLAG (0xfead0001)
+#define SHARE_MEM_BASE (0x100000)
+/*
+ * Borrow share memory space to temporarily store FSP parame.
+ * In the stage of DDR init write FSP parame to this space.
+ * In the stage of trust init move FSP parame to SRAM space
+ * from share memory space.
+ */
+#define FSP_PARAM_STORE_ADDR (SHARE_MEM_BASE)
+
+/* store result of read and write training, for ddr_dq_eye tool in u-boot */
+#define RW_TRN_RESULT_ADDR (0x2000000 + 0x8000) /* 32M + 32k */
+#define PRINT_STEP 1
+
+#undef FSP_NUM
+#undef CS_NUM
+#undef BYTE_NUM
+
+#define FSP_NUM 4
+#define CS_NUM 2
+#define BYTE_NUM 4
+#define RD_DESKEW_NUM 64
+#define WR_DESKEW_NUM 64
+
+#define LP4_WIDTH_REF_MHZ_H 1056
+#define LP4_RD_WIDTH_REF_H 12
+#define LP4_WR_WIDTH_REF_H 13
+
+#define LP4_WIDTH_REF_MHZ_L 924
+#define LP4_RD_WIDTH_REF_L 15
+#define LP4_WR_WIDTH_REF_L 15
+
+#define DDR4_WIDTH_REF_MHZ_H 1056
+#define DDR4_RD_WIDTH_REF_H 13
+#define DDR4_WR_WIDTH_REF_H 9
+
+#define DDR4_WIDTH_REF_MHZ_L 924
+#define DDR4_RD_WIDTH_REF_L 15
+#define DDR4_WR_WIDTH_REF_L 11
+
+#define LP3_WIDTH_REF_MHZ_H 1056
+#define LP3_RD_WIDTH_REF_H 15
+#define LP3_WR_WIDTH_REF_H 13
+
+#define LP3_WIDTH_REF_MHZ_L 924
+#define LP3_RD_WIDTH_REF_L 16
+#define LP3_WR_WIDTH_REF_L 15
+
+#define DDR3_WIDTH_REF_MHZ_H 1056
+#define DDR3_RD_WIDTH_REF_H 14
+#define DDR3_WR_WIDTH_REF_H 14
+
+#define DDR3_WIDTH_REF_MHZ_L 924
+#define DDR3_RD_WIDTH_REF_L 17
+#define DDR3_WR_WIDTH_REF_L 17
+
+#endif /* _ASM_ARCH_SDRAM_RK1126_H */
diff --git a/arch/arm/include/asm/arch-rv1126/boot0.h b/arch/arm/include/asm/arch-rv1126/boot0.h
new file mode 100644
index 0000000..2e78b07
--- /dev/null
+++ b/arch/arm/include/asm/arch-rv1126/boot0.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_BOOT0_H__
+#define __ASM_ARCH_BOOT0_H__
+
+#include <asm/arch-rockchip/boot0.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-rv1126/gpio.h b/arch/arm/include/asm/arch-rv1126/gpio.h
new file mode 100644
index 0000000..eca79d5
--- /dev/null
+++ b/arch/arm/include/asm/arch-rv1126/gpio.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ */
+
+#ifndef __ASM_ARCH_GPIO_H__
+#define __ASM_ARCH_GPIO_H__
+
+#include <asm/arch-rockchip/gpio.h>
+
+#endif
diff --git a/arch/arm/include/asm/arch-sunxi/i2c.h b/arch/arm/include/asm/arch-sunxi/i2c.h
index e3dcfdf..f0da46d 100644
--- a/arch/arm/include/asm/arch-sunxi/i2c.h
+++ b/arch/arm/include/asm/arch-sunxi/i2c.h
@@ -14,7 +14,7 @@
#define CFG_I2C_MVTWSI_BASE1 SUNXI_TWI1_BASE
#endif
#ifdef CONFIG_R_I2C_ENABLE
-#define CONFIG_I2C_MVTWSI_BASE2 SUNXI_R_TWI_BASE
+#define CFG_I2C_MVTWSI_BASE2 SUNXI_R_TWI_BASE
#endif
/* This is abp0-clk on sun4i/5i/7i / abp1-clk on sun6i/sun8i which is 24MHz */
diff --git a/arch/arm/lib/elf_aarch64_efi.lds b/arch/arm/lib/elf_aarch64_efi.lds
index 3e3da47..5dd9809 100644
--- a/arch/arm/lib/elf_aarch64_efi.lds
+++ b/arch/arm/lib/elf_aarch64_efi.lds
@@ -28,6 +28,10 @@
*(.dynamic);
. = ALIGN(512);
}
+ .rela.dyn : { *(.rela.dyn) }
+ .rela.plt : { *(.rela.plt) }
+ .rela.got : { *(.rela.got) }
+ .rela.data : { *(.rela.data) *(.rela.data*) }
_etext = .;
_text_size = . - _text;
. = ALIGN(4096);
@@ -57,10 +61,6 @@
_edata = .;
} :data
_data_size = _edata - _data;
- .rela.dyn : { *(.rela.dyn) }
- .rela.plt : { *(.rela.plt) }
- .rela.got : { *(.rela.got) }
- .rela.data : { *(.rela.data) *(.rela.data*) }
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index 7ff4446..de15d09 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -15,12 +15,11 @@
/*
* U-Boot compatibility bit, define empty UNWIND() macro as, since we
- * do not support stack unwinding and define CONFIG_AEABI to make all
- * of the functions available without diverging from Linux code.
+ * do not support stack unwinding to make all of the functions available
+ * without diverging from Linux code.
*/
#ifdef __UBOOT__
#define UNWIND(x...)
-#define CONFIG_AEABI
#endif
.macro ARM_DIV_BODY dividend, divisor, result, curbit
@@ -314,8 +313,6 @@
ENDPROC(__modsi3)
.popsection
-#ifdef CONFIG_AEABI
-
.pushsection .text.__aeabi_uidivmod, "ax"
ENTRY(__aeabi_uidivmod)
UNWIND(.fnstart)
@@ -348,8 +345,6 @@
ENDPROC(__aeabi_idivmod)
.popsection
-#endif
-
.pushsection .text.Ldiv0, "ax"
Ldiv0:
UNWIND(.fnstart)
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
index 3090393..24f3b4e 100644
--- a/arch/arm/mach-at91/include/mach/at91rm9200.h
+++ b/arch/arm/mach-at91/include/mach/at91rm9200.h
@@ -126,6 +126,4 @@
#define ATMEL_PIO_PORTS 4 /* theese SoCs have 4 PIO */
#define ATMEL_PMC_UHP AT91RM9200_PMC_UHP
-#define CONFIG_SYS_ATMEL_CPU_NAME "AT91RM9200"
-
#endif
diff --git a/arch/arm/mach-exynos/include/mach/cpu.h b/arch/arm/mach-exynos/include/mach/cpu.h
index fb5fdaf..dab148e 100644
--- a/arch/arm/mach-exynos/include/mach/cpu.h
+++ b/arch/arm/mach-exynos/include/mach/cpu.h
@@ -248,7 +248,7 @@
}
#define IS_SAMSUNG_TYPE(type, id) \
-static inline int __attribute__((no_instrument_function)) cpu_is_##type(void) \
+static inline int notrace cpu_is_##type(void) \
{ \
return (s5p_cpu_id >> 12) == id; \
}
@@ -257,7 +257,7 @@
IS_SAMSUNG_TYPE(exynos5, 0x5)
#define IS_EXYNOS_TYPE(type, id) \
-static inline int __attribute__((no_instrument_function)) \
+static inline int notrace \
proid_is_##type(void) \
{ \
return s5p_cpu_id == id; \
@@ -272,7 +272,7 @@
#define proid_is_exynos542x() (proid_is_exynos5420() || proid_is_exynos5422())
#define SAMSUNG_BASE(device, base) \
-static inline unsigned long __attribute__((no_instrument_function)) \
+static inline unsigned long notrace \
samsung_get_base_##device(void) \
{ \
if (cpu_is_exynos4()) { \
diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c
index 08f47cf..c2875e7 100644
--- a/arch/arm/mach-imx/mx6/soc.c
+++ b/arch/arm/mach-imx/mx6/soc.c
@@ -746,6 +746,16 @@
if (ret)
printf("Failed to initialize caam_jr: %d\n", ret);
}
+
+ if (IS_ENABLED(CONFIG_FSL_DCP_RNG)) {
+ struct udevice *dev;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_RNG, DM_DRIVER_GET(dcp_rng), &dev);
+ if (ret)
+ printf("Failed to initialize dcp rng: %d\n", ret);
+ }
+
setup_serial_number();
return 0;
}
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig
index 87da6b4..a8c3a59 100644
--- a/arch/arm/mach-k3/Kconfig
+++ b/arch/arm/mach-k3/Kconfig
@@ -69,7 +69,9 @@
default 0x41cffbfc if SOC_K3_J721E
default 0x41cfdbfc if SOC_K3_J721S2
default 0x701bebfc if SOC_K3_AM642
- default 0x43c3f290 if SOC_K3_AM625 || SOC_K3_AM62A7
+ default 0x43c3f290 if SOC_K3_AM625
+ default 0x43c3f290 if SOC_K3_AM62A7 && CPU_V7R
+ default 0x7000f290 if SOC_K3_AM62A7 && ARM64
help
Address at which ROM stores the value which determines if SPL
is booted up by primary boot media or secondary boot media.
diff --git a/arch/arm/mach-k3/am625_init.c b/arch/arm/mach-k3/am625_init.c
index da2229d..a91c15c 100644
--- a/arch/arm/mach-k3/am625_init.c
+++ b/arch/arm/mach-k3/am625_init.c
@@ -173,21 +173,20 @@
u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
{
u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT);
+ u32 bootmode = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_MASK) >>
+ MAIN_DEVSTAT_PRIMARY_BOOTMODE_SHIFT;
u32 bootmode_cfg = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_MASK) >>
MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_SHIFT;
- switch (boot_device) {
- case BOOT_DEVICE_MMC1:
- if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_MMC_FS_RAW_MASK) >>
- MAIN_DEVSTAT_PRIMARY_MMC_FS_RAW_SHIFT)
- return MMCSD_MODE_EMMCBOOT;
- return MMCSD_MODE_FS;
- case BOOT_DEVICE_MMC2:
- return MMCSD_MODE_FS;
-
+ switch (bootmode) {
+ case BOOT_DEVICE_EMMC:
+ return MMCSD_MODE_EMMCBOOT;
+ case BOOT_DEVICE_MMC:
+ if (bootmode_cfg & MAIN_DEVSTAT_PRIMARY_MMC_FS_RAW_MASK)
+ return MMCSD_MODE_RAW;
default:
- return MMCSD_MODE_RAW;
+ return MMCSD_MODE_FS;
}
}
diff --git a/arch/arm/mach-k3/am62a7_init.c b/arch/arm/mach-k3/am62a7_init.c
index e9569f0..02da24a 100644
--- a/arch/arm/mach-k3/am62a7_init.c
+++ b/arch/arm/mach-k3/am62a7_init.c
@@ -25,8 +25,11 @@
static void store_boot_info_from_rom(void)
{
bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
- memcpy(&bootdata, (uintptr_t *)ROM_ENTENDED_BOOT_DATA_INFO,
- sizeof(struct rom_extended_boot_data));
+
+ if (IS_ENABLED(CONFIG_CPU_V7R)) {
+ memcpy(&bootdata, (uintptr_t *)ROM_ENTENDED_BOOT_DATA_INFO,
+ sizeof(struct rom_extended_boot_data));
+ }
}
static void ctrl_mmr_unlock(void)
@@ -123,6 +126,15 @@
k3_sysfw_loader(true, NULL, NULL);
#endif
+#if defined(CONFIG_CPU_V7R)
+ /*
+ * Relocate boot information to OCRAM (after TIFS has opend this
+ * region for us) so the next bootloader stages can keep access to
+ * primary vs backup bootmodes.
+ */
+ writel(bootindex, K3_BOOT_PARAM_TABLE_INDEX_OCRAM);
+#endif
+
/*
* Force probe of clk_k3 driver here to ensure basic default clock
* configuration is always done.
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index d5e1f8e..a2adb79 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -181,7 +181,7 @@
if (!*loadaddr)
return 0;
- if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) {
+ if (!get_fs_loader(&fsdev)) {
size = request_firmware_into_buf(fsdev, name, (void *)*loadaddr,
0, 0);
}
diff --git a/arch/arm/mach-k3/include/mach/am62a_hardware.h b/arch/arm/mach-k3/include/mach/am62a_hardware.h
index 52b0d9b..13bf50f 100644
--- a/arch/arm/mach-k3/include/mach/am62a_hardware.h
+++ b/arch/arm/mach-k3/include/mach/am62a_hardware.h
@@ -68,7 +68,22 @@
#define ROM_ENTENDED_BOOT_DATA_INFO 0x43c3f1e0
-/* Use Last 2K as Scratch pad */
+#define K3_BOOT_PARAM_TABLE_INDEX_OCRAM 0x7000F290
+
+/*
+ * During the boot process ROM will kill anything that writes to OCSRAM.
+ * This means the wakeup SPL cannot use this region during boot. To
+ * complicate things, TIFS will set a firewall between HSM RAM and the
+ * main domain.
+ *
+ * So, during the wakeup SPL, we will need to store the EEPROM data
+ * somewhere in HSM RAM, and the main domain's SPL will need to store it
+ * somewhere in OCSRAM
+ */
+#ifdef CONFIG_CPU_V7R
+#define TI_SRAM_SCRATCH_BOARD_EEPROM_START 0x43c30000
+#else
#define TI_SRAM_SCRATCH_BOARD_EEPROM_START 0x70000001
+#endif /* CONFIG_CPU_V7R */
#endif /* __ASM_ARCH_AM62A_HARDWARE_H */
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index c8a193d..45cc932 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -12,6 +12,19 @@
config SHEEVA_88SV131
bool
+config KIRKWOOD_COMMON
+ bool
+ select DM_SERIAL
+
+config HAS_CUSTOM_SYS_INIT_SP_ADDR
+ bool "Use a custom location for the initial stack pointer address"
+ default y
+
+config CUSTOM_SYS_INIT_SP_ADDR
+ hex "Static location for the initial stack pointer"
+ depends on HAS_CUSTOM_SYS_INIT_SP_ADDR
+ default 0x5ff000
+
choice
prompt "Marvell Kirkwood board select"
optional
@@ -25,6 +38,7 @@
bool "DreamPlug Board"
select KW88F6281
select SHEEVA_88SV131
+ select KIRKWOOD_COMMON
config TARGET_DS109
bool "Synology DS109"
@@ -40,6 +54,7 @@
bool "SheevaPlug Board"
select FEROCEON_88FR131
select KW88F6281
+ select KIRKWOOD_COMMON
config TARGET_LSXL
bool "lsxl Board"
@@ -47,16 +62,19 @@
select KW88F6281
select BOARD_EARLY_INIT_R
select MISC_INIT_R
+ select KIRKWOOD_COMMON
config TARGET_POGO_E02
bool "pogo_e02 Board"
select FEROCEON_88FR131
select KW88F6281
+ select KIRKWOOD_COMMON
config TARGET_POGO_V4
bool "Pogoplug V4 Board"
select FEROCEON_88FR131
select KW88F6192
+ select KIRKWOOD_COMMON
config TARGET_DNS325
bool "dns325 Board"
@@ -67,6 +85,7 @@
bool "iconnect Board"
select FEROCEON_88FR131
select KW88F6281
+ select KIRKWOOD_COMMON
config TARGET_KM_KIRKWOOD
bool "KM Kirkwood Board"
@@ -92,11 +111,13 @@
bool "Dockstar Board"
select FEROCEON_88FR131
select KW88F6281
+ select KIRKWOOD_COMMON
config TARGET_GOFLEXHOME
bool "GoFlex Home Board"
select FEROCEON_88FR131
select KW88F6281
+ select KIRKWOOD_COMMON
config TARGET_NAS220
bool "BlackArmor NAS220"
@@ -107,6 +128,7 @@
bool "Zyxel NSA310S"
select FEROCEON_88FR131
select KW88F6192
+ select KIRKWOOD_COMMON
config TARGET_SBx81LIFKW
bool "Allied Telesis SBx81GS24/SBx81GT40/SBx81XS6/SBx81XS16"
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 1db71df..309b967 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -31,6 +31,7 @@
config OMAP44XX
bool "OMAP44XX SoC"
+ select DM_EVENT
select SPL_USE_TINY_PRINTF
select SPL_SYS_NO_VECTOR_TABLE if SPL
imply NAND_OMAP_ELM
@@ -55,6 +56,7 @@
bool "OMAP54XX SoC"
select ARM_CORTEX_A15_CVE_2017_5715
select ARM_ERRATA_798870
+ select DM_EVENT
select SYS_THUMB_BUILD
imply NAND_OMAP_ELM
imply NAND_OMAP_GPMC
@@ -111,6 +113,7 @@
config AM33XX
bool "AM33XX SoC"
select ARM_CORTEX_A8_CVE_2017_5715
+ select DM_EVENT
select SPECIFY_CONSOLE_INDEX
imply NAND_OMAP_ELM
imply NAND_OMAP_GPMC
diff --git a/arch/arm/mach-omap2/boot-common.c b/arch/arm/mach-omap2/boot-common.c
index d104f23..9a342a1 100644
--- a/arch/arm/mach-omap2/boot-common.c
+++ b/arch/arm/mach-omap2/boot-common.c
@@ -214,7 +214,7 @@
if (!*loadaddr)
return 0;
- if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) {
+ if (!get_fs_loader(&fsdev)) {
size = request_firmware_into_buf(fsdev, name_fw,
(void *)*loadaddr, 0, 0);
}
diff --git a/arch/arm/mach-omap2/fdt-common.c b/arch/arm/mach-omap2/fdt-common.c
index 5eb0447..e90d577 100644
--- a/arch/arm/mach-omap2/fdt-common.c
+++ b/arch/arm/mach-omap2/fdt-common.c
@@ -17,8 +17,8 @@
#ifndef TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ
#define TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ (0)
#endif
-#ifndef CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ
-#define CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ (0)
+#ifndef CFG_SECURE_RUNTIME_RESV_SRAM_SZ
+#define CFG_SECURE_RUNTIME_RESV_SRAM_SZ (0)
#endif
int ft_hs_disable_rng(void *fdt, struct bd_info *bd)
diff --git a/arch/arm/mach-omap2/omap3/Kconfig b/arch/arm/mach-omap2/omap3/Kconfig
index 3e97ec2..671e479 100644
--- a/arch/arm/mach-omap2/omap3/Kconfig
+++ b/arch/arm/mach-omap2/omap3/Kconfig
@@ -163,7 +163,7 @@
source "board/logicpd/am3517evm/Kconfig"
source "board/ti/beagle/Kconfig"
source "board/timll/devkit8000/Kconfig"
-source "board/ti/evm/Kconfig"
+source "board/ti/omap3evm/Kconfig"
source "board/isee/igep00x0/Kconfig"
source "board/logicpd/omap3som/Kconfig"
source "board/nokia/rx51/Kconfig"
diff --git a/arch/arm/mach-omap2/omap5/fdt.c b/arch/arm/mach-omap2/omap5/fdt.c
index c416242..a8c301c 100644
--- a/arch/arm/mach-omap2/omap5/fdt.c
+++ b/arch/arm/mach-omap2/omap5/fdt.c
@@ -19,8 +19,8 @@
#ifndef TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ
#define TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ (0)
#endif
-#ifndef CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ
-#define CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ (0)
+#ifndef CFG_SECURE_RUNTIME_RESV_SRAM_SZ
+#define CFG_SECURE_RUNTIME_RESV_SRAM_SZ (0)
#endif
static u32 hs_irq_skip[] = {
@@ -92,7 +92,7 @@
}
#if ((TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ != 0) || \
- (CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ != 0))
+ (CFG_SECURE_RUNTIME_RESV_SRAM_SZ != 0))
static int ft_hs_fixup_sram(void *fdt, struct bd_info *bd)
{
const char *path;
@@ -116,7 +116,7 @@
temp[0] = cpu_to_fdt32(0);
/* reservation size */
temp[1] = cpu_to_fdt32(max(TI_OMAP5_SECURE_BOOT_RESV_SRAM_SZ,
- CONFIG_SECURE_RUNTIME_RESV_SRAM_SZ));
+ CFG_SECURE_RUNTIME_RESV_SRAM_SZ));
fdt_delprop(fdt, offs, "reg");
ret = fdt_setprop(fdt, offs, "reg", temp, 2 * sizeof(u32));
if (ret < 0) {
diff --git a/arch/arm/mach-rmobile/include/mach/rcar-mstp.h b/arch/arm/mach-rmobile/include/mach/rcar-mstp.h
index f2f8ce9..d241652 100644
--- a/arch/arm/mach-rmobile/include/mach/rcar-mstp.h
+++ b/arch/arm/mach-rmobile/include/mach/rcar-mstp.h
@@ -22,78 +22,78 @@
#define mstp_setclrbits_le32(addr, set, clear) \
mstp_setclrbits(le32, addr, set, clear)
-#ifndef CONFIG_SMSTP0_ENA
-#define CONFIG_SMSTP0_ENA 0x00
+#ifndef CFG_SMSTP0_ENA
+#define CFG_SMSTP0_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP1_ENA
-#define CONFIG_SMSTP1_ENA 0x00
+#ifndef CFG_SMSTP1_ENA
+#define CFG_SMSTP1_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP2_ENA
-#define CONFIG_SMSTP2_ENA 0x00
+#ifndef CFG_SMSTP2_ENA
+#define CFG_SMSTP2_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP3_ENA
-#define CONFIG_SMSTP3_ENA 0x00
+#ifndef CFG_SMSTP3_ENA
+#define CFG_SMSTP3_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP4_ENA
-#define CONFIG_SMSTP4_ENA 0x00
+#ifndef CFG_SMSTP4_ENA
+#define CFG_SMSTP4_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP5_ENA
-#define CONFIG_SMSTP5_ENA 0x00
+#ifndef CFG_SMSTP5_ENA
+#define CFG_SMSTP5_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP6_ENA
-#define CONFIG_SMSTP6_ENA 0x00
+#ifndef CFG_SMSTP6_ENA
+#define CFG_SMSTP6_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP7_ENA
-#define CONFIG_SMSTP7_ENA 0x00
+#ifndef CFG_SMSTP7_ENA
+#define CFG_SMSTP7_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP8_ENA
-#define CONFIG_SMSTP8_ENA 0x00
+#ifndef CFG_SMSTP8_ENA
+#define CFG_SMSTP8_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP9_ENA
-#define CONFIG_SMSTP9_ENA 0x00
+#ifndef CFG_SMSTP9_ENA
+#define CFG_SMSTP9_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP10_ENA
-#define CONFIG_SMSTP10_ENA 0x00
+#ifndef CFG_SMSTP10_ENA
+#define CFG_SMSTP10_ENA 0x00
#endif
-#ifndef CONFIG_SMSTP11_ENA
-#define CONFIG_SMSTP11_ENA 0x00
+#ifndef CFG_SMSTP11_ENA
+#define CFG_SMSTP11_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP0_ENA
-#define CONFIG_RMSTP0_ENA 0x00
+#ifndef CFG_RMSTP0_ENA
+#define CFG_RMSTP0_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP1_ENA
-#define CONFIG_RMSTP1_ENA 0x00
+#ifndef CFG_RMSTP1_ENA
+#define CFG_RMSTP1_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP2_ENA
-#define CONFIG_RMSTP2_ENA 0x00
+#ifndef CFG_RMSTP2_ENA
+#define CFG_RMSTP2_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP3_ENA
-#define CONFIG_RMSTP3_ENA 0x00
+#ifndef CFG_RMSTP3_ENA
+#define CFG_RMSTP3_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP4_ENA
-#define CONFIG_RMSTP4_ENA 0x00
+#ifndef CFG_RMSTP4_ENA
+#define CFG_RMSTP4_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP5_ENA
-#define CONFIG_RMSTP5_ENA 0x00
+#ifndef CFG_RMSTP5_ENA
+#define CFG_RMSTP5_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP6_ENA
-#define CONFIG_RMSTP6_ENA 0x00
+#ifndef CFG_RMSTP6_ENA
+#define CFG_RMSTP6_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP7_ENA
-#define CONFIG_RMSTP7_ENA 0x00
+#ifndef CFG_RMSTP7_ENA
+#define CFG_RMSTP7_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP8_ENA
-#define CONFIG_RMSTP8_ENA 0x00
+#ifndef CFG_RMSTP8_ENA
+#define CFG_RMSTP8_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP9_ENA
-#define CONFIG_RMSTP9_ENA 0x00
+#ifndef CFG_RMSTP9_ENA
+#define CFG_RMSTP9_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP10_ENA
-#define CONFIG_RMSTP10_ENA 0x00
+#ifndef CFG_RMSTP10_ENA
+#define CFG_RMSTP10_ENA 0x00
#endif
-#ifndef CONFIG_RMSTP11_ENA
-#define CONFIG_RMSTP11_ENA 0x00
+#ifndef CFG_RMSTP11_ENA
+#define CFG_RMSTP11_ENA 0x00
#endif
struct mstp_ctl {
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 4898260..b678ec4 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -302,6 +302,51 @@
The Rockchip RV1108 is a ARM-based SoC with a single-core Cortex-A7
and a DSP.
+config ROCKCHIP_RV1126
+ bool "Support Rockchip RV1126"
+ select CPU_V7A
+ select SKIP_LOWLEVEL_INIT_ONLY
+ select TPL
+ select SUPPORT_TPL
+ select TPL_NEEDS_SEPARATE_STACK
+ select TPL_ROCKCHIP_BACK_TO_BROM
+ select SPL
+ select SUPPORT_SPL
+ select SPL_STACK_R
+ select CLK
+ select FIT
+ select PINCTRL
+ select RAM
+ select ROCKCHIP_SDRAM_COMMON
+ select REGMAP
+ select SYSCON
+ select DM_PMIC
+ select DM_REGULATOR_FIXED
+ select DM_RESET
+ select REGULATOR_RK8XX
+ select PMIC_RK8XX
+ select BOARD_LATE_INIT
+ imply ROCKCHIP_COMMON_BOARD
+ imply TPL_DM
+ imply TPL_LIBCOMMON_SUPPORT
+ imply TPL_LIBGENERIC_SUPPORT
+ imply TPL_OF_CONTROL
+ imply TPL_OF_PLATDATA
+ imply TPL_RAM
+ imply TPL_ROCKCHIP_COMMON_BOARD
+ imply TPL_SERIAL
+ imply SPL_CLK
+ imply SPL_DM
+ imply SPL_DRIVERS_MISC
+ imply SPL_LIBCOMMON_SUPPORT
+ imply SPL_LIBGENERIC_SUPPORT
+ imply SPL_OF_CONTROL
+ imply SPL_RAM
+ imply SPL_REGMAP
+ imply SPL_ROCKCHIP_COMMON_BOARD
+ imply SPL_SERIAL
+ imply SPL_SYSCON
+
config ROCKCHIP_USB_UART
bool "Route uart output to usb pins"
help
@@ -447,4 +492,5 @@
source "arch/arm/mach-rockchip/rk3399/Kconfig"
source "arch/arm/mach-rockchip/rk3568/Kconfig"
source "arch/arm/mach-rockchip/rv1108/Kconfig"
+source "arch/arm/mach-rockchip/rv1126/Kconfig"
endif
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
index 6c1c7b8..32138fa 100644
--- a/arch/arm/mach-rockchip/Makefile
+++ b/arch/arm/mach-rockchip/Makefile
@@ -45,6 +45,7 @@
obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399/
obj-$(CONFIG_ROCKCHIP_RK3568) += rk3568/
obj-$(CONFIG_ROCKCHIP_RV1108) += rv1108/
+obj-$(CONFIG_ROCKCHIP_RV1126) += rv1126/
# Clear out SPL objects, in case this is a TPL build
obj-spl-$(CONFIG_TPL_BUILD) =
diff --git a/arch/arm/mach-rockchip/make_fit_atf.py b/arch/arm/mach-rockchip/make_fit_atf.py
deleted file mode 100755
index 08cfe9f..0000000
--- a/arch/arm/mach-rockchip/make_fit_atf.py
+++ /dev/null
@@ -1,267 +0,0 @@
-#!/usr/bin/env python3
-"""
-# SPDX-License-Identifier: GPL-2.0+
-#
-# A script to generate FIT image source for rockchip boards
-# with ARM Trusted Firmware
-# and multiple device trees (given on the command line)
-#
-# usage: $0 <dt_name> [<dt_name> [<dt_name] ...]
-"""
-
-import os
-import sys
-import getopt
-import logging
-import struct
-
-DT_HEADER = """
-/*
- * This is a generated file.
- */
-/dts-v1/;
-
-/ {
- description = "FIT image for U-Boot with bl31 (TF-A)";
- #address-cells = <1>;
-
- images {
-"""
-
-DT_UBOOT = """
- uboot {
- description = "U-Boot (64-bit)";
- data = /incbin/("u-boot-nodtb.bin");
- type = "standalone";
- os = "U-Boot";
- arch = "arm64";
- compression = "none";
- load = <0x%08x>;
- };
-
-"""
-
-DT_IMAGES_NODE_END = """ };
-
-"""
-
-DT_END = "};"
-
-def append_bl31_node(file, atf_index, phy_addr, elf_entry):
- # Append BL31 DT node to input FIT dts file.
- data = 'bl31_0x%08x.bin' % phy_addr
- file.write('\t\tatf_%d {\n' % atf_index)
- file.write('\t\t\tdescription = \"ARM Trusted Firmware\";\n')
- file.write('\t\t\tdata = /incbin/("%s");\n' % data)
- file.write('\t\t\ttype = "firmware";\n')
- file.write('\t\t\tarch = "arm64";\n')
- file.write('\t\t\tos = "arm-trusted-firmware";\n')
- file.write('\t\t\tcompression = "none";\n')
- file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
- if atf_index == 1:
- file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
- file.write('\t\t};\n')
- file.write('\n')
-
-def append_tee_node(file, atf_index, phy_addr, elf_entry):
- # Append TEE DT node to input FIT dts file.
- data = 'tee_0x%08x.bin' % phy_addr
- file.write('\t\tatf_%d {\n' % atf_index)
- file.write('\t\t\tdescription = \"TEE\";\n')
- file.write('\t\t\tdata = /incbin/("%s");\n' % data)
- file.write('\t\t\ttype = "tee";\n')
- file.write('\t\t\tarch = "arm64";\n')
- file.write('\t\t\tos = "tee";\n')
- file.write('\t\t\tcompression = "none";\n')
- file.write('\t\t\tload = <0x%08x>;\n' % phy_addr)
- file.write('\t\t\tentry = <0x%08x>;\n' % elf_entry)
- file.write('\t\t};\n')
- file.write('\n')
-
-def append_fdt_node(file, dtbs):
- # Append FDT nodes.
- cnt = 1
- for dtb in dtbs:
- dtname = os.path.basename(dtb)
- file.write('\t\tfdt_%d {\n' % cnt)
- file.write('\t\t\tdescription = "%s";\n' % dtname)
- file.write('\t\t\tdata = /incbin/("%s");\n' % dtb)
- file.write('\t\t\ttype = "flat_dt";\n')
- file.write('\t\t\tcompression = "none";\n')
- file.write('\t\t};\n')
- file.write('\n')
- cnt = cnt + 1
-
-def append_conf_section(file, cnt, dtname, segments):
- file.write('\t\tconfig_%d {\n' % cnt)
- file.write('\t\t\tdescription = "%s";\n' % dtname)
- file.write('\t\t\tfirmware = "atf_1";\n')
- file.write('\t\t\tloadables = "uboot"')
- if segments > 1:
- file.write(',')
- for i in range(1, segments):
- file.write('"atf_%d"' % (i + 1))
- if i != (segments - 1):
- file.write(',')
- else:
- file.write(';\n')
- if segments <= 1:
- file.write(';\n')
- file.write('\t\t\tfdt = "fdt_%d";\n' % cnt)
- file.write('\t\t};\n')
- file.write('\n')
-
-def append_conf_node(file, dtbs, segments):
- # Append configeration nodes.
- cnt = 1
- file.write('\tconfigurations {\n')
- file.write('\t\tdefault = "config_1";\n')
- for dtb in dtbs:
- dtname = os.path.basename(dtb)
- append_conf_section(file, cnt, dtname, segments)
- cnt = cnt + 1
- file.write('\t};\n')
- file.write('\n')
-
-def generate_atf_fit_dts_uboot(fit_file, uboot_file_name):
- segments = unpack_elf(uboot_file_name)
- if len(segments) != 1:
- raise ValueError("Invalid u-boot ELF image '%s'" % uboot_file_name)
- index, entry, p_paddr, data = segments[0]
- fit_file.write(DT_UBOOT % p_paddr)
-
-def generate_atf_fit_dts_bl31(fit_file, bl31_file_name, tee_file_name, dtbs_file_name):
- segments = unpack_elf(bl31_file_name)
- for index, entry, paddr, data in segments:
- append_bl31_node(fit_file, index + 1, paddr, entry)
- num_segments = len(segments)
-
- if tee_file_name:
- tee_segments = unpack_tee_file(tee_file_name)
- for index, entry, paddr, data in tee_segments:
- append_tee_node(fit_file, num_segments + index + 1, paddr, entry)
- num_segments = num_segments + len(tee_segments)
-
- append_fdt_node(fit_file, dtbs_file_name)
- fit_file.write(DT_IMAGES_NODE_END)
- append_conf_node(fit_file, dtbs_file_name, num_segments)
-
-def generate_atf_fit_dts(fit_file_name, bl31_file_name, tee_file_name, uboot_file_name, dtbs_file_name):
- # Generate FIT script for ATF image.
- if fit_file_name != sys.stdout:
- fit_file = open(fit_file_name, "wb")
- else:
- fit_file = sys.stdout
-
- fit_file.write(DT_HEADER)
- generate_atf_fit_dts_uboot(fit_file, uboot_file_name)
- generate_atf_fit_dts_bl31(fit_file, bl31_file_name, tee_file_name, dtbs_file_name)
- fit_file.write(DT_END)
-
- if fit_file_name != sys.stdout:
- fit_file.close()
-
-def generate_atf_binary(bl31_file_name):
- for index, entry, paddr, data in unpack_elf(bl31_file_name):
- file_name = 'bl31_0x%08x.bin' % paddr
- with open(file_name, "wb") as atf:
- atf.write(data)
-
-def generate_tee_binary(tee_file_name):
- if tee_file_name:
- for index, entry, paddr, data in unpack_tee_file(tee_file_name):
- file_name = 'tee_0x%08x.bin' % paddr
- with open(file_name, "wb") as atf:
- atf.write(data)
-
-def unpack_elf(filename):
- with open(filename, 'rb') as file:
- elf = file.read()
- if elf[0:7] != b'\x7fELF\x02\x01\x01' or elf[18:20] != b'\xb7\x00':
- raise ValueError("Invalid arm64 ELF file '%s'" % filename)
-
- e_entry, e_phoff = struct.unpack_from('<2Q', elf, 0x18)
- e_phentsize, e_phnum = struct.unpack_from('<2H', elf, 0x36)
- segments = []
-
- for index in range(e_phnum):
- offset = e_phoff + e_phentsize * index
- p_type, p_flags, p_offset = struct.unpack_from('<LLQ', elf, offset)
- if p_type == 1: # PT_LOAD
- p_paddr, p_filesz = struct.unpack_from('<2Q', elf, offset + 0x18)
- if p_filesz > 0:
- p_data = elf[p_offset:p_offset + p_filesz]
- segments.append((index, e_entry, p_paddr, p_data))
- return segments
-
-def unpack_tee_file(filename):
- if filename.endswith('.elf'):
- return unpack_elf(filename)
- with open(filename, 'rb') as file:
- bin = file.read()
- segments = []
- if bin[0:5] == b'OPTE\x01':
- # OP-TEE v1 format (tee.bin)
- init_sz, start_hi, start_lo, _, paged_sz = struct.unpack_from('<5I',
- bin,
- 0x8)
- if paged_sz != 0:
- raise ValueError("OP-TEE paged mode not supported")
- e_entry = (start_hi << 32) + start_lo
- p_addr = e_entry
- p_data = bin[0x1c:]
- if len(p_data) != init_sz:
- raise ValueError("Invalid file '%s': size mismatch "
- "(expected %d, have %d)" % (filename, init_sz,
- len(p_data)))
- segments.append((0, e_entry, p_addr, p_data))
- else:
- raise ValueError("Unknown format for TEE file '%s'" % filename)
- return segments
-
-def main():
- uboot_elf = "./u-boot"
- fit_its = sys.stdout
- if "BL31" in os.environ:
- bl31_elf=os.getenv("BL31");
- elif os.path.isfile("./bl31.elf"):
- bl31_elf = "./bl31.elf"
- else:
- os.system("echo 'int main(){}' > bl31.c")
- os.system("${CROSS_COMPILE}gcc -c bl31.c -o bl31.elf")
- bl31_elf = "./bl31.elf"
- logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
- logging.warning(' BL31 file bl31.elf NOT found, resulting binary is non-functional')
- logging.warning(' Please read Building section in doc/README.rockchip')
-
- if "TEE" in os.environ:
- tee_file = os.getenv("TEE")
- elif os.path.isfile("./tee.bin"):
- tee_file = "./tee.bin"
- elif os.path.isfile("./tee.elf"):
- tee_file = "./tee.elf"
- else:
- tee_file = ""
-
- opts, args = getopt.getopt(sys.argv[1:], "o:u:b:t:h")
- for opt, val in opts:
- if opt == "-o":
- fit_its = val
- elif opt == "-u":
- uboot_elf = val
- elif opt == "-b":
- bl31_elf = val
- elif opt == "-t":
- tee_file = val
- elif opt == "-h":
- print(__doc__)
- sys.exit(2)
-
- dtbs = args
-
- generate_atf_fit_dts(fit_its, bl31_elf, tee_file, uboot_elf, dtbs)
- generate_atf_binary(bl31_elf)
- generate_tee_binary(tee_file)
-
-if __name__ == "__main__":
- main()
diff --git a/arch/arm/mach-rockchip/px30/Kconfig b/arch/arm/mach-rockchip/px30/Kconfig
index 28639c0..4189392 100644
--- a/arch/arm/mach-rockchip/px30/Kconfig
+++ b/arch/arm/mach-rockchip/px30/Kconfig
@@ -35,6 +35,30 @@
* PX30.Core needs to mount on top of C.TOUCH 2.0 carrier with pluged
10.1" OF for creating complete PX30.Core C.TOUCH 2.0 10.1" Open Frame.
+config TARGET_RINGNECK_PX30
+ bool "Theobroma Systems PX30-µQ7 (Ringneck)"
+ help
+ The PX30-uQ7 (Ringneck) SoM is a µQseven-compatible (40mmx70mm,
+ MXM-230 connector) system-on-module from Theobroma Systems[1],
+ featuring the Rockchip PX30.
+
+ It provides the following feature set:
+ * up to 4GB DDR4
+ * up to 128GB on-module eMMC (with 8-bit 1.8V interface)
+ * SD card (on a baseboard) via edge connector
+ * Fast Ethernet with on-module TI DP83825I PHY
+ * MIPI-DSI/LVDS
+ * MIPI-CSI
+ * USB
+ - 1x USB 2.0 dual-role
+ - 3x USB 2.0 host
+ * on-module companion controller (STM32 Cortex-M0 or ATtiny), implementing:
+ - low-power RTC functionality (ISL1208 emulation)
+ - fan controller (AMC6821 emulation)
+ - USB<->CAN bridge controller (STM32 only)
+ * on-module Espressif ESP32 for Bluetooth + 2.4GHz WiFi
+ * on-module NXP SE05x Secure Element
+
config ROCKCHIP_BOOT_MODE_REG
default 0xff010200
@@ -71,5 +95,6 @@
source "board/engicam/px30_core/Kconfig"
source "board/hardkernel/odroid_go2/Kconfig"
source "board/rockchip/evb_px30/Kconfig"
+source "board/theobroma-systems/ringneck_px30/Kconfig"
endif
diff --git a/arch/arm/mach-rockchip/px30/px30.c b/arch/arm/mach-rockchip/px30/px30.c
index 0641e6a..3bca25c 100644
--- a/arch/arm/mach-rockchip/px30/px30.c
+++ b/arch/arm/mach-rockchip/px30/px30.c
@@ -5,9 +5,12 @@
#include <common.h>
#include <clk.h>
#include <dm.h>
+#include <fdt_support.h>
#include <init.h>
+#include <spl.h>
#include <asm/armv8/mmu.h>
#include <asm/io.h>
+#include <asm/arch-rockchip/bootrom.h>
#include <asm/arch-rockchip/grf_px30.h>
#include <asm/arch-rockchip/hardware.h>
#include <asm/arch-rockchip/uart.h>
@@ -15,6 +18,11 @@
#include <asm/arch-rockchip/cru_px30.h>
#include <dt-bindings/clock/px30-cru.h>
+const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
+ [BROM_BOOTSOURCE_EMMC] = "/mmc@ff390000",
+ [BROM_BOOTSOURCE_SD] = "/mmc@ff370000",
+};
+
static struct mm_region px30_mem_map[] = {
{
.virt = 0x0UL,
@@ -234,6 +242,7 @@
int arch_cpu_init(void)
{
static struct px30_grf * const grf = (void *)GRF_BASE;
+ static struct px30_cru * const cru = (void *)CRU_BASE;
u32 __maybe_unused val;
#ifdef CONFIG_SPL_BUILD
@@ -285,6 +294,9 @@
/* Clear the force_jtag */
rk_clrreg(&grf->cpu_con[1], 1 << 7);
+ /* Make TSADC and WDT trigger a first global reset */
+ clrsetbits_le32(&cru->glb_rst_con, 0x3, 0x3);
+
return 0;
}
@@ -297,8 +309,18 @@
CONFIG_DEBUG_UART_BASE == 0xff030000)
static struct px30_pmugrf * const pmugrf = (void *)PMUGRF_BASE;
#endif
+#if !defined(CONFIG_DEBUG_UART_BASE) || \
+ (CONFIG_DEBUG_UART_BASE != 0xff158000 && \
+ CONFIG_DEBUG_UART_BASE != 0xff168000 && \
+ CONFIG_DEBUG_UART_BASE != 0xff178000 && \
+ CONFIG_DEBUG_UART_BASE != 0xff030000) || \
+ (defined(CONFIG_DEBUG_UART_BASE) && \
+ (CONFIG_DEBUG_UART_BASE == 0xff158000 || \
+ CONFIG_DEBUG_UART_BASE == 0xff168000 || \
+ CONFIG_DEBUG_UART_BASE == 0xff178000))
static struct px30_grf * const grf = (void *)GRF_BASE;
static struct px30_cru * const cru = (void *)CRU_BASE;
+#endif
#if defined(CONFIG_DEBUG_UART_BASE) && CONFIG_DEBUG_UART_BASE == 0xff030000
static struct px30_pmucru * const pmucru = (void *)PMUCRU_BASE;
#endif
@@ -421,3 +443,52 @@
#endif /* CONFIG_DEBUG_UART_BASE && CONFIG_DEBUG_UART_BASE == ... */
}
#endif /* CONFIG_DEBUG_UART_BOARD_INIT */
+
+#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD)
+const char *spl_decode_boot_device(u32 boot_device)
+{
+ int i;
+ static const struct {
+ u32 boot_device;
+ const char *ofpath;
+ } spl_boot_devices_tbl[] = {
+ { BOOT_DEVICE_MMC2, "/mmc@ff370000" },
+ { BOOT_DEVICE_MMC1, "/mmc@ff390000" },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(spl_boot_devices_tbl); ++i)
+ if (spl_boot_devices_tbl[i].boot_device == boot_device)
+ return spl_boot_devices_tbl[i].ofpath;
+
+ return NULL;
+}
+
+void spl_perform_fixups(struct spl_image_info *spl_image)
+{
+ void *blob = spl_image->fdt_addr;
+ const char *boot_ofpath;
+ int chosen;
+
+ /*
+ * Inject the ofpath of the device the full U-Boot (or Linux in
+ * Falcon-mode) was booted from into the FDT, if a FDT has been
+ * loaded at the same time.
+ */
+ if (!blob)
+ return;
+
+ boot_ofpath = spl_decode_boot_device(spl_image->boot_device);
+ if (!boot_ofpath) {
+ pr_err("%s: could not map boot_device to ofpath\n", __func__);
+ return;
+ }
+
+ chosen = fdt_find_or_add_subnode(blob, 0, "chosen");
+ if (chosen < 0) {
+ pr_err("%s: could not find/create '/chosen'\n", __func__);
+ return;
+ }
+ fdt_setprop_string(blob, chosen,
+ "u-boot,spl-boot-device", boot_ofpath);
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c b/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c
index 6ae254e..fcae65b 100644
--- a/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c
+++ b/arch/arm/mach-rockchip/rk3036/sdram_rk3036.c
@@ -198,7 +198,7 @@
/* PCTL_STAT */
INIT_MEM = 0,
CONFIG,
- CONFIG_REQ,
+ CFG_REQ,
ACCESS,
ACCESS_REQ,
LOW_POWER,
diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig
index b48feeb..d01063a 100644
--- a/arch/arm/mach-rockchip/rk3399/Kconfig
+++ b/arch/arm/mach-rockchip/rk3399/Kconfig
@@ -39,6 +39,13 @@
with 4Gb RAM, onboard eMMC, USB-C, a USB3 and USB2 port,
1920*1080 screen and all the usual laptop features.
+config TARGET_PINEPHONE_PRO_RK3399
+ bool "PinePhone Pro"
+ help
+ PinePhone Pro is a phone based on a variant of the Rockchip
+ rk3399 SoC with 4Gb RAM, onboard eMMC, USB-C, headphone jack,
+ 720x1440 screen and a Quectel 4G/LTE modem.
+
config TARGET_PUMA_RK3399
bool "Theobroma Systems RK3399-Q7 (Puma)"
help
@@ -165,6 +172,7 @@
source "board/firefly/roc-pc-rk3399/Kconfig"
source "board/google/gru/Kconfig"
source "board/pine64/pinebook-pro-rk3399/Kconfig"
+source "board/pine64/pinephone-pro-rk3399/Kconfig"
source "board/pine64/rockpro64_rk3399/Kconfig"
source "board/rockchip/evb_rk3399/Kconfig"
source "board/theobroma-systems/puma_rk3399/Kconfig"
diff --git a/arch/arm/mach-rockchip/rv1126/Kconfig b/arch/arm/mach-rockchip/rv1126/Kconfig
new file mode 100644
index 0000000..7382c55
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1126/Kconfig
@@ -0,0 +1,59 @@
+if ROCKCHIP_RV1126
+
+config TARGET_RV1126_NEU2
+ bool "Edgeble Neural Compute Module 2(Neu2) SoM"
+ help
+ Neu2:
+ Neural Compute Module 2(Neu2) is a 96boards SoM-CB compute module
+ based on Rockchip RV1126 from Edgeble AI.
+ Neu2 powered with Consumer grade (0 to +80 °C) RV1126 SoC.
+ Neu2k powered with Industrial grade (-40 °C to +85 °C) RV1126K SoC.
+
+ Neu2-IO:
+ Neural Compute Module 2(Neu2) IO board is an industrial form factor
+ IO board and Neu2 needs to mount on top of this IO board in order to
+ create complete Edgeble Neural Compute Module 2(Neu2) IO platform.
+
+config SOC_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select HAS_CUSTOM_SYS_INIT_SP_ADDR
+
+config ROCKCHIP_BOOT_MODE_REG
+ default 0xfe020200
+
+config ROCKCHIP_STIMER_BASE
+ default 0xff670020
+
+config SYS_SOC
+ default "rv1126"
+
+config CUSTOM_SYS_INIT_SP_ADDR
+ default 0x800000
+
+config SPL_STACK
+ default 0x600000
+
+config SPL_STACK_R_ADDR
+ default 0x800000
+
+config TPL_LDSCRIPT
+ default "arch/arm/mach-rockchip/u-boot-tpl.lds"
+
+config TPL_STACK
+ default 0xff718000
+
+config TPL_SYS_MALLOC_F_LEN
+ default 0x2000
+
+config TPL_TEXT_BASE
+ default 0xff701000
+
+config SYS_MALLOC_F_LEN
+ default 0x2000
+
+config TEXT_BASE
+ default 0x600000
+
+source board/edgeble/neural-compute-module-2/Kconfig
+
+endif
diff --git a/arch/arm/mach-rockchip/rv1126/Makefile b/arch/arm/mach-rockchip/rv1126/Makefile
new file mode 100644
index 0000000..b287563
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1126/Makefile
@@ -0,0 +1,13 @@
+#
+# (C) Copyright 2019 Rockchip Electronics Co., Ltd
+# Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += rv1126.o
+
+ifndef CONFIG_TPL_BUILD
+obj-y += clk_rv1126.o
+obj-y += syscon_rv1126.o
+endif
diff --git a/arch/arm/mach-rockchip/rv1126/clk_rv1126.c b/arch/arm/mach-rockchip/rv1126/clk_rv1126.c
new file mode 100644
index 0000000..bd89027
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1126/clk_rv1126.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rv1126.h>
+#include <linux/err.h>
+
+int rockchip_get_clk(struct udevice **devp)
+{
+ return uclass_get_device_by_driver(UCLASS_CLK,
+ DM_DRIVER_GET(rockchip_rv1126_cru), devp);
+}
+
+void *rockchip_get_cru(void)
+{
+ struct rv1126_clk_priv *priv;
+ struct udevice *dev;
+ int ret;
+
+ ret = rockchip_get_clk(&dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ priv = dev_get_priv(dev);
+
+ return priv->cru;
+}
diff --git a/arch/arm/mach-rockchip/rv1126/rv1126.c b/arch/arm/mach-rockchip/rv1126/rv1126.c
new file mode 100644
index 0000000..b9b8987
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1126/rv1126.c
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Rockchip Electronics Co., Ltd
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/bootrom.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/grf_rv1126.h>
+
+#define FIREWALL_APB_BASE 0xffa60000
+#define FW_DDR_CON_REG 0x80
+#define GRF_BASE 0xFE000000
+
+const char * const boot_devices[BROM_LAST_BOOTSOURCE + 1] = {
+ [BROM_BOOTSOURCE_EMMC] = "/mmc@ffc50000",
+ [BROM_BOOTSOURCE_SD] = "/mmc@ffc60000",
+};
+
+/* GRF_GPIO3A_IOMUX_L */
+enum {
+ GPIO3A3_SHIFT = 12,
+ GPIO3A3_MASK = GENMASK(14, 12),
+ GPIO3A3_GPIO = 0,
+ GPIO3A3_UART2_RX_M1,
+ GPIO3A3_A7_JTAG_TMS_M1,
+
+ GPIO3A2_SHIFT = 8,
+ GPIO3A2_MASK = GENMASK(10, 8),
+ GPIO3A2_GPIO = 0,
+ GPIO3A2_UART2_TX_M1,
+ GPIO3A2_A7_JTAG_TCK_M1,
+};
+
+/* GRF_IOFUNC_CON2 */
+enum {
+ UART2_IO_SEL_SHIFT = 8,
+ UART2_IO_SEL_MASK = GENMASK(8, 8),
+ UART2_IO_SEL_M0 = 0,
+ UART2_IO_SEL_M1,
+};
+
+void board_debug_uart_init(void)
+{
+ static struct rv1126_grf * const grf = (void *)GRF_BASE;
+
+ /* Enable early UART2 channel m1 on the rv1126 */
+ rk_clrsetreg(&grf->iofunc_con2, UART2_IO_SEL_MASK,
+ UART2_IO_SEL_M1 << UART2_IO_SEL_SHIFT);
+
+ /* Switch iomux */
+ rk_clrsetreg(&grf->gpio3a_iomux_l,
+ GPIO3A3_MASK | GPIO3A2_MASK,
+ GPIO3A3_UART2_RX_M1 << GPIO3A3_SHIFT |
+ GPIO3A2_UART2_TX_M1 << GPIO3A2_SHIFT);
+}
+
+#ifndef CONFIG_TPL_BUILD
+int arch_cpu_init(void)
+{
+ /**
+ * Set dram area unsecure in spl
+ *
+ * usb & mmc & sfc controllers can read data to dram
+ * since they are unsecure.
+ * (Note: only secure-world can access this register)
+ */
+ if (IS_ENABLED(CONFIG_SPL_BUILD))
+ writel(0, FIREWALL_APB_BASE + FW_DDR_CON_REG);
+
+ return 0;
+}
+#endif
diff --git a/arch/arm/mach-rockchip/rv1126/syscon_rv1126.c b/arch/arm/mach-rockchip/rv1126/syscon_rv1126.c
new file mode 100644
index 0000000..599ea66
--- /dev/null
+++ b/arch/arm/mach-rockchip/rv1126/syscon_rv1126.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+
+static const struct udevice_id rv1126_syscon_ids[] = {
+ { .compatible = "rockchip,rv1126-grf", .data = ROCKCHIP_SYSCON_GRF },
+ { .compatible = "rockchip,rv1126-pmugrf", .data = ROCKCHIP_SYSCON_PMUGRF },
+ { }
+};
+
+U_BOOT_DRIVER(syscon_rv1126) = {
+ .name = "rv1126_syscon",
+ .id = UCLASS_SYSCON,
+ .of_match = rv1126_syscon_ids,
+};
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+static int rv1126_syscon_bind_of_plat(struct udevice *dev)
+{
+ dev->driver_data = dev->driver->of_match->data;
+ debug("syscon: %s %d\n", dev->name, (uint)dev->driver_data);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(rockchip_rv1126_pmu) = {
+ .name = "rockchip_rv1126_pmu",
+ .id = UCLASS_SYSCON,
+ .of_match = rv1126_syscon_ids,
+ .bind = rv1126_syscon_bind_of_plat,
+};
+
+U_BOOT_DRIVER(rockchip_rv1126_pmugrf) = {
+ .name = "rockchip_rv1126_pmugrf",
+ .id = UCLASS_SYSCON,
+ .of_match = rv1126_syscon_ids + 1,
+ .bind = rv1126_syscon_bind_of_plat,
+};
+#endif
diff --git a/arch/arm/mach-rockchip/tpl.c b/arch/arm/mach-rockchip/tpl.c
index ed46a9a..fdd0c59 100644
--- a/arch/arm/mach-rockchip/tpl.c
+++ b/arch/arm/mach-rockchip/tpl.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
+#include <bootstage.h>
#include <debug_uart.h>
#include <dm.h>
#include <hang.h>
@@ -70,15 +71,15 @@
U_BOOT_TIME ")\n");
#endif
#endif
+ /* Init secure timer */
+ rockchip_stimer_init();
+
ret = spl_early_init();
if (ret) {
debug("spl_early_init() failed: %d\n", ret);
hang();
}
- /* Init secure timer */
- rockchip_stimer_init();
-
/* Init ARM arch timer */
if (IS_ENABLED(CONFIG_SYS_ARCH_TIMER))
timer_init();
@@ -93,6 +94,15 @@
int board_return_to_bootrom(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
+#ifdef CONFIG_BOOTSTAGE_STASH
+ int ret;
+
+ bootstage_mark_name(BOOTSTAGE_ID_END_TPL, "end tpl");
+ ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR,
+ CONFIG_BOOTSTAGE_STASH_SIZE);
+ if (ret)
+ debug("Failed to stash bootstage: err=%d\n", ret);
+#endif
back_to_bootrom(BROM_BOOT_NEXTSTAGE);
return 0;
diff --git a/arch/arm/mach-snapdragon/init_sdm845.c b/arch/arm/mach-snapdragon/init_sdm845.c
index 5f53c21..1f88502 100644
--- a/arch/arm/mach-snapdragon/init_sdm845.c
+++ b/arch/arm/mach-snapdragon/init_sdm845.c
@@ -78,5 +78,23 @@
env_set("key_power", "0");
}
+ /*
+ * search for kaslr address, set by primary bootloader by searching first
+ * 0x100 relocated bytes at u-boot's initial load address range
+ */
+ uintptr_t start = gd->ram_base;
+ uintptr_t end = start + 0x800000;
+ u8 *addr = (u8 *)start;
+ phys_addr_t *relocaddr = (phys_addr_t *)gd->relocaddr;
+ u32 block_size = 0x1000;
+
+ while (memcmp(addr, relocaddr, 0x100) && (uintptr_t)addr < end)
+ addr += block_size;
+
+ if ((uintptr_t)addr >= end)
+ printf("KASLR not found in range 0x%lx - 0x%lx", start, end);
+ else
+ env_set_addr("KASLR", addr);
+
return 0;
}
diff --git a/arch/arm/mach-socfpga/qts-filter-a10.sh b/arch/arm/mach-socfpga/qts-filter-a10.sh
index 57d77e8..ab16522 100755
--- a/arch/arm/mach-socfpga/qts-filter-a10.sh
+++ b/arch/arm/mach-socfpga/qts-filter-a10.sh
@@ -10,7 +10,7 @@
#filter out only what we need from a10 hps.xml
grep_a10_hps_config() {
- egrep "clk_hz|i_clk_mgr|i_io48_pin_mux|AXI_SLAVE|AXI_MASTER"
+ grep -E "clk_hz|i_clk_mgr|i_io48_pin_mux|AXI_SLAVE|AXI_MASTER"
}
#
@@ -35,35 +35,35 @@
echo "/* Clocks */"
fix_newlines_in_macros \
- ${hps_xml} | egrep "clk_hz" |
+ ${hps_xml} | grep "clk_hz" |
awk -F"'" '{ gsub("\\.","_",$2) ; \
print "#define" " " toupper($2) " " $4}' |
sed 's/\.[0-9]//' |
sed 's/I_CLK_MGR_//' |
sort
fix_newlines_in_macros \
- ${hps_xml} | egrep "i_clk_mgr_mainpll" |
+ ${hps_xml} | grep "i_clk_mgr_mainpll" |
awk -F"'" '{ gsub("\\.","_",$2) ; \
print "#define" " " toupper($2) " " $4}' |
sed 's/\.[0-9]//' |
sed 's/I_CLK_MGR_//' |
sort
fix_newlines_in_macros \
- ${hps_xml} | egrep "i_clk_mgr_perpll" |
+ ${hps_xml} | grep "i_clk_mgr_perpll" |
awk -F"'" '{ gsub("\\.","_",$2) ; \
print "#define" " " toupper($2) " " $4}' |
sed 's/\.[0-9]//' |
sed 's/I_CLK_MGR_//' |
sort
fix_newlines_in_macros \
- ${hps_xml} | egrep "i_clk_mgr_clkmgr" |
+ ${hps_xml} | grep "i_clk_mgr_clkmgr" |
awk -F"'" '{ gsub("\\.","_",$2) ; \
print "#define" " " toupper($2) " " $4}' |
sed 's/\.[0-9]//' |
sed 's/I_CLK_MGR_//' |
sort
fix_newlines_in_macros \
- ${hps_xml} | egrep "i_clk_mgr_alteragrp" |
+ ${hps_xml} | grep "i_clk_mgr_alteragrp" |
awk -F"'" '{ gsub("\\.","_",$2) ; \
print "#define" " " toupper($2) " " $4}' |
sed 's/\.[0-9]//' |
@@ -77,7 +77,7 @@
echo
echo "/* Pin Mux Configuration */"
fix_newlines_in_macros \
- ${hps_xml} | egrep "i_io48_pin_mux" |
+ ${hps_xml} | grep "i_io48_pin_mux" |
awk -F"'" '{ gsub("\\.","_",$2) ; \
print "#define" " " toupper($2) " " $4}' |
sed 's/I_IO48_PIN_MUX_//' |
@@ -90,7 +90,7 @@
echo
echo "/* Bridge Configuration */"
fix_newlines_in_macros \
- ${hps_xml} | egrep "AXI_SLAVE|AXI_MASTER" |
+ ${hps_xml} | grep -E "AXI_SLAVE|AXI_MASTER" |
awk -F"'" '{ gsub("\\.","_",$2) ; \
print "#define" " " toupper($2) " " $4}' |
sed 's/true/1/' |
diff --git a/arch/arm/mach-socfpga/qts-filter.sh b/arch/arm/mach-socfpga/qts-filter.sh
index 6416252..1610c89 100755
--- a/arch/arm/mach-socfpga/qts-filter.sh
+++ b/arch/arm/mach-socfpga/qts-filter.sh
@@ -128,7 +128,7 @@
# Filter out only the macros which are actually used by the code
#
grep_sdram_config() {
- egrep "#define (CFG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE|CFG_HPS_SDR_CTRLCFG_CTRLCFG_MEMBL|CFG_HPS_SDR_CTRLCFG_CTRLCFG_ADDRORDER|CFG_HPS_SDR_CTRLCFG_CTRLCFG_ECCEN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_ECCCORREN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_REORDEREN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_STARVELIMIT|CFG_HPS_SDR_CTRLCFG_CTRLCFG_DQSTRKEN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_NODMPINS|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCWL|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_AL|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCL|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRRD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TFAW|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRFC|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TREFI|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRCD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRP|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWR|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWTR|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRTP|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRAS|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRC|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TMRD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TCCD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING4_SELFRFSHEXIT|CFG_HPS_SDR_CTRLCFG_DRAMTIMING4_PWRDOWNEXIT|CFG_HPS_SDR_CTRLCFG_LOWPWRTIMING_AUTOPDCYCLES|CFG_HPS_SDR_CTRLCFG_LOWPWRTIMING_CLKDISABLECYCLES|CFG_HPS_SDR_CTRLCFG_DRAMODT_READ|CFG_HPS_SDR_CTRLCFG_DRAMODT_WRITE|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_BANKBITS|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS|CFG_HPS_SDR_CTRLCFG_DRAMIFWIDTH_IFWIDTH|CFG_HPS_SDR_CTRLCFG_DRAMDEVWIDTH_DEVWIDTH|CFG_HPS_SDR_CTRLCFG_DRAMINTR_INTREN|CFG_HPS_SDR_CTRLCFG_LOWPWREQ_SELFRFSHMASK|CFG_HPS_SDR_CTRLCFG_STATICCFG_MEMBL|CFG_HPS_SDR_CTRLCFG_STATICCFG_USEECCASDATA|CFG_HPS_SDR_CTRLCFG_CTRLWIDTH_CTRLWIDTH|CFG_HPS_SDR_CTRLCFG_CPORTWIDTH_CPORTWIDTH|CFG_HPS_SDR_CTRLCFG_CPORTWMAP_CPORTWMAP|CFG_HPS_SDR_CTRLCFG_CPORTRMAP_CPORTRMAP|CFG_HPS_SDR_CTRLCFG_RFIFOCMAP_RFIFOCMAP|CFG_HPS_SDR_CTRLCFG_WFIFOCMAP_WFIFOCMAP|CFG_HPS_SDR_CTRLCFG_CPORTRDWR_CPORTRDWR|CFG_HPS_SDR_CTRLCFG_PORTCFG_AUTOPCHEN|CFG_HPS_SDR_CTRLCFG_FPGAPORTRST|CFG_HPS_SDR_CTRLCFG_FIFOCFG_SYNCMODE|CFG_HPS_SDR_CTRLCFG_FIFOCFG_INCSYNC|CFG_HPS_SDR_CTRLCFG_MPPRIORITY_USERPRIORITY|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_0_STATICWEIGHT_31_0|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_STATICWEIGHT_49_32|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_SUMOFWEIGHT_13_0|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_2_SUMOFWEIGHT_45_14|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_3_SUMOFWEIGHT_63_46|CFG_HPS_SDR_CTRLCFG_PHYCTRL_PHYCTRL_0|CFG_HPS_SDR_CTRLCFG_MPPACING_0_THRESHOLD1_31_0|CFG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD1_59_32|CFG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD2_3_0|CFG_HPS_SDR_CTRLCFG_MPPACING_2_THRESHOLD2_35_4|CFG_HPS_SDR_CTRLCFG_MPPACING_3_THRESHOLD2_59_36|CFG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0|CFG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32|CFG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64|RW_MGR_ACTIVATE_0_AND_1|RW_MGR_ACTIVATE_0_AND_1_WAIT1|RW_MGR_ACTIVATE_0_AND_1_WAIT2|RW_MGR_ACTIVATE_1|RW_MGR_CLEAR_DQS_ENABLE|RW_MGR_EMR_OCD_ENABLE|RW_MGR_EMR|RW_MGR_EMR2|RW_MGR_EMR3|RW_MGR_GUARANTEED_READ|RW_MGR_GUARANTEED_READ_CONT|RW_MGR_GUARANTEED_WRITE|RW_MGR_GUARANTEED_WRITE_WAIT0|RW_MGR_GUARANTEED_WRITE_WAIT1|RW_MGR_GUARANTEED_WRITE_WAIT2|RW_MGR_GUARANTEED_WRITE_WAIT3|RW_MGR_IDLE|RW_MGR_IDLE_LOOP1|RW_MGR_IDLE_LOOP2|RW_MGR_INIT_RESET_0_CKE_0|RW_MGR_INIT_RESET_1_CKE_0|RW_MGR_INIT_CKE_0|RW_MGR_LFSR_WR_RD_BANK_0|RW_MGR_LFSR_WR_RD_BANK_0_DATA|RW_MGR_LFSR_WR_RD_BANK_0_DQS|RW_MGR_LFSR_WR_RD_BANK_0_NOP|RW_MGR_LFSR_WR_RD_BANK_0_WAIT|RW_MGR_LFSR_WR_RD_BANK_0_WL_1|RW_MGR_LFSR_WR_RD_DM_BANK_0|RW_MGR_LFSR_WR_RD_DM_BANK_0_DATA|RW_MGR_LFSR_WR_RD_DM_BANK_0_DQS|RW_MGR_LFSR_WR_RD_DM_BANK_0_NOP|RW_MGR_LFSR_WR_RD_DM_BANK_0_WAIT|RW_MGR_LFSR_WR_RD_DM_BANK_0_WL_1|RW_MGR_MR_CALIB|RW_MGR_MR_USER|RW_MGR_MR_DLL_RESET|RW_MGR_MRS0_DLL_RESET|RW_MGR_MRS0_DLL_RESET_MIRR|RW_MGR_MRS0_USER|RW_MGR_MRS0_USER_MIRR|RW_MGR_MRS1|RW_MGR_MRS1_MIRR|RW_MGR_MRS2|RW_MGR_MRS2_MIRR|RW_MGR_MRS3|RW_MGR_MRS3_MIRR|RW_MGR_NOP|RW_MGR_PRECHARGE_ALL|RW_MGR_READ_B2B|RW_MGR_READ_B2B_WAIT1|RW_MGR_READ_B2B_WAIT2|RW_MGR_REFRESH|RW_MGR_REFRESH_ALL|RW_MGR_RETURN|RW_MGR_SGLE_READ|RW_MGR_ZQCL|RW_MGR_TRUE_MEM_DATA_MASK_WIDTH|RW_MGR_MEM_ADDRESS_MIRRORING|RW_MGR_MEM_DATA_MASK_WIDTH|RW_MGR_MEM_DATA_WIDTH|RW_MGR_MEM_DQ_PER_READ_DQS|RW_MGR_MEM_DQ_PER_WRITE_DQS|RW_MGR_MEM_IF_READ_DQS_WIDTH|RW_MGR_MEM_IF_WRITE_DQS_WIDTH|RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM|RW_MGR_MEM_NUMBER_OF_RANKS|RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS|RW_MGR_MEM_VIRTUAL_GROUPS_PER_WRITE_DQS|IO_DELAY_PER_DCHAIN_TAP|IO_DELAY_PER_DQS_EN_DCHAIN_TAP|IO_DELAY_PER_OPA_TAP|IO_DLL_CHAIN_LENGTH|IO_DQDQS_OUT_PHASE_MAX|IO_DQS_EN_DELAY_MAX|IO_DQS_EN_DELAY_OFFSET|IO_DQS_EN_PHASE_MAX|IO_DQS_IN_DELAY_MAX|IO_DQS_IN_RESERVE|IO_DQS_OUT_RESERVE|IO_IO_IN_DELAY_MAX|IO_IO_OUT1_DELAY_MAX|IO_IO_OUT2_DELAY_MAX|IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS|AFI_RATE_RATIO|AFI_CLK_FREQ|CALIB_LFIFO_OFFSET|CALIB_VFIFO_OFFSET|ENABLE_SUPER_QUICK_CALIBRATION|MAX_LATENCY_COUNT_WIDTH|READ_VALID_FIFO_SIZE|REG_FILE_INIT_SEQ_SIGNATURE|TINIT_CNTR0_VAL|TINIT_CNTR1_VAL|TINIT_CNTR2_VAL|TRESET_CNTR0_VAL|TRESET_CNTR1_VAL|TRESET_CNTR2_VAL|CFG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR|CFG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_BC|CFG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP)[[:space:]]"
+ grep -E "#define (CFG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE|CFG_HPS_SDR_CTRLCFG_CTRLCFG_MEMBL|CFG_HPS_SDR_CTRLCFG_CTRLCFG_ADDRORDER|CFG_HPS_SDR_CTRLCFG_CTRLCFG_ECCEN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_ECCCORREN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_REORDEREN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_STARVELIMIT|CFG_HPS_SDR_CTRLCFG_CTRLCFG_DQSTRKEN|CFG_HPS_SDR_CTRLCFG_CTRLCFG_NODMPINS|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCWL|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_AL|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TCL|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRRD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TFAW|CFG_HPS_SDR_CTRLCFG_DRAMTIMING1_TRFC|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TREFI|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRCD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TRP|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWR|CFG_HPS_SDR_CTRLCFG_DRAMTIMING2_IF_TWTR|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRTP|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRAS|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TRC|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TMRD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING3_TCCD|CFG_HPS_SDR_CTRLCFG_DRAMTIMING4_SELFRFSHEXIT|CFG_HPS_SDR_CTRLCFG_DRAMTIMING4_PWRDOWNEXIT|CFG_HPS_SDR_CTRLCFG_LOWPWRTIMING_AUTOPDCYCLES|CFG_HPS_SDR_CTRLCFG_LOWPWRTIMING_CLKDISABLECYCLES|CFG_HPS_SDR_CTRLCFG_DRAMODT_READ|CFG_HPS_SDR_CTRLCFG_DRAMODT_WRITE|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_ROWBITS|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_BANKBITS|CFG_HPS_SDR_CTRLCFG_DRAMADDRW_CSBITS|CFG_HPS_SDR_CTRLCFG_DRAMIFWIDTH_IFWIDTH|CFG_HPS_SDR_CTRLCFG_DRAMDEVWIDTH_DEVWIDTH|CFG_HPS_SDR_CTRLCFG_DRAMINTR_INTREN|CFG_HPS_SDR_CTRLCFG_LOWPWREQ_SELFRFSHMASK|CFG_HPS_SDR_CTRLCFG_STATICCFG_MEMBL|CFG_HPS_SDR_CTRLCFG_STATICCFG_USEECCASDATA|CFG_HPS_SDR_CTRLCFG_CTRLWIDTH_CTRLWIDTH|CFG_HPS_SDR_CTRLCFG_CPORTWIDTH_CPORTWIDTH|CFG_HPS_SDR_CTRLCFG_CPORTWMAP_CPORTWMAP|CFG_HPS_SDR_CTRLCFG_CPORTRMAP_CPORTRMAP|CFG_HPS_SDR_CTRLCFG_RFIFOCMAP_RFIFOCMAP|CFG_HPS_SDR_CTRLCFG_WFIFOCMAP_WFIFOCMAP|CFG_HPS_SDR_CTRLCFG_CPORTRDWR_CPORTRDWR|CFG_HPS_SDR_CTRLCFG_PORTCFG_AUTOPCHEN|CFG_HPS_SDR_CTRLCFG_FPGAPORTRST|CFG_HPS_SDR_CTRLCFG_FIFOCFG_SYNCMODE|CFG_HPS_SDR_CTRLCFG_FIFOCFG_INCSYNC|CFG_HPS_SDR_CTRLCFG_MPPRIORITY_USERPRIORITY|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_0_STATICWEIGHT_31_0|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_STATICWEIGHT_49_32|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_1_SUMOFWEIGHT_13_0|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_2_SUMOFWEIGHT_45_14|CFG_HPS_SDR_CTRLCFG_MPWIEIGHT_3_SUMOFWEIGHT_63_46|CFG_HPS_SDR_CTRLCFG_PHYCTRL_PHYCTRL_0|CFG_HPS_SDR_CTRLCFG_MPPACING_0_THRESHOLD1_31_0|CFG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD1_59_32|CFG_HPS_SDR_CTRLCFG_MPPACING_1_THRESHOLD2_3_0|CFG_HPS_SDR_CTRLCFG_MPPACING_2_THRESHOLD2_35_4|CFG_HPS_SDR_CTRLCFG_MPPACING_3_THRESHOLD2_59_36|CFG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_0_THRESHOLDRSTCYCLES_31_0|CFG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_1_THRESHOLDRSTCYCLES_63_32|CFG_HPS_SDR_CTRLCFG_MPTHRESHOLDRST_2_THRESHOLDRSTCYCLES_79_64|RW_MGR_ACTIVATE_0_AND_1|RW_MGR_ACTIVATE_0_AND_1_WAIT1|RW_MGR_ACTIVATE_0_AND_1_WAIT2|RW_MGR_ACTIVATE_1|RW_MGR_CLEAR_DQS_ENABLE|RW_MGR_EMR_OCD_ENABLE|RW_MGR_EMR|RW_MGR_EMR2|RW_MGR_EMR3|RW_MGR_GUARANTEED_READ|RW_MGR_GUARANTEED_READ_CONT|RW_MGR_GUARANTEED_WRITE|RW_MGR_GUARANTEED_WRITE_WAIT0|RW_MGR_GUARANTEED_WRITE_WAIT1|RW_MGR_GUARANTEED_WRITE_WAIT2|RW_MGR_GUARANTEED_WRITE_WAIT3|RW_MGR_IDLE|RW_MGR_IDLE_LOOP1|RW_MGR_IDLE_LOOP2|RW_MGR_INIT_RESET_0_CKE_0|RW_MGR_INIT_RESET_1_CKE_0|RW_MGR_INIT_CKE_0|RW_MGR_LFSR_WR_RD_BANK_0|RW_MGR_LFSR_WR_RD_BANK_0_DATA|RW_MGR_LFSR_WR_RD_BANK_0_DQS|RW_MGR_LFSR_WR_RD_BANK_0_NOP|RW_MGR_LFSR_WR_RD_BANK_0_WAIT|RW_MGR_LFSR_WR_RD_BANK_0_WL_1|RW_MGR_LFSR_WR_RD_DM_BANK_0|RW_MGR_LFSR_WR_RD_DM_BANK_0_DATA|RW_MGR_LFSR_WR_RD_DM_BANK_0_DQS|RW_MGR_LFSR_WR_RD_DM_BANK_0_NOP|RW_MGR_LFSR_WR_RD_DM_BANK_0_WAIT|RW_MGR_LFSR_WR_RD_DM_BANK_0_WL_1|RW_MGR_MR_CALIB|RW_MGR_MR_USER|RW_MGR_MR_DLL_RESET|RW_MGR_MRS0_DLL_RESET|RW_MGR_MRS0_DLL_RESET_MIRR|RW_MGR_MRS0_USER|RW_MGR_MRS0_USER_MIRR|RW_MGR_MRS1|RW_MGR_MRS1_MIRR|RW_MGR_MRS2|RW_MGR_MRS2_MIRR|RW_MGR_MRS3|RW_MGR_MRS3_MIRR|RW_MGR_NOP|RW_MGR_PRECHARGE_ALL|RW_MGR_READ_B2B|RW_MGR_READ_B2B_WAIT1|RW_MGR_READ_B2B_WAIT2|RW_MGR_REFRESH|RW_MGR_REFRESH_ALL|RW_MGR_RETURN|RW_MGR_SGLE_READ|RW_MGR_ZQCL|RW_MGR_TRUE_MEM_DATA_MASK_WIDTH|RW_MGR_MEM_ADDRESS_MIRRORING|RW_MGR_MEM_DATA_MASK_WIDTH|RW_MGR_MEM_DATA_WIDTH|RW_MGR_MEM_DQ_PER_READ_DQS|RW_MGR_MEM_DQ_PER_WRITE_DQS|RW_MGR_MEM_IF_READ_DQS_WIDTH|RW_MGR_MEM_IF_WRITE_DQS_WIDTH|RW_MGR_MEM_NUMBER_OF_CS_PER_DIMM|RW_MGR_MEM_NUMBER_OF_RANKS|RW_MGR_MEM_VIRTUAL_GROUPS_PER_READ_DQS|RW_MGR_MEM_VIRTUAL_GROUPS_PER_WRITE_DQS|IO_DELAY_PER_DCHAIN_TAP|IO_DELAY_PER_DQS_EN_DCHAIN_TAP|IO_DELAY_PER_OPA_TAP|IO_DLL_CHAIN_LENGTH|IO_DQDQS_OUT_PHASE_MAX|IO_DQS_EN_DELAY_MAX|IO_DQS_EN_DELAY_OFFSET|IO_DQS_EN_PHASE_MAX|IO_DQS_IN_DELAY_MAX|IO_DQS_IN_RESERVE|IO_DQS_OUT_RESERVE|IO_IO_IN_DELAY_MAX|IO_IO_OUT1_DELAY_MAX|IO_IO_OUT2_DELAY_MAX|IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS|AFI_RATE_RATIO|AFI_CLK_FREQ|CALIB_LFIFO_OFFSET|CALIB_VFIFO_OFFSET|ENABLE_SUPER_QUICK_CALIBRATION|MAX_LATENCY_COUNT_WIDTH|READ_VALID_FIFO_SIZE|REG_FILE_INIT_SEQ_SIGNATURE|TINIT_CNTR0_VAL|TINIT_CNTR1_VAL|TINIT_CNTR2_VAL|TRESET_CNTR0_VAL|TRESET_CNTR1_VAL|TRESET_CNTR2_VAL|CFG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR|CFG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_BC|CFG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP)[[:space:]]"
}
#
diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile
index 1db9057..a19b279 100644
--- a/arch/arm/mach-stm32mp/Makefile
+++ b/arch/arm/mach-stm32mp/Makefile
@@ -11,10 +11,10 @@
obj-$(CONFIG_STM32MP13x) += stm32mp13x.o
obj-$(CONFIG_STM32MP15x) += stm32mp15x.o
+obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += tzc400.o
-obj-$(CONFIG_STM32_ECDSA_VERIFY) += ecdsa_romapi.o
else
obj-y += cmd_stm32prog/
obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o
diff --git a/arch/arm/mach-stm32mp/boot_params.c b/arch/arm/mach-stm32mp/boot_params.c
index e91ef1b..24d04dc 100644
--- a/arch/arm/mach-stm32mp/boot_params.c
+++ b/arch/arm/mach-stm32mp/boot_params.c
@@ -8,33 +8,18 @@
#include <common.h>
#include <log.h>
#include <linux/libfdt.h>
+#include <asm/arch/sys_proto.h>
#include <asm/sections.h>
#include <asm/system.h>
/*
- * Force data-section, as .bss will not be valid
- * when save_boot_params is invoked.
- */
-static unsigned long nt_fw_dtb __section(".data");
-
-/*
- * Save the FDT address provided by TF-A in r2 at boot time
- * This function is called from start.S
- */
-void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
- unsigned long r3)
-{
- nt_fw_dtb = r2;
-
- save_boot_params_ret();
-}
-
-/*
* Use the saved FDT address provided by TF-A at boot time (NT_FW_CONFIG =
* Non Trusted Firmware configuration file) when the pointer is valid
*/
void *board_fdt_blob_setup(int *err)
{
+ unsigned long nt_fw_dtb = get_stm32mp_bl2_dtb();
+
log_debug("%s: nt_fw_dtb=%lx\n", __func__, nt_fw_dtb);
*err = 0;
diff --git a/arch/arm/mach-stm32mp/bsec.c b/arch/arm/mach-stm32mp/bsec.c
index c00130b..f5f4b20 100644
--- a/arch/arm/mach-stm32mp/bsec.c
+++ b/arch/arm/mach-stm32mp/bsec.c
@@ -10,9 +10,11 @@
#include <dm.h>
#include <log.h>
#include <misc.h>
+#include <tee.h>
#include <asm/io.h>
#include <asm/arch/bsec.h>
#include <asm/arch/stm32mp1_smc.h>
+#include <dm/device.h>
#include <dm/device_compat.h>
#include <linux/arm-smccc.h>
#include <linux/iopoll.h>
@@ -63,10 +65,43 @@
*/
#define BSEC_LOCK_PROGRAM 0x04
+#define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \
+ { 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } }
+
/*
- * OTP status: bit 0 permanent lock
+ * Read OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [out] memref[1].buffer Output buffer to store read values
+ * [out] memref[1].size Size of OTP to be read
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
*/
-#define BSEC_LOCK_PERM BIT(0)
+#define PTA_BSEC_READ_MEM 0x0
+
+/*
+ * Write OTP memory
+ *
+ * [in] value[0].a OTP start offset in byte
+ * [in] value[0].b Access type (0:shadow, 1:fuse, 2:lock)
+ * [in] memref[1].buffer Input buffer to read values
+ * [in] memref[1].size Size of OTP to be written
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
+ * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller
+ */
+#define PTA_BSEC_WRITE_MEM 0x1
+
+/* value of PTA_BSEC access type = value[in] b */
+#define SHADOW_ACCESS 0
+#define FUSE_ACCESS 1
+#define LOCK_ACCESS 2
/**
* bsec_lock() - manage lock for each type SR/SP/SW
@@ -359,6 +394,10 @@
u32 base;
};
+struct stm32mp_bsec_priv {
+ struct udevice *tee;
+};
+
static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
{
struct stm32mp_bsec_plat *plat;
@@ -468,18 +507,111 @@
plat = dev_get_plat(dev);
return bsec_permanent_lock_otp(dev, plat->base, otp);
+}
- return -EINVAL;
+static int bsec_pta_open_session(struct udevice *tee, u32 *tee_session)
+{
+ const struct tee_optee_ta_uuid uuid = PTA_BSEC_UUID;
+ struct tee_open_session_arg arg;
+ int rc;
+
+ memset(&arg, 0, sizeof(arg));
+ tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
+ arg.clnt_login = TEE_LOGIN_REE_KERNEL;
+ rc = tee_open_session(tee, &arg, 0, NULL);
+ if (rc < 0)
+ return -ENODEV;
+
+ *tee_session = arg.session;
+
+ return 0;
+}
+
+static int bsec_optee_open(struct udevice *dev)
+{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
+ struct udevice *tee;
+ u32 tee_session;
+ int rc;
+
+ tee = tee_find_device(NULL, NULL, NULL, NULL);
+ if (!tee)
+ return -ENODEV;
+
+ /* try to open the STM32 BSEC TA */
+ rc = bsec_pta_open_session(tee, &tee_session);
+ if (rc)
+ return rc;
+
+ tee_close_session(tee, tee_session);
+
+ priv->tee = tee;
+
+ return 0;
+}
+
+static int bsec_optee_pta(struct udevice *dev, int cmd, int type, int offset,
+ void *buff, ulong size)
+{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
+ u32 tee_session;
+ struct tee_invoke_arg arg;
+ struct tee_param param[2];
+ struct tee_shm *fw_shm;
+ int rc;
+
+ rc = bsec_pta_open_session(priv->tee, &tee_session);
+ if (rc)
+ return rc;
+
+ rc = tee_shm_register(priv->tee, buff, size, 0, &fw_shm);
+ if (rc)
+ goto close_session;
+
+ memset(&arg, 0, sizeof(arg));
+ arg.func = cmd;
+ arg.session = tee_session;
+
+ memset(param, 0, sizeof(param));
+
+ param[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
+ param[0].u.value.a = offset;
+ param[0].u.value.b = type;
+
+ if (cmd == PTA_BSEC_WRITE_MEM)
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
+ else
+ param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
+
+ param[1].u.memref.shm = fw_shm;
+ param[1].u.memref.size = size;
+
+ rc = tee_invoke_func(priv->tee, &arg, 2, param);
+ if (rc < 0 || arg.ret != 0) {
+ dev_err(priv->tee,
+ "PTA_BSEC invoke failed TEE err: %x, err:%x\n",
+ arg.ret, rc);
+ if (!rc)
+ rc = -EIO;
+ }
+
+ tee_shm_free(fw_shm);
+
+close_session:
+ tee_close_session(priv->tee, tee_session);
+
+ return rc;
}
static int stm32mp_bsec_read(struct udevice *dev, int offset,
void *buf, int size)
{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
int ret;
int i;
bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32);
- int otp;
+ int otp, cmd;
unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) {
@@ -493,6 +625,19 @@
if ((offs % 4) || (size % 4))
return -EINVAL;
+ if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
+ cmd = FUSE_ACCESS;
+ if (shadow)
+ cmd = SHADOW_ACCESS;
+ if (lock)
+ cmd = LOCK_ACCESS;
+ ret = bsec_optee_pta(dev, PTA_BSEC_READ_MEM, cmd, offs, buf, size);
+ if (ret)
+ return ret;
+
+ return size;
+ }
+
otp = offs / sizeof(u32);
for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
@@ -517,11 +662,12 @@
static int stm32mp_bsec_write(struct udevice *dev, int offset,
const void *buf, int size)
{
+ struct stm32mp_bsec_priv *priv = dev_get_priv(dev);
int ret = 0;
int i;
bool shadow = true, lock = false;
int nb_otp = size / sizeof(u32);
- int otp;
+ int otp, cmd;
unsigned int offs = offset;
if (offs >= STM32_BSEC_LOCK_OFFSET) {
@@ -535,6 +681,19 @@
if ((offs % 4) || (size % 4))
return -EINVAL;
+ if (IS_ENABLED(CONFIG_OPTEE) && priv->tee) {
+ cmd = FUSE_ACCESS;
+ if (shadow)
+ cmd = SHADOW_ACCESS;
+ if (lock)
+ cmd = LOCK_ACCESS;
+ ret = bsec_optee_pta(dev, PTA_BSEC_WRITE_MEM, cmd, offs, (void *)buf, size);
+ if (ret)
+ return ret;
+
+ return size;
+ }
+
otp = offs / sizeof(u32);
for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
@@ -583,6 +742,9 @@
return ret;
}
+ if (IS_ENABLED(CONFIG_OPTEE))
+ bsec_optee_open(dev);
+
/*
* update unlocked shadow for OTP cleared by the rom code
* only executed in SPL, it is done in TF-A for TFABOOT
@@ -599,6 +761,7 @@
}
static const struct udevice_id stm32mp_bsec_ids[] = {
+ { .compatible = "st,stm32mp13-bsec" },
{ .compatible = "st,stm32mp15-bsec" },
{}
};
@@ -608,7 +771,8 @@
.id = UCLASS_MISC,
.of_match = stm32mp_bsec_ids,
.of_to_plat = stm32mp_bsec_of_to_plat,
- .plat_auto = sizeof(struct stm32mp_bsec_plat),
+ .plat_auto = sizeof(struct stm32mp_bsec_plat),
+ .priv_auto = sizeof(struct stm32mp_bsec_priv),
.ops = &stm32mp_bsec_ops,
.probe = stm32mp_bsec_probe,
};
diff --git a/arch/arm/mach-stm32mp/cmd_stm32key.c b/arch/arm/mach-stm32mp/cmd_stm32key.c
index 278253e..85be8e2 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32key.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32key.c
@@ -8,6 +8,7 @@
#include <console.h>
#include <log.h>
#include <misc.h>
+#include <asm/arch/bsec.h>
#include <dm/device.h>
#include <dm/uclass.h>
@@ -84,9 +85,6 @@
return STM32_OTP_STM32MP15x_CLOSE_MASK;
}
-#define BSEC_LOCK_ERROR (-1)
-#define BSEC_LOCK_PERM BIT(0)
-
static int get_misc_dev(struct udevice **dev)
{
int ret;
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
index cb13a14..a837235 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c
@@ -154,7 +154,7 @@
do_bootz(cmdtp, 0, 4, bootm_argv);
}
if (data->script)
- image_source_script(data->script, NULL, NULL);
+ cmd_source_script(data->script, NULL, NULL);
if (reset) {
puts("Reset...\n");
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index 855fc75..dc4112d 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -22,6 +22,7 @@
#include <dm/device.h>
#include <dm/uclass.h>
#include <linux/bitops.h>
+#include <spl.h>
/*
* early TLB into the .data section so that it not get cleared
@@ -378,3 +379,52 @@
return 0;
}
+
+/*
+ * Without forcing the ".data" section, this would get saved in ".bss". BSS
+ * will be cleared soon after, so it's not suitable.
+ */
+static uintptr_t rom_api_table __section(".data");
+static uintptr_t nt_fw_dtb __section(".data");
+
+/*
+ * The ROM gives us the API location in r0 when starting. This is only available
+ * during SPL, as there isn't (yet) a mechanism to pass this on to u-boot. Save
+ * the FDT address provided by TF-A in r2 at boot time. This function is called
+ * from start.S
+ */
+void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
+ unsigned long r3)
+{
+ if (IS_ENABLED(CONFIG_STM32_ECDSA_VERIFY))
+ rom_api_table = r0;
+
+ if (IS_ENABLED(CONFIG_TFABOOT))
+ nt_fw_dtb = r2;
+
+ save_boot_params_ret();
+}
+
+uintptr_t get_stm32mp_rom_api_table(void)
+{
+ return rom_api_table;
+}
+
+uintptr_t get_stm32mp_bl2_dtb(void)
+{
+ return nt_fw_dtb;
+}
+
+#ifdef CONFIG_SPL_BUILD
+void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
+{
+ typedef void __noreturn (*image_entry_stm32_t)(u32 romapi);
+ uintptr_t romapi = get_stm32mp_rom_api_table();
+
+ image_entry_stm32_t image_entry =
+ (image_entry_stm32_t)spl_image->entry_point;
+
+ printf("image entry point: 0x%lx\n", spl_image->entry_point);
+ image_entry(romapi);
+}
+#endif
diff --git a/arch/arm/mach-stm32mp/ecdsa_romapi.c b/arch/arm/mach-stm32mp/ecdsa_romapi.c
index a2f63ff..12b42b9 100644
--- a/arch/arm/mach-stm32mp/ecdsa_romapi.c
+++ b/arch/arm/mach-stm32mp/ecdsa_romapi.c
@@ -24,26 +24,10 @@
uint32_t ecc_algo);
};
-/*
- * Without forcing the ".data" section, this would get saved in ".bss". BSS
- * will be cleared soon after, so it's not suitable.
- */
-static uintptr_t rom_api_loc __section(".data");
-
-/*
- * The ROM gives us the API location in r0 when starting. This is only available
- * during SPL, as there isn't (yet) a mechanism to pass this on to u-boot.
- */
-void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
- unsigned long r3)
-{
- rom_api_loc = r0;
- save_boot_params_ret();
-}
-
static void stm32mp_rom_get_ecdsa_functions(struct ecdsa_rom_api *rom)
{
- uintptr_t verify_ptr = rom_api_loc + ROM_API_OFFSET_ECDSA_VERIFY;
+ uintptr_t verify_ptr = get_stm32mp_rom_api_table() +
+ ROM_API_OFFSET_ECDSA_VERIFY;
rom->ecdsa_verify_signature = *(void **)verify_ptr;
}
@@ -81,6 +65,10 @@
memcpy(raw_key + 32, pubkey->y, 32);
stm32mp_rom_get_ecdsa_functions(&rom);
+
+ /* Mark BootROM region as executable. */
+ mmu_set_region_dcache_behaviour(0, SZ_2M, DCACHE_DEFAULT_OPTION);
+
rom_ret = rom.ecdsa_verify_signature(hash, raw_key, signature, algo);
return rom_ret == ROM_API_SUCCESS ? 0 : -EPERM;
diff --git a/arch/arm/mach-stm32mp/include/mach/bsec.h b/arch/arm/mach-stm32mp/include/mach/bsec.h
index 252eac3..10ebc53 100644
--- a/arch/arm/mach-stm32mp/include/mach/bsec.h
+++ b/arch/arm/mach-stm32mp/include/mach/bsec.h
@@ -5,3 +5,10 @@
/* check self hosted debug status = BSEC_DENABLE.DBGSWENABLE */
bool bsec_dbgswenable(void);
+
+/* Bitfield definition for LOCK status */
+#define BSEC_LOCK_PERM BIT(30)
+#define BSEC_LOCK_SHADOW_R BIT(29)
+#define BSEC_LOCK_SHADOW_W BIT(28)
+#define BSEC_LOCK_SHADOW_P BIT(27)
+#define BSEC_LOCK_ERROR BIT(26)
diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
index f19a70e..0d39b67 100644
--- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h
+++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
@@ -77,3 +77,6 @@
/* helper function: read data from OTP */
u32 get_otp(int index, int shift, int mask);
+
+uintptr_t get_stm32mp_rom_api_table(void);
+uintptr_t get_stm32mp_bl2_dtb(void);
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index dbe6005..6417aee 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -652,33 +652,6 @@
Set the pin used to power the MAC. This takes a string in the format
understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
-config MMC0_CD_PIN
- string "Card detect pin for mmc0"
- default "PF6" if MACH_SUN8I_A83T || MACH_SUNXI_H3_H5 || MACH_SUN50I
- default ""
- ---help---
- Set the card detect pin for mmc0, leave empty to not use cd. This
- takes a string in the format understood by sunxi_name_to_gpio, e.g.
- PH1 for pin 1 of port H.
-
-config MMC1_CD_PIN
- string "Card detect pin for mmc1"
- default ""
- ---help---
- See MMC0_CD_PIN help text.
-
-config MMC2_CD_PIN
- string "Card detect pin for mmc2"
- default ""
- ---help---
- See MMC0_CD_PIN help text.
-
-config MMC3_CD_PIN
- string "Card detect pin for mmc3"
- default ""
- ---help---
- See MMC0_CD_PIN help text.
-
config MMC1_PINS_PH
bool "Pins for mmc1 are on Port H"
depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 0c4b6dd..391a65a 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -35,7 +35,6 @@
uint32_t cpsr;
uint32_t sctlr;
uint32_t vbar;
- uint32_t cr;
};
struct fel_stash fel_stash __section(".data");
@@ -365,6 +364,7 @@
struct blk_desc *bd = mmc_get_blk_desc(mmc);
u32 *buffer = (void *)(uintptr_t)CONFIG_TEXT_BASE;
struct boot_file_head *egon_head = (void *)buffer;
+ struct toc0_main_info *toc0_info = (void *)buffer;
int bootpart = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
uint32_t spl_size, emmc_checksum, chksum = 0;
ulong count;
@@ -391,11 +391,17 @@
/* Read the first block to do some sanity checks on the eGON header. */
count = blk_dread(bd, 0, 1, buffer);
- if (count != 1 || !sunxi_egon_valid(egon_head))
+ if (count != 1)
+ return false;
+
+ if (sunxi_egon_valid(egon_head))
+ spl_size = egon_head->length;
+ else if (sunxi_toc0_valid(toc0_info))
+ spl_size = toc0_info->length;
+ else
return false;
/* Read the rest of the SPL now we know it's halfway sane. */
- spl_size = buffer[4];
count = blk_dread(bd, 1, DIV_ROUND_UP(spl_size, bd->blksz) - 1,
buffer + bd->blksz / 4);
diff --git a/arch/arm/mach-tegra/tegra20/warmboot_avp.c b/arch/arm/mach-tegra/tegra20/warmboot_avp.c
index be801d1..94ce762 100644
--- a/arch/arm/mach-tegra/tegra20/warmboot_avp.c
+++ b/arch/arm/mach-tegra/tegra20/warmboot_avp.c
@@ -34,7 +34,7 @@
u32 reg;
/* enable JTAG & TBE */
- writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &apb_misc->cfg_ctl);
+ writel(CFG_CTL_TBE | CFG_CTL_JTAG, &apb_misc->cfg_ctl);
/* Are we running where we're supposed to be? */
asm volatile (
diff --git a/arch/arm/mach-tegra/tegra20/warmboot_avp.h b/arch/arm/mach-tegra/tegra20/warmboot_avp.h
index 19a476b..f300fe6 100644
--- a/arch/arm/mach-tegra/tegra20/warmboot_avp.h
+++ b/arch/arm/mach-tegra/tegra20/warmboot_avp.h
@@ -19,8 +19,8 @@
#define USEC_CFG_DIVISOR_MASK 0xffff
-#define CONFIG_CTL_TBE (1 << 7)
-#define CONFIG_CTL_JTAG (1 << 6)
+#define CFG_CTL_TBE (1 << 7)
+#define CFG_CTL_JTAG (1 << 6)
#define CPU_RST (1 << 0)
#define CLK_ENB_CPU (1 << 0)
diff --git a/arch/m68k/cpu/mcf523x/interrupts.c b/arch/m68k/cpu/mcf523x/interrupts.c
index b554c51..331288e 100644
--- a/arch/m68k/cpu/mcf523x/interrupts.c
+++ b/arch/m68k/cpu/mcf523x/interrupts.c
@@ -13,7 +13,7 @@
int interrupt_init(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
/* Make sure all interrupts are disabled */
setbits_be32(&intp->imrl0, 0x1);
@@ -25,10 +25,10 @@
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
- out_8(&intp->icr0[CONFIG_SYS_TMRINTR_NO], CONFIG_SYS_TMRINTR_PRI);
+ out_8(&intp->icr0[CFG_SYS_TMRINTR_NO], CFG_SYS_TMRINTR_PRI);
clrbits_be32(&intp->imrl0, INTC_IPRL_INT0);
- clrbits_be32(&intp->imrl0, CONFIG_SYS_TMRINTR_MASK);
+ clrbits_be32(&intp->imrl0, CFG_SYS_TMRINTR_MASK);
}
#endif
diff --git a/arch/m68k/cpu/mcf52x2/interrupts.c b/arch/m68k/cpu/mcf52x2/interrupts.c
index 35ed1e7..e8a1e13 100644
--- a/arch/m68k/cpu/mcf52x2/interrupts.c
+++ b/arch/m68k/cpu/mcf52x2/interrupts.c
@@ -37,10 +37,10 @@
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
- intctrl_t *intp = (intctrl_t *) (CONFIG_SYS_INTR_BASE);
+ intctrl_t *intp = (intctrl_t *) (CFG_SYS_INTR_BASE);
clrbits_be32(&intp->int_icr1, INT_ICR1_TMR3MASK);
- setbits_be32(&intp->int_icr1, CONFIG_SYS_TMRINTR_PRI);
+ setbits_be32(&intp->int_icr1, CFG_SYS_TMRINTR_PRI);
}
#endif /* CONFIG_MCFTMR */
#endif /* CONFIG_M5272 */
@@ -49,7 +49,7 @@
defined(CONFIG_M5271) || defined(CONFIG_M5275)
int interrupt_init(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
/* Make sure all interrupts are disabled */
#if defined(CONFIG_M5208)
@@ -66,11 +66,11 @@
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
- out_8(&intp->icr0[CONFIG_SYS_TMRINTR_NO], CONFIG_SYS_TMRINTR_PRI);
+ out_8(&intp->icr0[CFG_SYS_TMRINTR_NO], CFG_SYS_TMRINTR_PRI);
clrbits_be32(&intp->imrl0, 0x00000001);
- clrbits_be32(&intp->imrl0, CONFIG_SYS_TMRINTR_MASK);
+ clrbits_be32(&intp->imrl0, CFG_SYS_TMRINTR_MASK);
}
#endif /* CONFIG_MCFTMR */
#endif /* CONFIG_M5282 | CONFIG_M5271 | CONFIG_M5275 */
@@ -87,7 +87,7 @@
void dtimer_intr_setup(void)
{
mbar_writeLong(MCFSIM_IMR, mbar_readLong(MCFSIM_IMR) & ~0x00000400);
- mbar_writeByte(MCFSIM_TIMER2ICR, CONFIG_SYS_TMRINTR_PRI);
+ mbar_writeByte(MCFSIM_TIMER2ICR, CFG_SYS_TMRINTR_PRI);
}
#endif /* CONFIG_MCFTMR */
#endif /* CONFIG_M5249 || CONFIG_M5253 */
diff --git a/arch/m68k/cpu/mcf530x/interrupts.c b/arch/m68k/cpu/mcf530x/interrupts.c
index 2659e34..1168620 100644
--- a/arch/m68k/cpu/mcf530x/interrupts.c
+++ b/arch/m68k/cpu/mcf530x/interrupts.c
@@ -24,6 +24,6 @@
/* clearing TIMER2 mask, so enabling the related interrupt */
out_be32(&icr->imr, in_be32(&icr->imr) & ~0x00000400);
/* set TIMER2 interrupt priority */
- out_8(&icr->icr2, CONFIG_SYS_TMRINTR_PRI);
+ out_8(&icr->icr2, CFG_SYS_TMRINTR_PRI);
}
#endif
diff --git a/arch/m68k/cpu/mcf532x/interrupts.c b/arch/m68k/cpu/mcf532x/interrupts.c
index 8f2df45..64e0466 100644
--- a/arch/m68k/cpu/mcf532x/interrupts.c
+++ b/arch/m68k/cpu/mcf532x/interrupts.c
@@ -13,7 +13,7 @@
int interrupt_init(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
/* Make sure all interrupts are disabled */
setbits_be32(&intp->imrh0, 0xffffffff);
@@ -26,9 +26,9 @@
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
- out_8(&intp->icr0[CONFIG_SYS_TMRINTR_NO], CONFIG_SYS_TMRINTR_PRI);
- clrbits_be32(&intp->imrh0, CONFIG_SYS_TMRINTR_MASK);
+ out_8(&intp->icr0[CFG_SYS_TMRINTR_NO], CFG_SYS_TMRINTR_PRI);
+ clrbits_be32(&intp->imrh0, CFG_SYS_TMRINTR_MASK);
}
#endif
diff --git a/arch/m68k/cpu/mcf5445x/interrupts.c b/arch/m68k/cpu/mcf5445x/interrupts.c
index 5a6a88c..ea0cf87 100644
--- a/arch/m68k/cpu/mcf5445x/interrupts.c
+++ b/arch/m68k/cpu/mcf5445x/interrupts.c
@@ -16,7 +16,7 @@
int interrupt_init(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
/* Make sure all interrupts are disabled */
setbits_be32(&intp->imrh0, 0xffffffff);
@@ -29,9 +29,9 @@
#if defined(CONFIG_MCFTMR)
void dtimer_intr_setup(void)
{
- int0_t *intp = (int0_t *) (CONFIG_SYS_INTR_BASE);
+ int0_t *intp = (int0_t *) (CFG_SYS_INTR_BASE);
- out_8(&intp->icr0[CONFIG_SYS_TMRINTR_NO], CONFIG_SYS_TMRINTR_PRI);
- clrbits_be32(&intp->imrh0, CONFIG_SYS_TMRINTR_MASK);
+ out_8(&intp->icr0[CFG_SYS_TMRINTR_NO], CFG_SYS_TMRINTR_PRI);
+ clrbits_be32(&intp->imrh0, CFG_SYS_TMRINTR_MASK);
}
#endif
diff --git a/arch/m68k/include/asm/cache.h b/arch/m68k/include/asm/cache.h
index c05356f..8ed2b4d 100644
--- a/arch/m68k/include/asm/cache.h
+++ b/arch/m68k/include/asm/cache.h
@@ -11,21 +11,21 @@
#if defined(CONFIG_MCF520x) || defined(CONFIG_MCF523x) || \
defined(CONFIG_MCF52x2)
-#define CONFIG_CF_V2
+#define CFG_CF_V2
#endif
#if defined(CONFIG_MCF530x) || defined(CONFIG_MCF532x) || \
defined(CONFIG_MCF5301x)
-#define CONFIG_CF_V3
+#define CFG_CF_V3
#endif
#if defined(CONFIG_MCF5441x)
-#define CONFIG_CF_V4E /* Four Extra ACRn */
+#define CFG_CF_V4E /* Four Extra ACRn */
#endif
/* ***** CACR ***** */
/* V2 Core */
-#ifdef CONFIG_CF_V2
+#ifdef CFG_CF_V2
#define CF_CACR_CENB (1 << 31)
#define CF_CACR_CPD (1 << 28)
@@ -46,10 +46,10 @@
#define CF_CACR_EUSP (1 << 4)
#endif /* CONFIG_MCF5249 || CONFIG_MCF5253 */
-#endif /* CONFIG_CF_V2 */
+#endif /* CFG_CF_V2 */
/* V3 Core */
-#ifdef CONFIG_CF_V3
+#ifdef CFG_CF_V3
#define CF_CACR_EC (1 << 31)
#define CF_CACR_ESB (1 << 29)
@@ -65,10 +65,10 @@
#define CF_CACR_DW (1 << 5)
#define CF_CACR_EUSP (1 << 4)
-#endif /* CONFIG_CF_V3 */
+#endif /* CFG_CF_V3 */
/* V4 Core */
-#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
+#if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E)
#define CF_CACR_DEC (1 << 31)
#define CF_CACR_DW (1 << 30)
@@ -116,7 +116,7 @@
#define CF_ACR_WP (1 << 2)
/* V2 Core */
-#ifdef CONFIG_CF_V2
+#ifdef CFG_CF_V2
#define CF_ACR_CM (1 << 6)
#define CF_ACR_BWE (1 << 5)
#else
@@ -126,10 +126,10 @@
#define CF_ACR_CM_CB (1 << 5)
#define CF_ACR_CM_P (2 << 5)
#define CF_ACR_CM_IP (3 << 5)
-#endif /* CONFIG_CF_V2 */
+#endif /* CFG_CF_V2 */
/* V4 Core */
-#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
+#if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E)
#define CF_ACR_AMM (1 << 10)
#define CF_ACR_SP (1 << 3)
#endif /* CONFIG_CF_V4 */
@@ -159,24 +159,24 @@
#define CFG_SYS_CACHE_ACR2 0
#endif
-#ifndef CONFIG_SYS_CACHE_ACR3
-#define CONFIG_SYS_CACHE_ACR3 0
+#ifndef CFG_SYS_CACHE_ACR3
+#define CFG_SYS_CACHE_ACR3 0
#endif
-#ifndef CONFIG_SYS_CACHE_ACR4
-#define CONFIG_SYS_CACHE_ACR4 0
+#ifndef CFG_SYS_CACHE_ACR4
+#define CFG_SYS_CACHE_ACR4 0
#endif
-#ifndef CONFIG_SYS_CACHE_ACR5
-#define CONFIG_SYS_CACHE_ACR5 0
+#ifndef CFG_SYS_CACHE_ACR5
+#define CFG_SYS_CACHE_ACR5 0
#endif
-#ifndef CONFIG_SYS_CACHE_ACR6
-#define CONFIG_SYS_CACHE_ACR6 0
+#ifndef CFG_SYS_CACHE_ACR6
+#define CFG_SYS_CACHE_ACR6 0
#endif
-#ifndef CONFIG_SYS_CACHE_ACR7
-#define CONFIG_SYS_CACHE_ACR7 0
+#ifndef CFG_SYS_CACHE_ACR7
+#define CFG_SYS_CACHE_ACR7 0
#endif
#define CF_ADDRMASK(x) (((x > 0x10) ? ((x >> 4) - 1) : (x)) << 16)
diff --git a/arch/m68k/include/asm/coldfire/intctrl.h b/arch/m68k/include/asm/coldfire/intctrl.h
index f7f0f07..3f7c458 100644
--- a/arch/m68k/include/asm/coldfire/intctrl.h
+++ b/arch/m68k/include/asm/coldfire/intctrl.h
@@ -12,7 +12,7 @@
#if defined(CONFIG_M5235) || defined(CONFIG_M5271) || \
defined(CONFIG_M5275) || defined(CONFIG_M5282) || \
defined(CONFIG_M547x)
-# define CONFIG_SYS_CF_INTC_REG1
+# define CFG_SYS_CF_INTC_REG1
#endif
typedef struct int0_ctrl {
@@ -23,7 +23,7 @@
u32 imrl0; /* 0x0C Mask Low */
u32 frch0; /* 0x10 Force High */
u32 frcl0; /* 0x14 Force Low */
-#if defined(CONFIG_SYS_CF_INTC_REG1)
+#if defined(CFG_SYS_CF_INTC_REG1)
u8 irlr; /* 0x18 */
u8 iacklpr; /* 0x19 */
u16 res1[19]; /* 0x1a - 0x3c */
@@ -64,7 +64,7 @@
u32 imrl1; /* 0x0C Mask Low */
u32 frch1; /* 0x10 Force High */
u32 frcl1; /* 0x14 Force Low */
-#if defined(CONFIG_SYS_CF_INTC_REG1)
+#if defined(CFG_SYS_CF_INTC_REG1)
u8 irlr; /* 0x18 */
u8 iacklpr; /* 0x19 */
u16 res1[19]; /* 0x1a - 0x3c */
@@ -192,7 +192,7 @@
#define INTC_IACKLPR_PRI(x) ((x) & 0x0F)
#define INTC_IACKLPR_PRI_MASK (0xF0)
-#if defined(CONFIG_SYS_CF_INTC_REG1)
+#if defined(CFG_SYS_CF_INTC_REG1)
#define INTC_ICR_IL(x) (((x) & 0x07) << 3)
#define INTC_ICR_IL_MASK (0xC7)
#define INTC_ICR_IP(x) ((x) & 0x07)
diff --git a/arch/m68k/include/asm/immap.h b/arch/m68k/include/asm/immap.h
index dab8b26..8207c8d 100644
--- a/arch/m68k/include/asm/immap.h
+++ b/arch/m68k/include/asm/immap.h
@@ -13,67 +13,65 @@
#include <asm/immap_520x.h>
#include <asm/m520x.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC0)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x4000))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x4000))
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR1)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprh0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (6)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR1)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprh0)
+#define CFG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (6)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (128)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (128)
#endif /* CONFIG_M520x */
#ifdef CONFIG_M5235
#include <asm/immap_5235.h>
#include <asm/m5235.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR3)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprl0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRL_INT22)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (0x1E) /* Level must include inorder to work */
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR3)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprl0)
+#define CFG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRL_INT22)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (0x1E) /* Level must include inorder to work */
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (128)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (128)
#endif /* CONFIG_M5235 */
#ifdef CONFIG_M5249
#include <asm/immap_5249.h>
#include <asm/m5249.h>
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC)
-#define CONFIG_SYS_NUM_IRQS (64)
+#define CFG_SYS_INTR_BASE (MMAP_INTC)
+#define CFG_SYS_NUM_IRQS (64)
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR1)
-#define CONFIG_SYS_TMRPND_REG (mbar_readLong(MCFSIM_IPR))
-#define CONFIG_SYS_TMRINTR_NO (31)
-#define CONFIG_SYS_TMRINTR_MASK (0x00000400)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 2000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR1)
+#define CFG_SYS_TMRPND_REG (mbar_readLong(MCFSIM_IPR))
+#define CFG_SYS_TMRINTR_NO (31)
+#define CFG_SYS_TMRINTR_MASK (0x00000400)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 2000000) - 1) << 8)
#endif
#endif /* CONFIG_M5249 */
@@ -82,21 +80,21 @@
#include <asm/m5249.h>
#include <asm/m5253.h>
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC)
-#define CONFIG_SYS_NUM_IRQS (64)
+#define CFG_SYS_INTR_BASE (MMAP_INTC)
+#define CFG_SYS_NUM_IRQS (64)
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR1)
-#define CONFIG_SYS_TMRPND_REG (mbar_readLong(MCFSIM_IPR))
-#define CONFIG_SYS_TMRINTR_NO (27)
-#define CONFIG_SYS_TMRINTR_MASK (0x00000400)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL3 | MCFSIM_ICR_PRI3)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 2000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR1)
+#define CFG_SYS_TMRPND_REG (mbar_readLong(MCFSIM_IPR))
+#define CFG_SYS_TMRINTR_NO (27)
+#define CFG_SYS_TMRINTR_MASK (0x00000400)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL3 | MCFSIM_ICR_PRI3)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 2000000) - 1) << 8)
#endif
#endif /* CONFIG_M5253 */
@@ -104,45 +102,43 @@
#include <asm/immap_5271.h>
#include <asm/m5271.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR3)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprl0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRL_INT22)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (0x1E) /* Interrupt level 3, priority 6 */
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR3)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprl0)
+#define CFG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRL_INT22)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (0x1E) /* Interrupt level 3, priority 6 */
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (128)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (128)
#endif /* CONFIG_M5271 */
#ifdef CONFIG_M5272
#include <asm/immap_5272.h>
#include <asm/m5272.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC)
-#define CONFIG_SYS_NUM_IRQS (64)
+#define CFG_SYS_INTR_BASE (MMAP_INTC)
+#define CFG_SYS_NUM_IRQS (64)
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_TMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_TMR3)
-#define CONFIG_SYS_TMRPND_REG (((volatile intctrl_t *)(CONFIG_SYS_INTR_BASE))->int_isr)
-#define CONFIG_SYS_TMRINTR_NO (INT_TMR3)
-#define CONFIG_SYS_TMRINTR_MASK (INT_ISR_INT24)
-#define CONFIG_SYS_TMRINTR_PEND (0)
-#define CONFIG_SYS_TMRINTR_PRI (INT_ICR1_TMR3PI | INT_ICR1_TMR3IPL(5))
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_TMR0)
+#define CFG_SYS_TMR_BASE (MMAP_TMR3)
+#define CFG_SYS_TMRPND_REG (((volatile intctrl_t *)(CFG_SYS_INTR_BASE))->int_isr)
+#define CFG_SYS_TMRINTR_NO (INT_TMR3)
+#define CFG_SYS_TMRINTR_MASK (INT_ISR_INT24)
+#define CFG_SYS_TMRINTR_PEND (0)
+#define CFG_SYS_TMRINTR_PRI (INT_ICR1_TMR3PI | INT_ICR1_TMR3IPL(5))
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
#endif /* CONFIG_M5272 */
@@ -150,23 +146,21 @@
#include <asm/immap_5275.h>
#include <asm/m5275.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC0)
-#define CONFIG_SYS_FEC1_IOBASE (MMAP_FEC1)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (192)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (192)
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR3)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprl0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRL_INT22)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (0x1E)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR3)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprl0)
+#define CFG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRL_INT22)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (0x1E)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
#endif /* CONFIG_M5275 */
@@ -174,22 +168,21 @@
#include <asm/immap_5282.h>
#include <asm/m5282.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x40))
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (128)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (128)
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR3)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprl0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
-#define CONFIG_SYS_TMRINTR_MASK (1 << INT0_LO_DTMR3)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (0x1E) /* Level must include inorder to work */
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR3)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprl0)
+#define CFG_SYS_TMRINTR_NO (INT0_LO_DTMR3)
+#define CFG_SYS_TMRINTR_MASK (1 << INT0_LO_DTMR3)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (0x1E) /* Level must include inorder to work */
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
#endif /* CONFIG_M5282 */
@@ -197,23 +190,23 @@
#include <asm/immap_5307.h>
#include <asm/m5307.h>
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + \
+#define CFG_SYS_UART_BASE (MMAP_UART0 + \
(CFG_SYS_UART_PORT * 0x40))
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC)
-#define CONFIG_SYS_NUM_IRQS (64)
+#define CFG_SYS_INTR_BASE (MMAP_INTC)
+#define CFG_SYS_NUM_IRQS (64)
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR1)
-#define CONFIG_SYS_TMRPND_REG (((volatile intctrl_t *) \
- (CONFIG_SYS_INTR_BASE))->ipr)
-#define CONFIG_SYS_TMRINTR_NO (31)
-#define CONFIG_SYS_TMRINTR_MASK (0x00000400)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (MCFSIM_ICR_AUTOVEC | \
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR1)
+#define CFG_SYS_TMRPND_REG (((volatile intctrl_t *) \
+ (CFG_SYS_INTR_BASE))->ipr)
+#define CFG_SYS_TMRINTR_NO (31)
+#define CFG_SYS_TMRINTR_MASK (0x00000400)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (MCFSIM_ICR_AUTOVEC | \
MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
#endif /* CONFIG_M5307 */
@@ -221,61 +214,55 @@
#include <asm/immap_5301x.h>
#include <asm/m5301x.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC0)
-#define CONFIG_SYS_FEC1_IOBASE (MMAP_FEC1)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x4000))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x4000))
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR1)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprh0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (6)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR1)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprh0)
+#define CFG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (6)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (128)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (128)
#endif /* CONFIG_M5301x */
#if defined(CONFIG_M5329) || defined(CONFIG_M5373)
#include <asm/immap_5329.h>
#include <asm/m5329.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x4000))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x4000))
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR1)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprh0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (6)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR1)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprh0)
+#define CFG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (6)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (128)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (128)
#endif /* CONFIG_M5329 && CONFIG_M5373 */
#if defined(CONFIG_M54418)
#include <asm/immap_5441x.h>
#include <asm/m5441x.h>
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC0)
-#define CONFIG_SYS_FEC1_IOBASE (MMAP_FEC1)
-
#if (CFG_SYS_UART_PORT < 4)
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + \
+#define CFG_SYS_UART_BASE (MMAP_UART0 + \
(CFG_SYS_UART_PORT * 0x4000))
#else
-#define CONFIG_SYS_UART_BASE (MMAP_UART4 + \
+#define CFG_SYS_UART_BASE (MMAP_UART4 + \
((CFG_SYS_UART_PORT - 4) * 0x4000))
#endif
@@ -283,18 +270,18 @@
/* Timer */
#ifdef CONFIG_MCFTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_DTMR0)
-#define CONFIG_SYS_TMR_BASE (MMAP_DTMR1)
-#define CONFIG_SYS_TMRPND_REG (((int0_t *)(CONFIG_SYS_INTR_BASE))->iprh0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (6)
-#define CONFIG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
+#define CFG_SYS_UDELAY_BASE (MMAP_DTMR0)
+#define CFG_SYS_TMR_BASE (MMAP_DTMR1)
+#define CFG_SYS_TMRPND_REG (((int0_t *)(CFG_SYS_INTR_BASE))->iprh0)
+#define CFG_SYS_TMRINTR_NO (INT0_HI_DTMR1)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRH_INT33)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (6)
+#define CFG_SYS_TIMER_PRESCALER (((gd->bus_clk / 1000000) - 1) << 8)
#endif
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (192)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (192)
#endif /* CONFIG_M54418 */
@@ -303,9 +290,6 @@
#include <asm/m547x_8x.h>
#ifdef CONFIG_FSLDMAFEC
-#define CONFIG_SYS_FEC0_IOBASE (MMAP_FEC0)
-#define CONFIG_SYS_FEC1_IOBASE (MMAP_FEC1)
-
#define FEC0_RX_TASK 0
#define FEC0_TX_TASK 1
#define FEC0_RX_PRIORITY 6
@@ -320,21 +304,21 @@
#define FEC1_TX_INIT 31
#endif
-#define CONFIG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x100))
+#define CFG_SYS_UART_BASE (MMAP_UART0 + (CFG_SYS_UART_PORT * 0x100))
#ifdef CONFIG_SLTTMR
-#define CONFIG_SYS_UDELAY_BASE (MMAP_SLT1)
-#define CONFIG_SYS_TMR_BASE (MMAP_SLT0)
-#define CONFIG_SYS_TMRPND_REG (((volatile int0_t *)(CONFIG_SYS_INTR_BASE))->iprh0)
-#define CONFIG_SYS_TMRINTR_NO (INT0_HI_SLT0)
-#define CONFIG_SYS_TMRINTR_MASK (INTC_IPRH_INT54)
-#define CONFIG_SYS_TMRINTR_PEND (CONFIG_SYS_TMRINTR_MASK)
-#define CONFIG_SYS_TMRINTR_PRI (0x1E)
-#define CONFIG_SYS_TIMER_PRESCALER (gd->bus_clk / 1000000)
+#define CFG_SYS_UDELAY_BASE (MMAP_SLT1)
+#define CFG_SYS_TMR_BASE (MMAP_SLT0)
+#define CFG_SYS_TMRPND_REG (((volatile int0_t *)(CFG_SYS_INTR_BASE))->iprh0)
+#define CFG_SYS_TMRINTR_NO (INT0_HI_SLT0)
+#define CFG_SYS_TMRINTR_MASK (INTC_IPRH_INT54)
+#define CFG_SYS_TMRINTR_PEND (CFG_SYS_TMRINTR_MASK)
+#define CFG_SYS_TMRINTR_PRI (0x1E)
+#define CFG_SYS_TIMER_PRESCALER (gd->bus_clk / 1000000)
#endif
-#define CONFIG_SYS_INTR_BASE (MMAP_INTC0)
-#define CONFIG_SYS_NUM_IRQS (128)
+#define CFG_SYS_INTR_BASE (MMAP_INTC0)
+#define CFG_SYS_NUM_IRQS (128)
#ifdef CONFIG_PCI
#define CFG_SYS_PCI_BAR0 (0x40000000)
diff --git a/arch/m68k/lib/cache.c b/arch/m68k/lib/cache.c
index 4ddda69..57e5632 100644
--- a/arch/m68k/lib/cache.c
+++ b/arch/m68k/lib/cache.c
@@ -33,12 +33,12 @@
*cf_icache_status = 1;
-#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
+#if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr2"::"r"(CFG_SYS_CACHE_ACR2));
- __asm__ __volatile__("movec %0, %%acr3"::"r"(CONFIG_SYS_CACHE_ACR3));
-#if defined(CONFIG_CF_V4E)
- __asm__ __volatile__("movec %0, %%acr6"::"r"(CONFIG_SYS_CACHE_ACR6));
- __asm__ __volatile__("movec %0, %%acr7"::"r"(CONFIG_SYS_CACHE_ACR7));
+ __asm__ __volatile__("movec %0, %%acr3"::"r"(CFG_SYS_CACHE_ACR3));
+#if defined(CFG_CF_V4E)
+ __asm__ __volatile__("movec %0, %%acr6"::"r"(CFG_SYS_CACHE_ACR6));
+ __asm__ __volatile__("movec %0, %%acr7"::"r"(CFG_SYS_CACHE_ACR7));
#endif
#else
__asm__ __volatile__("movec %0, %%acr0"::"r"(CFG_SYS_CACHE_ACR0));
@@ -55,10 +55,10 @@
*cf_icache_status = 0;
icache_invalid();
-#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
+#if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr2"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr3"::"r"(temp));
-#if defined(CONFIG_CF_V4E)
+#if defined(CFG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr6"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr7"::"r"(temp));
#endif
@@ -88,12 +88,12 @@
dcache_invalid();
*cf_dcache_status = 1;
-#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
+#if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr0"::"r"(CFG_SYS_CACHE_ACR0));
__asm__ __volatile__("movec %0, %%acr1"::"r"(CFG_SYS_CACHE_ACR1));
-#if defined(CONFIG_CF_V4E)
- __asm__ __volatile__("movec %0, %%acr4"::"r"(CONFIG_SYS_CACHE_ACR4));
- __asm__ __volatile__("movec %0, %%acr5"::"r"(CONFIG_SYS_CACHE_ACR5));
+#if defined(CFG_CF_V4E)
+ __asm__ __volatile__("movec %0, %%acr4"::"r"(CFG_SYS_CACHE_ACR4));
+ __asm__ __volatile__("movec %0, %%acr5"::"r"(CFG_SYS_CACHE_ACR5));
#endif
#endif
@@ -109,10 +109,10 @@
__asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
-#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
+#if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr0"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr1"::"r"(temp));
-#if defined(CONFIG_CF_V4E)
+#if defined(CFG_CF_V4E)
__asm__ __volatile__("movec %0, %%acr4"::"r"(temp));
__asm__ __volatile__("movec %0, %%acr5"::"r"(temp));
#endif
@@ -121,7 +121,7 @@
void dcache_invalid(void)
{
-#if defined(CONFIG_CF_V4) || defined(CONFIG_CF_V4E)
+#if defined(CONFIG_CF_V4) || defined(CFG_CF_V4E)
u32 temp;
temp = CFG_SYS_DCACHE_INV;
diff --git a/arch/m68k/lib/interrupts.c b/arch/m68k/lib/interrupts.c
index 1caef61..799daab 100644
--- a/arch/m68k/lib/interrupts.c
+++ b/arch/m68k/lib/interrupts.c
@@ -14,7 +14,7 @@
#include <asm/immap.h>
#include <asm/ptrace.h>
-#define NR_IRQS (CONFIG_SYS_NUM_IRQS)
+#define NR_IRQS (CFG_SYS_NUM_IRQS)
/*
* Interrupt vector functions.
diff --git a/arch/m68k/lib/time.c b/arch/m68k/lib/time.c
index cd7437b..2ce6908 100644
--- a/arch/m68k/lib/time.c
+++ b/arch/m68k/lib/time.c
@@ -21,23 +21,23 @@
static volatile ulong timestamp = 0;
-#ifndef CONFIG_SYS_WATCHDOG_FREQ
-#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
+#ifndef CFG_SYS_WATCHDOG_FREQ
+#define CFG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
#endif
#if defined(CONFIG_MCFTMR)
-#ifndef CONFIG_SYS_UDELAY_BASE
+#ifndef CFG_SYS_UDELAY_BASE
# error "uDelay base not defined!"
#endif
-#if !defined(CONFIG_SYS_TMR_BASE) || !defined(CONFIG_SYS_INTR_BASE) || !defined(CONFIG_SYS_TMRINTR_NO) || !defined(CONFIG_SYS_TMRINTR_MASK)
+#if !defined(CFG_SYS_TMR_BASE) || !defined(CFG_SYS_INTR_BASE) || !defined(CFG_SYS_TMRINTR_NO) || !defined(CFG_SYS_TMRINTR_MASK)
# error "TMR_BASE, INTR_BASE, TMRINTR_NO or TMRINTR_MASk not defined!"
#endif
extern void dtimer_intr_setup(void);
void __udelay(unsigned long usec)
{
- volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_UDELAY_BASE);
+ volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_UDELAY_BASE);
uint start, now, tmp;
while (usec > 0) {
@@ -52,7 +52,7 @@
timerp->tcn = 0;
/* set period to 1 us */
timerp->tmr =
- CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
+ CFG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 | DTIM_DTMR_FRR |
DTIM_DTMR_RST_EN;
start = now = timerp->tcn;
@@ -63,15 +63,15 @@
void dtimer_interrupt(void *not_used)
{
- volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
+ volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_TMR_BASE);
/* check for timer interrupt asserted */
- if ((CONFIG_SYS_TMRPND_REG & CONFIG_SYS_TMRINTR_MASK) == CONFIG_SYS_TMRINTR_PEND) {
+ if ((CFG_SYS_TMRPND_REG & CFG_SYS_TMRINTR_MASK) == CFG_SYS_TMRINTR_PEND) {
timerp->ter = (DTIM_DTER_CAP | DTIM_DTER_REF);
timestamp++;
#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
- if (CONFIG_SYS_WATCHDOG_FREQ && (timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0) {
+ if (CFG_SYS_WATCHDOG_FREQ && (timestamp % (CFG_SYS_WATCHDOG_FREQ)) == 0) {
schedule();
}
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
@@ -81,7 +81,7 @@
int timer_init(void)
{
- volatile dtmr_t *timerp = (dtmr_t *) (CONFIG_SYS_TMR_BASE);
+ volatile dtmr_t *timerp = (dtmr_t *) (CFG_SYS_TMR_BASE);
timestamp = 0;
@@ -92,7 +92,7 @@
timerp->tmr = DTIM_DTMR_RST_RST;
/* initialize and enable timer interrupt */
- irq_install_handler(CONFIG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
+ irq_install_handler(CFG_SYS_TMRINTR_NO, dtimer_interrupt, 0);
timerp->tcn = 0;
timerp->trr = 1000; /* Interrupt every ms */
@@ -100,7 +100,7 @@
dtimer_intr_setup();
/* set a period of 1us, set timer mode to restart and enable timer and interrupt */
- timerp->tmr = CONFIG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
+ timerp->tmr = CFG_SYS_TIMER_PRESCALER | DTIM_DTMR_CLK_DIV1 |
DTIM_DTMR_FRR | DTIM_DTMR_ORRI | DTIM_DTMR_RST_EN;
return 0;
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 23142bd..569f5f4 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -121,6 +121,7 @@
bool "Support Microchip PIC32"
select HAS_FIXED_TIMER_FREQUENCY
select DM
+ select DM_EVENT
select OF_CONTROL
imply CMD_DM
@@ -128,7 +129,6 @@
bool "Support Boston"
select HAS_FIXED_TIMER_FREQUENCY
select DM
- imply DM_EVENT
select DM_SERIAL
select MIPS_CM
select SYS_CACHE_SHIFT_6
diff --git a/arch/mips/mach-mtmips/mt7621/spl/start.S b/arch/mips/mach-mtmips/mt7621/spl/start.S
index 7063f32..d2f9c03 100644
--- a/arch/mips/mach-mtmips/mt7621/spl/start.S
+++ b/arch/mips/mach-mtmips/mt7621/spl/start.S
@@ -17,8 +17,8 @@
#include "../mt7621.h"
#include "dram.h"
-#ifndef CONFIG_SYS_INIT_SP_ADDR
-#define CONFIG_SYS_INIT_SP_ADDR (CFG_SYS_SDRAM_BASE + \
+#ifndef CFG_SYS_INIT_SP_ADDR
+#define CFG_SYS_INIT_SP_ADDR (CFG_SYS_SDRAM_BASE + \
CFG_SYS_INIT_SP_OFFSET)
#endif
@@ -31,7 +31,7 @@
.macro setup_stack_gd
li t0, -16
- PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR
+ PTR_LI t1, CFG_SYS_INIT_SP_ADDR
and sp, t1, t0 # force 16 byte alignment
PTR_SUBU \
sp, sp, GD_SIZE # reserve space for gd
@@ -201,7 +201,7 @@
#if CONFIG_IS_ENABLED(INIT_STACK_WITHOUT_MALLOC_F)
/* Set malloc base */
- li t0, (CONFIG_SYS_INIT_SP_ADDR + 15) & (~15)
+ li t0, (CFG_SYS_INIT_SP_ADDR + 15) & (~15)
PTR_S t0, GD_MALLOC_BASE(k0) # gd->malloc_base offset
#endif
diff --git a/arch/powerpc/cpu/mpc83xx/bats/bats.h b/arch/powerpc/cpu/mpc83xx/bats/bats.h
index f0754c2..2629cd5 100644
--- a/arch/powerpc/cpu/mpc83xx/bats/bats.h
+++ b/arch/powerpc/cpu/mpc83xx/bats/bats.h
@@ -1,223 +1,223 @@
#ifdef CONFIG_BAT0
-#define CONFIG_SYS_IBAT0L (\
+#define CFG_SYS_IBAT0L (\
(CONFIG_BAT0_BASE) |\
(CONFIG_BAT0_PAGE_PROTECTION) |\
(CONFIG_BAT0_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT0U (\
+#define CFG_SYS_IBAT0U (\
(CONFIG_BAT0_BASE) |\
(CONFIG_BAT0_LENGTH) |\
(CONFIG_BAT0_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT0L (\
+#define CFG_SYS_DBAT0L (\
(CONFIG_BAT0_BASE) |\
(CONFIG_BAT0_PAGE_PROTECTION) |\
(CONFIG_BAT0_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT0U (\
+#define CFG_SYS_DBAT0U (\
(CONFIG_BAT0_BASE) |\
(CONFIG_BAT0_LENGTH) |\
(CONFIG_BAT0_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT0L (0)
-#define CONFIG_SYS_IBAT0U (0)
-#define CONFIG_SYS_DBAT0L (0)
-#define CONFIG_SYS_DBAT0U (0)
+#define CFG_SYS_IBAT0L (0)
+#define CFG_SYS_IBAT0U (0)
+#define CFG_SYS_DBAT0L (0)
+#define CFG_SYS_DBAT0U (0)
#endif /* CONFIG_BAT0 */
#ifdef CONFIG_BAT1
-#define CONFIG_SYS_IBAT1L (\
+#define CFG_SYS_IBAT1L (\
(CONFIG_BAT1_BASE) |\
(CONFIG_BAT1_PAGE_PROTECTION) |\
(CONFIG_BAT1_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT1U (\
+#define CFG_SYS_IBAT1U (\
(CONFIG_BAT1_BASE) |\
(CONFIG_BAT1_LENGTH) |\
(CONFIG_BAT1_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT1L (\
+#define CFG_SYS_DBAT1L (\
(CONFIG_BAT1_BASE) |\
(CONFIG_BAT1_PAGE_PROTECTION) |\
(CONFIG_BAT1_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT1U (\
+#define CFG_SYS_DBAT1U (\
(CONFIG_BAT1_BASE) |\
(CONFIG_BAT1_LENGTH) |\
(CONFIG_BAT1_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT1L (0)
-#define CONFIG_SYS_IBAT1U (0)
-#define CONFIG_SYS_DBAT1L (0)
-#define CONFIG_SYS_DBAT1U (0)
+#define CFG_SYS_IBAT1L (0)
+#define CFG_SYS_IBAT1U (0)
+#define CFG_SYS_DBAT1L (0)
+#define CFG_SYS_DBAT1U (0)
#endif /* CONFIG_BAT1 */
#ifdef CONFIG_BAT2
-#define CONFIG_SYS_IBAT2L (\
+#define CFG_SYS_IBAT2L (\
(CONFIG_BAT2_BASE) |\
(CONFIG_BAT2_PAGE_PROTECTION) |\
(CONFIG_BAT2_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT2U (\
+#define CFG_SYS_IBAT2U (\
(CONFIG_BAT2_BASE) |\
(CONFIG_BAT2_LENGTH) |\
(CONFIG_BAT2_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT2L (\
+#define CFG_SYS_DBAT2L (\
(CONFIG_BAT2_BASE) |\
(CONFIG_BAT2_PAGE_PROTECTION) |\
(CONFIG_BAT2_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT2U (\
+#define CFG_SYS_DBAT2U (\
(CONFIG_BAT2_BASE) |\
(CONFIG_BAT2_LENGTH) |\
(CONFIG_BAT2_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT2L (0)
-#define CONFIG_SYS_IBAT2U (0)
-#define CONFIG_SYS_DBAT2L (0)
-#define CONFIG_SYS_DBAT2U (0)
+#define CFG_SYS_IBAT2L (0)
+#define CFG_SYS_IBAT2U (0)
+#define CFG_SYS_DBAT2L (0)
+#define CFG_SYS_DBAT2U (0)
#endif /* CONFIG_BAT2 */
#ifdef CONFIG_BAT3
-#define CONFIG_SYS_IBAT3L (\
+#define CFG_SYS_IBAT3L (\
(CONFIG_BAT3_BASE) |\
(CONFIG_BAT3_PAGE_PROTECTION) |\
(CONFIG_BAT3_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT3U (\
+#define CFG_SYS_IBAT3U (\
(CONFIG_BAT3_BASE) |\
(CONFIG_BAT3_LENGTH) |\
(CONFIG_BAT3_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT3L (\
+#define CFG_SYS_DBAT3L (\
(CONFIG_BAT3_BASE) |\
(CONFIG_BAT3_PAGE_PROTECTION) |\
(CONFIG_BAT3_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT3U (\
+#define CFG_SYS_DBAT3U (\
(CONFIG_BAT3_BASE) |\
(CONFIG_BAT3_LENGTH) |\
(CONFIG_BAT3_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT3L (0)
-#define CONFIG_SYS_IBAT3U (0)
-#define CONFIG_SYS_DBAT3L (0)
-#define CONFIG_SYS_DBAT3U (0)
+#define CFG_SYS_IBAT3L (0)
+#define CFG_SYS_IBAT3U (0)
+#define CFG_SYS_DBAT3L (0)
+#define CFG_SYS_DBAT3U (0)
#endif /* CONFIG_BAT3 */
#ifdef CONFIG_BAT4
-#define CONFIG_SYS_IBAT4L (\
+#define CFG_SYS_IBAT4L (\
(CONFIG_BAT4_BASE) |\
(CONFIG_BAT4_PAGE_PROTECTION) |\
(CONFIG_BAT4_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT4U (\
+#define CFG_SYS_IBAT4U (\
(CONFIG_BAT4_BASE) |\
(CONFIG_BAT4_LENGTH) |\
(CONFIG_BAT4_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT4L (\
+#define CFG_SYS_DBAT4L (\
(CONFIG_BAT4_BASE) |\
(CONFIG_BAT4_PAGE_PROTECTION) |\
(CONFIG_BAT4_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT4U (\
+#define CFG_SYS_DBAT4U (\
(CONFIG_BAT4_BASE) |\
(CONFIG_BAT4_LENGTH) |\
(CONFIG_BAT4_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT4L (0)
-#define CONFIG_SYS_IBAT4U (0)
-#define CONFIG_SYS_DBAT4L (0)
-#define CONFIG_SYS_DBAT4U (0)
+#define CFG_SYS_IBAT4L (0)
+#define CFG_SYS_IBAT4U (0)
+#define CFG_SYS_DBAT4L (0)
+#define CFG_SYS_DBAT4U (0)
#endif /* CONFIG_BAT4 */
#ifdef CONFIG_BAT5
-#define CONFIG_SYS_IBAT5L (\
+#define CFG_SYS_IBAT5L (\
(CONFIG_BAT5_BASE) |\
(CONFIG_BAT5_PAGE_PROTECTION) |\
(CONFIG_BAT5_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT5U (\
+#define CFG_SYS_IBAT5U (\
(CONFIG_BAT5_BASE) |\
(CONFIG_BAT5_LENGTH) |\
(CONFIG_BAT5_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT5L (\
+#define CFG_SYS_DBAT5L (\
(CONFIG_BAT5_BASE) |\
(CONFIG_BAT5_PAGE_PROTECTION) |\
(CONFIG_BAT5_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT5U (\
+#define CFG_SYS_DBAT5U (\
(CONFIG_BAT5_BASE) |\
(CONFIG_BAT5_LENGTH) |\
(CONFIG_BAT5_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT5L (0)
-#define CONFIG_SYS_IBAT5U (0)
-#define CONFIG_SYS_DBAT5L (0)
-#define CONFIG_SYS_DBAT5U (0)
+#define CFG_SYS_IBAT5L (0)
+#define CFG_SYS_IBAT5U (0)
+#define CFG_SYS_DBAT5L (0)
+#define CFG_SYS_DBAT5U (0)
#endif /* CONFIG_BAT5 */
#ifdef CONFIG_BAT6
-#define CONFIG_SYS_IBAT6L (\
+#define CFG_SYS_IBAT6L (\
(CONFIG_BAT6_BASE) |\
(CONFIG_BAT6_PAGE_PROTECTION) |\
(CONFIG_BAT6_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT6U (\
+#define CFG_SYS_IBAT6U (\
(CONFIG_BAT6_BASE) |\
(CONFIG_BAT6_LENGTH) |\
(CONFIG_BAT6_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT6L (\
+#define CFG_SYS_DBAT6L (\
(CONFIG_BAT6_BASE) |\
(CONFIG_BAT6_PAGE_PROTECTION) |\
(CONFIG_BAT6_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT6U (\
+#define CFG_SYS_DBAT6U (\
(CONFIG_BAT6_BASE) |\
(CONFIG_BAT6_LENGTH) |\
(CONFIG_BAT6_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT6L (0)
-#define CONFIG_SYS_IBAT6U (0)
-#define CONFIG_SYS_DBAT6L (0)
-#define CONFIG_SYS_DBAT6U (0)
+#define CFG_SYS_IBAT6L (0)
+#define CFG_SYS_IBAT6U (0)
+#define CFG_SYS_DBAT6L (0)
+#define CFG_SYS_DBAT6U (0)
#endif /* CONFIG_BAT6 */
#ifdef CONFIG_BAT7
-#define CONFIG_SYS_IBAT7L (\
+#define CFG_SYS_IBAT7L (\
(CONFIG_BAT7_BASE) |\
(CONFIG_BAT7_PAGE_PROTECTION) |\
(CONFIG_BAT7_WIMG_ICACHE) \
)
-#define CONFIG_SYS_IBAT7U (\
+#define CFG_SYS_IBAT7U (\
(CONFIG_BAT7_BASE) |\
(CONFIG_BAT7_LENGTH) |\
(CONFIG_BAT7_VALID_BITS) \
)
-#define CONFIG_SYS_DBAT7L (\
+#define CFG_SYS_DBAT7L (\
(CONFIG_BAT7_BASE) |\
(CONFIG_BAT7_PAGE_PROTECTION) |\
(CONFIG_BAT7_WIMG_DCACHE) \
)
-#define CONFIG_SYS_DBAT7U (\
+#define CFG_SYS_DBAT7U (\
(CONFIG_BAT7_BASE) |\
(CONFIG_BAT7_LENGTH) |\
(CONFIG_BAT7_VALID_BITS) \
)
#else
-#define CONFIG_SYS_IBAT7L (0)
-#define CONFIG_SYS_IBAT7U (0)
-#define CONFIG_SYS_DBAT7L (0)
-#define CONFIG_SYS_DBAT7U (0)
+#define CFG_SYS_IBAT7L (0)
+#define CFG_SYS_IBAT7U (0)
+#define CFG_SYS_DBAT7L (0)
+#define CFG_SYS_DBAT7U (0)
#endif /* CONFIG_BAT7 */
diff --git a/arch/powerpc/cpu/mpc83xx/cpu_init.c b/arch/powerpc/cpu/mpc83xx/cpu_init.c
index 63c2729..2af5c89 100644
--- a/arch/powerpc/cpu/mpc83xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc83xx/cpu_init.c
@@ -208,24 +208,24 @@
init_early_memctl_regs();
/* Local Access window setup */
-#if defined(CONFIG_SYS_LBLAWBAR0_PRELIM) && defined(CONFIG_SYS_LBLAWAR0_PRELIM)
- im->sysconf.lblaw[0].bar = CONFIG_SYS_LBLAWBAR0_PRELIM;
- im->sysconf.lblaw[0].ar = CONFIG_SYS_LBLAWAR0_PRELIM;
+#if defined(CFG_SYS_LBLAWBAR0_PRELIM) && defined(CFG_SYS_LBLAWAR0_PRELIM)
+ im->sysconf.lblaw[0].bar = CFG_SYS_LBLAWBAR0_PRELIM;
+ im->sysconf.lblaw[0].ar = CFG_SYS_LBLAWAR0_PRELIM;
#else
-#error CONFIG_SYS_LBLAWBAR0_PRELIM & CONFIG_SYS_LBLAWAR0_PRELIM must be defined
+#error CFG_SYS_LBLAWBAR0_PRELIM & CFG_SYS_LBLAWAR0_PRELIM must be defined
#endif
-#if defined(CONFIG_SYS_LBLAWBAR1_PRELIM) && defined(CONFIG_SYS_LBLAWAR1_PRELIM)
- im->sysconf.lblaw[1].bar = CONFIG_SYS_LBLAWBAR1_PRELIM;
- im->sysconf.lblaw[1].ar = CONFIG_SYS_LBLAWAR1_PRELIM;
+#if defined(CFG_SYS_LBLAWBAR1_PRELIM) && defined(CFG_SYS_LBLAWAR1_PRELIM)
+ im->sysconf.lblaw[1].bar = CFG_SYS_LBLAWBAR1_PRELIM;
+ im->sysconf.lblaw[1].ar = CFG_SYS_LBLAWAR1_PRELIM;
#endif
-#if defined(CONFIG_SYS_LBLAWBAR2_PRELIM) && defined(CONFIG_SYS_LBLAWAR2_PRELIM)
- im->sysconf.lblaw[2].bar = CONFIG_SYS_LBLAWBAR2_PRELIM;
- im->sysconf.lblaw[2].ar = CONFIG_SYS_LBLAWAR2_PRELIM;
+#if defined(CFG_SYS_LBLAWBAR2_PRELIM) && defined(CFG_SYS_LBLAWAR2_PRELIM)
+ im->sysconf.lblaw[2].bar = CFG_SYS_LBLAWBAR2_PRELIM;
+ im->sysconf.lblaw[2].ar = CFG_SYS_LBLAWAR2_PRELIM;
#endif
-#if defined(CONFIG_SYS_LBLAWBAR3_PRELIM) && defined(CONFIG_SYS_LBLAWAR3_PRELIM)
- im->sysconf.lblaw[3].bar = CONFIG_SYS_LBLAWBAR3_PRELIM;
- im->sysconf.lblaw[3].ar = CONFIG_SYS_LBLAWAR3_PRELIM;
+#if defined(CFG_SYS_LBLAWBAR3_PRELIM) && defined(CFG_SYS_LBLAWAR3_PRELIM)
+ im->sysconf.lblaw[3].bar = CFG_SYS_LBLAWBAR3_PRELIM;
+ im->sysconf.lblaw[3].ar = CFG_SYS_LBLAWAR3_PRELIM;
#endif
#if defined(CONFIG_SYS_LBLAWBAR4_PRELIM) && defined(CONFIG_SYS_LBLAWAR4_PRELIM)
im->sysconf.lblaw[4].bar = CONFIG_SYS_LBLAWBAR4_PRELIM;
diff --git a/arch/powerpc/cpu/mpc83xx/hid/hid.h b/arch/powerpc/cpu/mpc83xx/hid/hid.h
index 9f5260c..089d1d7 100644
--- a/arch/powerpc/cpu/mpc83xx/hid/hid.h
+++ b/arch/powerpc/cpu/mpc83xx/hid/hid.h
@@ -1,4 +1,4 @@
-#define CONFIG_SYS_HID0_FINAL ( \
+#define CFG_SYS_HID0_FINAL ( \
CONFIG_HID0_FINAL_ABE_BIT |\
CONFIG_HID0_FINAL_CLKOUT |\
CONFIG_HID0_FINAL_DCE_BIT |\
@@ -24,7 +24,7 @@
CONFIG_HID0_FINAL_SLEEP_BIT \
)
-#define CONFIG_SYS_HID0_INIT ( \
+#define CFG_SYS_HID0_INIT ( \
CONFIG_HID0_INIT_ABE_BIT |\
CONFIG_HID0_INIT_CLKOUT |\
CONFIG_HID0_INIT_DCE_BIT |\
@@ -50,12 +50,12 @@
#ifdef CONFIG_TARGET_IDS8313
/* IDS8313 defines a reserved bit; keep to not break compatibility */
-#define CONFIG_HID2_SPECIAL 0x00020000
+#define CFG_HID2_SPECIAL 0x00020000
#else
-#define CONFIG_HID2_SPECIAL 0x0
+#define CFG_HID2_SPECIAL 0x0
#endif
-#define CONFIG_SYS_HID2 ( \
+#define CFG_SYS_HID2 ( \
CONFIG_HID2_LET_BIT |\
CONFIG_HID2_IFEB_BIT |\
CONFIG_HID2_MESISTATE_BIT |\
@@ -68,5 +68,5 @@
CONFIG_HID2_IWLCK |\
CONFIG_HID2_ICWP_BIT |\
CONFIG_HID2_DWLCK |\
- CONFIG_HID2_SPECIAL \
+ CFG_HID2_SPECIAL \
)
diff --git a/arch/powerpc/cpu/mpc83xx/hrcw/hrcw.h b/arch/powerpc/cpu/mpc83xx/hrcw/hrcw.h
index 0f34267..7f8787f 100644
--- a/arch/powerpc/cpu/mpc83xx/hrcw/hrcw.h
+++ b/arch/powerpc/cpu/mpc83xx/hrcw/hrcw.h
@@ -1,4 +1,4 @@
-#define CONFIG_SYS_HRCW_LOW (\
+#define CFG_SYS_HRCW_LOW (\
(CONFIG_LBMC_CLOCK_MODE << (31 - 0)) |\
(CONFIG_DDR_MC_CLOCK_MODE << (31 - 1)) |\
(CONFIG_SYSTEM_PLL_VCO_DIV << (31 - 3)) |\
@@ -9,7 +9,7 @@
(CONFIG_QUICC_MULT_FACTOR << (31 - 31)) \
)
-#define CONFIG_SYS_HRCW_HIGH (\
+#define CFG_SYS_HRCW_HIGH (\
(CONFIG_PCI_HOST_MODE << (31 - 0)) |\
(CONFIG_PCI_64BIT_MODE << (31 - 1)) |\
(CONFIG_PCI_INT_ARBITER1 << (31 - 2)) |\
diff --git a/arch/powerpc/cpu/mpc83xx/lblaw/lblaw.h b/arch/powerpc/cpu/mpc83xx/lblaw/lblaw.h
index 6972afc..082b2b9 100644
--- a/arch/powerpc/cpu/mpc83xx/lblaw/lblaw.h
+++ b/arch/powerpc/cpu/mpc83xx/lblaw/lblaw.h
@@ -1,55 +1,55 @@
#if defined(CONFIG_LBLAW0)
-#define CONFIG_SYS_LBLAWBAR0_PRELIM \
+#define CFG_SYS_LBLAWBAR0_PRELIM \
CONFIG_LBLAW0_BASE
-#define CONFIG_SYS_LBLAWAR0_PRELIM (\
+#define CFG_SYS_LBLAWAR0_PRELIM (\
CONFIG_LBLAW0_ENABLE_BIT |\
CONFIG_LBLAW0_LENGTH \
)
#endif
#if defined(CONFIG_LBLAW1)
-#define CONFIG_SYS_LBLAWBAR1_PRELIM \
+#define CFG_SYS_LBLAWBAR1_PRELIM \
CONFIG_LBLAW1_BASE
-#define CONFIG_SYS_LBLAWAR1_PRELIM (\
+#define CFG_SYS_LBLAWAR1_PRELIM (\
CONFIG_LBLAW1_ENABLE_BIT |\
CONFIG_LBLAW1_LENGTH \
)
#endif
#if defined(CONFIG_LBLAW2)
-#define CONFIG_SYS_LBLAWBAR2_PRELIM \
+#define CFG_SYS_LBLAWBAR2_PRELIM \
CONFIG_LBLAW2_BASE
-#define CONFIG_SYS_LBLAWAR2_PRELIM (\
+#define CFG_SYS_LBLAWAR2_PRELIM (\
CONFIG_LBLAW2_ENABLE_BIT |\
CONFIG_LBLAW2_LENGTH \
)
#endif
#if defined(CONFIG_LBLAW3)
-#define CONFIG_SYS_LBLAWBAR3_PRELIM \
+#define CFG_SYS_LBLAWBAR3_PRELIM \
CONFIG_LBLAW3_BASE
-#define CONFIG_SYS_LBLAWAR3_PRELIM (\
+#define CFG_SYS_LBLAWAR3_PRELIM (\
CONFIG_LBLAW3_ENABLE_BIT |\
CONFIG_LBLAW3_LENGTH \
)
#endif
#ifdef CONFIG_NAND_LBLAWBAR_PRELIM_0
-#define CONFIG_SYS_NAND_LBLAWBAR_PRELIM CONFIG_SYS_LBLAWBAR0_PRELIM
-#define CONFIG_SYS_NAND_LBLAWAR_PRELIM CONFIG_SYS_LBLAWAR0_PRELIM
+#define CFG_SYS_NAND_LBLAWBAR_PRELIM CFG_SYS_LBLAWBAR0_PRELIM
+#define CFG_SYS_NAND_LBLAWAR_PRELIM CFG_SYS_LBLAWAR0_PRELIM
#endif
#ifdef CONFIG_NAND_LBLAWBAR_PRELIM_1
-#define CONFIG_SYS_NAND_LBLAWBAR_PRELIM CONFIG_SYS_LBLAWBAR1_PRELIM
-#define CONFIG_SYS_NAND_LBLAWAR_PRELIM CONFIG_SYS_LBLAWAR1_PRELIM
+#define CFG_SYS_NAND_LBLAWBAR_PRELIM CFG_SYS_LBLAWBAR1_PRELIM
+#define CFG_SYS_NAND_LBLAWAR_PRELIM CFG_SYS_LBLAWAR1_PRELIM
#endif
#ifdef CONFIG_NAND_LBLAWBAR_PRELIM_2
-#define CONFIG_SYS_NAND_LBLAWBAR_PRELIM CONFIG_SYS_LBLAWBAR2_PRELIM
-#define CONFIG_SYS_NAND_LBLAWAR_PRELIM CONFIG_SYS_LBLAWAR2_PRELIM
+#define CFG_SYS_NAND_LBLAWBAR_PRELIM CFG_SYS_LBLAWBAR2_PRELIM
+#define CFG_SYS_NAND_LBLAWAR_PRELIM CFG_SYS_LBLAWAR2_PRELIM
#endif
#ifdef CONFIG_NAND_LBLAWBAR_PRELIM_3
-#define CONFIG_SYS_NAND_LBLAWBAR_PRELIM CONFIG_SYS_LBLAWBAR3_PRELIM
-#define CONFIG_SYS_NAND_LBLAWAR_PRELIM CONFIG_SYS_LBLAWAR3_PRELIM
+#define CFG_SYS_NAND_LBLAWBAR_PRELIM CFG_SYS_LBLAWBAR3_PRELIM
+#define CFG_SYS_NAND_LBLAWAR_PRELIM CFG_SYS_LBLAWAR3_PRELIM
#endif
diff --git a/arch/powerpc/cpu/mpc83xx/spd_sdram.c b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
index 4f982b8..6da8fc4 100644
--- a/arch/powerpc/cpu/mpc83xx/spd_sdram.c
+++ b/arch/powerpc/cpu/mpc83xx/spd_sdram.c
@@ -66,8 +66,8 @@
}
#ifdef CONFIG_SPD_EEPROM
-#ifndef CONFIG_SYS_READ_SPD
-#define CONFIG_SYS_READ_SPD i2c_read
+#ifndef CFG_SYS_READ_SPD
+#define CFG_SYS_READ_SPD i2c_read
#endif
#ifndef SPD_EEPROM_OFFSET
#define SPD_EEPROM_OFFSET 0
@@ -167,7 +167,7 @@
isync();
/* Read SPD parameters with I2C */
- CONFIG_SYS_READ_SPD(SPD_EEPROM_ADDRESS, SPD_EEPROM_OFFSET,
+ CFG_SYS_READ_SPD(SPD_EEPROM_ADDRESS, SPD_EEPROM_OFFSET,
SPD_EEPROM_ADDR_LEN, (uchar *) &spd, sizeof(spd));
#ifdef SPD_DEBUG
spd_debug(&spd);
diff --git a/arch/powerpc/cpu/mpc83xx/spl_minimal.c b/arch/powerpc/cpu/mpc83xx/spl_minimal.c
index 7cc0383..b55bfaf 100644
--- a/arch/powerpc/cpu/mpc83xx/spl_minimal.c
+++ b/arch/powerpc/cpu/mpc83xx/spl_minimal.c
@@ -73,14 +73,14 @@
#if defined(CFG_SYS_NAND_BR_PRELIM) \
&& defined(CFG_SYS_NAND_OR_PRELIM) \
- && defined(CONFIG_SYS_NAND_LBLAWBAR_PRELIM) \
- && defined(CONFIG_SYS_NAND_LBLAWAR_PRELIM)
+ && defined(CFG_SYS_NAND_LBLAWBAR_PRELIM) \
+ && defined(CFG_SYS_NAND_LBLAWAR_PRELIM)
set_lbc_br(0, CFG_SYS_NAND_BR_PRELIM);
set_lbc_or(0, CFG_SYS_NAND_OR_PRELIM);
- im->sysconf.lblaw[0].bar = CONFIG_SYS_NAND_LBLAWBAR_PRELIM;
- im->sysconf.lblaw[0].ar = CONFIG_SYS_NAND_LBLAWAR_PRELIM;
+ im->sysconf.lblaw[0].bar = CFG_SYS_NAND_LBLAWBAR_PRELIM;
+ im->sysconf.lblaw[0].ar = CFG_SYS_NAND_LBLAWAR_PRELIM;
#else
-#error CFG_SYS_NAND_BR_PRELIM, CFG_SYS_NAND_OR_PRELIM, CONFIG_SYS_NAND_LBLAWBAR_PRELIM & CONFIG_SYS_NAND_LBLAWAR_PRELIM must be defined
+#error CFG_SYS_NAND_BR_PRELIM, CFG_SYS_NAND_OR_PRELIM, CFG_SYS_NAND_LBLAWBAR_PRELIM & CFG_SYS_NAND_LBLAWAR_PRELIM must be defined
#endif
}
diff --git a/arch/powerpc/cpu/mpc83xx/start.S b/arch/powerpc/cpu/mpc83xx/start.S
index 52326f0..e3878e4 100644
--- a/arch/powerpc/cpu/mpc83xx/start.S
+++ b/arch/powerpc/cpu/mpc83xx/start.S
@@ -46,7 +46,7 @@
#if !defined(CONFIG_SPL_BUILD) && !defined(CONFIG_NAND_SPL) && \
!defined(CONFIG_SYS_RAMBOOT)
-#define CONFIG_SYS_FLASHBOOT
+#define CFG_SYS_FLASHBOOT
#endif
/*
@@ -81,8 +81,8 @@
.fill 8,1,(((w)>> 8)&0xff); \
.fill 8,1,(((w) )&0xff)
- _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_LOW)
- _HRCW_TABLE_ENTRY(CONFIG_SYS_HRCW_HIGH)
+ _HRCW_TABLE_ENTRY(CFG_SYS_HRCW_LOW)
+ _HRCW_TABLE_ENTRY(CFG_SYS_HRCW_HIGH)
/*
* Magic number and version string - put it after the HRCW since it
@@ -180,7 +180,7 @@
bl init_e300_core
-#ifdef CONFIG_SYS_FLASHBOOT
+#ifdef CFG_SYS_FLASHBOOT
/* Inflate flash location so it appears everywhere, calculate */
/* the absolute address in final location of the FLASH, jump */
@@ -196,7 +196,7 @@
#if 1 /* Remapping flash with LAW0. */
bl remap_flash_by_law0
#endif
-#endif /* CONFIG_SYS_FLASHBOOT */
+#endif /* CFG_SYS_FLASHBOOT */
/* setup the bats */
bl setup_bats
@@ -525,18 +525,18 @@
/* - force invalidation of data and instruction caches */
/*------------------------------------------------------*/
- lis r3, CONFIG_SYS_HID0_INIT@h
- ori r3, r3, (CONFIG_SYS_HID0_INIT | HID0_ICFI | HID0_DCFI)@l
+ lis r3, CFG_SYS_HID0_INIT@h
+ ori r3, r3, (CFG_SYS_HID0_INIT | HID0_ICFI | HID0_DCFI)@l
SYNC
mtspr HID0, r3
- lis r3, CONFIG_SYS_HID0_FINAL@h
- ori r3, r3, (CONFIG_SYS_HID0_FINAL & ~(HID0_ICFI | HID0_DCFI))@l
+ lis r3, CFG_SYS_HID0_FINAL@h
+ ori r3, r3, (CFG_SYS_HID0_FINAL & ~(HID0_ICFI | HID0_DCFI))@l
SYNC
mtspr HID0, r3
- lis r3, CONFIG_SYS_HID2@h
- ori r3, r3, CONFIG_SYS_HID2@l
+ lis r3, CFG_SYS_HID2@h
+ ori r3, r3, CFG_SYS_HID2@l
SYNC
mtspr HID2, r3
@@ -550,131 +550,131 @@
addis r0, r0, 0x0000
/* IBAT 0 */
- addis r4, r0, CONFIG_SYS_IBAT0L@h
- ori r4, r4, CONFIG_SYS_IBAT0L@l
- addis r3, r0, CONFIG_SYS_IBAT0U@h
- ori r3, r3, CONFIG_SYS_IBAT0U@l
+ addis r4, r0, CFG_SYS_IBAT0L@h
+ ori r4, r4, CFG_SYS_IBAT0L@l
+ addis r3, r0, CFG_SYS_IBAT0U@h
+ ori r3, r3, CFG_SYS_IBAT0U@l
mtspr IBAT0L, r4
mtspr IBAT0U, r3
/* DBAT 0 */
- addis r4, r0, CONFIG_SYS_DBAT0L@h
- ori r4, r4, CONFIG_SYS_DBAT0L@l
- addis r3, r0, CONFIG_SYS_DBAT0U@h
- ori r3, r3, CONFIG_SYS_DBAT0U@l
+ addis r4, r0, CFG_SYS_DBAT0L@h
+ ori r4, r4, CFG_SYS_DBAT0L@l
+ addis r3, r0, CFG_SYS_DBAT0U@h
+ ori r3, r3, CFG_SYS_DBAT0U@l
mtspr DBAT0L, r4
mtspr DBAT0U, r3
/* IBAT 1 */
- addis r4, r0, CONFIG_SYS_IBAT1L@h
- ori r4, r4, CONFIG_SYS_IBAT1L@l
- addis r3, r0, CONFIG_SYS_IBAT1U@h
- ori r3, r3, CONFIG_SYS_IBAT1U@l
+ addis r4, r0, CFG_SYS_IBAT1L@h
+ ori r4, r4, CFG_SYS_IBAT1L@l
+ addis r3, r0, CFG_SYS_IBAT1U@h
+ ori r3, r3, CFG_SYS_IBAT1U@l
mtspr IBAT1L, r4
mtspr IBAT1U, r3
/* DBAT 1 */
- addis r4, r0, CONFIG_SYS_DBAT1L@h
- ori r4, r4, CONFIG_SYS_DBAT1L@l
- addis r3, r0, CONFIG_SYS_DBAT1U@h
- ori r3, r3, CONFIG_SYS_DBAT1U@l
+ addis r4, r0, CFG_SYS_DBAT1L@h
+ ori r4, r4, CFG_SYS_DBAT1L@l
+ addis r3, r0, CFG_SYS_DBAT1U@h
+ ori r3, r3, CFG_SYS_DBAT1U@l
mtspr DBAT1L, r4
mtspr DBAT1U, r3
/* IBAT 2 */
- addis r4, r0, CONFIG_SYS_IBAT2L@h
- ori r4, r4, CONFIG_SYS_IBAT2L@l
- addis r3, r0, CONFIG_SYS_IBAT2U@h
- ori r3, r3, CONFIG_SYS_IBAT2U@l
+ addis r4, r0, CFG_SYS_IBAT2L@h
+ ori r4, r4, CFG_SYS_IBAT2L@l
+ addis r3, r0, CFG_SYS_IBAT2U@h
+ ori r3, r3, CFG_SYS_IBAT2U@l
mtspr IBAT2L, r4
mtspr IBAT2U, r3
/* DBAT 2 */
- addis r4, r0, CONFIG_SYS_DBAT2L@h
- ori r4, r4, CONFIG_SYS_DBAT2L@l
- addis r3, r0, CONFIG_SYS_DBAT2U@h
- ori r3, r3, CONFIG_SYS_DBAT2U@l
+ addis r4, r0, CFG_SYS_DBAT2L@h
+ ori r4, r4, CFG_SYS_DBAT2L@l
+ addis r3, r0, CFG_SYS_DBAT2U@h
+ ori r3, r3, CFG_SYS_DBAT2U@l
mtspr DBAT2L, r4
mtspr DBAT2U, r3
/* IBAT 3 */
- addis r4, r0, CONFIG_SYS_IBAT3L@h
- ori r4, r4, CONFIG_SYS_IBAT3L@l
- addis r3, r0, CONFIG_SYS_IBAT3U@h
- ori r3, r3, CONFIG_SYS_IBAT3U@l
+ addis r4, r0, CFG_SYS_IBAT3L@h
+ ori r4, r4, CFG_SYS_IBAT3L@l
+ addis r3, r0, CFG_SYS_IBAT3U@h
+ ori r3, r3, CFG_SYS_IBAT3U@l
mtspr IBAT3L, r4
mtspr IBAT3U, r3
/* DBAT 3 */
- addis r4, r0, CONFIG_SYS_DBAT3L@h
- ori r4, r4, CONFIG_SYS_DBAT3L@l
- addis r3, r0, CONFIG_SYS_DBAT3U@h
- ori r3, r3, CONFIG_SYS_DBAT3U@l
+ addis r4, r0, CFG_SYS_DBAT3L@h
+ ori r4, r4, CFG_SYS_DBAT3L@l
+ addis r3, r0, CFG_SYS_DBAT3U@h
+ ori r3, r3, CFG_SYS_DBAT3U@l
mtspr DBAT3L, r4
mtspr DBAT3U, r3
#ifdef CONFIG_HIGH_BATS
/* IBAT 4 */
- addis r4, r0, CONFIG_SYS_IBAT4L@h
- ori r4, r4, CONFIG_SYS_IBAT4L@l
- addis r3, r0, CONFIG_SYS_IBAT4U@h
- ori r3, r3, CONFIG_SYS_IBAT4U@l
+ addis r4, r0, CFG_SYS_IBAT4L@h
+ ori r4, r4, CFG_SYS_IBAT4L@l
+ addis r3, r0, CFG_SYS_IBAT4U@h
+ ori r3, r3, CFG_SYS_IBAT4U@l
mtspr IBAT4L, r4
mtspr IBAT4U, r3
/* DBAT 4 */
- addis r4, r0, CONFIG_SYS_DBAT4L@h
- ori r4, r4, CONFIG_SYS_DBAT4L@l
- addis r3, r0, CONFIG_SYS_DBAT4U@h
- ori r3, r3, CONFIG_SYS_DBAT4U@l
+ addis r4, r0, CFG_SYS_DBAT4L@h
+ ori r4, r4, CFG_SYS_DBAT4L@l
+ addis r3, r0, CFG_SYS_DBAT4U@h
+ ori r3, r3, CFG_SYS_DBAT4U@l
mtspr DBAT4L, r4
mtspr DBAT4U, r3
/* IBAT 5 */
- addis r4, r0, CONFIG_SYS_IBAT5L@h
- ori r4, r4, CONFIG_SYS_IBAT5L@l
- addis r3, r0, CONFIG_SYS_IBAT5U@h
- ori r3, r3, CONFIG_SYS_IBAT5U@l
+ addis r4, r0, CFG_SYS_IBAT5L@h
+ ori r4, r4, CFG_SYS_IBAT5L@l
+ addis r3, r0, CFG_SYS_IBAT5U@h
+ ori r3, r3, CFG_SYS_IBAT5U@l
mtspr IBAT5L, r4
mtspr IBAT5U, r3
/* DBAT 5 */
- addis r4, r0, CONFIG_SYS_DBAT5L@h
- ori r4, r4, CONFIG_SYS_DBAT5L@l
- addis r3, r0, CONFIG_SYS_DBAT5U@h
- ori r3, r3, CONFIG_SYS_DBAT5U@l
+ addis r4, r0, CFG_SYS_DBAT5L@h
+ ori r4, r4, CFG_SYS_DBAT5L@l
+ addis r3, r0, CFG_SYS_DBAT5U@h
+ ori r3, r3, CFG_SYS_DBAT5U@l
mtspr DBAT5L, r4
mtspr DBAT5U, r3
/* IBAT 6 */
- addis r4, r0, CONFIG_SYS_IBAT6L@h
- ori r4, r4, CONFIG_SYS_IBAT6L@l
- addis r3, r0, CONFIG_SYS_IBAT6U@h
- ori r3, r3, CONFIG_SYS_IBAT6U@l
+ addis r4, r0, CFG_SYS_IBAT6L@h
+ ori r4, r4, CFG_SYS_IBAT6L@l
+ addis r3, r0, CFG_SYS_IBAT6U@h
+ ori r3, r3, CFG_SYS_IBAT6U@l
mtspr IBAT6L, r4
mtspr IBAT6U, r3
/* DBAT 6 */
- addis r4, r0, CONFIG_SYS_DBAT6L@h
- ori r4, r4, CONFIG_SYS_DBAT6L@l
- addis r3, r0, CONFIG_SYS_DBAT6U@h
- ori r3, r3, CONFIG_SYS_DBAT6U@l
+ addis r4, r0, CFG_SYS_DBAT6L@h
+ ori r4, r4, CFG_SYS_DBAT6L@l
+ addis r3, r0, CFG_SYS_DBAT6U@h
+ ori r3, r3, CFG_SYS_DBAT6U@l
mtspr DBAT6L, r4
mtspr DBAT6U, r3
/* IBAT 7 */
- addis r4, r0, CONFIG_SYS_IBAT7L@h
- ori r4, r4, CONFIG_SYS_IBAT7L@l
- addis r3, r0, CONFIG_SYS_IBAT7U@h
- ori r3, r3, CONFIG_SYS_IBAT7U@l
+ addis r4, r0, CFG_SYS_IBAT7L@h
+ ori r4, r4, CFG_SYS_IBAT7L@l
+ addis r3, r0, CFG_SYS_IBAT7U@h
+ ori r3, r3, CFG_SYS_IBAT7U@l
mtspr IBAT7L, r4
mtspr IBAT7U, r3
/* DBAT 7 */
- addis r4, r0, CONFIG_SYS_DBAT7L@h
- ori r4, r4, CONFIG_SYS_DBAT7L@l
- addis r3, r0, CONFIG_SYS_DBAT7U@h
- ori r3, r3, CONFIG_SYS_DBAT7U@l
+ addis r4, r0, CFG_SYS_DBAT7L@h
+ ori r4, r4, CFG_SYS_DBAT7L@l
+ addis r3, r0, CFG_SYS_DBAT7U@h
+ ori r3, r3, CFG_SYS_DBAT7U@l
mtspr DBAT7L, r4
mtspr DBAT7U, r3
#endif
@@ -1095,7 +1095,7 @@
#endif /* !MINIMAL_SPL */
#endif /* CONFIG_SYS_INIT_RAM_LOCK */
-#ifdef CONFIG_SYS_FLASHBOOT
+#ifdef CFG_SYS_FLASHBOOT
map_flash_by_law1:
/* When booting from ROM (Flash or EPROM), clear the */
/* Address Mask in OR0 so ROM appears everywhere */
@@ -1182,4 +1182,4 @@
twi 0,r4,0
isync
blr
-#endif /* CONFIG_SYS_FLASHBOOT */
+#endif /* CFG_SYS_FLASHBOOT */
diff --git a/arch/powerpc/cpu/mpc85xx/Kconfig b/arch/powerpc/cpu/mpc85xx/Kconfig
index 1b18048..e813bf0 100644
--- a/arch/powerpc/cpu/mpc85xx/Kconfig
+++ b/arch/powerpc/cpu/mpc85xx/Kconfig
@@ -248,6 +248,7 @@
config TARGET_KMCENT2
bool "Support kmcent2"
select VENDOR_KM
+ select EVENT
select FSL_CORENET
select SYS_DPAA_FMAN
select SYS_DPAA_PME
@@ -312,6 +313,8 @@
select SYS_FSL_PCIE_COMPAT_QORIQ_PCIE_v24
select SYS_FSL_SEC_BE
select SYS_FSL_SEC_COMPAT_4
+ select SYS_FSL_SRDS_1
+ select SYS_FSL_SRDS_2
select SYS_FSL_SRIO_LIODN
select SYS_FSL_QMAN_V3 if SYS_DPAA_QBMAN
select SYS_FSL_USB1_PHY_ENABLE
@@ -779,6 +782,7 @@
select SYS_FSL_SEC_BE
select SYS_FSL_SEC_COMPAT_5
select SYS_FSL_SINGLE_SOURCE_CLK
+ select SYS_FSL_SRDS_1
select SYS_FSL_QMAN_V3 if SYS_DPAA_QBMAN
select SYS_FSL_USB_DUAL_PHY_ENABLE
select FSL_IFC
@@ -812,6 +816,7 @@
select SYS_FSL_SEC_BE
select SYS_FSL_SEC_COMPAT_5
select SYS_FSL_SINGLE_SOURCE_CLK
+ select SYS_FSL_SRDS_1
select SYS_FSL_QMAN_V3 if SYS_DPAA_QBMAN
select SYS_FSL_USB_DUAL_PHY_ENABLE
select FSL_IFC
@@ -844,6 +849,7 @@
select SYS_FSL_SEC_BE
select SYS_FSL_SEC_COMPAT_5
select SYS_FSL_SINGLE_SOURCE_CLK
+ select SYS_FSL_SRDS_1
select SYS_FSL_QMAN_V3 if SYS_DPAA_QBMAN
select SYS_FSL_USB_DUAL_PHY_ENABLE
select FSL_IFC
@@ -879,6 +885,8 @@
select SYS_FSL_PCIE_COMPAT_QORIQ_PCIE_v30
select SYS_FSL_SEC_BE
select SYS_FSL_SEC_COMPAT_4
+ select SYS_FSL_SRDS_1
+ select SYS_FSL_SRDS_2
select SYS_FSL_SRIO_LIODN
select SYS_FSL_QMAN_V3 if SYS_DPAA_QBMAN
select SYS_FSL_USB_DUAL_PHY_ENABLE
@@ -920,6 +928,8 @@
select SYS_FSL_PCIE_COMPAT_QORIQ_PCIE_v30
select SYS_FSL_SEC_BE
select SYS_FSL_SEC_COMPAT_4
+ select SYS_FSL_SRDS_1
+ select SYS_FSL_SRDS_2
select SYS_FSL_SRIO_LIODN
select SYS_FSL_QMAN_V3 if SYS_DPAA_QBMAN
select SYS_FSL_USB_DUAL_PHY_ENABLE
@@ -1197,9 +1207,6 @@
config SYS_FSL_ERRATUM_USB14
bool
-config SYS_HAS_SERDES
- bool
-
config SYS_P4080_ERRATUM_CPU22
bool
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index f07e8ab..96183ac 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -73,11 +73,11 @@
get_sys_info(&sysinfo);
if (sysinfo.diff_sysclk == 1) {
clrbits_be32(&usb_phy->pllprg[1],
- CONFIG_SYS_FSL_USB_PLLPRG2_MFI);
+ CFG_SYS_FSL_USB_PLLPRG2_MFI);
setbits_be32(&usb_phy->pllprg[1],
- CONFIG_SYS_FSL_USB_PLLPRG2_REF_DIV_INTERNAL_CLK |
- CONFIG_SYS_FSL_USB_PLLPRG2_MFI_INTERNAL_CLK |
- CONFIG_SYS_FSL_USB_INTERNAL_SOC_CLK_EN);
+ CFG_SYS_FSL_USB_PLLPRG2_REF_DIV_INTERNAL_CLK |
+ CFG_SYS_FSL_USB_PLLPRG2_MFI_INTERNAL_CLK |
+ CFG_SYS_FSL_USB_INTERNAL_SOC_CLK_EN);
}
}
#endif
@@ -89,18 +89,18 @@
u32 xcvrprg = in_be32(&usb_phy->port1.xcvrprg);
/* Increase Disconnect Threshold by 50mV */
- xcvrprg &= ~CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK |
+ xcvrprg &= ~CFG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK |
INC_DCNT_THRESHOLD_50MV;
/* Enable programming of USB High speed Disconnect threshold */
- xcvrprg |= CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN;
+ xcvrprg |= CFG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN;
out_be32(&usb_phy->port1.xcvrprg, xcvrprg);
xcvrprg = in_be32(&usb_phy->port2.xcvrprg);
/* Increase Disconnect Threshold by 50mV */
- xcvrprg &= ~CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK |
+ xcvrprg &= ~CFG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK |
INC_DCNT_THRESHOLD_50MV;
/* Enable programming of USB High speed Disconnect threshold */
- xcvrprg |= CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN;
+ xcvrprg |= CFG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN;
out_be32(&usb_phy->port2.xcvrprg, xcvrprg);
#else
@@ -108,22 +108,22 @@
u32 status = in_be32(&usb_phy->status1);
u32 squelch_prog_rd_0_2 =
- (status >> CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_0)
- & CONFIG_SYS_FSL_USB_SQUELCH_PROG_MASK;
+ (status >> CFG_SYS_FSL_USB_SQUELCH_PROG_RD_0)
+ & CFG_SYS_FSL_USB_SQUELCH_PROG_MASK;
u32 squelch_prog_rd_3_5 =
- (status >> CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_3)
- & CONFIG_SYS_FSL_USB_SQUELCH_PROG_MASK;
+ (status >> CFG_SYS_FSL_USB_SQUELCH_PROG_RD_3)
+ & CFG_SYS_FSL_USB_SQUELCH_PROG_MASK;
setbits_be32(&usb_phy->config1,
- CONFIG_SYS_FSL_USB_HS_DISCNCT_INC);
+ CFG_SYS_FSL_USB_HS_DISCNCT_INC);
setbits_be32(&usb_phy->config2,
- CONFIG_SYS_FSL_USB_RX_AUTO_CAL_RD_WR_SEL);
+ CFG_SYS_FSL_USB_RX_AUTO_CAL_RD_WR_SEL);
- temp = squelch_prog_rd_0_2 << CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_3;
+ temp = squelch_prog_rd_0_2 << CFG_SYS_FSL_USB_SQUELCH_PROG_WR_3;
out_be32(&usb_phy->config2, in_be32(&usb_phy->config2) | temp);
- temp = squelch_prog_rd_3_5 << CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_0;
+ temp = squelch_prog_rd_3_5 << CFG_SYS_FSL_USB_SQUELCH_PROG_WR_0;
out_be32(&usb_phy->config2, in_be32(&usb_phy->config2) | temp);
#endif
}
@@ -827,7 +827,7 @@
fsl_erratum_a006261_workaround(usb_phy1);
#endif
out_be32(&usb_phy1->usb_enable_override,
- CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE);
+ CFG_SYS_FSL_USB_ENABLE_OVERRIDE);
}
#endif
#ifdef CONFIG_SYS_FSL_USB2_PHY_ENABLE
@@ -839,7 +839,7 @@
fsl_erratum_a006261_workaround(usb_phy2);
#endif
out_be32(&usb_phy2->usb_enable_override,
- CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE);
+ CFG_SYS_FSL_USB_ENABLE_OVERRIDE);
}
#endif
@@ -861,25 +861,25 @@
struct ccsr_usb_phy __iomem *usb_phy =
(void *)CFG_SYS_MPC85xx_USB1_PHY_ADDR;
setbits_be32(&usb_phy->pllprg[1],
- CONFIG_SYS_FSL_USB_PLLPRG2_PHY2_CLK_EN |
- CONFIG_SYS_FSL_USB_PLLPRG2_PHY1_CLK_EN |
- CONFIG_SYS_FSL_USB_PLLPRG2_MFI |
- CONFIG_SYS_FSL_USB_PLLPRG2_PLL_EN);
+ CFG_SYS_FSL_USB_PLLPRG2_PHY2_CLK_EN |
+ CFG_SYS_FSL_USB_PLLPRG2_PHY1_CLK_EN |
+ CFG_SYS_FSL_USB_PLLPRG2_MFI |
+ CFG_SYS_FSL_USB_PLLPRG2_PLL_EN);
#ifdef CONFIG_SYS_FSL_SINGLE_SOURCE_CLK
usb_single_source_clk_configure(usb_phy);
#endif
setbits_be32(&usb_phy->port1.ctrl,
- CONFIG_SYS_FSL_USB_CTRL_PHY_EN);
+ CFG_SYS_FSL_USB_CTRL_PHY_EN);
setbits_be32(&usb_phy->port1.drvvbuscfg,
- CONFIG_SYS_FSL_USB_DRVVBUS_CR_EN);
+ CFG_SYS_FSL_USB_DRVVBUS_CR_EN);
setbits_be32(&usb_phy->port1.pwrfltcfg,
- CONFIG_SYS_FSL_USB_PWRFLT_CR_EN);
+ CFG_SYS_FSL_USB_PWRFLT_CR_EN);
setbits_be32(&usb_phy->port2.ctrl,
- CONFIG_SYS_FSL_USB_CTRL_PHY_EN);
+ CFG_SYS_FSL_USB_CTRL_PHY_EN);
setbits_be32(&usb_phy->port2.drvvbuscfg,
- CONFIG_SYS_FSL_USB_DRVVBUS_CR_EN);
+ CFG_SYS_FSL_USB_DRVVBUS_CR_EN);
setbits_be32(&usb_phy->port2.pwrfltcfg,
- CONFIG_SYS_FSL_USB_PWRFLT_CR_EN);
+ CFG_SYS_FSL_USB_PWRFLT_CR_EN);
#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
if (has_erratum_a006261())
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
index a7e1df1..e26436b 100644
--- a/arch/powerpc/cpu/mpc85xx/fdt.c
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -92,7 +92,6 @@
}
#if defined(T1040_TDM_QUIRK_CCSR_BASE)
-#define CONFIG_MEM_HOLE_16M 0x1000000
/*
* Extract hwconfig from environment.
* Search for tdm entry in hwconfig.
@@ -103,8 +102,7 @@
/* Reserve the memory hole created by TDM LAW, so OSes dont use it */
if (tdm_hwconfig_enabled) {
- off = fdt_add_mem_rsv(blob, T1040_TDM_QUIRK_CCSR_BASE,
- CONFIG_MEM_HOLE_16M);
+ off = fdt_add_mem_rsv(blob, T1040_TDM_QUIRK_CCSR_BASE, SZ_16);
if (off < 0)
printf("Failed to reserve memory for tdm: %s\n",
fdt_strerror(off));
@@ -534,7 +532,7 @@
int nodeoff;
ccsr_gur_t __iomem *gur = (void *)(CFG_SYS_MPC85xx_GUTS_ADDR);
-#define CONFIG_SYS_ELO3_DMA3 (0xffe000000 + 0x102300)
+#define CFG_SYS_ELO3_DMA3 (0xffe000000 + 0x102300)
#if defined(CONFIG_ARCH_T2080)
u32 srds_prtcl_s2 = in_be32(&gur->rcwsr[4]) &
FSL_CORENET2_RCWSR4_SRDS2_PRTCL;
@@ -556,7 +554,7 @@
case 16:
#endif
nodeoff = fdt_node_offset_by_compat_reg(blob, "fsl,elo3-dma",
- CONFIG_SYS_ELO3_DMA3);
+ CFG_SYS_ELO3_DMA3);
if (nodeoff > 0)
fdt_status_disabled(blob, nodeoff);
else
@@ -618,11 +616,11 @@
fdt_add_enet_stashing(blob);
-#ifndef CONFIG_FSL_TBCLK_EXTRA_DIV
-#define CONFIG_FSL_TBCLK_EXTRA_DIV 1
+#ifndef CFG_FSL_TBCLK_EXTRA_DIV
+#define CFG_FSL_TBCLK_EXTRA_DIV 1
#endif
do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
- "timebase-frequency", get_tbclk() / CONFIG_FSL_TBCLK_EXTRA_DIV,
+ "timebase-frequency", get_tbclk() / CFG_FSL_TBCLK_EXTRA_DIV,
1);
do_fixup_by_prop_u32(blob, "device_type", "cpu", 4,
"bus-frequency", bd->bi_busfreq, 1);
diff --git a/arch/powerpc/cpu/mpc85xx/liodn.c b/arch/powerpc/cpu/mpc85xx/liodn.c
index 1879092..4b8844a 100644
--- a/arch/powerpc/cpu/mpc85xx/liodn.c
+++ b/arch/powerpc/cpu/mpc85xx/liodn.c
@@ -255,14 +255,14 @@
}
#endif
-#define CONFIG_SYS_MAX_PCI_EPS 8
+#define CFG_SYS_MAX_PCI_EPS 8
static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat,
int ep_liodn_start)
{
int off, pci_idx = 0, pci_cnt = 0, i, rc;
const uint32_t *base_liodn;
- uint32_t liodn_offs[CONFIG_SYS_MAX_PCI_EPS + 1] = { 0 };
+ uint32_t liodn_offs[CFG_SYS_MAX_PCI_EPS + 1] = { 0 };
/*
* Count the number of pci nodes.
@@ -282,7 +282,7 @@
path, fdt_strerror(rc));
continue;
}
- for (i = 0; i < CONFIG_SYS_MAX_PCI_EPS; i++)
+ for (i = 0; i < CFG_SYS_MAX_PCI_EPS; i++)
liodn_offs[i + 1] = ep_liodn_start +
i * pci_cnt + pci_idx - *base_liodn;
rc = fdt_setprop(fdt, off, "fsl,liodn-offset-list",
diff --git a/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c b/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c
index 1c051d1..8e1f6c9 100644
--- a/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c
+++ b/arch/powerpc/cpu/mpc8xxx/fsl_pamu.c
@@ -240,8 +240,8 @@
spaact_size = sizeof(struct paace) * NUM_SPAACT_ENTRIES;
/* Allocate space for Primary PAACT Table */
-#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_PPAACT_ADDR))
- ppaact = (void *)CONFIG_SPL_PPAACT_ADDR;
+#if (defined(CONFIG_SPL_BUILD) && defined(CFG_SPL_PPAACT_ADDR))
+ ppaact = (void *)CFG_SPL_PPAACT_ADDR;
#else
ppaact = memalign(PAMU_TABLE_ALIGNMENT, ppaact_size);
if (!ppaact)
@@ -250,8 +250,8 @@
memset(ppaact, 0, ppaact_size);
/* Allocate space for Secondary PAACT Table */
-#if (defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_SPAACT_ADDR))
- sec = (void *)CONFIG_SPL_SPAACT_ADDR;
+#if (defined(CONFIG_SPL_BUILD) && defined(CFG_SPL_SPAACT_ADDR))
+ sec = (void *)CFG_SPL_SPAACT_ADDR;
#else
sec = memalign(PAMU_TABLE_ALIGNMENT, spaact_size);
if (!sec)
@@ -266,7 +266,7 @@
spaact_lim = spaact_phys + spaact_size;
/* Configure all PAMU's */
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
+ for (i = 0; i < CFG_NUM_PAMU; i++) {
regs = (struct ccsr_pamu *)base_addr;
out_be32(®s->ppbah, ppaact_phys >> 32);
@@ -293,7 +293,7 @@
{
u32 i = 0;
u32 base_addr = CFG_SYS_PAMU_ADDR;
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
+ for (i = 0; i < CFG_NUM_PAMU; i++) {
setbits_be32((void *)base_addr + PAMU_PCR_OFFSET,
PAMU_PCR_PE);
sync();
@@ -307,7 +307,7 @@
u32 base_addr = CFG_SYS_PAMU_ADDR;
struct ccsr_pamu *regs;
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
+ for (i = 0; i < CFG_NUM_PAMU; i++) {
regs = (struct ccsr_pamu *)base_addr;
/* Clear PPAACT Base register */
out_be32(®s->ppbah, 0);
@@ -331,7 +331,7 @@
u32 base_addr = CFG_SYS_PAMU_ADDR;
- for (i = 0; i < CONFIG_NUM_PAMU; i++) {
+ for (i = 0; i < CFG_NUM_PAMU; i++) {
clrbits_be32((void *)base_addr + PAMU_PCR_OFFSET, PAMU_PCR_PE);
sync();
base_addr += PAMU_OFFSET;
diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h
index d731ac3..d990ecf 100644
--- a/arch/powerpc/include/asm/config_mpc85xx.h
+++ b/arch/powerpc/include/asm/config_mpc85xx.h
@@ -16,9 +16,6 @@
#define CFG_SYS_FSL_SRIO_IB_WIN_NUM 5
#define CFG_SYS_FSL_SRIO_MSG_UNIT_NUM 2
-#elif defined(CONFIG_ARCH_P1010)
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
-
#elif defined(CONFIG_ARCH_P1021)
#define QE_MURAM_SIZE 0x6000UL
#define MAX_QE_RISC 1
@@ -85,11 +82,6 @@
#define CFG_SYS_FM_MURAM_SIZE 0x28000
#define CFG_SYS_FSL_CORENET_SNOOPVEC_COREONLY 0xf0000000
-#elif defined(CONFIG_ARCH_BSC9131)
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 3
-
-#elif defined(CONFIG_ARCH_BSC9132)
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 3
#elif defined(CONFIG_ARCH_T4240)
#ifdef CONFIG_ARCH_T4240
@@ -104,13 +96,10 @@
#define CFG_SYS_NUM_FM2_DTSEC 8
#define CFG_SYS_NUM_FM2_10GEC 1
#endif
-#define CONFIG_SYS_FSL_SRDS_1
-#define CONFIG_SYS_FSL_SRDS_2
#define CFG_SYS_FSL_SRDS_3
#define CFG_SYS_FSL_SRDS_4
#define CFG_SYS_NUM_FMAN 2
#define CFG_SYS_PME_CLK 0
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 8
#define CFG_SYS_FM1_CLK 3
#define CFG_SYS_FM2_CLK 3
#define CFG_SYS_FM_MURAM_SIZE 0x60000
@@ -119,11 +108,8 @@
#define CFG_SYS_FSL_SRIO_IB_WIN_NUM 5
#elif defined(CONFIG_ARCH_B4860) || defined(CONFIG_ARCH_B4420)
-#define CONFIG_SYS_FSL_SRDS_1
-#define CONFIG_SYS_FSL_SRDS_2
#define CFG_SYS_NUM_FMAN 1
#define CFG_SYS_FM1_CLK 0
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
#define CFG_SYS_FM_MURAM_SIZE 0x60000
#ifdef CONFIG_ARCH_B4860
@@ -141,12 +127,10 @@
#elif defined(CONFIG_ARCH_T1040) || defined(CONFIG_ARCH_T1042)
#define CFG_SYS_FSL_CLUSTER_CLOCKS { 1, 1, 1, 1 }
-#define CONFIG_SYS_FSL_SRDS_1
#define CFG_SYS_NUM_FMAN 1
#define CFG_SYS_NUM_FM1_DTSEC 5
#define CFG_PME_PLAT_CLK_DIV 2
#define CFG_SYS_PME_CLK CFG_PME_PLAT_CLK_DIV
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 8
#define CFG_FM_PLAT_CLK_DIV 1
#define CFG_SYS_FM1_CLK CFG_FM_PLAT_CLK_DIV
#define CFG_SYS_FM_MURAM_SIZE 0x30000
@@ -157,11 +141,9 @@
#elif defined(CONFIG_ARCH_T1024)
#define CFG_SYS_FSL_CLUSTER_CLOCKS { 1, 1, 1, 1 }
-#define CONFIG_SYS_FSL_SRDS_1
#define CFG_SYS_NUM_FMAN 1
#define CFG_SYS_NUM_FM1_DTSEC 4
#define CFG_SYS_NUM_FM1_10GEC 1
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 8
#define CFG_SYS_FM1_CLK 0
#define CFG_QBMAN_CLK_DIV 1
#define CFG_SYS_FM_MURAM_SIZE 0x30000
@@ -173,11 +155,9 @@
#elif defined(CONFIG_ARCH_T2080)
#define CFG_SYS_NUM_FMAN 1
#define CFG_SYS_FSL_CLUSTER_CLOCKS { 1, 4, 4, 4 }
-#define CONFIG_SYS_FSL_SRDS_1
#if defined(CONFIG_ARCH_T2080)
#define CFG_SYS_NUM_FM1_DTSEC 8
#define CFG_SYS_NUM_FM1_10GEC 4
-#define CONFIG_SYS_FSL_SRDS_2
#define CFG_SYS_FSL_SRIO_MAX_PORTS 2
#define CFG_SYS_FSL_SRIO_OB_WIN_NUM 9
#define CFG_SYS_FSL_SRIO_IB_WIN_NUM 5
@@ -185,13 +165,11 @@
#define CFG_PME_PLAT_CLK_DIV 1
#define CFG_SYS_PME_CLK CFG_PME_PLAT_CLK_DIV
#define CFG_SYS_FM1_CLK 0
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 8
#define CFG_SYS_FM_MURAM_SIZE 0x28000
#define ESDHCI_QUIRK_BROKEN_TIMEOUT_VALUE
#elif defined(CONFIG_ARCH_C29X)
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 8
#define CFG_SYS_FSL_SEC_IDX_OFFSET 0x20000
#endif
diff --git a/arch/powerpc/include/asm/fsl_pamu.h b/arch/powerpc/include/asm/fsl_pamu.h
index 07e822b..d0d33fd 100644
--- a/arch/powerpc/include/asm/fsl_pamu.h
+++ b/arch/powerpc/include/asm/fsl_pamu.h
@@ -6,7 +6,7 @@
#ifndef __PAMU_H
#define __PAMU_H
-#define CONFIG_NUM_PAMU 16
+#define CFG_NUM_PAMU 16
#define NUM_PPAACT_ENTRIES 512
#define NUM_SPAACT_ENTRIES 256
diff --git a/arch/powerpc/include/asm/fsl_secure_boot.h b/arch/powerpc/include/asm/fsl_secure_boot.h
index 236098e..221f9d8 100644
--- a/arch/powerpc/include/asm/fsl_secure_boot.h
+++ b/arch/powerpc/include/asm/fsl_secure_boot.h
@@ -41,10 +41,10 @@
* PPAACT and SPAACT table for PAMU must be placed on DDR after DDR init
* due to space crunch on CPC and thus malloc will not work.
*/
-#define CONFIG_SPL_PPAACT_ADDR 0x2e000000
-#define CONFIG_SPL_SPAACT_ADDR 0x2f000000
-#define CONFIG_SPL_JR0_LIODN_S 454
-#define CONFIG_SPL_JR0_LIODN_NS 458
+#define CFG_SPL_PPAACT_ADDR 0x2e000000
+#define CFG_SPL_SPAACT_ADDR 0x2f000000
+#define CFG_SPL_JR0_LIODN_S 454
+#define CFG_SPL_JR0_LIODN_NS 458
#endif /* ifdef CONFIG_SPL_BUILD */
#ifndef CONFIG_SPL_BUILD
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 19e63eb..f7e1a80 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -980,37 +980,6 @@
#define PVR_5200B 0x80822014
/*
- * 405EX/EXr CHIP_21 Errata
- */
-#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY
-#define CONFIG_SYS_4xx_CHIP_21_ERRATA
-#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX1_RC
-#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX1_RD
-#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x0
-#endif
-
-#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY
-#define CONFIG_SYS_4xx_CHIP_21_ERRATA
-#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EX2_RC
-#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EX2_RD
-#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x1
-#endif
-
-#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY
-#define CONFIG_SYS_4xx_CHIP_21_ERRATA
-#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR1_RC
-#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR1_RD
-#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x2
-#endif
-
-#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY
-#define CONFIG_SYS_4xx_CHIP_21_ERRATA
-#define CONFIG_405EX_CHIP21_PVR_REV_C PVR_405EXR2_RC
-#define CONFIG_405EX_CHIP21_PVR_REV_D PVR_405EXR2_RD
-#define CONFIG_405EX_CHIP21_ECID3_REV_D 0x3
-#endif
-
-/*
* System Version Register
*/
diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c
index 1df0822..7b392b0 100644
--- a/arch/powerpc/lib/bootm.c
+++ b/arch/powerpc/lib/bootm.c
@@ -41,8 +41,8 @@
extern void ft_fixup_num_cores(void *blob);
static void set_clocks_in_mhz (struct bd_info *kbd);
-#ifndef CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE
-#define CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE (768*1024*1024)
+#ifndef CFG_SYS_LINUX_LOWMEM_MAX_SIZE
+#define CFG_SYS_LINUX_LOWMEM_MAX_SIZE (768*1024*1024)
#endif
static void boot_jump_linux(struct bootm_headers *images)
@@ -133,7 +133,7 @@
#endif
size = min(bootm_size, get_effective_memsize());
- size = min(size, (ulong)CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE);
+ size = min(size, (ulong)CFG_SYS_LINUX_LOWMEM_MAX_SIZE);
if (size < bootm_size) {
ulong base = bootmap_base + size;
diff --git a/arch/powerpc/lib/interrupts.c b/arch/powerpc/lib/interrupts.c
index bdb8030..df312df 100644
--- a/arch/powerpc/lib/interrupts.c
+++ b/arch/powerpc/lib/interrupts.c
@@ -17,8 +17,8 @@
#include <asm/ptrace.h>
#ifndef CONFIG_MPC83XX_TIMER
-#ifndef CONFIG_SYS_WATCHDOG_FREQ
-#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
+#ifndef CFG_SYS_WATCHDOG_FREQ
+#define CFG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
#endif
static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
@@ -80,7 +80,7 @@
timestamp++;
#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG)
- if (CONFIG_SYS_WATCHDOG_FREQ && (timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
+ if (CFG_SYS_WATCHDOG_FREQ && (timestamp % (CFG_SYS_WATCHDOG_FREQ)) == 0)
schedule();
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
diff --git a/arch/riscv/include/asm/encoding.h b/arch/riscv/include/asm/encoding.h
index edafad3..56c5da8 100644
--- a/arch/riscv/include/asm/encoding.h
+++ b/arch/riscv/include/asm/encoding.h
@@ -93,7 +93,7 @@
#define DEFAULT_RSTVEC 0x00001000
#define DEFAULT_NMIVEC 0x00001004
#define DEFAULT_MTVEC 0x00001010
-#define CONFIG_STRING_ADDR 0x0000100C
+#define CFG_STRING_ADDR 0x0000100C
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
index dd7978c..69da378 100644
--- a/arch/sandbox/cpu/state.c
+++ b/arch/sandbox/cpu/state.c
@@ -12,6 +12,7 @@
#include <os.h>
#include <asm/malloc.h>
#include <asm/state.h>
+#include <asm/test.h>
/* Main state record for the sandbox */
static struct sandbox_state main_state;
@@ -366,6 +367,7 @@
state->sysreset_allowed[SYSRESET_POWER_OFF] = true;
state->sysreset_allowed[SYSRESET_COLD] = true;
state->allow_memio = false;
+ sandbox_set_eth_enable(true);
memset(&state->wdt, '\0', sizeof(state->wdt));
memset(state->spi, '\0', sizeof(state->spi));
@@ -444,6 +446,34 @@
return 0;
}
+void sandbox_set_eth_enable(bool enable)
+{
+ struct sandbox_state *state = state_get_current();
+
+ state->disable_eth = !enable;
+}
+
+bool sandbox_eth_enabled(void)
+{
+ struct sandbox_state *state = state_get_current();
+
+ return !state->disable_eth;
+}
+
+void sandbox_sf_set_enable_bootdevs(bool enable)
+{
+ struct sandbox_state *state = state_get_current();
+
+ state->disable_sf_bootdevs = !enable;
+}
+
+bool sandbox_sf_bootdev_enabled(void)
+{
+ struct sandbox_state *state = state_get_current();
+
+ return !state->disable_sf_bootdevs;
+}
+
int state_init(void)
{
state = &main_state;
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index afe598a..18bf1cb 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -12,19 +12,6 @@
chosen {
stdout-path = "/serial";
-
- fwupd {
- compatible = "simple-bus";
- firmware {
- compatible = "fwupd,vbe-simple";
- cur-version = "1.2.3";
- bootloader-version = "2022.01";
- storage = "mmc1";
- area-start = <0x0>;
- area-size = <0x1000000>;
- skip-offset = <0x8000>;
- };
- };
};
alarm_wdt: alarm-wdt {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index dffe10a..9d96e47 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -94,6 +94,10 @@
compatible = "u-boot,distro-efi";
};
+ theme {
+ font-size = <30>;
+ };
+
/*
* This is used for the VBE OS-request tests. A FAT filesystem
* created in a partition with the VBE information appearing
@@ -1013,6 +1017,13 @@
non-removable;
};
+ /* This is used for bootstd bootmenu tests */
+ mmc4 {
+ status = "disabled";
+ compatible = "sandbox,mmc";
+ filename = "mmc4.img";
+ };
+
pch {
compatible = "sandbox,pch";
};
@@ -1516,12 +1527,18 @@
sandbox_virtio1 {
compatible = "sandbox,virtio1";
+ virtio-type = <4>; /* rng */
};
sandbox_virtio2 {
compatible = "sandbox,virtio2";
};
+ sandbox-virtio-blk {
+ compatible = "sandbox,virtio1";
+ virtio-type = <2>; /* block */
+ };
+
sandbox_scmi {
compatible = "sandbox,scmi-devices";
clocks = <&clk_scmi 2>, <&clk_scmi 0>;
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 49ea483..59a2059 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -96,6 +96,8 @@
const char *select_unittests; /* Unit test to run */
bool handle_signals; /* Handle signals within sandbox */
bool autoboot_keyed; /* Use keyed-autoboot feature */
+ bool disable_eth; /* Disable Ethernet devices */
+ bool disable_sf_bootdevs; /* Don't bind SPI flash bootdevs */
/* Pointer to information for each SPI bus/cs */
struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h
index 568738c..4853dc94 100644
--- a/arch/sandbox/include/asm/test.h
+++ b/arch/sandbox/include/asm/test.h
@@ -344,4 +344,34 @@
*/
int sandbox_load_other_fdt(void **fdtp, int *sizep);
+/**
+ * sandbox_set_eth_enable() - Enable / disable Ethernet
+ *
+ * Allows control of whether Ethernet packets are actually send/received
+ *
+ * @enable: true to enable Ethernet, false to disable
+ */
+void sandbox_set_eth_enable(bool enable);
+
+/**
+ * sandbox_eth_enabled() - Check if Ethernet is enabled
+ *
+ * Returns: true if Ethernet is enabled on sandbox, False if not
+ */
+bool sandbox_eth_enabled(void);
+
+/**
+ * sandbox_sf_bootdev_enabled() - Check if SPI flash bootdevs should be bound
+ *
+ * Returns: true if sandbox should bind bootdevs for SPI flash, false if not
+ */
+bool sandbox_sf_bootdev_enabled(void);
+
+/**
+ * sandbox_sf_set_enable_bootdevs() - Enable / disable the SPI flash bootdevs
+ *
+ * @enable: true to bind the SPI flash bootdevs, false to skip
+ */
+void sandbox_sf_set_enable_bootdevs(bool enable);
+
#endif
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 93f1c77..07be5cd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -395,6 +395,7 @@
config FSP_VERSION2
bool "FSP version 2.x"
+ select DM_EVENT
help
This covers versions 2.0 and 2.1. See here for details:
https://github.com/IntelFsp/fsp/wiki
diff --git a/arch/x86/cpu/baytrail/Kconfig b/arch/x86/cpu/baytrail/Kconfig
index d2c3473..a8efea8 100644
--- a/arch/x86/cpu/baytrail/Kconfig
+++ b/arch/x86/cpu/baytrail/Kconfig
@@ -7,6 +7,7 @@
select HAVE_FSP
select ARCH_MISC_INIT
select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED
+ select DM_EVENT
imply HAVE_INTEL_ME
imply ENABLE_MRC_CACHE
imply AHCI_PCI
diff --git a/arch/x86/cpu/broadwell/Kconfig b/arch/x86/cpu/broadwell/Kconfig
index 5b015c8..39deda3 100644
--- a/arch/x86/cpu/broadwell/Kconfig
+++ b/arch/x86/cpu/broadwell/Kconfig
@@ -6,6 +6,7 @@
config INTEL_BROADWELL
bool
select CACHE_MRC_BIN
+ select DM_EVENT
select ARCH_EARLY_INIT_R
imply HAVE_INTEL_ME
imply ENABLE_MRC_CACHE
diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig
index be3ef5e..704f145 100644
--- a/arch/x86/cpu/ivybridge/Kconfig
+++ b/arch/x86/cpu/ivybridge/Kconfig
@@ -8,6 +8,7 @@
config NORTHBRIDGE_INTEL_IVYBRIDGE
bool
select CACHE_MRC_BIN if HAVE_MRC
+ select DM_EVENT
imply HAVE_INTEL_ME
imply ENABLE_MRC_CACHE
imply AHCI_PCI
diff --git a/arch/x86/cpu/quark/Kconfig b/arch/x86/cpu/quark/Kconfig
index 61bb579..0d4008a 100644
--- a/arch/x86/cpu/quark/Kconfig
+++ b/arch/x86/cpu/quark/Kconfig
@@ -7,6 +7,7 @@
select HAVE_RMU
select ARCH_EARLY_INIT_R
select ARCH_MISC_INIT
+ select DM_EVENT
imply ENABLE_MRC_CACHE
imply ETH_DESIGNWARE
imply ICH_SPI
diff --git a/arch/x86/include/asm/acpi/chromeos.asl b/arch/x86/include/asm/acpi/chromeos.asl
index 2a0fd33..4fb13f3 100644
--- a/arch/x86/include/asm/acpi/chromeos.asl
+++ b/arch/x86/include/asm/acpi/chromeos.asl
@@ -5,7 +5,7 @@
#ifdef CONFIG_CHROMEOS
-#define CONFIG_VBOOT_VBNV_OFFSET 0x26
+#define CFG_VBOOT_VBNV_OFFSET 0x26
#include <asm/acpi/vbnv_layout.h>
@@ -68,7 +68,7 @@
Name(VNBV, Package() {
// See src/vendorcode/google/chromeos/Kconfig
// for the definition of these:
- CONFIG_VBOOT_VBNV_OFFSET,
+ CFG_VBOOT_VBNV_OFFSET,
VBOOT_VBNV_BLOCK_SIZE
})
Return(VNBV)
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index 23693f8..22d103d 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -137,7 +137,7 @@
#define DECLARE_GLOBAL_DATA_PTR extern struct global_data *global_data_ptr
# else
-static inline __attribute__((no_instrument_function)) gd_t *get_fs_gd_ptr(void)
+static inline notrace gd_t *get_fs_gd_ptr(void)
{
gd_t *gd_ptr;
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 3e613de..27764fc 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -71,7 +71,7 @@
#define EAX_EDX_RET(val, low, high) "=A" (val)
#endif
-static inline __attribute__((no_instrument_function))
+static inline notrace
unsigned long long native_read_msr(unsigned int msr)
{
DECLARE_ARGS(val, low, high);
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 4cf41e9..8f38c2d 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -108,7 +108,7 @@
int arch_misc_init(void);
/* Read the time stamp counter */
-static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void)
+static inline notrace uint64_t rdtsc(void)
{
uint32_t high, low;
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c
index 34ef68f..bdf57ef 100644
--- a/arch/x86/lib/spl.c
+++ b/arch/x86/lib/spl.c
@@ -92,7 +92,7 @@
#ifndef CONFIG_TPL
ret = fsp_setup_pinctrl(NULL, NULL);
if (ret) {
- debug("%s: arch_cpu_init_dm() failed\n", __func__);
+ debug("%s: fsp_setup_pinctrl() failed\n", __func__);
return ret;
}
#endif
diff --git a/board/alliedtelesis/x530/x530.c b/board/alliedtelesis/x530/x530.c
index 0cfb7c5..80ad62c 100644
--- a/board/alliedtelesis/x530/x530.c
+++ b/board/alliedtelesis/x530/x530.c
@@ -26,8 +26,8 @@
#define MVEBU_DEV_BUS_BASE (MVEBU_REGISTER(0x10400))
-#define CONFIG_NVS_LOCATION 0xf4800000
-#define CONFIG_NVS_SIZE (512 << 10)
+#define CFG_NVS_LOCATION 0xf4800000
+#define CFG_NVS_SIZE (512 << 10)
static struct serdes_map board_serdes_map[] = {
{PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
@@ -109,7 +109,7 @@
gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
/* window for NVS */
- mbus_dt_setup_win(CONFIG_NVS_LOCATION, CONFIG_NVS_SIZE,
+ mbus_dt_setup_win(CFG_NVS_LOCATION, CFG_NVS_SIZE,
CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_DEV_CS1);
/* DEV_READYn is not needed for NVS, ignore it when accessing CS1 */
diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
index 99fb67e..ee65a59 100644
--- a/board/armltd/vexpress64/vexpress64.c
+++ b/board/armltd/vexpress64/vexpress64.c
@@ -220,7 +220,7 @@
int rc = 0;
#ifndef CONFIG_DM_ETH
#ifdef CONFIG_SMC911X
- rc = smc911x_initialize(0, CONFIG_SMC911X_BASE);
+ rc = smc911x_initialize(0, CFG_SMC911X_BASE);
#endif
#endif
return rc;
diff --git a/board/compulab/imx8mm-cl-iot-gate/eeprom_spl.c b/board/compulab/imx8mm-cl-iot-gate/eeprom_spl.c
index ee6d2bb..90cc33a 100644
--- a/board/compulab/imx8mm-cl-iot-gate/eeprom_spl.c
+++ b/board/compulab/imx8mm-cl-iot-gate/eeprom_spl.c
@@ -12,8 +12,7 @@
#ifdef CONFIG_SPL_BUILD
-#define CONFIG_SYS_I2C_EEPROM_ADDR_P1 0x51
-#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1
+#define CFG_SYS_I2C_EEPROM_ADDR_P1 0x51
static iomux_v3_cfg_t const eeprom_pads[] = {
IMX8MQ_PAD_GPIO1_IO13__GPIO1_IO13 | MUX_PAD_CTRL(NO_PAD_CTRL),
@@ -41,7 +40,7 @@
struct udevice *dev;
int ret;
- ret = i2c_get_chip_for_busnum(1, CONFIG_SYS_I2C_EEPROM_ADDR_P1,
+ ret = i2c_get_chip_for_busnum(1, CFG_SYS_I2C_EEPROM_ADDR_P1,
CONFIG_SYS_I2C_EEPROM_ADDR_LEN, &dev);
if (ret) {
printf("%s: Cannot find EEPROM: %d\n", __func__, ret);
@@ -58,7 +57,7 @@
cl_eeprom_we(1);
- ret = i2c_get_chip_for_busnum(1, CONFIG_SYS_I2C_EEPROM_ADDR_P1,
+ ret = i2c_get_chip_for_busnum(1, CFG_SYS_I2C_EEPROM_ADDR_P1,
CONFIG_SYS_I2C_EEPROM_ADDR_LEN, &dev);
if (ret) {
printf("%s: Cannot find EEPROM: %d\n", __func__, ret);
diff --git a/board/davinci/da8xxevm/da850evm.c b/board/davinci/da8xxevm/da850evm.c
index e3a0f26..474dca7 100644
--- a/board/davinci/da8xxevm/da850evm.c
+++ b/board/davinci/da8xxevm/da850evm.c
@@ -226,8 +226,8 @@
const int lpsc_size = ARRAY_SIZE(lpsc);
-#ifndef CONFIG_DA850_EVM_MAX_CPU_CLK
-#define CONFIG_DA850_EVM_MAX_CPU_CLK 300000000
+#ifndef CFG_DA850_EVM_MAX_CPU_CLK
+#define CFG_DA850_EVM_MAX_CPU_CLK 300000000
#endif
#define REV_AM18X_EVM 0x100
@@ -245,7 +245,7 @@
u32 get_board_rev(void)
{
char *s;
- u32 maxcpuclk = CONFIG_DA850_EVM_MAX_CPU_CLK;
+ u32 maxcpuclk = CFG_DA850_EVM_MAX_CPU_CLK;
u32 rev = 0;
s = env_get("maxcpuclk");
diff --git a/board/davinci/da8xxevm/omapl138_lcdk.c b/board/davinci/da8xxevm/omapl138_lcdk.c
index cd021cc..5ffd420 100644
--- a/board/davinci/da8xxevm/omapl138_lcdk.c
+++ b/board/davinci/da8xxevm/omapl138_lcdk.c
@@ -139,8 +139,8 @@
const int lpsc_size = ARRAY_SIZE(lpsc);
-#ifndef CONFIG_DA850_EVM_MAX_CPU_CLK
-#define CONFIG_DA850_EVM_MAX_CPU_CLK 456000000
+#ifndef CFG_DA850_EVM_MAX_CPU_CLK
+#define CFG_DA850_EVM_MAX_CPU_CLK 456000000
#endif
int board_early_init_f(void)
diff --git a/board/edgeble/neural-compute-module-2/Kconfig b/board/edgeble/neural-compute-module-2/Kconfig
new file mode 100644
index 0000000..21faf4a
--- /dev/null
+++ b/board/edgeble/neural-compute-module-2/Kconfig
@@ -0,0 +1,16 @@
+if TARGET_RV1126_NEU2
+
+config SYS_BOARD
+ default "neural-compute-module-2"
+
+config SYS_VENDOR
+ default "edgeble"
+
+config SYS_CONFIG_NAME
+ default "neural-compute-module-2"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select RAM_ROCKCHIP_LPDDR4
+
+endif
diff --git a/board/edgeble/neural-compute-module-2/MAINTAINERS b/board/edgeble/neural-compute-module-2/MAINTAINERS
new file mode 100644
index 0000000..38edb3a
--- /dev/null
+++ b/board/edgeble/neural-compute-module-2/MAINTAINERS
@@ -0,0 +1,6 @@
+RV1126-ECM0
+M: Jagan Teki <jagan@edgeble.ai>
+S: Maintained
+F: board/edgeble/neural-compute-module-2
+F: include/configs/neural-compute-module-2.h
+F: configs/neu2-io-rv1126_defconfig
diff --git a/board/edgeble/neural-compute-module-2/Makefile b/board/edgeble/neural-compute-module-2/Makefile
new file mode 100644
index 0000000..3bfc89f
--- /dev/null
+++ b/board/edgeble/neural-compute-module-2/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += neu2.o
diff --git a/board/edgeble/neural-compute-module-2/neu2.c b/board/edgeble/neural-compute-module-2/neu2.c
new file mode 100644
index 0000000..3d2262c
--- /dev/null
+++ b/board/edgeble/neural-compute-module-2/neu2.c
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
diff --git a/board/eets/pdu001/board.c b/board/eets/pdu001/board.c
index 648d77f..de224d4 100644
--- a/board/eets/pdu001/board.c
+++ b/board/eets/pdu001/board.c
@@ -62,8 +62,8 @@
* To get the boot device from 'am33xx_spl_board_init' to
* 'board_late_init' we therefore use a scratch register from the RTC.
*/
-#define CONFIG_SYS_RTC_SCRATCH0 0x60
-#define BOOT_DEVICE_SAVE_REGISTER (RTC_BASE + CONFIG_SYS_RTC_SCRATCH0)
+#define CFG_SYS_RTC_SCRATCH0 0x60
+#define BOOT_DEVICE_SAVE_REGISTER (RTC_BASE + CFG_SYS_RTC_SCRATCH0)
#ifdef CONFIG_SPL_BUILD
static void save_boot_device(void)
diff --git a/board/engicam/px30_core/Kconfig b/board/engicam/px30_core/Kconfig
index a03be78..924c30f 100644
--- a/board/engicam/px30_core/Kconfig
+++ b/board/engicam/px30_core/Kconfig
@@ -11,6 +11,6 @@
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
- select RAM_PX30_DDR4
+ select RAM_ROCKCHIP_DDR4
endif
diff --git a/board/freescale/common/cadmus.c b/board/freescale/common/cadmus.c
index 8f3fb5f..e7e07ff 100644
--- a/board/freescale/common/cadmus.c
+++ b/board/freescale/common/cadmus.c
@@ -10,8 +10,8 @@
/*
* CADMUS Board System Registers
*/
-#ifndef CONFIG_SYS_CADMUS_BASE_REG
-#define CONFIG_SYS_CADMUS_BASE_REG (CADMUS_BASE_ADDR + 0x4000)
+#ifndef CFG_SYS_CADMUS_BASE_REG
+#define CFG_SYS_CADMUS_BASE_REG (CADMUS_BASE_ADDR + 0x4000)
#endif
typedef struct cadmus_reg {
@@ -30,7 +30,7 @@
unsigned int
get_board_version(void)
{
- volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
+ volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CFG_SYS_CADMUS_BASE_REG;
return cadmus->cm_ver;
}
@@ -39,7 +39,7 @@
unsigned long
get_board_sys_clk(void)
{
- volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
+ volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CFG_SYS_CADMUS_BASE_REG;
uint pci1_speed = (cadmus->cm_pci >> 2) & 0x3; /* PSPEED in [4:5] */
@@ -57,7 +57,7 @@
unsigned int
get_pci_slot(void)
{
- volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
+ volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CFG_SYS_CADMUS_BASE_REG;
/*
* PCI slot in USER bits CSR[6:7] by convention.
@@ -69,7 +69,7 @@
unsigned int
get_pci_dual(void)
{
- volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CONFIG_SYS_CADMUS_BASE_REG;
+ volatile cadmus_reg_t *cadmus = (cadmus_reg_t *)CFG_SYS_CADMUS_BASE_REG;
/*
* PCI DUAL in CM_PCI[3]
diff --git a/board/freescale/common/fsl_chain_of_trust.c b/board/freescale/common/fsl_chain_of_trust.c
index 029d06b..b47ce05 100644
--- a/board/freescale/common/fsl_chain_of_trust.c
+++ b/board/freescale/common/fsl_chain_of_trust.c
@@ -28,9 +28,9 @@
#endif
#if defined(CONFIG_MPC85xx)
-#define CONFIG_DCFG_ADDR CFG_SYS_MPC85xx_GUTS_ADDR
+#define CFG_DCFG_ADDR CFG_SYS_MPC85xx_GUTS_ADDR
#else
-#define CONFIG_DCFG_ADDR CFG_SYS_FSL_GUTS_ADDR
+#define CFG_DCFG_ADDR CFG_SYS_FSL_GUTS_ADDR
#endif
#ifdef CONFIG_SYS_FSL_CCSR_GUR_LE
@@ -44,7 +44,7 @@
{
uint32_t val;
struct ccsr_sfp_regs *sfp_regs = (void *)(CFG_SYS_SFP_ADDR);
- struct ccsr_gur __iomem *gur = (void *)(CONFIG_DCFG_ADDR);
+ struct ccsr_gur __iomem *gur = (void *)(CFG_DCFG_ADDR);
val = sfp_in32(&sfp_regs->ospr) & ITS_MASK;
if (val == ITS_MASK)
diff --git a/board/freescale/common/pixis.c b/board/freescale/common/pixis.c
index cb9f454..7096b10 100644
--- a/board/freescale/common/pixis.c
+++ b/board/freescale/common/pixis.c
@@ -149,8 +149,8 @@
return 1;
}
-#ifndef CONFIG_SYS_PIXIS_VCFGEN0_ENABLE
-#define CONFIG_SYS_PIXIS_VCFGEN0_ENABLE 0x1C
+#ifndef CFG_SYS_PIXIS_VCFGEN0_ENABLE
+#define CFG_SYS_PIXIS_VCFGEN0_ENABLE 0x1C
#endif
/* Tell the PIXIS where to find the COREPLL, MPXPLL, SYSCLK values
@@ -159,7 +159,7 @@
* or various other PIXIS registers to determine the values for COREPLL,
* MPXPLL, and SYSCLK.
*
- * CONFIG_SYS_PIXIS_VCFGEN0_ENABLE is the value to write to the PIXIS_VCFGEN0
+ * CFG_SYS_PIXIS_VCFGEN0_ENABLE is the value to write to the PIXIS_VCFGEN0
* register that tells the pixis to use the various PIXIS register.
*/
static void read_from_px_regs(int set)
@@ -167,18 +167,18 @@
u8 tmp = in_8(pixis_base + PIXIS_VCFGEN0);
if (set)
- tmp = tmp | CONFIG_SYS_PIXIS_VCFGEN0_ENABLE;
+ tmp = tmp | CFG_SYS_PIXIS_VCFGEN0_ENABLE;
else
- tmp = tmp & ~CONFIG_SYS_PIXIS_VCFGEN0_ENABLE;
+ tmp = tmp & ~CFG_SYS_PIXIS_VCFGEN0_ENABLE;
out_8(pixis_base + PIXIS_VCFGEN0, tmp);
}
-/* CONFIG_SYS_PIXIS_VBOOT_ENABLE is the value to write to the PX_VCFGEN1
+/* CFG_SYS_PIXIS_VBOOT_ENABLE is the value to write to the PX_VCFGEN1
* register that tells the pixis to use the PX_VBOOT[LBMAP] register.
*/
-#ifndef CONFIG_SYS_PIXIS_VBOOT_ENABLE
-#define CONFIG_SYS_PIXIS_VBOOT_ENABLE 0x04
+#ifndef CFG_SYS_PIXIS_VBOOT_ENABLE
+#define CFG_SYS_PIXIS_VBOOT_ENABLE 0x04
#endif
/* Configure the source of the boot location
@@ -194,14 +194,14 @@
u8 tmp = in_8(pixis_base + PIXIS_VCFGEN1);
if (set)
- tmp = tmp | CONFIG_SYS_PIXIS_VBOOT_ENABLE;
+ tmp = tmp | CFG_SYS_PIXIS_VBOOT_ENABLE;
else
- tmp = tmp & ~CONFIG_SYS_PIXIS_VBOOT_ENABLE;
+ tmp = tmp & ~CFG_SYS_PIXIS_VBOOT_ENABLE;
out_8(pixis_base + PIXIS_VCFGEN1, tmp);
}
-/* CONFIG_SYS_PIXIS_VBOOT_MASK contains the bits to set in VBOOT register that
+/* CFG_SYS_PIXIS_VBOOT_MASK contains the bits to set in VBOOT register that
* tells the PIXIS what the alternate flash bank is.
*
* Note that it's not really a mask. It contains the actual LBMAP bits that
@@ -209,8 +209,8 @@
* primary bank has these bits set to 0, and the alternate bank has these
* bits set to 1.
*/
-#ifndef CONFIG_SYS_PIXIS_VBOOT_MASK
-#define CONFIG_SYS_PIXIS_VBOOT_MASK (0x40)
+#ifndef CFG_SYS_PIXIS_VBOOT_MASK
+#define CFG_SYS_PIXIS_VBOOT_MASK (0x40)
#endif
/* Tell the PIXIS to boot from the default flash bank
@@ -220,7 +220,7 @@
*/
static void clear_altbank(void)
{
- clrbits_8(pixis_base + PIXIS_VBOOT, CONFIG_SYS_PIXIS_VBOOT_MASK);
+ clrbits_8(pixis_base + PIXIS_VBOOT, CFG_SYS_PIXIS_VBOOT_MASK);
}
/* Tell the PIXIS to boot from the alternate flash bank
@@ -230,7 +230,7 @@
*/
static void set_altbank(void)
{
- setbits_8(pixis_base + PIXIS_VBOOT, CONFIG_SYS_PIXIS_VBOOT_MASK);
+ setbits_8(pixis_base + PIXIS_VBOOT, CFG_SYS_PIXIS_VBOOT_MASK);
}
/* Reset the board with watchdog disabled.
diff --git a/board/freescale/ls1043aqds/eth.c b/board/freescale/ls1043aqds/eth.c
index 645c56c..cd1f83e 100644
--- a/board/freescale/ls1043aqds/eth.c
+++ b/board/freescale/ls1043aqds/eth.c
@@ -314,7 +314,7 @@
mdio_mux[i] = EMI_NONE;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
@@ -322,7 +322,7 @@
fm_memac_mdio_init(bis, &dtsec_mdio_info);
tgec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_TGEC_MDIO_ADDR;
tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the 10G MDIO bus */
diff --git a/board/freescale/ls1043ardb/eth.c b/board/freescale/ls1043ardb/eth.c
index 3cae2a0..cc95214 100644
--- a/board/freescale/ls1043ardb/eth.c
+++ b/board/freescale/ls1043ardb/eth.c
@@ -28,7 +28,7 @@
srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
@@ -36,7 +36,7 @@
fm_memac_mdio_init(bis, &dtsec_mdio_info);
tgec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_TGEC_MDIO_ADDR;
tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the 10G MDIO bus */
diff --git a/board/freescale/ls1046afrwy/eth.c b/board/freescale/ls1046afrwy/eth.c
index 71c4c21..d1a2bfe 100644
--- a/board/freescale/ls1046afrwy/eth.c
+++ b/board/freescale/ls1046afrwy/eth.c
@@ -27,7 +27,7 @@
srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
diff --git a/board/freescale/ls1046aqds/eth.c b/board/freescale/ls1046aqds/eth.c
index 926bd74..bbf8b8c 100644
--- a/board/freescale/ls1046aqds/eth.c
+++ b/board/freescale/ls1046aqds/eth.c
@@ -285,7 +285,7 @@
mdio_mux[i] = EMI_NONE;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
diff --git a/board/freescale/ls1046ardb/eth.c b/board/freescale/ls1046ardb/eth.c
index af70d10..bbc22a3 100644
--- a/board/freescale/ls1046ardb/eth.c
+++ b/board/freescale/ls1046ardb/eth.c
@@ -29,7 +29,7 @@
srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
@@ -37,7 +37,7 @@
fm_memac_mdio_init(bis, &dtsec_mdio_info);
tgec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_TGEC_MDIO_ADDR;
tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the 10G MDIO bus */
diff --git a/board/freescale/p2041rdb/eth.c b/board/freescale/p2041rdb/eth.c
index 3e12c81..c0d0553 100644
--- a/board/freescale/p2041rdb/eth.c
+++ b/board/freescale/p2041rdb/eth.c
@@ -139,14 +139,14 @@
initialize_lane_to_slot();
dtsec_mdio_info.regs =
- (struct tsec_mii_mng *)CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR;
+ (struct tsec_mii_mng *)CFG_SYS_FM1_DTSEC1_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
/* Register the real 1G MDIO bus */
fsl_pq_mdio_init(bis, &dtsec_mdio_info);
tgec_mdio_info.regs =
- (struct tgec_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
+ (struct tgec_mdio_controller *)CFG_SYS_FM1_TGEC_MDIO_ADDR;
tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the real 10G MDIO bus */
diff --git a/board/freescale/t102xrdb/eth_t102xrdb.c b/board/freescale/t102xrdb/eth_t102xrdb.c
index ed6b363..ad78f72 100644
--- a/board/freescale/t102xrdb/eth_t102xrdb.c
+++ b/board/freescale/t102xrdb/eth_t102xrdb.c
@@ -41,7 +41,7 @@
srds_s1 >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
@@ -49,7 +49,7 @@
fm_memac_mdio_init(bis, &dtsec_mdio_info);
tgec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_TGEC_MDIO_ADDR;
tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the 10G MDIO bus */
diff --git a/board/freescale/t104xrdb/eth.c b/board/freescale/t104xrdb/eth.c
index 3906c83..5eca938 100644
--- a/board/freescale/t104xrdb/eth.c
+++ b/board/freescale/t104xrdb/eth.c
@@ -26,7 +26,7 @@
printf("Initializing Fman\n");
memac_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
memac_mdio_info.name = DEFAULT_FM_MDIO_NAME;
/* Register the real 1G MDIO bus */
diff --git a/board/freescale/t208xqds/eth_t208xqds.c b/board/freescale/t208xqds/eth_t208xqds.c
index 62261f5..569b193 100644
--- a/board/freescale/t208xqds/eth_t208xqds.c
+++ b/board/freescale/t208xqds/eth_t208xqds.c
@@ -474,7 +474,7 @@
mdio_mux[i] = EMI_NONE;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
@@ -482,7 +482,7 @@
fm_memac_mdio_init(bis, &dtsec_mdio_info);
tgec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM1_TGEC_MDIO_ADDR;
tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the 10G MDIO bus */
diff --git a/board/freescale/t4rdb/eth.c b/board/freescale/t4rdb/eth.c
index 241ee5a..2e52543 100644
--- a/board/freescale/t4rdb/eth.c
+++ b/board/freescale/t4rdb/eth.c
@@ -54,7 +54,7 @@
srds_prtcl_s2 >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT;
dtsec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM2_DTSEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM2_DTSEC_MDIO_ADDR;
dtsec_mdio_info.name = DEFAULT_FM_MDIO_NAME;
@@ -62,7 +62,7 @@
fm_memac_mdio_init(bis, &dtsec_mdio_info);
tgec_mdio_info.regs =
- (struct memac_mdio_controller *)CONFIG_SYS_FM2_TGEC_MDIO_ADDR;
+ (struct memac_mdio_controller *)CFG_SYS_FM2_TGEC_MDIO_ADDR;
tgec_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME;
/* Register the 10G MDIO bus */
diff --git a/board/google/Kconfig b/board/google/Kconfig
index 0474b4e..a0f1a60 100644
--- a/board/google/Kconfig
+++ b/board/google/Kconfig
@@ -18,6 +18,7 @@
config TARGET_CHROMEBOOK_CORAL
bool "Chromebook coral"
select BIOSEMU
+ select EVENT
help
This is a range of Intel-based laptops released in 2018. They use an
Intel Apollo Lake SoC. The design supports WiFi, 4GB to 16GB of
diff --git a/board/keymile/Kconfig b/board/keymile/Kconfig
index e5d7c80..bf899d0 100644
--- a/board/keymile/Kconfig
+++ b/board/keymile/Kconfig
@@ -124,6 +124,7 @@
config PG_WCOM_UBOOT_UPDATE_SUPPORTED
bool "Enable U-boot Field Fail-Safe Update Functionality"
+ select EVENT
default n
help
Indicates that field fail-safe u-boot update is supported.
diff --git a/board/logicpd/omap3som/omap3logic.c b/board/logicpd/omap3som/omap3logic.c
index 559192e..8699282 100644
--- a/board/logicpd/omap3som/omap3logic.c
+++ b/board/logicpd/omap3som/omap3logic.c
@@ -58,7 +58,7 @@
#define LOGIC_MT28_OMAP35_ASYNC_GPMC_CONFIG6 0x09030000
#define LOGIC_MT28_OMAP35_ASYNC_GPMC_CONFIG7 0x00000C50
-#define CONFIG_SMC911X_BASE 0x08000000
+#define CFG_SMC911X_BASE 0x08000000
#ifdef CONFIG_SPL_OS_BOOT
int spl_start_uboot(void)
@@ -226,7 +226,7 @@
#ifdef CONFIG_SMC911X
enable_gpmc_cs_config(gpmc_lan92xx_config, &gpmc_cfg->cs[1],
- CONFIG_SMC911X_BASE, GPMC_SIZE_16M);
+ CFG_SMC911X_BASE, GPMC_SIZE_16M);
#endif
return 0;
}
diff --git a/board/pine64/pinephone-pro-rk3399/Kconfig b/board/pine64/pinephone-pro-rk3399/Kconfig
new file mode 100644
index 0000000..13d6465
--- /dev/null
+++ b/board/pine64/pinephone-pro-rk3399/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_PINEPHONE_PRO_RK3399
+
+config SYS_BOARD
+ default "pinephone-pro-rk3399"
+
+config SYS_VENDOR
+ default "pine64"
+
+config SYS_CONFIG_NAME
+ default "pinephone-pro-rk3399"
+
+config BOARD_SPECIFIC_OPTIONS
+ def_bool y
+
+endif
diff --git a/board/pine64/pinephone-pro-rk3399/MAINTAINERS b/board/pine64/pinephone-pro-rk3399/MAINTAINERS
new file mode 100644
index 0000000..c923ff1
--- /dev/null
+++ b/board/pine64/pinephone-pro-rk3399/MAINTAINERS
@@ -0,0 +1,8 @@
+PINEPHONE_PRO
+M: Peter Robinson <pbrobinson@gmail.com>
+S: Maintained
+F: board/pine64/rk3399-pinephone-pro/
+F: include/configs/rk3399-pinephone-pro.h
+F: arch/arm/dts/rk3399-pinephone-pro.dts
+F: arch/arm/dts/rk3399-pinephone-pro-u-boot.dtsi
+F: configs/pinephone-pro-rk3399_defconfig
diff --git a/board/pine64/pinephone-pro-rk3399/Makefile b/board/pine64/pinephone-pro-rk3399/Makefile
new file mode 100644
index 0000000..8d92030
--- /dev/null
+++ b/board/pine64/pinephone-pro-rk3399/Makefile
@@ -0,0 +1 @@
+obj-y += pinephone-pro-rk3399.o
diff --git a/board/pine64/pinephone-pro-rk3399/pinephone-pro-rk3399.c b/board/pine64/pinephone-pro-rk3399/pinephone-pro-rk3399.c
new file mode 100644
index 0000000..eb639cd
--- /dev/null
+++ b/board/pine64/pinephone-pro-rk3399/pinephone-pro-rk3399.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2016 Rockchip Electronics Co., Ltd
+ * (C) Copyright 2022 Peter Robinson <pbrobinson at gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <init.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/grf_rk3399.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/misc.h>
+#include <power/regulator.h>
+
+#define GRF_IO_VSEL_BT565_SHIFT 0
+#define PMUGRF_CON0_VSEL_SHIFT 8
+
+#ifndef CONFIG_SPL_BUILD
+int board_early_init_f(void)
+{
+ struct udevice *regulator;
+ int ret;
+
+ ret = regulator_get_by_platname("vcc5v0_usb", ®ulator);
+ if (ret) {
+ pr_debug("%s vcc5v0_usb init fail! ret %d\n", __func__, ret);
+ goto out;
+ }
+
+ ret = regulator_set_enable(regulator, true);
+ if (ret)
+ pr_debug("%s vcc5v0-host-en-gpio set fail! ret %d\n", __func__, ret);
+
+out:
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_MISC_INIT_R
+static void setup_iodomain(void)
+{
+ struct rk3399_grf_regs *grf =
+ syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ struct rk3399_pmugrf_regs *pmugrf =
+ syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+
+ /* BT565 is in 1.8v domain */
+ rk_setreg(&grf->io_vsel, 1 << GRF_IO_VSEL_BT565_SHIFT);
+
+ /* Set GPIO1 1.8v/3.0v source select to PMU1830_VOL */
+ rk_setreg(&pmugrf->soc_con0, 1 << PMUGRF_CON0_VSEL_SHIFT);
+}
+
+int misc_init_r(void)
+{
+ const u32 cpuid_offset = 0x7;
+ const u32 cpuid_length = 0x10;
+ u8 cpuid[cpuid_length];
+ int ret;
+
+ setup_iodomain();
+
+ ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid);
+ if (ret)
+ return ret;
+
+ ret = rockchip_cpuid_set(cpuid, cpuid_length);
+ if (ret)
+ return ret;
+
+ return ret;
+}
+#endif
diff --git a/board/renesas/blanche/blanche.c b/board/renesas/blanche/blanche.c
index ea09057..8e1ae29 100644
--- a/board/renesas/blanche/blanche.c
+++ b/board/renesas/blanche/blanche.c
@@ -327,7 +327,7 @@
struct eth_device *dev;
uchar eth_addr[6];
- rc = smc911x_initialize(0, CONFIG_SMC911X_BASE);
+ rc = smc911x_initialize(0, CFG_SMC911X_BASE);
if (!eth_env_get_enetaddr("ethaddr", eth_addr)) {
dev = eth_get_dev_by_index(0);
diff --git a/board/st/common/Kconfig b/board/st/common/Kconfig
index 2f57118..aba3590 100644
--- a/board/st/common/Kconfig
+++ b/board/st/common/Kconfig
@@ -1,7 +1,7 @@
config CMD_STBOARD
bool "stboard - command for OTP board information"
depends on ARCH_STM32MP
- default y if TARGET_ST_STM32MP15x
+ default y if TARGET_ST_STM32MP15x || TARGET_ST_STM32MP13x
help
This compile the stboard command to
read and write the board in the OTP.
diff --git a/board/st/common/cmd_stboard.c b/board/st/common/cmd_stboard.c
index e12669b..853ab78 100644
--- a/board/st/common/cmd_stboard.c
+++ b/board/st/common/cmd_stboard.c
@@ -2,8 +2,8 @@
/*
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
*
- * the st command stboard supports the STMicroelectronics board identification
- * saved in OTP 59.
+ * the command stboard supports the STMicroelectronics board identification
+ * saved in OTP_BOARD.
*
* The ST product codification have several element
* - "Commercial Product Name" (CPN): type of product board (DKX, EVX)
@@ -18,7 +18,7 @@
* - Finished Good = EVA32MP157A1$AU1
*
* Both information are written on board and these information are also saved
- * in OTP59, with:
+ * in OTP_BOARD (59 for STM32MP15x or 60 for STM32MP13x), with:
* bit [31:16] (hex) => Board id, MBxxxx
* bit [15:12] (dec) => Variant CPN (1....15)
* bit [11:8] (dec) => Revision board (index with A = 1, Z = 26)
@@ -34,6 +34,7 @@
#include <command.h>
#include <console.h>
#include <misc.h>
+#include <asm/arch/bsec.h>
#include <dm/device.h>
#include <dm/uclass.h>
@@ -48,6 +49,7 @@
0x1298,
0x1341,
0x1497,
+ 0x1635,
};
for (i = 0; i < ARRAY_SIZE(st_board_id); i++)
@@ -109,7 +111,7 @@
else
display_stboard(otp);
printf(" OTP %d %s locked !\n", BSEC_OTP_BOARD,
- lock == 1 ? "" : "NOT");
+ lock & BSEC_LOCK_PERM ? "" : "NOT");
return CMD_RET_SUCCESS;
}
@@ -178,7 +180,7 @@
}
/* write persistent lock */
- otp = 1;
+ otp = BSEC_LOCK_PERM;
ret = misc_write(dev, STM32_BSEC_LOCK(BSEC_OTP_BOARD),
&otp, sizeof(otp));
if (ret != sizeof(otp)) {
diff --git a/board/sysam/amcore/amcore.c b/board/sysam/amcore/amcore.c
index 429f886..086421d 100644
--- a/board/sysam/amcore/amcore.c
+++ b/board/sysam/amcore/amcore.c
@@ -109,7 +109,7 @@
}
static struct coldfire_serial_plat mcf5307_serial_plat = {
- .base = CONFIG_SYS_UART_BASE,
+ .base = CFG_SYS_UART_BASE,
.port = 0,
.baudrate = CONFIG_BAUDRATE,
};
diff --git a/board/theobroma-systems/ringneck_px30/Kconfig b/board/theobroma-systems/ringneck_px30/Kconfig
new file mode 100644
index 0000000..24d9480
--- /dev/null
+++ b/board/theobroma-systems/ringneck_px30/Kconfig
@@ -0,0 +1,18 @@
+if TARGET_RINGNECK_PX30
+
+config SYS_BOARD
+ default "ringneck_px30"
+
+config SYS_VENDOR
+ default "theobroma-systems"
+
+config SYS_CONFIG_NAME
+ default "ringneck_px30"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+
+config ENV_SIZE
+ default 0x3000
+
+endif
diff --git a/board/theobroma-systems/ringneck_px30/MAINTAINERS b/board/theobroma-systems/ringneck_px30/MAINTAINERS
new file mode 100644
index 0000000..d764e26
--- /dev/null
+++ b/board/theobroma-systems/ringneck_px30/MAINTAINERS
@@ -0,0 +1,9 @@
+RINGNECK-PX30
+M: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+M: Klaus Goger <klaus.goger@theobroma-systems.com>
+S: Maintained
+F: board/theobroma-systems/ringneck_px30
+F: include/configs/ringneck_px30.h
+F: arch/arm/dts/px30-ringneck*
+F: configs/ringneck-px30_defconfig
+W: https://www.theobroma-systems.com/px30-uq7#tech-spec
diff --git a/board/theobroma-systems/ringneck_px30/Makefile b/board/theobroma-systems/ringneck_px30/Makefile
new file mode 100644
index 0000000..31ada1a
--- /dev/null
+++ b/board/theobroma-systems/ringneck_px30/Makefile
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2022 Theobroma Systems Design und Consulting GmbH
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += ringneck-px30.o
diff --git a/board/theobroma-systems/ringneck_px30/README b/board/theobroma-systems/ringneck_px30/README
new file mode 100644
index 0000000..e756b3a
--- /dev/null
+++ b/board/theobroma-systems/ringneck_px30/README
@@ -0,0 +1,69 @@
+Introduction
+============
+
+The PX30-uQ7 (Ringneck) SoM is a µQseven-compatible (40mmx70mm, MXM-230
+connector) system-on-module from Theobroma Systems[1], featuring the
+Rockchip PX30.
+
+It provides the following feature set:
+ * up to 4GB DDR4
+ * up to 128GB on-module eMMC (with 8-bit 1.8V interface)
+ * SD card (on a baseboard) via edge connector
+ * Fast Ethernet with on-module TI DP83825I PHY
+ * MIPI-DSI/LVDS
+ * MIPI-CSI
+ * USB
+ - 1x USB 2.0 dual-role
+ - 3x USB 2.0 host
+ * on-module companion controller (STM32 Cortex-M0 or ATtiny), implementing:
+ - low-power RTC functionality (ISL1208 emulation)
+ - fan controller (AMC6821 emulation)
+ - USB<->CAN bridge controller (STM32 only)
+ * on-module Espressif ESP32 for Bluetooth + 2.4GHz WiFi
+ * on-module NXP SE05x Secure Element
+
+Here is the step-by-step to boot to U-Boot on px30.
+
+Get the Source and build ATF binary
+===================================
+
+ > git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
+
+Compile the ATF
+===============
+
+ > cd trusted-firmware-a
+ > make CROSS_COMPILE=aarch64-linux-gnu- PLAT=px30 bl31
+ > cp build/px30/release/bl31/bl31.elf ../u-boot/bl31.elf
+
+Compile the U-Boot
+==================
+
+ > cd ../u-boot
+ > make CROSS_COMPILE=aarch64-linux-gnu- ringneck-px30_defconfig all
+
+Flash the image
+===============
+
+Copy u-boot-rockchip.bin to offset 32k for SD/eMMC.
+
+SD-Card
+-------
+
+ > dd if=u-boot-rockchip.bin of=/dev/sdb seek=64
+
+eMMC
+----
+
+rkdeveloptool allows to flash the on-board eMMC via the USB OTG interface with
+help of the Rockchip loader binary.
+
+ > git clone https://github.com/rockchip-linux/rkdeveloptool
+ > cd rkdeveloptool
+ > autoreconf -i && ./configure && make
+ > git clone https://github.com/rockchip-linux/rkbin.git
+ > cd rkbin
+ > ./tools/boot_merger RKBOOT/PX30MINIALL.ini
+ > cd ..
+ > ./rkdeveloptool db rkbin/px30_loader_v1.16.131.bin
+ > ./rkdeveloptool wl 64 ../u-boot-rockchip.bin
diff --git a/board/theobroma-systems/ringneck_px30/ringneck-px30.c b/board/theobroma-systems/ringneck_px30/ringneck-px30.c
new file mode 100644
index 0000000..47d1a40
--- /dev/null
+++ b/board/theobroma-systems/ringneck_px30/ringneck-px30.c
@@ -0,0 +1,175 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Theobroma Systems Design und Consulting GmbH
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <env.h>
+#include <env_internal.h>
+#include <init.h>
+#include <log.h>
+#include <misc.h>
+#include <spl.h>
+#include <syscon.h>
+#include <u-boot/crc.h>
+#include <usb.h>
+#include <dm/pinctrl.h>
+#include <dm/uclass-internal.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/periph.h>
+#include <asm/arch-rockchip/misc.h>
+#include <power/regulator.h>
+#include <u-boot/sha256.h>
+
+/*
+ * Swap mmc0 and mmc1 in boot_targets if booted from SD-Card.
+ *
+ * If bootsource is uSD-card we can assume that we want to use the
+ * SD-Card instead of the eMMC as first boot_target for distroboot.
+ * We only want to swap the defaults and not any custom environment a
+ * user has set. We exit early if a changed boot_targets environment
+ * is detected.
+ */
+static int setup_boottargets(void)
+{
+ const char *boot_device =
+ ofnode_read_chosen_string("u-boot,spl-boot-device");
+ char *env_default, *env;
+
+ if (!boot_device) {
+ debug("%s: /chosen/u-boot,spl-boot-device not set\n",
+ __func__);
+ return -1;
+ }
+ debug("%s: booted from %s\n", __func__, boot_device);
+
+ env_default = env_get_default("boot_targets");
+ env = env_get("boot_targets");
+ if (!env) {
+ debug("%s: boot_targets does not exist\n", __func__);
+ return -1;
+ }
+ debug("%s: boot_targets current: %s - default: %s\n",
+ __func__, env, env_default);
+
+ if (strcmp(env_default, env) != 0) {
+ debug("%s: boot_targets not default, don't change it\n",
+ __func__);
+ return 0;
+ }
+
+ /*
+ * Make the default boot medium between SD Card and eMMC, the one that
+ * was used to load U-Boot proper.
+ */
+ bool sd_booted = !strcmp(boot_device, "/mmc@ff370000");
+ char *mmc0, *mmc1;
+
+ debug("%s: booted from %s\n", __func__,
+ sd_booted ? "SD-Card" : "eMMC");
+ mmc0 = strstr(env, "mmc0");
+ mmc1 = strstr(env, "mmc1");
+
+ if (!mmc0 || !mmc1) {
+ debug("%s: only one mmc boot_target found\n", __func__);
+ return -1;
+ }
+
+ /*
+ * If mmc0 comes first in the boot order and U-Boot proper was
+ * loaded from mmc1, swap mmc0 and mmc1 in the list.
+ * If mmc1 comes first in the boot order and U-Boot proper was
+ * loaded from mmc0, swap mmc0 and mmc1 in the list.
+ */
+ if ((mmc0 < mmc1 && sd_booted) ||
+ (mmc0 > mmc1 && !sd_booted)) {
+ mmc0[3] = '1';
+ mmc1[3] = '0';
+ debug("%s: set boot_targets to: %s\n", __func__, env);
+ env_set("boot_targets", env);
+ }
+
+ return 0;
+}
+
+int mmc_get_env_dev(void)
+{
+ const char *boot_device =
+ ofnode_read_chosen_string("u-boot,spl-boot-device");
+
+ if (!boot_device) {
+ debug("%s: /chosen/u-boot,spl-boot-device not set\n",
+ __func__);
+ return CONFIG_SYS_MMC_ENV_DEV;
+ }
+
+ debug("%s: booted from %s\n", __func__, boot_device);
+
+ if (!strcmp(boot_device, "/mmc@ff370000"))
+ return 1;
+
+ if (!strcmp(boot_device, "/mmc@ff390000"))
+ return 0;
+
+ return CONFIG_SYS_MMC_ENV_DEV;
+}
+
+#if !IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
+#error Please enable CONFIG_ENV_IS_NOWHERE
+#endif
+
+enum env_location arch_env_get_location(enum env_operation op, int prio)
+{
+ const char *boot_device =
+ ofnode_read_chosen_string("u-boot,spl-boot-device");
+
+ if (prio > 0)
+ return ENVL_UNKNOWN;
+
+ if (!boot_device) {
+ debug("%s: /chosen/u-boot,spl-boot-device not set\n",
+ __func__);
+ return ENVL_NOWHERE;
+ }
+
+ debug("%s: booted from %s\n", __func__, boot_device);
+
+ if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC) &&
+ (!strcmp(boot_device, "/mmc@ff370000") ||
+ !strcmp(boot_device, "/mmc@ff390000")))
+ return ENVL_MMC;
+
+ printf("%s: No environment available: booted from %s but U-Boot "
+ "config does not allow loading environment from it.",
+ __func__, boot_device);
+
+ return ENVL_NOWHERE;
+}
+
+int misc_init_r(void)
+{
+ const u32 cpuid_offset = 0x7;
+ const u32 cpuid_length = 0x10;
+ u8 cpuid[cpuid_length];
+ int ret;
+
+ ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid);
+ if (ret)
+ return ret;
+
+ ret = rockchip_cpuid_set(cpuid, cpuid_length);
+ if (ret)
+ return ret;
+
+ ret = rockchip_setup_macaddr();
+ if (ret)
+ return ret;
+
+ setup_boottargets();
+
+ return 0;
+}
diff --git a/board/ti/evm/Kconfig b/board/ti/omap3evm/Kconfig
similarity index 85%
rename from board/ti/evm/Kconfig
rename to board/ti/omap3evm/Kconfig
index 4f490dd..08a8aa2 100644
--- a/board/ti/evm/Kconfig
+++ b/board/ti/omap3evm/Kconfig
@@ -1,7 +1,7 @@
if TARGET_OMAP3_EVM
config SYS_BOARD
- default "evm"
+ default "omap3evm"
config SYS_VENDOR
default "ti"
diff --git a/board/ti/evm/MAINTAINERS b/board/ti/omap3evm/MAINTAINERS
similarity index 85%
rename from board/ti/evm/MAINTAINERS
rename to board/ti/omap3evm/MAINTAINERS
index cd315c1..fb4268b 100644
--- a/board/ti/evm/MAINTAINERS
+++ b/board/ti/omap3evm/MAINTAINERS
@@ -1,6 +1,6 @@
EVM BOARD
M: Derald D. Woods <woods.technical@gmail.com>
S: Maintained
-F: board/ti/evm/
+F: board/ti/omap3evm/
F: include/configs/omap3_evm.h
F: configs/omap3_evm_defconfig
diff --git a/board/ti/evm/Makefile b/board/ti/omap3evm/Makefile
similarity index 100%
rename from board/ti/evm/Makefile
rename to board/ti/omap3evm/Makefile
diff --git a/board/ti/evm/evm.c b/board/ti/omap3evm/evm.c
similarity index 98%
rename from board/ti/evm/evm.c
rename to board/ti/omap3evm/evm.c
index a7f9a7e..a4d6a01 100644
--- a/board/ti/evm/evm.c
+++ b/board/ti/omap3evm/evm.c
@@ -33,7 +33,7 @@
#define OMAP3EVM_GPIO_ETH_RST_GEN1 64
#define OMAP3EVM_GPIO_ETH_RST_GEN2 7
-#define CONFIG_SMC911X_BASE 0x2C000000
+#define CFG_SMC911X_BASE 0x2C000000
DECLARE_GLOBAL_DATA_PTR;
@@ -54,7 +54,7 @@
unsigned int smsc_id;
/* Ethernet PHY ID is stored at ID_REV register */
- smsc_id = readl(CONFIG_SMC911X_BASE + 0x50) & 0xFFFF0000;
+ smsc_id = readl(CFG_SMC911X_BASE + 0x50) & 0xFFFF0000;
printf("Read back SMSC id 0x%x\n", smsc_id);
switch (smsc_id) {
diff --git a/board/ti/evm/evm.h b/board/ti/omap3evm/evm.h
similarity index 100%
rename from board/ti/evm/evm.h
rename to board/ti/omap3evm/evm.h
diff --git a/boot/Kconfig b/boot/Kconfig
index 30bc182..fdcfbae 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -282,12 +282,11 @@
config USE_SPL_FIT_GENERATOR
bool "Use a script to generate the .its script"
depends on SPL_FIT
- default y if !ARCH_SUNXI && !RISCV
+ default y if SPL_FIT && ARCH_ZYNQMP
config SPL_FIT_GENERATOR
string ".its file generator script for U-Boot FIT image"
depends on USE_SPL_FIT_GENERATOR
- default "arch/arm/mach-rockchip/make_fit_atf.py" if SPL_LOAD_FIT && ARCH_ROCKCHIP
default "arch/arm/mach-zynqmp/mkimage_fit_atf.sh" if SPL_LOAD_FIT && ARCH_ZYNQMP
help
Specifies a (platform specific) script file to generate the FIT
@@ -474,6 +473,7 @@
depends on FIT
default y
select BOOTMETH_GLOBAL
+ select EVENT
help
Enables support for VBE boot. This is a standard boot method which
supports selection of various firmware components, seleciton of an OS to
@@ -482,6 +482,7 @@
config SPL_BOOTMETH_VBE
bool "Bootdev support for Verified Boot for Embedded (SPL)"
depends on SPL && FIT
+ select EVENT
default y if VPL
help
Enables support for VBE boot. This is a standard boot method which
@@ -491,6 +492,7 @@
config VPL_BOOTMETH_VBE
bool "Bootdev support for Verified Boot for Embedded (VPL)"
depends on VPL && FIT
+ select EVENT
default y
help
Enables support for VBE boot. This is a standard boot method which
@@ -557,6 +559,18 @@
endif # BOOTMETH_VBE
+config EXPO
+ bool "Support for expos - groups of scenes displaying a UI"
+ default y if BOOTMETH_VBE
+ help
+ An expo is a way of presenting and collecting information from the
+ user. It consists of a collection of 'scenes' of which only one is
+ presented at a time. An expo is typically used to show a boot menu
+ and allow settings to be changed.
+
+ The expo can be presented in graphics form using a vidconsole, or in
+ text form on a serial console.
+
config BOOTMETH_SANDBOX
def_bool y
depends on SANDBOX
diff --git a/boot/Makefile b/boot/Makefile
index f0c3154..f990e66 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -30,6 +30,7 @@
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o
ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL
obj-$(CONFIG_$(SPL_TPL_)CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow_menu.o
endif
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
@@ -47,6 +48,8 @@
obj-$(CONFIG_SPL_LOAD_FIT) += common_fit.o
endif
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += expo.o scene.o scene_menu.o
+
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE) += vbe.o vbe_request.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE) += vbe_simple.o
obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE_FW) += vbe_simple_fw.o
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index affe0d3..99ee08e 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -12,7 +12,6 @@
#include <bootflow.h>
#include <bootmeth.h>
#include <bootstd.h>
-#include <env.h>
#include <fs.h>
#include <log.h>
#include <malloc.h>
@@ -164,7 +163,15 @@
*/
iter->max_part = MAX_PART_PER_BOOTDEV;
- if (iter->part) {
+ /* If this is the whole disk, check if we have bootable partitions */
+ if (!iter->part) {
+ iter->first_bootable = part_get_bootable(desc);
+ log_debug("checking bootable=%d\n", iter->first_bootable);
+
+ /* if there are bootable partitions, scan only those */
+ } else if (iter->first_bootable ? !info.bootable : iter->part != 1) {
+ return log_msg_ret("boot", -EINVAL);
+ } else {
ret = fs_set_blk_dev_with_part(desc, bflow->part);
bflow->state = BOOTFLOWST_PART;
@@ -235,13 +242,27 @@
return 0;
}
+static int bootdev_get_suffix_start(struct udevice *dev, const char *suffix)
+{
+ int len, slen;
+
+ len = strlen(dev->name);
+ slen = strlen(suffix);
+ if (len > slen && !strcmp(suffix, dev->name + len - slen))
+ return len - slen;
+
+ return len;
+}
+
int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name)
{
struct udevice *parent, *dev;
char dev_name[50];
- int ret;
+ int ret, len;
- snprintf(dev_name, sizeof(dev_name), "%s.%s", blk->name, "bootdev");
+ len = bootdev_get_suffix_start(blk, ".blk");
+ snprintf(dev_name, sizeof(dev_name), "%.*s.%s", len, blk->name,
+ "bootdev");
parent = dev_get_parent(blk);
ret = device_find_child_by_name(parent, dev_name, &dev);
@@ -272,20 +293,22 @@
struct udevice *parent = dev_get_parent(dev);
struct udevice *blk;
int ret, len;
- char *p;
if (device_get_uclass_id(dev) != UCLASS_BOOTDEV)
return -EINVAL;
/* This should always work if bootdev_setup_sibling_blk() was used */
- p = strstr(dev->name, ".bootdev");
- if (!p)
- return log_msg_ret("str", -EINVAL);
-
- len = p - dev->name;
+ len = bootdev_get_suffix_start(dev, ".bootdev");
ret = device_find_child_by_namelen(parent, dev->name, len, &blk);
- if (ret)
- return log_msg_ret("find", ret);
+ if (ret) {
+ char dev_name[50];
+
+ snprintf(dev_name, sizeof(dev_name), "%.*s.blk", len,
+ dev->name);
+ ret = device_find_child_by_name(parent, dev_name, &blk);
+ if (ret)
+ return log_msg_ret("find", ret);
+ }
*blkp = blk;
return 0;
@@ -296,13 +319,15 @@
struct udevice *parent = dev_get_parent(blk);
struct udevice *bootdev;
char dev_name[50];
- int ret;
+ int ret, len;
if (device_get_uclass_id(blk) != UCLASS_BLK)
return -EINVAL;
/* This should always work if bootdev_setup_sibling_blk() was used */
- snprintf(dev_name, sizeof(dev_name), "%s.%s", blk->name, "bootdev");
+ len = bootdev_get_suffix_start(blk, ".blk");
+ snprintf(dev_name, sizeof(dev_name), "%.*s.%s", len, blk->name,
+ "bootdev");
ret = device_find_child_by_name(parent, dev_name, &bootdev);
if (ret)
return log_msg_ret("find", ret);
@@ -330,36 +355,67 @@
}
/**
- * bootdev_find_by_label() - Convert a label string to a bootdev device
+ * label_to_uclass() - Convert a label to a uclass and sequence number
*
- * Looks up a label name to find the associated bootdev. For example, if the
- * label name is "mmc2", this will find a bootdev for an mmc device whose
- * sequence number is 2.
- *
- * @label: Label string to convert, e.g. "mmc2"
- * @devp: Returns bootdev device corresponding to that boot label
- * Return: 0 if OK, -EINVAL if the label name (e.g. "mmc") does not refer to a
- * uclass, -ENOENT if no bootdev for that media has the sequence number
- * (e.g. 2)
+ * @label: Label to look up (e.g. "mmc1" or "mmc0")
+ * @seqp: Returns the sequence number, or -1 if none
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none
+ * Returns: sequence number on success, else -ve error code
*/
-int bootdev_find_by_label(const char *label, struct udevice **devp)
+static int label_to_uclass(const char *label, int *seqp, int *method_flagsp)
{
- struct udevice *media;
- struct uclass *uc;
+ int seq, len, method_flags;
enum uclass_id id;
const char *end;
- int seq;
+ method_flags = 0;
seq = trailing_strtoln_end(label, NULL, &end);
- id = uclass_get_by_namelen(label, end - label);
+ len = end - label;
+ if (!len)
+ return -EINVAL;
+ id = uclass_get_by_namelen(label, len);
log_debug("find %s: seq=%d, id=%d/%s\n", label, seq, id,
uclass_get_name(id));
if (id == UCLASS_INVALID) {
- log_warning("Unknown uclass '%s' in label\n", label);
- return -EINVAL;
+ /* try some special cases */
+ if (IS_ENABLED(CONFIG_BOOTDEV_SPI_FLASH) &&
+ !strncmp("spi", label, len)) {
+ id = UCLASS_SPI_FLASH;
+ } else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) &&
+ !strncmp("pxe", label, len)) {
+ id = UCLASS_ETH;
+ method_flags |= BOOTFLOW_METHF_PXE_ONLY;
+ } else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) &&
+ !strncmp("dhcp", label, len)) {
+ id = UCLASS_ETH;
+ method_flags |= BOOTFLOW_METHF_DHCP_ONLY;
+ } else {
+ log_warning("Unknown uclass '%s' in label\n", label);
+ return -EINVAL;
+ }
}
if (id == UCLASS_USB)
id = UCLASS_MASS_STORAGE;
+ *seqp = seq;
+ if (method_flagsp)
+ *method_flagsp = method_flags;
+
+ return id;
+}
+
+int bootdev_find_by_label(const char *label, struct udevice **devp,
+ int *method_flagsp)
+{
+ int seq, ret, method_flags = 0;
+ struct udevice *media;
+ struct uclass *uc;
+ enum uclass_id id;
+
+ ret = label_to_uclass(label, &seq, &method_flags);
+ if (ret < 0)
+ return log_msg_ret("uc", ret);
+ id = ret;
/* Iterate through devices in the media uclass (e.g. UCLASS_MMC) */
uclass_id_foreach_dev(id, media, uc) {
@@ -386,6 +442,15 @@
if (!ret) {
log_debug("- found %s\n", bdev->name);
*devp = bdev;
+
+ /*
+ * if no sequence number was provided, we must scan all
+ * bootdevs for this media uclass
+ */
+ if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && seq == -1)
+ method_flags |= BOOTFLOW_METHF_SINGLE_UCLASS;
+ if (method_flagsp)
+ *method_flagsp = method_flags;
return 0;
}
log_debug("- no device in %s\n", media->name);
@@ -395,10 +460,12 @@
return -ENOENT;
}
-int bootdev_find_by_any(const char *name, struct udevice **devp)
+int bootdev_find_by_any(const char *name, struct udevice **devp,
+ int *method_flagsp)
{
struct udevice *dev;
- int ret, seq;
+ int method_flags = 0;
+ int ret = -ENODEV, seq;
char *endp;
seq = simple_strtol(name, &endp, 16);
@@ -407,21 +474,22 @@
if (*endp) {
ret = uclass_get_device_by_name(UCLASS_BOOTDEV, name, &dev);
if (ret == -ENODEV) {
- ret = bootdev_find_by_label(name, &dev);
+ ret = bootdev_find_by_label(name, &dev, &method_flags);
if (ret) {
printf("Cannot find bootdev '%s' (err=%d)\n",
name, ret);
- return ret;
+ return log_msg_ret("lab", ret);
}
ret = device_probe(dev);
}
if (ret) {
printf("Cannot probe bootdev '%s' (err=%d)\n", name,
ret);
- return ret;
+ return log_msg_ret("pro", ret);
}
- } else {
+ } else if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
ret = uclass_get_device_by_seq(UCLASS_BOOTDEV, seq, &dev);
+ method_flags |= BOOTFLOW_METHF_SINGLE_DEV;
}
if (ret) {
printf("Cannot find '%s' (err=%d)\n", name, ret);
@@ -429,6 +497,46 @@
}
*devp = dev;
+ if (method_flagsp)
+ *method_flagsp = method_flags;
+
+ return 0;
+}
+
+int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
+ int *method_flagsp)
+{
+ int ret;
+
+ ret = bootdev_hunt(label, false);
+ if (ret)
+ return log_msg_ret("scn", ret);
+ ret = bootdev_find_by_label(label, devp, method_flagsp);
+ if (ret)
+ return log_msg_ret("fnd", ret);
+
+ return 0;
+}
+
+static int default_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+ struct bootflow *bflow)
+{
+ struct udevice *blk;
+ int ret;
+
+ ret = bootdev_get_sibling_blk(dev, &blk);
+ /*
+ * If there is no media, indicate that no more partitions should be
+ * checked
+ */
+ if (ret == -EOPNOTSUPP)
+ ret = -ESHUTDOWN;
+ if (ret)
+ return log_msg_ret("blk", ret);
+ assert(blk);
+ ret = bootdev_find_in_blk(dev, blk, iter, bflow);
+ if (ret)
+ return log_msg_ret("find", ret);
return 0;
}
@@ -438,9 +546,10 @@
{
const struct bootdev_ops *ops = bootdev_get_ops(dev);
- if (!ops->get_bootflow)
- return -ENOSYS;
+ log_debug("->get_bootflow %s=%p\n", dev->name, ops->get_bootflow);
bootflow_init(bflow, dev, iter->method);
+ if (!ops->get_bootflow)
+ return default_get_bootflow(dev, iter, bflow);
return ops->get_bootflow(dev, iter, bflow);
}
@@ -458,116 +567,95 @@
}
}
-/**
- * h_cmp_bootdev() - Compare two bootdevs to find out which should go first
- *
- * @v1: struct udevice * of first bootdev device
- * @v2: struct udevice * of second bootdev device
- * Return: sort order (<0 if dev1 < dev2, ==0 if equal, >0 if dev1 > dev2)
- */
-static int h_cmp_bootdev(const void *v1, const void *v2)
+int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
+ int *method_flagsp)
{
- const struct udevice *dev1 = *(struct udevice **)v1;
- const struct udevice *dev2 = *(struct udevice **)v2;
- const struct bootdev_uc_plat *ucp1 = dev_get_uclass_plat(dev1);
- const struct bootdev_uc_plat *ucp2 = dev_get_uclass_plat(dev2);
- int diff;
-
- /* Use priority first */
- diff = ucp1->prio - ucp2->prio;
- if (diff)
- return diff;
-
- /* Fall back to seq for devices of the same priority */
- diff = dev_seq(dev1) - dev_seq(dev2);
-
- return diff;
-}
-
-/**
- * build_order() - Build the ordered list of bootdevs to use
- *
- * This builds an ordered list of devices by one of three methods:
- * - using the boot_targets environment variable, if non-empty
- * - using the bootdev-order devicetree property, if present
- * - sorted by priority and sequence number
- *
- * @bootstd: BOOTSTD device to use
- * @order: Bootdevs listed in default order
- * @max_count: Number of entries in @order
- * Return: number of bootdevs found in the ordering, or -E2BIG if the
- * boot_targets string is too long, or -EXDEV if the ordering produced 0 results
- */
-static int build_order(struct udevice *bootstd, struct udevice **order,
- int max_count)
-{
- const char *overflow_target = NULL;
- const char *const *labels;
struct udevice *dev;
- const char *targets;
- int i, ret, count;
- targets = env_get("boot_targets");
- labels = IS_ENABLED(CONFIG_BOOTSTD_FULL) ?
- bootstd_get_bootdev_order(bootstd) : NULL;
- if (targets) {
- char str[BOOT_TARGETS_MAX_LEN];
- char *target;
-
- if (strlen(targets) >= BOOT_TARGETS_MAX_LEN)
- return log_msg_ret("len", -E2BIG);
-
- /* make a copy of the string, since strok() will change it */
- strcpy(str, targets);
- for (i = 0, target = strtok(str, " "); target;
- target = strtok(NULL, " ")) {
- ret = bootdev_find_by_label(target, &dev);
- if (!ret) {
- if (i == max_count) {
- overflow_target = target;
- break;
- }
- order[i++] = dev;
- }
- }
- count = i;
- } else if (labels) {
- int upto;
-
- upto = 0;
- for (i = 0; labels[i]; i++) {
- ret = bootdev_find_by_label(labels[i], &dev);
- if (!ret) {
- if (upto == max_count) {
- overflow_target = labels[i];
- break;
- }
- order[upto++] = dev;
- }
- }
- count = upto;
- } else {
- /* sort them into priority order */
- count = max_count;
- qsort(order, count, sizeof(struct udevice *), h_cmp_bootdev);
+ log_debug("next\n");
+ for (dev = NULL; !dev && iter->labels[++iter->cur_label];) {
+ log_debug("Scanning: %s\n", iter->labels[iter->cur_label]);
+ bootdev_hunt_and_find_by_label(iter->labels[iter->cur_label],
+ &dev, method_flagsp);
}
- if (overflow_target) {
- log_warning("Expected at most %d bootdevs, but overflowed with boot_target '%s'\n",
- max_count, overflow_target);
- }
+ if (!dev)
+ return log_msg_ret("fin", -ENODEV);
+ *devp = dev;
- if (!count)
- return log_msg_ret("targ", -EXDEV);
-
- return count;
+ return 0;
}
-int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp)
+int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp)
{
- struct udevice *bootstd, *dev = *devp, **order;
- int upto, i;
- int count;
+ struct udevice *dev = *devp;
+ bool found;
+ int ret;
+
+ /* find the next device with this priority */
+ *devp = NULL;
+ log_debug("next prio %d: dev=%p/%s\n", iter->cur_prio, dev,
+ dev ? dev->name : "none");
+ do {
+ /*
+ * Don't probe devices here since they may not be of the
+ * required priority
+ */
+ if (!dev)
+ uclass_find_first_device(UCLASS_BOOTDEV, &dev);
+ else
+ uclass_find_next_device(&dev);
+ found = false;
+
+ /* scan for the next device with the correct priority */
+ while (dev) {
+ struct bootdev_uc_plat *plat;
+
+ plat = dev_get_uclass_plat(dev);
+ log_debug("- %s: %d, want %d\n", dev->name, plat->prio,
+ iter->cur_prio);
+ if (plat->prio == iter->cur_prio)
+ break;
+ uclass_find_next_device(&dev);
+ }
+
+ /* none found for this priority, so move to the next */
+ if (!dev) {
+ log_debug("None found at prio %d, moving to %d\n",
+ iter->cur_prio, iter->cur_prio + 1);
+ if (++iter->cur_prio == BOOTDEVP_COUNT)
+ return log_msg_ret("fin", -ENODEV);
+
+ if (iter->flags & BOOTFLOWF_HUNT) {
+ /* hunt to find new bootdevs */
+ ret = bootdev_hunt_prio(iter->cur_prio,
+ iter->flags &
+ BOOTFLOWF_SHOW);
+ log_debug("- hunt ret %d\n", ret);
+ if (ret)
+ return log_msg_ret("hun", ret);
+ }
+ } else {
+ ret = device_probe(dev);
+ if (ret) {
+ log_debug("Device '%s' failed to probe\n",
+ dev->name);
+ dev = NULL;
+ }
+ }
+ } while (!dev);
+
+ *devp = dev;
+
+ return 0;
+}
+
+int bootdev_setup_iter(struct bootflow_iter *iter, const char *label,
+ struct udevice **devp, int *method_flagsp)
+{
+ struct udevice *bootstd, *dev = NULL;
+ bool show = iter->flags & BOOTFLOWF_SHOW;
+ int method_flags;
int ret;
ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
@@ -576,53 +664,182 @@
return log_msg_ret("std", ret);
}
+ /* hunt for any pre-scan devices */
+ if (iter->flags & BOOTFLOWF_HUNT) {
+ ret = bootdev_hunt_prio(BOOTDEVP_1_PRE_SCAN, show);
+ if (ret)
+ return log_msg_ret("pre", ret);
+ }
+
/* Handle scanning a single device */
- if (dev) {
- iter->flags |= BOOTFLOWF_SINGLE_DEV;
- return 0;
+ if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && label) {
+ if (iter->flags & BOOTFLOWF_HUNT) {
+ ret = bootdev_hunt(label, show);
+ if (ret)
+ return log_msg_ret("hun", ret);
+ }
+ ret = bootdev_find_by_any(label, &dev, &method_flags);
+ if (ret)
+ return log_msg_ret("lab", ret);
+
+ log_debug("method_flags: %x\n", method_flags);
+ if (method_flags & BOOTFLOW_METHF_SINGLE_UCLASS)
+ iter->flags |= BOOTFLOWF_SINGLE_UCLASS;
+ else if (method_flags & BOOTFLOW_METHF_SINGLE_DEV)
+ iter->flags |= BOOTFLOWF_SINGLE_DEV;
+ else
+ iter->flags |= BOOTFLOWF_SINGLE_MEDIA;
+ log_debug("Selected label: %s, flags %x\n", label, iter->flags);
+ } else {
+ bool ok;
+
+ /* This either returns a non-empty list or NULL */
+ iter->labels = bootstd_get_bootdev_order(bootstd, &ok);
+ if (!ok)
+ return log_msg_ret("ord", -ENOMEM);
+ log_debug("setup labels %p\n", iter->labels);
+ if (iter->labels) {
+ iter->cur_label = -1;
+ ret = bootdev_next_label(iter, &dev, &method_flags);
+ } else {
+ ret = bootdev_next_prio(iter, &dev);
+ method_flags = 0;
+ }
+ if (!dev)
+ return log_msg_ret("fin", -ENOENT);
+ log_debug("Selected bootdev: %s\n", dev->name);
}
- count = uclass_id_count(UCLASS_BOOTDEV);
- if (!count)
- return log_msg_ret("count", -ENOENT);
-
- order = calloc(count, sizeof(struct udevice *));
- if (!order)
- return log_msg_ret("order", -ENOMEM);
-
- /*
- * Get a list of bootdevs, in seq order (i.e. using aliases). There may
- * be gaps so try to count up high enough to find them all.
- */
- for (i = 0, upto = 0; upto < count && i < 20 + count * 2; i++) {
- ret = uclass_find_device_by_seq(UCLASS_BOOTDEV, i, &dev);
- if (!ret)
- order[upto++] = dev;
- }
- log_debug("Found %d bootdevs\n", count);
- if (upto != count)
- log_debug("Expected %d bootdevs, found %d using aliases\n",
- count, upto);
-
- ret = build_order(bootstd, order, upto);
- if (ret < 0) {
- free(order);
- return log_msg_ret("build", ret);
- }
-
- iter->num_devs = ret;
- iter->dev_order = order;
- iter->cur_dev = 0;
-
- dev = *order;
ret = device_probe(dev);
if (ret)
return log_msg_ret("probe", ret);
+ if (method_flagsp)
+ *method_flagsp = method_flags;
*devp = dev;
return 0;
}
+static int bootdev_hunt_drv(struct bootdev_hunter *info, uint seq, bool show)
+{
+ const char *name = uclass_get_name(info->uclass);
+ struct bootstd_priv *std;
+ int ret;
+
+ ret = bootstd_get_priv(&std);
+ if (ret)
+ return log_msg_ret("std", ret);
+
+ if (!(std->hunters_used & BIT(seq))) {
+ if (show)
+ printf("Hunting with: %s\n",
+ uclass_get_name(info->uclass));
+ log_debug("Hunting with: %s\n", name);
+ if (info->hunt) {
+ ret = info->hunt(info, show);
+ if (ret)
+ return ret;
+ }
+ std->hunters_used |= BIT(seq);
+ }
+
+ return 0;
+}
+
+int bootdev_hunt(const char *spec, bool show)
+{
+ struct bootdev_hunter *start;
+ const char *end;
+ int n_ent, i;
+ int result;
+ size_t len;
+
+ start = ll_entry_start(struct bootdev_hunter, bootdev_hunter);
+ n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter);
+ result = 0;
+
+ len = SIZE_MAX;
+ if (spec) {
+ trailing_strtoln_end(spec, NULL, &end);
+ len = end - spec;
+ }
+
+ for (i = 0; i < n_ent; i++) {
+ struct bootdev_hunter *info = start + i;
+ const char *name = uclass_get_name(info->uclass);
+ int ret;
+
+ log_debug("looking at %.*s for %s\n",
+ (int)max(strlen(name), len), spec, name);
+ if (spec && strncmp(spec, name, max(strlen(name), len))) {
+ if (info->uclass != UCLASS_ETH ||
+ (strcmp("dhcp", spec) && strcmp("pxe", spec)))
+ continue;
+ }
+ ret = bootdev_hunt_drv(info, i, show);
+ if (ret)
+ result = ret;
+ }
+
+ return result;
+}
+
+int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show)
+{
+ struct bootdev_hunter *start;
+ int n_ent, i;
+ int result;
+
+ start = ll_entry_start(struct bootdev_hunter, bootdev_hunter);
+ n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter);
+ result = 0;
+
+ log_debug("Hunting for priority %d\n", prio);
+ for (i = 0; i < n_ent; i++) {
+ struct bootdev_hunter *info = start + i;
+ int ret;
+
+ if (prio != info->prio)
+ continue;
+ ret = bootdev_hunt_drv(info, i, show);
+ if (ret && ret != -ENOENT)
+ result = ret;
+ }
+
+ return result;
+}
+
+void bootdev_list_hunters(struct bootstd_priv *std)
+{
+ struct bootdev_hunter *orig, *start;
+ int n_ent, i;
+
+ orig = ll_entry_start(struct bootdev_hunter, bootdev_hunter);
+ n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter);
+
+ /*
+ * workaround for strange bug in clang-12 which sees all the below data
+ * as zeroes. Any access of start seems to fix it, such as
+ *
+ * printf("%p", start);
+ *
+ * Use memcpy() to force the correct behaviour.
+ */
+ memcpy(&start, &orig, sizeof(orig));
+ printf("%4s %4s %-15s %s\n", "Prio", "Used", "Uclass", "Hunter");
+ printf("%4s %4s %-15s %s\n", "----", "----", "---------------", "---------------");
+ for (i = 0; i < n_ent; i++) {
+ struct bootdev_hunter *info = start + i;
+
+ printf("%4d %4s %-15s %s\n", info->prio,
+ std->hunters_used & BIT(i) ? "*" : "",
+ uclass_get_name(info->uclass),
+ info->drv ? info->drv->name : "(none)");
+ }
+
+ printf("(total hunters: %d)\n", n_ent);
+}
+
static int bootdev_post_bind(struct udevice *dev)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
diff --git a/boot/bootflow.c b/boot/bootflow.c
index f9ad409..dc3f1f0 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -88,11 +88,13 @@
memset(iter, '\0', sizeof(*iter));
iter->first_glob_method = -1;
iter->flags = flags;
+
+ /* remember the first bootdevs we see */
+ iter->max_devs = BOOTFLOW_MAX_USED_DEVS;
}
void bootflow_iter_uninit(struct bootflow_iter *iter)
{
- free(iter->dev_order);
free(iter->method_order);
}
@@ -113,22 +115,41 @@
return 0;
}
+/**
+ * bootflow_iter_set_dev() - switch to the next bootdev when iterating
+ *
+ * This sets iter->dev, records the device in the dev_used[] list and shows a
+ * message if required
+ *
+ * @iter: Iterator to update
+ * @dev: Bootdev to use, or NULL if there are no more
+ */
static void bootflow_iter_set_dev(struct bootflow_iter *iter,
- struct udevice *dev)
+ struct udevice *dev, int method_flags)
{
struct bootmeth_uc_plat *ucp = dev_get_uclass_plat(iter->method);
+ log_debug("iter: Setting dev to %s, flags %x\n",
+ dev ? dev->name : "(none)", method_flags);
iter->dev = dev;
- if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
- BOOTFLOWF_SHOW) {
- if (dev)
- printf("Scanning bootdev '%s':\n", dev->name);
- else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
- ucp->flags & BOOTMETHF_GLOBAL)
- printf("Scanning global bootmeth '%s':\n",
- iter->method->name);
- else
- printf("No more bootdevs\n");
+ iter->method_flags = method_flags;
+
+ if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
+ /* record the device for later */
+ if (dev && iter->num_devs < iter->max_devs)
+ iter->dev_used[iter->num_devs++] = dev;
+
+ if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
+ BOOTFLOWF_SHOW) {
+ if (dev)
+ printf("Scanning bootdev '%s':\n", dev->name);
+ else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
+ ucp->flags & BOOTMETHF_GLOBAL)
+ printf("Scanning global bootmeth '%s':\n",
+ iter->method->name);
+ else
+ printf("No more bootdevs\n");
+ }
}
}
@@ -144,6 +165,7 @@
bool global;
int ret;
+ log_debug("entry: err=%d\n", iter->err);
global = iter->doing_global;
if (iter->err == BF_NO_MORE_DEVICES)
@@ -182,7 +204,7 @@
return 0;
}
- /* No more partitions; start at the first one and...*/
+ /* No more partitions; start at the first one and... */
iter->part = 0;
/*
@@ -196,16 +218,62 @@
if (iter->flags & BOOTFLOWF_SINGLE_DEV) {
ret = -ENOENT;
} else {
- if (inc_dev)
- iter->cur_dev++;
- if (iter->cur_dev == iter->num_devs) {
- ret = -ENOENT;
- bootflow_iter_set_dev(iter, NULL);
+ int method_flags;
+
+ ret = 0;
+ dev = iter->dev;
+ log_debug("inc_dev=%d\n", inc_dev);
+ if (!inc_dev) {
+ ret = bootdev_setup_iter(iter, NULL, &dev,
+ &method_flags);
+ } else if (IS_ENABLED(CONFIG_BOOTSTD_FULL) &&
+ (iter->flags & BOOTFLOWF_SINGLE_UCLASS)) {
+ /* Move to the next bootdev in this uclass */
+ uclass_find_next_device(&dev);
+ if (!dev) {
+ log_debug("finished uclass %s\n",
+ dev_get_uclass_name(dev));
+ ret = -ENODEV;
+ }
+ } else if (IS_ENABLED(CONFIG_BOOTSTD_FULL) &&
+ iter->flags & BOOTFLOWF_SINGLE_MEDIA) {
+ log_debug("next in single\n");
+ method_flags = 0;
+ do {
+ /*
+ * Move to the next bootdev child of this media
+ * device. This ensures that we cover all the
+ * available SCSI IDs and LUNs.
+ */
+ device_find_next_child(&dev);
+ log_debug("- next %s\n",
+ dev ? dev->name : "(none)");
+ } while (dev && device_get_uclass_id(dev) !=
+ UCLASS_BOOTDEV);
+ if (!dev) {
+ log_debug("finished uclass %s\n",
+ dev_get_uclass_name(dev));
+ ret = -ENODEV;
+ }
} else {
- dev = iter->dev_order[iter->cur_dev];
+ log_debug("labels %p\n", iter->labels);
+ if (iter->labels) {
+ ret = bootdev_next_label(iter, &dev,
+ &method_flags);
+ } else {
+ ret = bootdev_next_prio(iter, &dev);
+ method_flags = 0;
+ }
+ }
+ log_debug("ret=%d, dev=%p %s\n", ret, dev,
+ dev ? dev->name : "none");
+ if (ret) {
+ bootflow_iter_set_dev(iter, NULL, 0);
+ } else {
ret = device_probe(dev);
+ log_debug("probe %s %d\n", dev->name, ret);
if (!log_msg_ret("probe", ret))
- bootflow_iter_set_dev(iter, dev);
+ bootflow_iter_set_dev(iter, dev, method_flags);
}
}
@@ -230,7 +298,7 @@
int ret;
if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->doing_global) {
- bootflow_iter_set_dev(iter, NULL);
+ bootflow_iter_set_dev(iter, NULL, 0);
ret = bootmeth_get_bootflow(iter->method, bflow);
if (ret)
return log_msg_ret("glob", ret);
@@ -265,30 +333,41 @@
return 0;
}
-int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
- int flags, struct bootflow *bflow)
+int bootflow_scan_first(struct udevice *dev, const char *label,
+ struct bootflow_iter *iter, int flags,
+ struct bootflow *bflow)
{
int ret;
- if (dev)
+ if (dev || label)
flags |= BOOTFLOWF_SKIP_GLOBAL;
bootflow_iter_init(iter, flags);
- ret = bootdev_setup_iter_order(iter, &dev);
- if (ret)
- return log_msg_ret("obdev", -ENODEV);
-
+ /*
+ * Set up the ordering of bootmeths. This sets iter->doing_global and
+ * iter->first_glob_method if we are starting with the global bootmeths
+ */
ret = bootmeth_setup_iter_order(iter, !(flags & BOOTFLOWF_SKIP_GLOBAL));
if (ret)
return log_msg_ret("obmeth", -ENODEV);
/* Find the first bootmeth (there must be at least one!) */
iter->method = iter->method_order[iter->cur_method];
- if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) || !iter->doing_global)
- bootflow_iter_set_dev(iter, dev);
+
+ if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) || !iter->doing_global) {
+ struct udevice *dev = NULL;
+ int method_flags;
+
+ ret = bootdev_setup_iter(iter, label, &dev, &method_flags);
+ if (ret)
+ return log_msg_ret("obdev", -ENODEV);
+
+ bootflow_iter_set_dev(iter, dev, method_flags);
+ }
ret = bootflow_check(iter, bflow);
if (ret) {
+ log_debug("check - ret=%d\n", ret);
if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) {
if (iter->flags & BOOTFLOWF_ALL)
return log_msg_ret("all", ret);
@@ -302,29 +381,19 @@
return 0;
}
-int bootflow_scan_first(struct bootflow_iter *iter, int flags,
- struct bootflow *bflow)
-{
- int ret;
-
- ret = bootflow_scan_bootdev(NULL, iter, flags, bflow);
- if (ret)
- return log_msg_ret("start", ret);
-
- return 0;
-}
-
int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow)
{
int ret;
do {
ret = iter_incr(iter);
+ log_debug("iter_incr: ret=%d\n", ret);
if (ret == BF_NO_MORE_DEVICES)
return log_msg_ret("done", ret);
if (!ret) {
ret = bootflow_check(iter, bflow);
+ log_debug("check - ret=%d\n", ret);
if (!ret)
return 0;
iter->err = ret;
@@ -333,6 +402,7 @@
return log_msg_ret("all", ret);
}
} else {
+ log_debug("incr failed, err=%d\n", ret);
iter->err = ret;
}
@@ -354,6 +424,8 @@
free(bflow->subdir);
free(bflow->fname);
free(bflow->buf);
+ free(bflow->os_name);
+ free(bflow->fdt_fname);
}
void bootflow_remove(struct bootflow *bflow)
@@ -426,7 +498,7 @@
return ret;
}
-int bootflow_iter_uses_blk_dev(const struct bootflow_iter *iter)
+int bootflow_iter_check_blk(const struct bootflow_iter *iter)
{
const struct udevice *media = dev_get_parent(iter->dev);
enum uclass_id id = device_get_uclass_id(media);
@@ -438,7 +510,19 @@
return -ENOTSUPP;
}
-int bootflow_iter_uses_network(const struct bootflow_iter *iter)
+int bootflow_iter_check_sf(const struct bootflow_iter *iter)
+{
+ const struct udevice *media = dev_get_parent(iter->dev);
+ enum uclass_id id = device_get_uclass_id(media);
+
+ log_debug("uclass %d: %s\n", id, uclass_get_name(id));
+ if (id == UCLASS_SPI_FLASH)
+ return 0;
+
+ return -ENOTSUPP;
+}
+
+int bootflow_iter_check_net(const struct bootflow_iter *iter)
{
const struct udevice *media = dev_get_parent(iter->dev);
enum uclass_id id = device_get_uclass_id(media);
@@ -450,7 +534,7 @@
return -ENOTSUPP;
}
-int bootflow_iter_uses_system(const struct bootflow_iter *iter)
+int bootflow_iter_check_system(const struct bootflow_iter *iter)
{
const struct udevice *media = dev_get_parent(iter->dev);
enum uclass_id id = device_get_uclass_id(media);
diff --git a/boot/bootflow_internal.h b/boot/bootflow_internal.h
new file mode 100644
index 0000000..38cf02a
--- /dev/null
+++ b/boot/bootflow_internal.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Internal header file for bootflow
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __BOOTFLOW_INTERNAL_H
+#define __BOOTFLOW_INTERNAL_H
+
+/* expo IDs for elements of the bootflow menu */
+enum {
+ START,
+
+ /* strings */
+ STR_PROMPT,
+ STR_MENU_TITLE,
+ STR_POINTER,
+
+ /* scene */
+ MAIN,
+
+ /* objects */
+ OBJ_U_BOOT_LOGO,
+ OBJ_MENU,
+ OBJ_PROMPT,
+ OBJ_MENU_TITLE,
+ OBJ_POINTER,
+
+ /* strings for menu items */
+ STR_LABEL = 100,
+ STR_DESC = 200,
+ STR_KEY = 300,
+
+ /* menu items / components (bootflow number is added to these) */
+ ITEM = 400,
+ ITEM_LABEL = 500,
+ ITEM_DESC = 600,
+ ITEM_KEY = 700,
+ ITEM_PREVIEW = 800,
+
+ /* left margin for the main menu */
+ MARGIN_LEFT = 100,
+};
+
+#endif /* __BOOTFLOW_INTERNAL_H */
diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
new file mode 100644
index 0000000..7f06dac
--- /dev/null
+++ b/boot/bootflow_menu.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Provide a menu of available bootflows and related options
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <common.h>
+#include <bootflow.h>
+#include <bootstd.h>
+#include <cli.h>
+#include <dm.h>
+#include <expo.h>
+#include <malloc.h>
+#include <menu.h>
+#include <video_console.h>
+#include <watchdog.h>
+#include <linux/delay.h>
+#include "bootflow_internal.h"
+
+/**
+ * struct menu_priv - information about the menu
+ *
+ * @num_bootflows: Number of bootflows in the menu
+ */
+struct menu_priv {
+ int num_bootflows;
+};
+
+int bootflow_menu_new(struct expo **expp)
+{
+ struct udevice *last_bootdev;
+ struct scene_obj_menu *menu;
+ struct menu_priv *priv;
+ struct bootflow *bflow;
+ struct scene *scn;
+ struct expo *exp;
+ void *logo;
+ int ret, i;
+
+ priv = calloc(1, sizeof(*priv));
+ if (!priv)
+ return log_msg_ret("prv", -ENOMEM);
+
+ ret = expo_new("bootflows", priv, &exp);
+ if (ret)
+ return log_msg_ret("exp", ret);
+
+ ret = scene_new(exp, "main", MAIN, &scn);
+ if (ret < 0)
+ return log_msg_ret("scn", ret);
+
+ ret |= scene_txt_str(scn, "prompt", OBJ_PROMPT, STR_PROMPT,
+ "UP and DOWN to choose, ENTER to select", NULL);
+
+ ret = scene_menu(scn, "main", OBJ_MENU, &menu);
+ ret |= scene_obj_set_pos(scn, OBJ_MENU, MARGIN_LEFT, 100);
+ ret |= scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
+ "U-Boot - Boot Menu", NULL);
+ ret |= scene_menu_set_title(scn, OBJ_MENU, OBJ_PROMPT);
+
+ logo = video_get_u_boot_logo();
+ if (logo) {
+ ret |= scene_img(scn, "ulogo", OBJ_U_BOOT_LOGO, logo, NULL);
+ ret |= scene_obj_set_pos(scn, OBJ_U_BOOT_LOGO, -4, 4);
+ }
+
+ ret |= scene_txt_str(scn, "cur_item", OBJ_POINTER, STR_POINTER, ">",
+ NULL);
+ ret |= scene_menu_set_pointer(scn, OBJ_MENU, OBJ_POINTER);
+ if (ret < 0)
+ return log_msg_ret("new", -EINVAL);
+
+ last_bootdev = NULL;
+ for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
+ ret = bootflow_next_glob(&bflow), i++) {
+ char str[2], *label, *key;
+ uint preview_id;
+ bool add_gap;
+
+ if (bflow->state != BOOTFLOWST_READY)
+ continue;
+
+ *str = i < 10 ? '0' + i : 'A' + i - 10;
+ str[1] = '\0';
+ key = strdup(str);
+ if (!key)
+ return log_msg_ret("key", -ENOMEM);
+ label = strdup(dev_get_parent(bflow->dev)->name);
+ if (!label) {
+ free(key);
+ return log_msg_ret("nam", -ENOMEM);
+ }
+
+ add_gap = last_bootdev != bflow->dev;
+ last_bootdev = bflow->dev;
+
+ ret = expo_str(exp, "prompt", STR_POINTER, ">");
+ ret |= scene_txt_str(scn, "label", ITEM_LABEL + i,
+ STR_LABEL + i, label, NULL);
+ ret |= scene_txt_str(scn, "desc", ITEM_DESC + i, STR_DESC + i,
+ bflow->os_name ? bflow->os_name :
+ bflow->name, NULL);
+ ret |= scene_txt_str(scn, "key", ITEM_KEY + i, STR_KEY + i, key,
+ NULL);
+ preview_id = 0;
+ if (bflow->logo) {
+ preview_id = ITEM_PREVIEW + i;
+ ret |= scene_img(scn, "preview", preview_id,
+ bflow->logo, NULL);
+ }
+ ret |= scene_menuitem(scn, OBJ_MENU, "item", ITEM + i,
+ ITEM_KEY + i, ITEM_LABEL + i,
+ ITEM_DESC + i, preview_id,
+ add_gap ? SCENEMIF_GAP_BEFORE : 0,
+ NULL);
+
+ if (ret < 0)
+ return log_msg_ret("itm", -EINVAL);
+ ret = 0;
+ priv->num_bootflows++;
+ }
+
+ *expp = exp;
+
+ return 0;
+}
+
+int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
+{
+ struct menu_priv *priv = exp->priv;
+ struct scene *scn;
+ u32 font_size;
+ int ret;
+
+ log_debug("Applying theme %s\n", ofnode_get_name(node));
+ scn = expo_lookup_scene_id(exp, MAIN);
+ if (!scn)
+ return log_msg_ret("scn", -ENOENT);
+
+ /* Avoid error-checking optional items */
+ if (!ofnode_read_u32(node, "font-size", &font_size)) {
+ int i;
+
+ log_debug("font size %d\n", font_size);
+ scene_txt_set_font(scn, OBJ_PROMPT, NULL, font_size);
+ scene_txt_set_font(scn, OBJ_POINTER, NULL, font_size);
+ for (i = 0; i < priv->num_bootflows; i++) {
+ ret = scene_txt_set_font(scn, ITEM_DESC + i, NULL,
+ font_size);
+ if (ret)
+ return log_msg_ret("des", ret);
+ scene_txt_set_font(scn, ITEM_KEY + i, NULL, font_size);
+ scene_txt_set_font(scn, ITEM_LABEL + i, NULL,
+ font_size);
+ }
+ }
+
+ ret = scene_arrange(scn);
+ if (ret)
+ return log_msg_ret("arr", ret);
+
+ return 0;
+}
+
+int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
+ struct bootflow **bflowp)
+{
+ struct cli_ch_state s_cch, *cch = &s_cch;
+ struct bootflow *sel_bflow;
+ struct udevice *dev;
+ struct expo *exp;
+ uint sel_id;
+ bool done;
+ int ret;
+
+ cli_ch_init(cch);
+
+ sel_bflow = NULL;
+ *bflowp = NULL;
+
+ ret = bootflow_menu_new(&exp);
+ if (ret)
+ return log_msg_ret("exp", ret);
+
+ if (ofnode_valid(std->theme)) {
+ ret = bootflow_menu_apply_theme(exp, std->theme);
+ if (ret)
+ return log_msg_ret("thm", ret);
+ }
+
+ /* For now we only support a video console */
+ ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
+ if (ret)
+ return log_msg_ret("vid", ret);
+ ret = expo_set_display(exp, dev);
+ if (ret)
+ return log_msg_ret("dis", ret);
+
+ ret = expo_set_scene_id(exp, MAIN);
+ if (ret)
+ return log_msg_ret("scn", ret);
+
+ if (text_mode)
+ exp_set_text_mode(exp, text_mode);
+
+ done = false;
+ do {
+ struct expo_action act;
+ int ichar, key;
+
+ ret = expo_render(exp);
+ if (ret)
+ break;
+
+ ichar = cli_ch_process(cch, 0);
+ if (!ichar) {
+ while (!ichar && !tstc()) {
+ schedule();
+ mdelay(2);
+ ichar = cli_ch_process(cch, -ETIMEDOUT);
+ }
+ if (!ichar) {
+ ichar = getchar();
+ ichar = cli_ch_process(cch, ichar);
+ }
+ }
+
+ key = 0;
+ if (ichar) {
+ key = bootmenu_conv_key(ichar);
+ if (key == BKEY_NONE)
+ key = ichar;
+ }
+ if (!key)
+ continue;
+
+ ret = expo_send_key(exp, key);
+ if (ret)
+ break;
+
+ ret = expo_action_get(exp, &act);
+ if (!ret) {
+ switch (act.type) {
+ case EXPOACT_SELECT:
+ sel_id = act.select.id;
+ done = true;
+ break;
+ case EXPOACT_QUIT:
+ done = true;
+ break;
+ default:
+ break;
+ }
+ }
+ } while (!done);
+
+ if (ret)
+ return log_msg_ret("end", ret);
+
+ if (sel_id) {
+ struct bootflow *bflow;
+ int i;
+
+ for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
+ ret = bootflow_next_glob(&bflow), i++) {
+ if (i == sel_id - ITEM) {
+ sel_bflow = bflow;
+ break;
+ }
+ }
+ }
+
+ expo_destroy(exp);
+
+ if (!sel_bflow)
+ return -EAGAIN;
+ *bflowp = sel_bflow;
+
+ return 0;
+}
diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c
index 25552dd..2aee1e0 100644
--- a/boot/bootmeth-uclass.c
+++ b/boot/bootmeth-uclass.c
@@ -50,6 +50,17 @@
return ops->read_bootflow(dev, bflow);
}
+int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow,
+ char *buf, int size)
+{
+ const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
+
+ if (!ops->set_bootflow)
+ return -ENOSYS;
+
+ return ops->set_bootflow(dev, bflow, buf, size);
+}
+
int bootmeth_boot(struct udevice *dev, struct bootflow *bflow)
{
const struct bootmeth_ops *ops = bootmeth_get_ops(dev);
@@ -290,11 +301,35 @@
return 0;
}
-int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align)
+static int alloc_file(const char *fname, uint size, void **bufp)
{
loff_t bytes_read;
ulong addr;
char *buf;
+ int ret;
+
+ buf = malloc(size + 1);
+ if (!buf)
+ return log_msg_ret("buf", -ENOMEM);
+ addr = map_to_sysmem(buf);
+
+ ret = fs_read(fname, addr, 0, size, &bytes_read);
+ if (ret) {
+ free(buf);
+ return log_msg_ret("read", ret);
+ }
+ if (size != bytes_read)
+ return log_msg_ret("bread", -EINVAL);
+ buf[size] = '\0';
+
+ *bufp = buf;
+
+ return 0;
+}
+
+int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align)
+{
+ void *buf;
uint size;
int ret;
@@ -303,25 +338,52 @@
if (size > size_limit)
return log_msg_ret("chk", -E2BIG);
- buf = memalign(align, size + 1);
- if (!buf)
- return log_msg_ret("buf", -ENOMEM);
- addr = map_to_sysmem(buf);
+ ret = alloc_file(bflow->fname, bflow->size, &buf);
+ if (ret)
+ return log_msg_ret("all", ret);
- ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read);
- if (ret) {
- free(buf);
- return log_msg_ret("read", ret);
- }
- if (size != bytes_read)
- return log_msg_ret("bread", -EINVAL);
- buf[size] = '\0';
bflow->state = BOOTFLOWST_READY;
bflow->buf = buf;
return 0;
}
+int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
+ void **bufp, uint *sizep)
+{
+ struct blk_desc *desc = NULL;
+ char path[200];
+ loff_t size;
+ void *buf;
+ int ret;
+
+ snprintf(path, sizeof(path), "%s%s", bflow->subdir, fname);
+ log_debug("trying: %s\n", path);
+
+ if (bflow->blk)
+ desc = dev_get_uclass_plat(bflow->blk);
+
+ ret = setup_fs(bflow, desc);
+ if (ret)
+ return log_msg_ret("fs", ret);
+
+ ret = fs_size(path, &size);
+ log_debug(" %s - err=%d\n", path, ret);
+
+ ret = setup_fs(bflow, desc);
+ if (ret)
+ return log_msg_ret("fs", ret);
+
+ ret = alloc_file(path, size, &buf);
+ if (ret)
+ return log_msg_ret("all", ret);
+
+ *bufp = buf;
+ *sizep = size;
+
+ return 0;
+}
+
int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
const char *file_path, ulong addr, ulong *sizep)
{
diff --git a/boot/bootmeth_distro.c b/boot/bootmeth_distro.c
index 5c6c687..3569298 100644
--- a/boot/bootmeth_distro.c
+++ b/boot/bootmeth_distro.c
@@ -59,13 +59,45 @@
int ret;
/* This only works on block devices */
- ret = bootflow_iter_uses_blk_dev(iter);
+ ret = bootflow_iter_check_blk(iter);
if (ret)
return log_msg_ret("blk", ret);
return 0;
}
+/**
+ * distro_fill_info() - Decode the extlinux file to find out distro info
+ *
+ * @bflow: Bootflow to process
+ * @return 0 if OK, -ve on error
+ */
+static int distro_fill_info(struct bootflow *bflow)
+{
+ struct membuff mb;
+ char line[200];
+ char *data;
+ int len;
+
+ log_debug("parsing bflow file size %x\n", bflow->size);
+ membuff_init(&mb, bflow->buf, bflow->size);
+ membuff_putraw(&mb, bflow->size, true, &data);
+ while (len = membuff_readline(&mb, line, sizeof(line) - 1, ' '), len) {
+ char *tok, *p = line;
+
+ tok = strsep(&p, " ");
+ if (p) {
+ if (!strcmp("label", tok)) {
+ bflow->os_name = strdup(p);
+ if (!bflow->os_name)
+ return log_msg_ret("os", -ENOMEM);
+ }
+ }
+ }
+
+ return 0;
+}
+
static int distro_read_bootflow(struct udevice *dev, struct bootflow *bflow)
{
struct blk_desc *desc;
@@ -99,6 +131,10 @@
if (ret)
return log_msg_ret("read", ret);
+ ret = distro_fill_info(bflow);
+ if (ret)
+ return log_msg_ret("inf", ret);
+
return 0;
}
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index d5438eb..67c972e 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -19,6 +19,7 @@
#include <malloc.h>
#include <mapmem.h>
#include <mmc.h>
+#include <net.h>
#include <pxe_utils.h>
#define EFI_DIRNAME "efi/boot/"
@@ -59,6 +60,40 @@
return 0;
}
+static int get_efi_pxe_arch(void)
+{
+ /* http://www.iana.org/assignments/dhcpv6-parameters/dhcpv6-parameters.xml */
+ if (IS_ENABLED(CONFIG_ARM64))
+ return 0xb;
+ else if (IS_ENABLED(CONFIG_ARM))
+ return 0xa;
+ else if (IS_ENABLED(CONFIG_X86_64))
+ return 0x6;
+ else if (IS_ENABLED(CONFIG_X86))
+ return 0x7;
+ else if (IS_ENABLED(CONFIG_ARCH_RV32I))
+ return 0x19;
+ else if (IS_ENABLED(CONFIG_ARCH_RV64I))
+ return 0x1b;
+ else if (IS_ENABLED(CONFIG_SANDBOX))
+ return 0; /* not used */
+
+ return -EINVAL;
+}
+
+static int get_efi_pxe_vci(char *str, int max_len)
+{
+ int ret;
+
+ ret = get_efi_pxe_arch();
+ if (ret < 0)
+ return ret;
+
+ snprintf(str, max_len, "PXEClient:Arch:%05x:UNDI:003000", ret);
+
+ return 0;
+}
+
static int efiload_read_file(struct blk_desc *desc, struct bootflow *bflow)
{
const struct udevice *media_dev;
@@ -101,20 +136,44 @@
static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
{
- int ret;
+ /* This only works on block and network devices */
+ if (bootflow_iter_check_blk(iter) && bootflow_iter_check_net(iter))
+ return log_msg_ret("blk", -ENOTSUPP);
- /* This only works on block devices */
- ret = bootflow_iter_uses_blk_dev(iter);
- if (ret)
- return log_msg_ret("blk", ret);
+ /* This works on block devices and network devices */
+ if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
+ return log_msg_ret("pxe", -ENOTSUPP);
return 0;
}
-static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+static void distro_efi_get_fdt_name(char *fname, int size)
+{
+ const char *fdt_fname;
+
+ fdt_fname = env_get("fdtfile");
+ if (fdt_fname) {
+ snprintf(fname, size, "dtb/%s", fdt_fname);
+ log_debug("Using device tree: %s\n", fname);
+ } else {
+ const char *soc = env_get("soc");
+ const char *board = env_get("board");
+ const char *boardver = env_get("boardver");
+
+ /* cf the code in label_boot() which seems very complex */
+ snprintf(fname, size, "dtb/%s%s%s%s.dtb",
+ soc ? soc : "", soc ? "-" : "", board ? board : "",
+ boardver ? boardver : "");
+ log_debug("Using default device tree: %s\n", fname);
+ }
+}
+
+static int distro_efi_read_bootflow_file(struct udevice *dev,
+ struct bootflow *bflow)
{
struct blk_desc *desc = NULL;
- char fname[sizeof(EFI_DIRNAME) + 16];
+ ulong fdt_addr, size;
+ char fname[256];
int ret;
/* We require a partition table */
@@ -137,20 +196,159 @@
if (ret)
return log_msg_ret("read", -EINVAL);
+ distro_efi_get_fdt_name(fname, sizeof(fname));
+ bflow->fdt_fname = strdup(fname);
+ if (!bflow->fdt_fname)
+ return log_msg_ret("fil", -ENOMEM);
+
+ fdt_addr = env_get_hex("fdt_addr_r", 0);
+ ret = bootmeth_common_read_file(dev, bflow, fname, fdt_addr, &size);
+ if (!ret) {
+ bflow->fdt_size = size;
+ bflow->fdt_addr = fdt_addr;
+
+ /*
+ * TODO: Apply extension overlay
+ *
+ * Here we need to load and apply the extension overlay. This is
+ * not implemented. See do_extension_apply(). The extension
+ * stuff needs an implementation in boot/extension.c so it is
+ * separate from the command code. Really the extension stuff
+ * should use the device tree and a uclass / driver interface
+ * rather than implementing its own list
+ */
+ } else {
+ log_debug("No device tree available\n");
+ }
+
+ return 0;
+}
+
+static int distro_efi_read_bootflow_net(struct bootflow *bflow)
+{
+ char file_addr[17], fname[256];
+ char *tftp_argv[] = {"tftp", file_addr, fname, NULL};
+ struct cmd_tbl cmdtp = {}; /* dummy */
+ const char *addr_str, *fdt_addr_str;
+ int ret, arch, size;
+ ulong addr, fdt_addr;
+ char str[36];
+
+ ret = get_efi_pxe_vci(str, sizeof(str));
+ if (ret)
+ return log_msg_ret("vci", ret);
+ ret = get_efi_pxe_arch();
+ if (ret < 0)
+ return log_msg_ret("arc", ret);
+ arch = ret;
+
+ ret = env_set("bootp_vci", str);
+ if (ret)
+ return log_msg_ret("vcs", ret);
+ ret = env_set_ulong("bootp_arch", arch);
+ if (ret)
+ return log_msg_ret("ars", ret);
+
+ /* figure out the load address */
+ addr_str = env_get("kernel_addr_r");
+ addr = addr_str ? hextoul(addr_str, NULL) : image_load_addr;
+
+ /* clear any previous bootfile */
+ env_set("bootfile", NULL);
+
+ /* read the kernel */
+ ret = dhcp_run(addr, NULL, true);
+ if (ret)
+ return log_msg_ret("dhc", ret);
+
+ size = env_get_hex("filesize", -1);
+ if (size <= 0)
+ return log_msg_ret("sz", -EINVAL);
+ bflow->size = size;
+
+ /* do the hideous EFI hack */
+ efi_set_bootdev("Net", "", bflow->fname, map_sysmem(addr, 0),
+ bflow->size);
+
+ /* read the DT file also */
+ fdt_addr_str = env_get("fdt_addr_r");
+ if (!fdt_addr_str)
+ return log_msg_ret("fdt", -EINVAL);
+ fdt_addr = hextoul(fdt_addr_str, NULL);
+ sprintf(file_addr, "%lx", fdt_addr);
+
+ distro_efi_get_fdt_name(fname, sizeof(fname));
+ bflow->fdt_fname = strdup(fname);
+ if (!bflow->fdt_fname)
+ return log_msg_ret("fil", -ENOMEM);
+
+ if (!do_tftpb(&cmdtp, 0, 3, tftp_argv)) {
+ bflow->fdt_size = env_get_hex("filesize", 0);
+ bflow->fdt_addr = fdt_addr;
+ } else {
+ log_debug("No device tree available\n");
+ }
+
+ bflow->state = BOOTFLOWST_READY;
+
+ return 0;
+}
+
+static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+ const struct udevice *media = dev_get_parent(bflow->dev);
+ int ret;
+
+ if (IS_ENABLED(CONFIG_CMD_DHCP) &&
+ device_get_uclass_id(media) == UCLASS_ETH) {
+ /* we only support reading from one device, so ignore 'dev' */
+ ret = distro_efi_read_bootflow_net(bflow);
+ if (ret)
+ return log_msg_ret("net", ret);
+ } else {
+ ret = distro_efi_read_bootflow_file(dev, bflow);
+ if (ret)
+ return log_msg_ret("blk", ret);
+ }
+
return 0;
}
int distro_efi_boot(struct udevice *dev, struct bootflow *bflow)
{
+ ulong kernel, fdt;
char cmd[50];
+ /* A non-zero buffer indicates the kernel is there */
+ if (bflow->buf) {
+ kernel = (ulong)map_to_sysmem(bflow->buf);
+
+ /*
+ * use the provided device tree if available, else fall back to
+ * the control FDT
+ */
+ if (bflow->fdt_fname)
+ fdt = bflow->fdt_addr;
+ else
+ fdt = (ulong)map_to_sysmem(gd->fdt_blob);
+ } else {
+ /*
+ * This doesn't actually work for network devices:
+ *
+ * do_bootefi_image() No UEFI binary known at 0x02080000
+ *
+ * But this is the same behaviour for distro boot, so it can be
+ * fixed here.
+ */
+ kernel = env_get_hex("kernel_addr_r", 0);
+ fdt = env_get_hex("fdt_addr_r", 0);
+ }
+
/*
* At some point we can add a real interface to bootefi so we can call
- * this directly. For now, go through the CLI like distro boot.
+ * this directly. For now, go through the CLI, like distro boot.
*/
- snprintf(cmd, sizeof(cmd), "bootefi %lx %lx",
- (ulong)map_to_sysmem(bflow->buf),
- (ulong)map_to_sysmem(gd->fdt_blob));
+ snprintf(cmd, sizeof(cmd), "bootefi %lx %lx", kernel, fdt);
if (run_command(cmd, 0))
return log_msg_ret("run", -EINVAL);
diff --git a/boot/bootmeth_efi_mgr.c b/boot/bootmeth_efi_mgr.c
index 2f327c1..e9d9734 100644
--- a/boot/bootmeth_efi_mgr.c
+++ b/boot/bootmeth_efi_mgr.c
@@ -36,7 +36,7 @@
int ret;
/* Must be an bootstd device */
- ret = bootflow_iter_uses_system(iter);
+ ret = bootflow_iter_check_system(iter);
if (ret)
return log_msg_ret("net", ret);
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c
index e699216..ecf8557 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -44,10 +44,13 @@
int ret;
/* This only works on network devices */
- ret = bootflow_iter_uses_network(iter);
+ ret = bootflow_iter_check_net(iter);
if (ret)
return log_msg_ret("net", ret);
+ if (iter->method_flags & BOOTFLOW_METHF_DHCP_ONLY)
+ return log_msg_ret("dhcp", -ENOTSUPP);
+
return 0;
}
diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c
index 6c84721..225eb18 100644
--- a/boot/bootmeth_script.c
+++ b/boot/bootmeth_script.c
@@ -19,27 +19,55 @@
#include <image.h>
#include <malloc.h>
#include <mapmem.h>
+#include <net.h>
#define SCRIPT_FNAME1 "boot.scr.uimg"
#define SCRIPT_FNAME2 "boot.scr"
static int script_check(struct udevice *dev, struct bootflow_iter *iter)
{
- int ret;
-
- /* This only works on block devices */
- ret = bootflow_iter_uses_blk_dev(iter);
- if (ret)
- return log_msg_ret("blk", ret);
+ /* This works on block devices, network devices and SPI Flash */
+ if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
+ return log_msg_ret("pxe", -ENOTSUPP);
return 0;
}
-static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+/**
+ * script_fill_info() - Decode the U-Boot script to find out distro info
+ *
+ * @bflow: Bootflow to process
+ * @return 0 if OK, -ve on error
+ */
+static int script_fill_info(struct bootflow *bflow)
+{
+ char *name = NULL;
+ char *data;
+ uint len;
+ int ret;
+
+ log_debug("parsing bflow file size %x\n", bflow->size);
+
+ ret = image_locate_script(bflow->buf, bflow->size, NULL, NULL, &data, &len);
+ if (!ret) {
+ if (strstr(data, "armbianEnv"))
+ name = "Armbian";
+ }
+
+ if (name) {
+ bflow->os_name = strdup(name);
+ if (!bflow->os_name)
+ return log_msg_ret("os", -ENOMEM);
+ }
+
+ return 0;
+}
+
+static int script_read_bootflow_file(struct udevice *bootstd,
+ struct bootflow *bflow)
{
struct blk_desc *desc = NULL;
const char *const *prefixes;
- struct udevice *bootstd;
const char *prefix;
int ret, i;
@@ -47,12 +75,12 @@
if (ret)
return log_msg_ret("std", ret);
- /* We require a partition table */
- if (!bflow->part)
- return -ENOENT;
-
- if (bflow->blk)
+ if (bflow->blk) {
+ /* We require a partition table */
+ if (!bflow->part)
+ return -ENOENT;
desc = dev_get_uclass_plat(bflow->blk);
+ }
prefixes = bootstd_get_prefixes(bootstd);
i = 0;
@@ -75,6 +103,84 @@
if (ret)
return log_msg_ret("read", ret);
+ ret = script_fill_info(bflow);
+ if (ret)
+ return log_msg_ret("inf", ret);
+
+ ret = bootmeth_alloc_other(bflow, "boot.bmp", &bflow->logo,
+ &bflow->logo_size);
+ /* ignore error */
+
+ return 0;
+}
+
+static int script_read_bootflow_net(struct bootflow *bflow)
+{
+ const char *addr_str;
+ int size, ret;
+ char *fname;
+ ulong addr;
+
+ /* figure out the load address */
+ addr_str = env_get("scriptaddr");
+ addr = addr_str ? hextoul(addr_str, NULL) : image_load_addr;
+
+ fname = env_get("boot_script_dhcp");
+ if (!fname)
+ return log_msg_ret("dhc", -EINVAL);
+
+ ret = dhcp_run(addr, fname, true);
+ if (ret)
+ return log_msg_ret("dhc", ret);
+
+ size = env_get_hex("filesize", 0);
+ if (!size)
+ return log_msg_ret("sz", -EINVAL);
+
+ bflow->buf = malloc(size + 1);
+ if (!bflow->buf)
+ return log_msg_ret("buf", -ENOMEM);
+ memcpy(bflow->buf, map_sysmem(addr, size), size);
+ bflow->buf[size] = '\0';
+ bflow->size = size;
+ bflow->state = BOOTFLOWST_READY;
+
+ return 0;
+}
+
+static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+ const struct udevice *media = dev_get_parent(bflow->dev);
+ struct udevice *bootstd;
+ int ret;
+
+ ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
+ if (ret)
+ return log_msg_ret("std", ret);
+
+ if (IS_ENABLED(CONFIG_CMD_DHCP) &&
+ device_get_uclass_id(media) == UCLASS_ETH) {
+ /* we only support reading from one device, so ignore 'dev' */
+ ret = script_read_bootflow_net(bflow);
+ if (ret)
+ return log_msg_ret("net", ret);
+ } else {
+ ret = script_read_bootflow_file(bootstd, bflow);
+ if (ret)
+ return log_msg_ret("blk", ret);
+ }
+
+ return 0;
+}
+
+static int script_set_bootflow(struct udevice *dev, struct bootflow *bflow,
+ char *buf, int size)
+{
+ buf[size] = '\0';
+ bflow->buf = buf;
+ bflow->size = size;
+ bflow->state = BOOTFLOWST_READY;
+
return 0;
}
@@ -88,6 +194,8 @@
if (!ret)
ret = env_set_hex("devnum", desc->devnum);
if (!ret)
+ ret = env_set_hex("distro_bootpart", bflow->part);
+ if (!ret)
ret = env_set("prefix", bflow->subdir);
if (!ret && IS_ENABLED(CONFIG_ARCH_SUNXI) &&
!strcmp("mmc", blk_get_devtype(bflow->blk)))
@@ -97,11 +205,12 @@
log_debug("devtype: %s\n", env_get("devtype"));
log_debug("devnum: %s\n", env_get("devnum"));
+ log_debug("distro_bootpart: %s\n", env_get("distro_bootpart"));
log_debug("prefix: %s\n", env_get("prefix"));
log_debug("mmc_bootdev: %s\n", env_get("mmc_bootdev"));
addr = map_to_sysmem(bflow->buf);
- ret = image_source_script(addr, NULL, NULL);
+ ret = cmd_source_script(addr, NULL, NULL);
if (ret)
return log_msg_ret("boot", ret);
@@ -121,6 +230,7 @@
static struct bootmeth_ops script_bootmeth_ops = {
.check = script_check,
.read_bootflow = script_read_bootflow,
+ .set_bootflow = script_set_bootflow,
.read_file = bootmeth_common_read_file,
.boot = script_boot,
};
diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
index 565c22a..81555d3 100644
--- a/boot/bootstd-uclass.c
+++ b/boot/bootstd-uclass.c
@@ -10,6 +10,7 @@
#include <bootflow.h>
#include <bootstd.h>
#include <dm.h>
+#include <env.h>
#include <log.h>
#include <malloc.h>
#include <dm/device-internal.h>
@@ -33,6 +34,8 @@
&priv->prefixes);
dev_read_string_list(dev, "bootdev-order",
&priv->bootdev_order);
+
+ priv->theme = ofnode_find_subnode(dev_ofnode(dev), "theme");
}
return 0;
@@ -70,9 +73,23 @@
return 0;
}
-const char *const *const bootstd_get_bootdev_order(struct udevice *dev)
+const char *const *const bootstd_get_bootdev_order(struct udevice *dev,
+ bool *okp)
{
struct bootstd_priv *std = dev_get_priv(dev);
+ const char *targets = env_get("boot_targets");
+
+ *okp = true;
+ log_debug("- targets %s %p\n", targets, std->bootdev_order);
+ if (targets && *targets) {
+ str_free_list(std->env_order);
+ std->env_order = str_to_list(targets);
+ if (!std->env_order) {
+ *okp = false;
+ return NULL;
+ }
+ return std->env_order;
+ }
return std->bootdev_order;
}
diff --git a/boot/expo.c b/boot/expo.c
new file mode 100644
index 0000000..05950a1
--- /dev/null
+++ b/boot/expo.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Implementation of a expo, a collection of scenes providing menu options
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <expo.h>
+#include <malloc.h>
+#include <video.h>
+#include "scene_internal.h"
+
+int expo_new(const char *name, void *priv, struct expo **expp)
+{
+ struct expo *exp;
+
+ exp = calloc(1, sizeof(struct expo));
+ if (!exp)
+ return log_msg_ret("expo", -ENOMEM);
+ exp->name = strdup(name);
+ if (!exp->name) {
+ free(exp);
+ return log_msg_ret("name", -ENOMEM);
+ }
+ exp->priv = priv;
+ INIT_LIST_HEAD(&exp->scene_head);
+ INIT_LIST_HEAD(&exp->str_head);
+
+ *expp = exp;
+
+ return 0;
+}
+
+static void estr_destroy(struct expo_string *estr)
+{
+ free(estr);
+}
+
+void expo_destroy(struct expo *exp)
+{
+ struct scene *scn, *next;
+ struct expo_string *estr, *enext;
+
+ list_for_each_entry_safe(scn, next, &exp->scene_head, sibling)
+ scene_destroy(scn);
+
+ list_for_each_entry_safe(estr, enext, &exp->str_head, sibling)
+ estr_destroy(estr);
+
+ free(exp->name);
+ free(exp);
+}
+
+int expo_str(struct expo *exp, const char *name, uint id, const char *str)
+{
+ struct expo_string *estr;
+
+ estr = calloc(1, sizeof(struct expo_string));
+ if (!estr)
+ return log_msg_ret("obj", -ENOMEM);
+
+ estr->id = resolve_id(exp, id);
+ estr->str = str;
+ list_add_tail(&estr->sibling, &exp->str_head);
+
+ return estr->id;
+}
+
+const char *expo_get_str(struct expo *exp, uint id)
+{
+ struct expo_string *estr;
+
+ list_for_each_entry(estr, &exp->str_head, sibling) {
+ if (estr->id == id)
+ return estr->str;
+ }
+
+ return NULL;
+}
+
+int expo_set_display(struct expo *exp, struct udevice *dev)
+{
+ exp->display = dev;
+
+ return 0;
+}
+
+void exp_set_text_mode(struct expo *exp, bool text_mode)
+{
+ exp->text_mode = text_mode;
+}
+
+struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id)
+{
+ struct scene *scn;
+
+ list_for_each_entry(scn, &exp->scene_head, sibling) {
+ if (scn->id == scene_id)
+ return scn;
+ }
+
+ return NULL;
+}
+
+int expo_set_scene_id(struct expo *exp, uint scene_id)
+{
+ if (!expo_lookup_scene_id(exp, scene_id))
+ return log_msg_ret("id", -ENOENT);
+ exp->scene_id = scene_id;
+
+ return 0;
+}
+
+int expo_render(struct expo *exp)
+{
+ struct udevice *dev = exp->display;
+ struct video_priv *vid_priv = dev_get_uclass_priv(dev);
+ struct scene *scn = NULL;
+ u32 colour;
+ int ret;
+
+ colour = video_index_to_colour(vid_priv, VID_WHITE);
+ ret = video_fill(dev, colour);
+ if (ret)
+ return log_msg_ret("fill", ret);
+
+ if (exp->scene_id) {
+ scn = expo_lookup_scene_id(exp, exp->scene_id);
+ if (!scn)
+ return log_msg_ret("scn", -ENOENT);
+
+ ret = scene_render(scn);
+ if (ret)
+ return log_msg_ret("ren", ret);
+ }
+
+ video_sync(dev, true);
+
+ return scn ? 0 : -ECHILD;
+}
+
+int expo_send_key(struct expo *exp, int key)
+{
+ struct scene *scn = NULL;
+
+ if (exp->scene_id) {
+ int ret;
+
+ scn = expo_lookup_scene_id(exp, exp->scene_id);
+ if (!scn)
+ return log_msg_ret("scn", -ENOENT);
+
+ ret = scene_send_key(scn, key, &exp->action);
+ if (ret)
+ return log_msg_ret("key", ret);
+ }
+
+ return scn ? 0 : -ECHILD;
+}
+
+int expo_action_get(struct expo *exp, struct expo_action *act)
+{
+ *act = exp->action;
+ exp->action.type = EXPOACT_NONE;
+
+ return act->type == EXPOACT_NONE ? -EAGAIN : 0;
+}
diff --git a/boot/image-board.c b/boot/image-board.c
index 0fd6329..e5d71a3 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -971,3 +971,162 @@
tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
+
+/**
+ * get_default_image() - Return default property from /images
+ *
+ * Return: Pointer to value of default property (or NULL)
+ */
+static const char *get_default_image(const void *fit)
+{
+ int images_noffset;
+
+ images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+ if (images_noffset < 0)
+ return NULL;
+
+ return fdt_getprop(fit, images_noffset, FIT_DEFAULT_PROP, NULL);
+}
+
+int image_locate_script(void *buf, int size, const char *fit_uname,
+ const char *confname, char **datap, uint *lenp)
+{
+ const struct legacy_img_hdr *hdr;
+ const void *fit_data;
+ const void *fit_hdr;
+ size_t fit_len;
+ int noffset;
+ int verify;
+ ulong len;
+ u32 *data;
+
+ verify = env_get_yesno("verify");
+
+ switch (genimg_get_format(buf)) {
+ case IMAGE_FORMAT_LEGACY:
+ if (IS_ENABLED(CONFIG_LEGACY_IMAGE_FORMAT)) {
+ hdr = buf;
+
+ if (!image_check_magic(hdr)) {
+ puts("Bad magic number\n");
+ return 1;
+ }
+
+ if (!image_check_hcrc(hdr)) {
+ puts("Bad header crc\n");
+ return 1;
+ }
+
+ if (verify) {
+ if (!image_check_dcrc(hdr)) {
+ puts("Bad data crc\n");
+ return 1;
+ }
+ }
+
+ if (!image_check_type(hdr, IH_TYPE_SCRIPT)) {
+ puts("Bad image type\n");
+ return 1;
+ }
+
+ /* get length of script */
+ data = (u32 *)image_get_data(hdr);
+
+ len = uimage_to_cpu(*data);
+ if (!len) {
+ puts("Empty Script\n");
+ return 1;
+ }
+
+ /*
+ * scripts are just multi-image files with one
+ * component, so seek past the zero-terminated sequence
+ * of image lengths to get to the actual image data
+ */
+ while (*data++);
+ }
+ break;
+ case IMAGE_FORMAT_FIT:
+ if (IS_ENABLED(CONFIG_FIT)) {
+ fit_hdr = buf;
+ if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+ puts("Bad FIT image format\n");
+ return 1;
+ }
+
+ if (!fit_uname) {
+ /* If confname is empty, use the default */
+ if (confname && *confname)
+ noffset = fit_conf_get_node(fit_hdr, confname);
+ else
+ noffset = fit_conf_get_node(fit_hdr, NULL);
+ if (noffset < 0) {
+ if (!confname)
+ goto fallback;
+ printf("Could not find config %s\n", confname);
+ return 1;
+ }
+
+ if (verify && fit_config_verify(fit_hdr, noffset))
+ return 1;
+
+ noffset = fit_conf_get_prop_node(fit_hdr,
+ noffset,
+ FIT_SCRIPT_PROP,
+ IH_PHASE_NONE);
+ if (noffset < 0) {
+ if (!confname)
+ goto fallback;
+ printf("Could not find script in %s\n", confname);
+ return 1;
+ }
+ } else {
+fallback:
+ if (!fit_uname || !*fit_uname)
+ fit_uname = get_default_image(fit_hdr);
+ if (!fit_uname) {
+ puts("No FIT subimage unit name\n");
+ return 1;
+ }
+
+ /* get script component image node offset */
+ noffset = fit_image_get_node(fit_hdr, fit_uname);
+ if (noffset < 0) {
+ printf("Can't find '%s' FIT subimage\n",
+ fit_uname);
+ return 1;
+ }
+ }
+
+ if (!fit_image_check_type(fit_hdr, noffset,
+ IH_TYPE_SCRIPT)) {
+ puts("Not a image image\n");
+ return 1;
+ }
+
+ /* verify integrity */
+ if (verify && !fit_image_verify(fit_hdr, noffset)) {
+ puts("Bad Data Hash\n");
+ return 1;
+ }
+
+ /* get script subimage data address and length */
+ if (fit_image_get_data(fit_hdr, noffset, &fit_data, &fit_len)) {
+ puts("Could not find script subimage data\n");
+ return 1;
+ }
+
+ data = (u32 *)fit_data;
+ len = (ulong)fit_len;
+ }
+ break;
+ default:
+ puts("Wrong image format for \"source\" command\n");
+ return -EPERM;
+ }
+
+ *datap = (char *)data;
+ *lenp = len;
+
+ return 0;
+}
diff --git a/boot/scene.c b/boot/scene.c
new file mode 100644
index 0000000..030f6aa
--- /dev/null
+++ b/boot/scene.c
@@ -0,0 +1,414 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Implementation of a scene, a collection of text/image/menu items in an expo
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <expo.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <video.h>
+#include <video_console.h>
+#include <linux/input.h>
+#include "scene_internal.h"
+
+uint resolve_id(struct expo *exp, uint id)
+{
+ if (!id)
+ id = exp->next_id++;
+ else if (id >= exp->next_id)
+ exp->next_id = id + 1;
+
+ return id;
+}
+
+int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp)
+{
+ struct scene *scn;
+
+ scn = calloc(1, sizeof(struct scene));
+ if (!scn)
+ return log_msg_ret("expo", -ENOMEM);
+ scn->name = strdup(name);
+ if (!scn->name) {
+ free(scn);
+ return log_msg_ret("name", -ENOMEM);
+ }
+
+ INIT_LIST_HEAD(&scn->obj_head);
+ scn->id = resolve_id(exp, id);
+ scn->expo = exp;
+ list_add_tail(&scn->sibling, &exp->scene_head);
+
+ *scnp = scn;
+
+ return scn->id;
+}
+
+void scene_obj_destroy(struct scene_obj *obj)
+{
+ if (obj->type == SCENEOBJT_MENU)
+ scene_menu_destroy((struct scene_obj_menu *)obj);
+ free(obj->name);
+ free(obj);
+}
+
+void scene_destroy(struct scene *scn)
+{
+ struct scene_obj *obj, *next;
+
+ list_for_each_entry_safe(obj, next, &scn->obj_head, sibling)
+ scene_obj_destroy(obj);
+
+ free(scn->name);
+ free(scn->title);
+ free(scn);
+}
+
+int scene_title_set(struct scene *scn, const char *title)
+{
+ free(scn->title);
+ scn->title = strdup(title);
+ if (!scn->title)
+ return log_msg_ret("tit", -ENOMEM);
+
+ return 0;
+}
+
+int scene_obj_count(struct scene *scn)
+{
+ struct scene_obj *obj;
+ int count = 0;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling)
+ count++;
+
+ return count;
+}
+
+void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type)
+{
+ struct scene_obj *obj;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ if (obj->id == id &&
+ (type == SCENEOBJT_NONE || obj->type == type))
+ return obj;
+ }
+
+ return NULL;
+}
+
+int scene_obj_add(struct scene *scn, const char *name, uint id,
+ enum scene_obj_t type, uint size, struct scene_obj **objp)
+{
+ struct scene_obj *obj;
+
+ obj = calloc(1, size);
+ if (!obj)
+ return log_msg_ret("obj", -ENOMEM);
+ obj->name = strdup(name);
+ if (!obj->name) {
+ free(obj);
+ return log_msg_ret("name", -ENOMEM);
+ }
+
+ obj->id = resolve_id(scn->expo, id);
+ obj->scene = scn;
+ obj->type = type;
+ list_add_tail(&obj->sibling, &scn->obj_head);
+ *objp = obj;
+
+ return obj->id;
+}
+
+int scene_img(struct scene *scn, const char *name, uint id, char *data,
+ struct scene_obj_img **imgp)
+{
+ struct scene_obj_img *img;
+ int ret;
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_IMAGE,
+ sizeof(struct scene_obj_img),
+ (struct scene_obj **)&img);
+ if (ret < 0)
+ return log_msg_ret("obj", -ENOMEM);
+
+ img->data = data;
+
+ if (imgp)
+ *imgp = img;
+
+ return img->obj.id;
+}
+
+int scene_txt(struct scene *scn, const char *name, uint id, uint str_id,
+ struct scene_obj_txt **txtp)
+{
+ struct scene_obj_txt *txt;
+ int ret;
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXT,
+ sizeof(struct scene_obj_txt),
+ (struct scene_obj **)&txt);
+ if (ret < 0)
+ return log_msg_ret("obj", -ENOMEM);
+
+ txt->str_id = str_id;
+
+ if (txtp)
+ *txtp = txt;
+
+ return txt->obj.id;
+}
+
+int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id,
+ const char *str, struct scene_obj_txt **txtp)
+{
+ struct scene_obj_txt *txt;
+ int ret;
+
+ ret = expo_str(scn->expo, name, str_id, str);
+ if (ret < 0)
+ return log_msg_ret("str", ret);
+ else if (ret != str_id)
+ return log_msg_ret("id", -EEXIST);
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXT,
+ sizeof(struct scene_obj_txt),
+ (struct scene_obj **)&txt);
+ if (ret < 0)
+ return log_msg_ret("obj", -ENOMEM);
+
+ txt->str_id = str_id;
+
+ if (txtp)
+ *txtp = txt;
+
+ return txt->obj.id;
+}
+
+int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
+ uint font_size)
+{
+ struct scene_obj_txt *txt;
+
+ txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
+ if (!txt)
+ return log_msg_ret("find", -ENOENT);
+ txt->font_name = font_name;
+ txt->font_size = font_size;
+
+ return 0;
+}
+
+int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->x = x;
+ obj->y = y;
+ if (obj->type == SCENEOBJT_MENU)
+ scene_menu_arrange(scn, (struct scene_obj_menu *)obj);
+
+ return 0;
+}
+
+int scene_obj_set_hide(struct scene *scn, uint id, bool hide)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->hide = hide;
+
+ return 0;
+}
+
+int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+
+ switch (obj->type) {
+ case SCENEOBJT_NONE:
+ case SCENEOBJT_MENU:
+ break;
+ case SCENEOBJT_IMAGE: {
+ struct scene_obj_img *img = (struct scene_obj_img *)obj;
+ ulong width, height;
+ uint bpix;
+
+ video_bmp_get_info(img->data, &width, &height, &bpix);
+ if (widthp)
+ *widthp = width;
+ return height;
+ }
+ case SCENEOBJT_TEXT: {
+ struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
+ struct expo *exp = scn->expo;
+
+ if (widthp)
+ *widthp = 16; /* fake value for now */
+ if (txt->font_size)
+ return txt->font_size;
+ if (exp->display)
+ return video_default_font_height(exp->display);
+
+ /* use a sensible default */
+ return 16;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * scene_obj_render() - Render an object
+ *
+ */
+static int scene_obj_render(struct scene_obj *obj, bool text_mode)
+{
+ struct scene *scn = obj->scene;
+ struct expo *exp = scn->expo;
+ struct udevice *cons, *dev = exp->display;
+ int x, y, ret;
+
+ cons = NULL;
+ if (!text_mode) {
+ ret = device_find_first_child_by_uclass(dev,
+ UCLASS_VIDEO_CONSOLE,
+ &cons);
+ }
+
+ x = obj->x;
+ y = obj->y;
+
+ switch (obj->type) {
+ case SCENEOBJT_NONE:
+ break;
+ case SCENEOBJT_IMAGE: {
+ struct scene_obj_img *img = (struct scene_obj_img *)obj;
+
+ if (!cons)
+ return -ENOTSUPP;
+ ret = video_bmp_display(dev, map_to_sysmem(img->data), x, y,
+ true);
+ if (ret < 0)
+ return log_msg_ret("img", ret);
+ break;
+ }
+ case SCENEOBJT_TEXT: {
+ struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
+ const char *str;
+
+ if (!cons)
+ return -ENOTSUPP;
+
+ if (txt->font_name || txt->font_size) {
+ ret = vidconsole_select_font(cons,
+ txt->font_name,
+ txt->font_size);
+ } else {
+ ret = vidconsole_select_font(cons, NULL, 0);
+ }
+ if (ret && ret != -ENOSYS)
+ return log_msg_ret("font", ret);
+ vidconsole_set_cursor_pos(cons, x, y);
+ str = expo_get_str(exp, txt->str_id);
+ if (str)
+ vidconsole_put_string(cons, str);
+ break;
+ }
+ case SCENEOBJT_MENU: {
+ struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
+ /*
+ * With a vidconsole, the text and item pointer are rendered as
+ * normal objects so we don't need to do anything here. The menu
+ * simply controls where they are positioned.
+ */
+ if (cons)
+ return -ENOTSUPP;
+
+ ret = scene_menu_display(menu);
+ if (ret < 0)
+ return log_msg_ret("img", ret);
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int scene_arrange(struct scene *scn)
+{
+ struct scene_obj *obj;
+ int ret;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ if (obj->type == SCENEOBJT_MENU) {
+ struct scene_obj_menu *menu;
+
+ menu = (struct scene_obj_menu *)obj,
+ ret = scene_menu_arrange(scn, menu);
+ if (ret)
+ return log_msg_ret("arr", ret);
+ }
+ }
+
+ return 0;
+}
+
+int scene_render(struct scene *scn)
+{
+ struct expo *exp = scn->expo;
+ struct scene_obj *obj;
+ int ret;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ if (!obj->hide) {
+ ret = scene_obj_render(obj, exp->text_mode);
+ if (ret && ret != -ENOTSUPP)
+ return log_msg_ret("ren", ret);
+ }
+ }
+
+ return 0;
+}
+
+int scene_send_key(struct scene *scn, int key, struct expo_action *event)
+{
+ struct scene_obj *obj;
+ int ret;
+
+ list_for_each_entry(obj, &scn->obj_head, sibling) {
+ if (obj->type == SCENEOBJT_MENU) {
+ struct scene_obj_menu *menu;
+
+ menu = (struct scene_obj_menu *)obj,
+ ret = scene_menu_send_key(scn, menu, key, event);
+ if (ret)
+ return log_msg_ret("key", ret);
+
+ /* only allow one menu */
+ ret = scene_menu_arrange(scn, menu);
+ if (ret)
+ return log_msg_ret("arr", ret);
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/boot/scene_internal.h b/boot/scene_internal.h
new file mode 100644
index 0000000..e8fd765
--- /dev/null
+++ b/boot/scene_internal.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Internal header file for scenes
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __SCENE_INTERNAL_H
+#define __SCENE_INTERNAL_H
+
+/**
+ * expo_lookup_scene_id() - Look up a scene ID
+ *
+ * @exp: Expo to use
+ * @id: scene ID to look up
+ * Returns: Scene for that ID, or NULL if none
+ */
+struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id);
+
+/**
+ * resolve_id() - Automatically allocate an ID if needed
+ *
+ * @exp: Expo to use
+ * @id: ID to use, or 0 to auto-allocate one
+ * @return: Either @id, or the auto-allocated ID
+ */
+uint resolve_id(struct expo *exp, uint id);
+
+/**
+ * scene_obj_find() - Find an object in a scene
+ *
+ * Note that @type is used to restrict the search when the object type is known.
+ * If any type is acceptable, set @type to SCENEOBJT_NONE
+ *
+ * @scn: Scene to search
+ * @id: ID of object to find
+ * @type: Type of the object, or SCENEOBJT_NONE to match any type
+ */
+void *scene_obj_find(struct scene *scn, uint id, enum scene_obj_t type);
+
+/**
+ * scene_obj_add() - Add a new object to a scene
+ *
+ * @scn: Scene to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @type: Type of object to add
+ * @size: Size to allocate for the object, in bytes
+ * @objp: Returns a pointer to the new object (must not be NULL)
+ * Returns: ID number for the object (generally @id), or -ve on error
+ */
+int scene_obj_add(struct scene *scn, const char *name, uint id,
+ enum scene_obj_t type, uint size, struct scene_obj **objp);
+
+/**
+ * scene_menu_arrange() - Set the position of things in the menu
+ *
+ * This updates any items associated with a menu to make sure they are
+ * positioned correctly relative to the menu. It also selects the first item
+ * if not already done
+ *
+ * @scn: Scene to update
+ * @menu: Menu to process
+ */
+int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu);
+
+/**
+ * scene_menu_send_key() - Send a key to a menu for processing
+ *
+ * @scn: Scene to use
+ * @menu: Menu to use
+ * @key: Key code to send (KEY_...)
+ * @event: Place to put any event which is generated by the key
+ * @return 0 if OK, -ENOTTY if there is no current menu item, other -ve on other
+ * error
+ */
+int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
+ struct expo_action *event);
+
+/**
+ * scene_menu_destroy() - Destroy a menu in a scene
+ *
+ * @scn: Scene to destroy
+ */
+void scene_menu_destroy(struct scene_obj_menu *menu);
+
+/**
+ * scene_menu_display() - Display a menu as text
+ *
+ * @menu: Menu to display
+ * @return 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_menu_display(struct scene_obj_menu *menu);
+
+/**
+ * scene_destroy() - Destroy a scene and all its memory
+ *
+ * @scn: Scene to destroy
+ */
+void scene_destroy(struct scene *scn);
+
+/**
+ * scene_render() - Render a scene
+ *
+ * This is called from expo_render()
+ *
+ * @scn: Scene to render
+ * Returns: 0 if OK, -ve on error
+ */
+int scene_render(struct scene *scn);
+
+/**
+ * scene_send_key() - set a keypress to a scene
+ *
+ * @scn: Scene to receive the key
+ * @key: Key to send (KEYCODE_UP)
+ * @event: Returns resulting event from this keypress
+ * Returns: 0 if OK, -ve on error
+ */
+int scene_send_key(struct scene *scn, int key, struct expo_action *event);
+
+#endif /* __SCENE_INTERNAL_H */
diff --git a/boot/scene_menu.c b/boot/scene_menu.c
new file mode 100644
index 0000000..18998e8
--- /dev/null
+++ b/boot/scene_menu.c
@@ -0,0 +1,390 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Implementation of a menu in a scene
+ *
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY LOGC_BOOT
+
+#include <common.h>
+#include <dm.h>
+#include <expo.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <menu.h>
+#include <video.h>
+#include <video_console.h>
+#include <linux/input.h>
+#include "scene_internal.h"
+
+static void scene_menuitem_destroy(struct scene_menitem *item)
+{
+ free(item->name);
+ free(item);
+}
+
+void scene_menu_destroy(struct scene_obj_menu *menu)
+{
+ struct scene_menitem *item, *next;
+
+ list_for_each_entry_safe(item, next, &menu->item_head, sibling)
+ scene_menuitem_destroy(item);
+}
+
+/**
+ * menu_point_to_item() - Point to a particular menu item
+ *
+ * Sets the currently pointed-to / highlighted menu item
+ */
+static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
+{
+ menu->cur_item_id = item_id;
+}
+
+int scene_menu_arrange(struct scene *scn, struct scene_obj_menu *menu)
+{
+ struct scene_menitem *item;
+ int y, cur_y;
+ int ret;
+
+ y = menu->obj.y;
+ if (menu->title_id) {
+ ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.x, y);
+ if (ret < 0)
+ return log_msg_ret("tit", ret);
+
+ ret = scene_obj_get_hw(scn, menu->title_id, NULL);
+ if (ret < 0)
+ return log_msg_ret("hei", ret);
+
+ y += ret * 2;
+ }
+
+ /*
+ * Currently everything is hard-coded to particular columns so this
+ * won't work on small displays and looks strange if the font size is
+ * small. This can be updated once text measuring is supported in
+ * vidconsole
+ */
+ cur_y = -1;
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ int height;
+
+ ret = scene_obj_get_hw(scn, item->desc_id, NULL);
+ if (ret < 0)
+ return log_msg_ret("get", ret);
+ height = ret;
+
+ if (item->flags & SCENEMIF_GAP_BEFORE)
+ y += height;
+
+ /* select an item if not done already */
+ if (!menu->cur_item_id)
+ menu_point_to_item(menu, item->id);
+
+ /*
+ * Put the label on the left, then leave a space for the
+ * pointer, then the key and the description
+ */
+ if (item->label_id) {
+ ret = scene_obj_set_pos(scn, item->label_id, menu->obj.x,
+ y);
+ if (ret < 0)
+ return log_msg_ret("nam", ret);
+ }
+
+ ret = scene_obj_set_pos(scn, item->key_id, menu->obj.x + 230,
+ y);
+ if (ret < 0)
+ return log_msg_ret("key", ret);
+
+ ret = scene_obj_set_pos(scn, item->desc_id, menu->obj.x + 280,
+ y);
+ if (ret < 0)
+ return log_msg_ret("des", ret);
+
+ if (menu->cur_item_id == item->id)
+ cur_y = y;
+
+ if (item->preview_id) {
+ bool hide;
+
+ /*
+ * put all previews on top of each other, on the right
+ * size of the display
+ */
+ ret = scene_obj_set_pos(scn, item->preview_id, -4, y);
+ if (ret < 0)
+ return log_msg_ret("prev", ret);
+
+ hide = menu->cur_item_id != item->id;
+ ret = scene_obj_set_hide(scn, item->preview_id, hide);
+ if (ret < 0)
+ return log_msg_ret("hid", ret);
+ }
+
+ y += height;
+ }
+
+ if (menu->pointer_id && cur_y != -1) {
+ /*
+ * put the pointer to the right of and level with the item it
+ * points to
+ */
+ ret = scene_obj_set_pos(scn, menu->pointer_id,
+ menu->obj.x + 200, cur_y);
+ if (ret < 0)
+ return log_msg_ret("ptr", ret);
+ }
+
+ return 0;
+}
+
+int scene_menu(struct scene *scn, const char *name, uint id,
+ struct scene_obj_menu **menup)
+{
+ struct scene_obj_menu *menu;
+ int ret;
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_MENU,
+ sizeof(struct scene_obj_menu),
+ (struct scene_obj **)&menu);
+ if (ret < 0)
+ return log_msg_ret("obj", -ENOMEM);
+
+ if (menup)
+ *menup = menu;
+ INIT_LIST_HEAD(&menu->item_head);
+
+ ret = scene_menu_arrange(scn, menu);
+ if (ret)
+ return log_msg_ret("pos", ret);
+
+ return menu->obj.id;
+}
+
+static struct scene_menitem *scene_menu_find_key(struct scene *scn,
+ struct scene_obj_menu *menu,
+ int key)
+{
+ struct scene_menitem *item;
+
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ if (item->key_id) {
+ struct scene_obj_txt *txt;
+ const char *str;
+
+ txt = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
+ if (txt) {
+ str = expo_get_str(scn->expo, txt->str_id);
+ if (str && *str == key)
+ return item;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
+ struct expo_action *event)
+{
+ struct scene_menitem *item, *cur, *key_item;
+
+ cur = NULL;
+ key_item = NULL;
+
+ if (!list_empty(&menu->item_head)) {
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ /* select an item if not done already */
+ if (menu->cur_item_id == item->id) {
+ cur = item;
+ break;
+ }
+ }
+ }
+
+ if (!cur)
+ return -ENOTTY;
+
+ switch (key) {
+ case BKEY_UP:
+ if (item != list_first_entry(&menu->item_head,
+ struct scene_menitem, sibling)) {
+ item = list_entry(item->sibling.prev,
+ struct scene_menitem, sibling);
+ event->type = EXPOACT_POINT;
+ event->select.id = item->id;
+ log_debug("up to item %d\n", event->select.id);
+ }
+ break;
+ case BKEY_DOWN:
+ if (!list_is_last(&item->sibling, &menu->item_head)) {
+ item = list_entry(item->sibling.next,
+ struct scene_menitem, sibling);
+ event->type = EXPOACT_POINT;
+ event->select.id = item->id;
+ log_debug("down to item %d\n", event->select.id);
+ }
+ break;
+ case BKEY_SELECT:
+ event->type = EXPOACT_SELECT;
+ event->select.id = item->id;
+ log_debug("select item %d\n", event->select.id);
+ break;
+ case BKEY_QUIT:
+ event->type = EXPOACT_QUIT;
+ log_debug("quit\n");
+ break;
+ case '0'...'9':
+ key_item = scene_menu_find_key(scn, menu, key);
+ if (key_item) {
+ event->type = EXPOACT_SELECT;
+ event->select.id = key_item->id;
+ }
+ break;
+ }
+
+ menu_point_to_item(menu, item->id);
+
+ return 0;
+}
+
+int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id,
+ uint key_id, uint label_id, uint desc_id, uint preview_id,
+ uint flags, struct scene_menitem **itemp)
+{
+ struct scene_obj_menu *menu;
+ struct scene_menitem *item;
+ int ret;
+
+ menu = scene_obj_find(scn, menu_id, SCENEOBJT_MENU);
+ if (!menu)
+ return log_msg_ret("find", -ENOENT);
+
+ /* Check that the text ID is valid */
+ if (!scene_obj_find(scn, desc_id, SCENEOBJT_TEXT))
+ return log_msg_ret("txt", -EINVAL);
+
+ item = calloc(1, sizeof(struct scene_obj_menu));
+ if (!item)
+ return log_msg_ret("item", -ENOMEM);
+ item->name = strdup(name);
+ if (!item->name) {
+ free(item);
+ return log_msg_ret("name", -ENOMEM);
+ }
+
+ item->id = resolve_id(scn->expo, id);
+ item->key_id = key_id;
+ item->label_id = label_id;
+ item->desc_id = desc_id;
+ item->preview_id = preview_id;
+ item->flags = flags;
+ list_add_tail(&item->sibling, &menu->item_head);
+
+ ret = scene_menu_arrange(scn, menu);
+ if (ret)
+ return log_msg_ret("pos", ret);
+
+ if (itemp)
+ *itemp = item;
+
+ return item->id;
+}
+
+int scene_menu_set_title(struct scene *scn, uint id, uint title_id)
+{
+ struct scene_obj_menu *menu;
+ struct scene_obj_txt *txt;
+
+ menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
+ if (!menu)
+ return log_msg_ret("menu", -ENOENT);
+
+ /* Check that the ID is valid */
+ if (title_id) {
+ txt = scene_obj_find(scn, title_id, SCENEOBJT_TEXT);
+ if (!txt)
+ return log_msg_ret("txt", -EINVAL);
+ }
+
+ menu->title_id = title_id;
+
+ return 0;
+}
+
+int scene_menu_set_pointer(struct scene *scn, uint id, uint pointer_id)
+{
+ struct scene_obj_menu *menu;
+ struct scene_obj *obj;
+
+ menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
+ if (!menu)
+ return log_msg_ret("menu", -ENOENT);
+
+ /* Check that the ID is valid */
+ if (pointer_id) {
+ obj = scene_obj_find(scn, pointer_id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("obj", -EINVAL);
+ }
+
+ menu->pointer_id = pointer_id;
+
+ return 0;
+}
+
+int scene_menu_display(struct scene_obj_menu *menu)
+{
+ struct scene *scn = menu->obj.scene;
+ struct scene_obj_txt *pointer;
+ struct expo *exp = scn->expo;
+ struct scene_menitem *item;
+ const char *pstr;
+
+ printf("U-Boot : Boot Menu\n\n");
+ if (menu->title_id) {
+ struct scene_obj_txt *txt;
+ const char *str;
+
+ txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_TEXT);
+ if (!txt)
+ return log_msg_ret("txt", -EINVAL);
+
+ str = expo_get_str(exp, txt->str_id);
+ printf("%s\n\n", str);
+ }
+
+ if (list_empty(&menu->item_head))
+ return 0;
+
+ pointer = scene_obj_find(scn, menu->pointer_id, SCENEOBJT_TEXT);
+ pstr = expo_get_str(scn->expo, pointer->str_id);
+
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ struct scene_obj_txt *key = NULL, *label = NULL;
+ struct scene_obj_txt *desc = NULL;
+ const char *kstr = NULL, *lstr = NULL, *dstr = NULL;
+
+ key = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
+ if (key)
+ kstr = expo_get_str(exp, key->str_id);
+
+ label = scene_obj_find(scn, item->label_id, SCENEOBJT_TEXT);
+ if (label)
+ lstr = expo_get_str(exp, label->str_id);
+
+ desc = scene_obj_find(scn, item->desc_id, SCENEOBJT_TEXT);
+ if (desc)
+ dstr = expo_get_str(exp, desc->str_id);
+
+ printf("%3s %3s %-10s %s\n",
+ pointer && menu->cur_item_id == item->id ? pstr : "",
+ kstr, lstr, dstr);
+ }
+
+ return -ENOTSUPP;
+}
diff --git a/boot/vbe_simple_fw.c b/boot/vbe_simple_fw.c
index 0a49d28..d59a704 100644
--- a/boot/vbe_simple_fw.c
+++ b/boot/vbe_simple_fw.c
@@ -176,7 +176,7 @@
priv = dev_get_priv(meth);
log_debug("simple %s\n", priv->storage);
- ret = bootdev_find_by_label(priv->storage, &bdev);
+ ret = bootdev_find_by_label(priv->storage, &bdev, NULL);
if (ret)
return log_msg_ret("bd", ret);
log_debug("bootdev %s\n", bdev->name);
diff --git a/boot/vbe_simple_os.c b/boot/vbe_simple_os.c
index b2041a9..8c641ec 100644
--- a/boot/vbe_simple_os.c
+++ b/boot/vbe_simple_os.c
@@ -72,6 +72,18 @@
chosen = oftree_path(tree, "/chosen");
if (!ofnode_valid(chosen))
continue;
+
+ ret = device_probe(dev);
+ if (ret) {
+ /*
+ * This should become an error when VBE is updated to
+ * only bind this device when a node exists
+ */
+ log_debug("VBE device '%s' failed to probe (err=%d)",
+ dev->name, ret);
+ return 0;
+ }
+
ret = ofnode_add_subnode(chosen, "fwupd", &node);
if (ret && ret != -EEXIST)
return log_msg_ret("fwu", ret);
@@ -80,10 +92,6 @@
if (ret && ret != -EEXIST)
return log_msg_ret("dev", ret);
- ret = device_probe(dev);
- if (ret)
- return log_msg_ret("probe", ret);
-
/* Copy over the vbe properties for fwupd */
log_debug("Fixing up: %s\n", dev->name);
ret = ofnode_copy_props(dev_ofnode(dev), subnode);
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 199a553..4fe2c75 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2539,6 +2539,7 @@
config MTDIDS_DEFAULT
string "Default MTD IDs"
depends on MTD || SPI_FLASH
+ depends on !SYS_MTDPARTS_RUNTIME
help
Defines a default MTD IDs list for use with MTD partitions in the
Linux MTD command line partitions format.
@@ -2546,6 +2547,7 @@
config MTDPARTS_DEFAULT
string "Default MTD partition scheme"
depends on MTD || SPI_FLASH
+ depends on !SYS_MTDPARTS_RUNTIME
help
Defines a default MTD partitioning scheme in the Linux MTD command
line partitions format
@@ -2620,6 +2622,7 @@
config CMD_EVENT
bool "event - Show information about events"
+ depends on EVENT
default y if EVENT_DEBUG
help
This enables the 'event' command which provides information about
diff --git a/cmd/bootdev.c b/cmd/bootdev.c
index ecd797c..5b1efaa 100644
--- a/cmd/bootdev.c
+++ b/cmd/bootdev.c
@@ -57,7 +57,7 @@
std->cur_bootdev = NULL;
return 0;
}
- if (bootdev_find_by_any(argv[1], &dev))
+ if (bootdev_find_by_any(argv[1], &dev, NULL))
return CMD_RET_FAILURE;
std->cur_bootdev = dev;
@@ -107,14 +107,48 @@
return 0;
}
+static int do_bootdev_hunt(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct bootstd_priv *priv;
+ const char *spec = NULL;
+ bool list = false;
+ int ret = 0;
+
+ if (argc >= 2) {
+ if (!strcmp(argv[1], "-l"))
+ list = true;
+ else
+ spec = argv[1];
+ }
+
+ ret = bootstd_get_priv(&priv);
+ if (ret)
+ return ret;
+ if (list) {
+ bootdev_list_hunters(priv);
+ } else {
+ ret = bootdev_hunt(spec, true);
+ if (ret) {
+ printf("Failed (err=%dE)\n", ret);
+
+ return CMD_RET_FAILURE;
+ }
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_SYS_LONGHELP
static char bootdev_help_text[] =
- "list [-p] - list all available bootdevs (-p to probe)\n"
- "bootdev select <bd> - select a bootdev by name | label | seq\n"
- "bootdev info [-p] - show information about a bootdev (-p to probe)";
+ "list [-p] - list all available bootdevs (-p to probe)\n"
+ "bootdev hunt [-l|<spec>] - use hunt drivers to find bootdevs\n"
+ "bootdev select <bd> - select a bootdev by name | label | seq\n"
+ "bootdev info [-p] - show information about a bootdev (-p to probe)";
#endif
U_BOOT_CMD_WITH_SUBCMDS(bootdev, "Boot devices", bootdev_help_text,
U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootdev_list),
+ U_BOOT_SUBCMD_MKENT(hunt, 2, 1, do_bootdev_hunt),
U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootdev_select),
U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootdev_info));
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 313103d..692bc6d 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -93,11 +93,12 @@
{
struct bootstd_priv *std;
struct bootflow_iter iter;
- struct udevice *dev;
+ struct udevice *dev = NULL;
struct bootflow bflow;
bool all = false, boot = false, errors = false, no_global = false;
- bool list = false;
+ bool list = false, no_hunter = false;
int num_valid = 0;
+ const char *label = NULL;
bool has_args;
int ret, i;
int flags;
@@ -105,7 +106,6 @@
ret = bootstd_get_priv(&std);
if (ret)
return CMD_RET_FAILURE;
- dev = std->cur_bootdev;
has_args = argc > 1 && *argv[1] == '-';
if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL)) {
@@ -115,15 +115,14 @@
errors = strchr(argv[1], 'e');
no_global = strchr(argv[1], 'G');
list = strchr(argv[1], 'l');
+ no_hunter = strchr(argv[1], 'H');
argc--;
argv++;
}
- if (argc > 1) {
- const char *label = argv[1];
-
- if (bootdev_find_by_any(label, &dev))
- return CMD_RET_FAILURE;
- }
+ if (argc > 1)
+ label = argv[1];
+ if (!label)
+ dev = std->cur_bootdev;
} else {
if (has_args) {
printf("Flags not supported: enable CONFIG_BOOTFLOW_FULL\n");
@@ -141,58 +140,42 @@
flags |= BOOTFLOWF_ALL;
if (no_global)
flags |= BOOTFLOWF_SKIP_GLOBAL;
+ if (!no_hunter)
+ flags |= BOOTFLOWF_HUNT;
/*
* If we have a device, just scan for bootflows attached to that device
*/
- if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && dev) {
- if (list) {
- printf("Scanning for bootflows in bootdev '%s'\n",
- dev->name);
- show_header();
- }
+ if (list) {
+ printf("Scanning for bootflows ");
+ if (dev)
+ printf("in bootdev '%s'\n", dev->name);
+ else if (label)
+ printf("with label '%s'\n", label);
+ else
+ printf("in all bootdevs\n");
+ show_header();
+ }
+ if (dev)
bootdev_clear_bootflows(dev);
- for (i = 0,
- ret = bootflow_scan_bootdev(dev, &iter, flags, &bflow);
- i < 1000 && ret != -ENODEV;
- i++, ret = bootflow_scan_next(&iter, &bflow)) {
- bflow.err = ret;
- if (!ret)
- num_valid++;
- ret = bootdev_add_bootflow(&bflow);
- if (ret) {
- printf("Out of memory\n");
- return CMD_RET_FAILURE;
- }
- if (list)
- show_bootflow(i, &bflow, errors);
- if (boot && !bflow.err)
- bootflow_run_boot(&iter, &bflow);
- }
- } else {
- if (list) {
- printf("Scanning for bootflows in all bootdevs\n");
- show_header();
- }
+ else
bootstd_clear_glob();
-
- for (i = 0,
- ret = bootflow_scan_first(&iter, flags, &bflow);
- i < 1000 && ret != -ENODEV;
- i++, ret = bootflow_scan_next(&iter, &bflow)) {
- bflow.err = ret;
- if (!ret)
- num_valid++;
- ret = bootdev_add_bootflow(&bflow);
- if (ret) {
- printf("Out of memory\n");
- return CMD_RET_FAILURE;
- }
- if (list)
- show_bootflow(i, &bflow, errors);
- if (boot && !bflow.err)
- bootflow_run_boot(&iter, &bflow);
+ for (i = 0,
+ ret = bootflow_scan_first(dev, label, &iter, flags, &bflow);
+ i < 1000 && ret != -ENODEV;
+ i++, ret = bootflow_scan_next(&iter, &bflow)) {
+ bflow.err = ret;
+ if (!ret)
+ num_valid++;
+ ret = bootdev_add_bootflow(&bflow);
+ if (ret) {
+ printf("Out of memory\n");
+ return CMD_RET_FAILURE;
}
+ if (list)
+ show_bootflow(i, &bflow, errors);
+ if (boot && !bflow.err)
+ bootflow_run_boot(&iter, &bflow);
}
bootflow_iter_uninit(&iter);
if (list)
@@ -337,6 +320,19 @@
printf("Filename: %s\n", bflow->fname);
printf("Buffer: %lx\n", (ulong)map_to_sysmem(bflow->buf));
printf("Size: %x (%d bytes)\n", bflow->size, bflow->size);
+ printf("OS: %s\n", bflow->os_name ? bflow->os_name : "(none)");
+ printf("Logo: %s\n", bflow->logo ?
+ simple_xtoa((ulong)map_to_sysmem(bflow->logo)) : "(none)");
+ if (bflow->logo) {
+ printf("Logo size: %x (%d bytes)\n", bflow->logo_size,
+ bflow->logo_size);
+ }
+ printf("FDT: %s\n", bflow->fdt_fname);
+ if (bflow->fdt_fname) {
+ printf("FDT size: %x (%d bytes)\n", bflow->fdt_size,
+ bflow->fdt_size);
+ printf("FDT addr: %lx\n", bflow->fdt_addr);
+ }
printf("Error: %d\n", bflow->err);
if (dump && bflow->buf) {
/* Set some sort of maximum on the size */
@@ -382,6 +378,37 @@
return 0;
}
+
+static int do_bootflow_menu(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct bootstd_priv *std;
+ struct bootflow *bflow;
+ bool text_mode = false;
+ int ret;
+
+ if (argc > 1 && *argv[1] == '-')
+ text_mode = strchr(argv[1], 't');
+
+ ret = bootstd_get_priv(&std);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ ret = bootflow_menu_run(std, text_mode, &bflow);
+ if (ret) {
+ if (ret == -EAGAIN)
+ printf("Nothing chosen\n");
+ else
+ printf("Menu failed (err=%d)\n", ret);
+
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name);
+ std->cur_bootflow = bflow;
+
+ return 0;
+}
#endif /* CONFIG_CMD_BOOTFLOW_FULL */
#ifdef CONFIG_SYS_LONGHELP
@@ -391,7 +418,8 @@
"bootflow list [-e] - list scanned bootflows (-e errors)\n"
"bootflow select [<num>|<name>] - select a bootflow\n"
"bootflow info [-d] - show info on current bootflow (-d dump bootflow)\n"
- "bootflow boot - boot current bootflow (or first available if none selected)";
+ "bootflow boot - boot current bootflow (or first available if none selected)\n"
+ "bootflow menu [-t] - show a menu of available bootflows";
#else
"scan - boot first available bootflow\n";
#endif
@@ -403,6 +431,7 @@
U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootflow_list),
U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootflow_select),
U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info),
- U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot)
+ U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot),
+ U_BOOT_SUBCMD_MKENT(menu, 2, 1, do_bootflow_menu),
#endif
);
diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c
index e5a10f5..3236ca5 100644
--- a/cmd/bootmenu.c
+++ b/cmd/bootmenu.c
@@ -4,6 +4,7 @@
*/
#include <charset.h>
+#include <cli.h>
#include <common.h>
#include <command.h>
#include <ansi.h>
@@ -84,38 +85,40 @@
static char *bootmenu_choice_entry(void *data)
{
+ struct cli_ch_state s_cch, *cch = &s_cch;
struct bootmenu_data *menu = data;
struct bootmenu_entry *iter;
- enum bootmenu_key key = KEY_NONE;
- int esc = 0;
+ enum bootmenu_key key = BKEY_NONE;
int i;
+ cli_ch_init(cch);
+
while (1) {
if (menu->delay >= 0) {
/* Autoboot was not stopped */
- bootmenu_autoboot_loop(menu, &key, &esc);
+ key = bootmenu_autoboot_loop(menu, cch);
} else {
/* Some key was pressed, so autoboot was stopped */
- bootmenu_loop(menu, &key, &esc);
+ key = bootmenu_loop(menu, cch);
}
switch (key) {
- case KEY_UP:
+ case BKEY_UP:
if (menu->active > 0)
--menu->active;
/* no menu key selected, regenerate menu */
return NULL;
- case KEY_DOWN:
+ case BKEY_DOWN:
if (menu->active < menu->count - 1)
++menu->active;
/* no menu key selected, regenerate menu */
return NULL;
- case KEY_SELECT:
+ case BKEY_SELECT:
iter = menu->first;
for (i = 0; i < menu->active; ++i)
iter = iter->next;
return iter->key;
- case KEY_QUIT:
+ case BKEY_QUIT:
/* Quit by choosing the last entry - U-Boot console */
iter = menu->first;
while (iter->next)
diff --git a/cmd/dm.c b/cmd/dm.c
index 218be85..979cd36 100644
--- a/cmd/dm.c
+++ b/cmd/dm.c
@@ -59,7 +59,11 @@
static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
- dm_dump_tree();
+ bool sort;
+
+ sort = argc > 1 && !strcmp(argv[1], "-s");
+
+ dm_dump_tree(sort);
return 0;
}
@@ -87,7 +91,7 @@
"dm drivers Dump list of drivers with uclass and instances\n"
DM_MEM_HELP
"dm static Dump list of drivers with static platform data\n"
- "dm tree Dump tree of driver model devices ('*' = activated)\n"
+ "dm tree [-s] Dump tree of driver model devices (-s=sort)\n"
"dm uclass Dump list of instances for each uclass"
;
#endif
@@ -98,5 +102,5 @@
U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_dm_dump_drivers),
DM_MEM
U_BOOT_SUBCMD_MKENT(static, 1, 1, do_dm_dump_static_driver_info),
- U_BOOT_SUBCMD_MKENT(tree, 1, 1, do_dm_dump_tree),
+ U_BOOT_SUBCMD_MKENT(tree, 2, 1, do_dm_dump_tree),
U_BOOT_SUBCMD_MKENT(uclass, 1, 1, do_dm_dump_uclass));
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index ce7175a..d830e4a 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -6,6 +6,7 @@
*/
#include <ansi.h>
+#include <cli.h>
#include <common.h>
#include <charset.h>
#include <efi_loader.h>
@@ -184,34 +185,36 @@
*/
static char *eficonfig_choice_entry(void *data)
{
- int esc = 0;
+ struct cli_ch_state s_cch, *cch = &s_cch;
struct list_head *pos, *n;
struct eficonfig_entry *entry;
- enum bootmenu_key key = KEY_NONE;
+ enum bootmenu_key key = BKEY_NONE;
struct efimenu *efi_menu = data;
+ cli_ch_init(cch);
+
while (1) {
- bootmenu_loop((struct bootmenu_data *)efi_menu, &key, &esc);
+ key = bootmenu_loop((struct bootmenu_data *)efi_menu, cch);
switch (key) {
- case KEY_UP:
+ case BKEY_UP:
if (efi_menu->active > 0)
--efi_menu->active;
/* no menu key selected, regenerate menu */
return NULL;
- case KEY_DOWN:
+ case BKEY_DOWN:
if (efi_menu->active < efi_menu->count - 1)
++efi_menu->active;
/* no menu key selected, regenerate menu */
return NULL;
- case KEY_SELECT:
+ case BKEY_SELECT:
list_for_each_safe(pos, n, &efi_menu->list) {
entry = list_entry(pos, struct eficonfig_entry, list);
if (entry->num == efi_menu->active)
return entry->key;
}
break;
- case KEY_QUIT:
+ case BKEY_QUIT:
/* Quit by choosing the last entry */
entry = list_last_entry(&efi_menu->list, struct eficonfig_entry, list);
return entry->key;
@@ -1862,16 +1865,17 @@
*/
static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
{
- int esc = 0;
+ struct cli_ch_state s_cch, *cch = &s_cch;
struct list_head *pos, *n;
- enum bootmenu_key key = KEY_NONE;
+ enum bootmenu_key key = BKEY_NONE;
struct eficonfig_entry *entry, *tmp;
+ cli_ch_init(cch);
while (1) {
- bootmenu_loop(NULL, &key, &esc);
+ key = bootmenu_loop(NULL, cch);
switch (key) {
- case KEY_PLUS:
+ case BKEY_PLUS:
if (efi_menu->active > 0) {
list_for_each_safe(pos, n, &efi_menu->list) {
entry = list_entry(pos, struct eficonfig_entry, list);
@@ -1885,11 +1889,11 @@
list_add(&tmp->list, &entry->list);
}
fallthrough;
- case KEY_UP:
+ case BKEY_UP:
if (efi_menu->active > 0)
--efi_menu->active;
return EFI_NOT_READY;
- case KEY_MINUS:
+ case BKEY_MINUS:
if (efi_menu->active < efi_menu->count - 3) {
list_for_each_safe(pos, n, &efi_menu->list) {
entry = list_entry(pos, struct eficonfig_entry, list);
@@ -1905,11 +1909,11 @@
++efi_menu->active;
}
return EFI_NOT_READY;
- case KEY_DOWN:
+ case BKEY_DOWN:
if (efi_menu->active < efi_menu->count - 1)
++efi_menu->active;
return EFI_NOT_READY;
- case KEY_SELECT:
+ case BKEY_SELECT:
/* "Save" */
if (efi_menu->active == efi_menu->count - 2)
return EFI_SUCCESS;
@@ -1919,7 +1923,7 @@
return EFI_ABORTED;
break;
- case KEY_SPACE:
+ case BKEY_SPACE:
if (efi_menu->active < efi_menu->count - 2) {
list_for_each_safe(pos, n, &efi_menu->list) {
entry = list_entry(pos, struct eficonfig_entry, list);
@@ -1932,7 +1936,7 @@
}
}
break;
- case KEY_QUIT:
+ case BKEY_QUIT:
return EFI_ABORTED;
default:
/* Pressed key is not valid, no need to regenerate the menu */
diff --git a/cmd/event.c b/cmd/event.c
index 9cac202..b4b779f 100644
--- a/cmd/event.c
+++ b/cmd/event.c
@@ -20,7 +20,7 @@
#ifdef CONFIG_SYS_LONGHELP
static char event_help_text[] =
- "event list - list event spies";
+ "list - list event spies";
#endif
U_BOOT_CMD_WITH_SUBCMDS(event, "Events", event_help_text,
diff --git a/cmd/exit.c b/cmd/exit.c
index 2c71326..7bf241e 100644
--- a/cmd/exit.c
+++ b/cmd/exit.c
@@ -10,10 +10,13 @@
static int do_exit(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
- if (argc > 1)
- return dectoul(argv[1], NULL);
+ int r;
- return 0;
+ r = 0;
+ if (argc > 1)
+ r = simple_strtoul(argv[1], NULL, 10);
+
+ return -r - 2;
}
U_BOOT_CMD(
diff --git a/cmd/extension_board.c b/cmd/extension_board.c
index f94abd6..2b672d8 100644
--- a/cmd/extension_board.c
+++ b/cmd/extension_board.c
@@ -5,7 +5,9 @@
*/
#include <common.h>
+#include <bootdev.h>
#include <command.h>
+#include <dm.h>
#include <malloc.h>
#include <extension_board.h>
#include <mapmem.h>
@@ -80,8 +82,7 @@
return CMD_RET_SUCCESS;
}
-static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
- int argc, char *const argv[])
+static int extension_scan(bool show)
{
struct extension *extension, *next;
int extension_num;
@@ -91,12 +92,23 @@
free(extension);
}
extension_num = extension_board_scan(&extension_list);
+ if (show && extension_num >= 0)
+ printf("Found %d extension board(s).\n", extension_num);
+ /* either the number of extensions, or -ve for error */
+ return extension_num;
+}
+
+
+static int do_extension_scan(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ int extension_num;
+
+ extension_num = extension_scan(true);
if (extension_num < 0)
return CMD_RET_FAILURE;
- printf("Found %d extension board(s).\n", extension_num);
-
return CMD_RET_SUCCESS;
}
@@ -166,3 +178,26 @@
"extension list - lists available extension(s) board(s)\n"
"extension apply <extension number|all> - applies DT overlays corresponding to extension boards\n"
);
+
+static int extension_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ ret = env_set_hex("extension_overlay_addr",
+ env_get_hex("fdtoverlay_addr_r", 0));
+ if (ret)
+ return log_msg_ret("env", ret);
+
+ ret = extension_scan(show);
+ if (ret < 0)
+ return log_msg_ret("ext", ret);
+
+ return 0;
+}
+
+/* extensions should have a uclass - for now we use UCLASS_SIMPLE_BUS uclass */
+BOOTDEV_HUNTER(extension_bootdev_hunter) = {
+ .prio = BOOTDEVP_1_PRE_SCAN,
+ .uclass = UCLASS_SIMPLE_BUS,
+ .hunt = extension_bootdev_hunt,
+};
diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index b498e4b..b94dbd5 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -19,8 +19,14 @@
static int do_fastboot_udp(int argc, char *const argv[],
uintptr_t buf_addr, size_t buf_size)
{
-#if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)
- int err = net_loop(FASTBOOT);
+ int err;
+
+ if (!CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)) {
+ pr_err("Fastboot UDP not enabled\n");
+ return CMD_RET_FAILURE;
+ }
+
+ err = net_loop(FASTBOOT);
if (err < 0) {
printf("fastboot udp error: %d\n", err);
@@ -28,21 +34,21 @@
}
return CMD_RET_SUCCESS;
-#else
- pr_err("Fastboot UDP not enabled\n");
- return CMD_RET_FAILURE;
-#endif
}
static int do_fastboot_usb(int argc, char *const argv[],
uintptr_t buf_addr, size_t buf_size)
{
-#if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)
int controller_index;
char *usb_controller;
char *endp;
int ret;
+ if (!CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)) {
+ pr_err("Fastboot USB not enabled\n");
+ return CMD_RET_FAILURE;
+ }
+
if (argc < 2)
return CMD_RET_USAGE;
@@ -88,10 +94,6 @@
g_dnl_clear_detach();
return ret;
-#else
- pr_err("Fastboot USB not enabled\n");
- return CMD_RET_FAILURE;
-#endif
}
static int do_fastboot(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -148,17 +150,12 @@
return do_fastboot_usb(argc, argv, buf_addr, buf_size);
}
-#ifdef CONFIG_SYS_LONGHELP
-static char fastboot_help_text[] =
+U_BOOT_CMD(
+ fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
+ "run as a fastboot usb or udp device",
"[-l addr] [-s size] usb <controller> | udp\n"
"\taddr - address of buffer used during data transfers ("
__stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
"\tsize - size of buffer used during data transfers ("
__stringify(CONFIG_FASTBOOT_BUF_SIZE) ")"
- ;
-#endif
-
-U_BOOT_CMD(
- fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
- "run as a fastboot usb or udp device", fastboot_help_text
);
diff --git a/cmd/font.c b/cmd/font.c
index 3e522f3..7b4347f 100644
--- a/cmd/font.c
+++ b/cmd/font.c
@@ -15,7 +15,11 @@
static int do_font_list(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
- vidconsole_list_fonts();
+ struct udevice *dev;
+
+ if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
+ return CMD_RET_FAILURE;
+ vidconsole_list_fonts(dev);
return 0;
}
@@ -47,6 +51,7 @@
static int do_font_size(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
+ const char *font_name;
struct udevice *dev;
uint size;
int ret;
@@ -56,9 +61,11 @@
if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev))
return CMD_RET_FAILURE;
+ font_name = vidconsole_get_font_size(dev, &size);
size = dectoul(argv[1], NULL);
- ret = vidconsole_select_font(dev, NULL, size);
+
+ ret = vidconsole_select_font(dev, font_name, size);
if (ret) {
printf("Failed (error %d)\n", ret);
return CMD_RET_FAILURE;
diff --git a/cmd/mvebu/comphy_rx_training.c b/cmd/mvebu/comphy_rx_training.c
index 25a9e15..4ee8f54 100644
--- a/cmd/mvebu/comphy_rx_training.c
+++ b/cmd/mvebu/comphy_rx_training.c
@@ -22,7 +22,7 @@
if (argc != 3) {
printf("missing arguments\n");
- return -1;
+ return CMD_RET_USAGE;
}
cp_index = hextoul(argv[1], NULL);
diff --git a/cmd/net.c b/cmd/net.c
index dd50930..4227321 100644
--- a/cmd/net.c
+++ b/cmd/net.c
@@ -4,6 +4,8 @@
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*/
+#define LOG_CATEGORY UCLASS_ETH
+
/*
* Boot support
*/
@@ -13,6 +15,7 @@
#include <dm.h>
#include <env.h>
#include <image.h>
+#include <log.h>
#include <net.h>
#include <net6.h>
#include <net/udp.h>
@@ -120,6 +123,38 @@
"boot image via network using DHCP/TFTP protocol",
"[loadAddress] [[hostIPaddr:]bootfilename]"
);
+
+int dhcp_run(ulong addr, const char *fname, bool autoload)
+{
+ char *dhcp_argv[] = {"dhcp", NULL, (char *)fname, NULL};
+ struct cmd_tbl cmdtp = {}; /* dummy */
+ char file_addr[17];
+ int old_autoload;
+ int ret, result;
+
+ log_debug("addr=%lx, fname=%s, autoload=%d\n", addr, fname, autoload);
+ old_autoload = env_get_yesno("autoload");
+ ret = env_set("autoload", autoload ? "y" : "n");
+ if (ret)
+ return log_msg_ret("en1", -EINVAL);
+
+ if (autoload) {
+ sprintf(file_addr, "%lx", addr);
+ dhcp_argv[1] = file_addr;
+ }
+
+ result = do_dhcp(&cmdtp, 0, !autoload ? 1 : fname ? 3 : 2, dhcp_argv);
+
+ ret = env_set("autoload", old_autoload == -1 ? NULL :
+ old_autoload ? "y" : "n");
+ if (ret)
+ return log_msg_ret("en2", -EINVAL);
+
+ if (result)
+ return log_msg_ret("res", -ENOENT);
+
+ return 0;
+}
#endif
#if defined(CONFIG_CMD_NFS)
diff --git a/cmd/part.c b/cmd/part.c
index 9d419c9..28f2b7f 100644
--- a/cmd/part.c
+++ b/cmd/part.c
@@ -182,6 +182,31 @@
return do_part_info(argc, argv, CMD_PART_INFO_NUMBER);
}
+#ifdef CONFIG_PARTITION_TYPE_GUID
+static int do_part_type(int argc, char *const argv[])
+{
+ int part;
+ struct blk_desc *dev_desc;
+ struct disk_partition info;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ if (argc > 3)
+ return CMD_RET_USAGE;
+
+ part = blk_get_device_part_str(argv[0], argv[1], &dev_desc, &info, 0);
+ if (part < 0)
+ return 1;
+
+ if (argc > 2)
+ env_set(argv[2], info.type_guid);
+ else
+ printf("%s\n", info.type_guid);
+
+ return 0;
+}
+#endif
+
static int do_part_types(int argc, char * const argv[])
{
struct part_driver *drv = ll_entry_start(struct part_driver,
@@ -220,6 +245,10 @@
return do_part_number(argc - 2, argv + 2);
else if (!strcmp(argv[1], "types"))
return do_part_types(argc - 2, argv + 2);
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ else if (!strcmp(argv[1], "type"))
+ return do_part_type(argc - 2, argv + 2);
+#endif
return CMD_RET_USAGE;
}
@@ -244,6 +273,12 @@
"part number <interface> <dev> <part> <varname>\n"
" - set environment variable to the partition number using the partition name\n"
" part must be specified as partition name\n"
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ "part type <interface> <dev>:<part>\n"
+ " - print partition type\n"
+#endif
+ "part type <interface> <dev>:<part> <varname>\n"
+ " - set environment variable to partition type\n"
"part types\n"
" - list supported partition table types"
);
diff --git a/cmd/sf.c b/cmd/sf.c
index cf92ac4..11b9c25 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -281,33 +281,33 @@
loff_t offset, len, maxsize;
if (argc < 3)
- return -1;
+ return CMD_RET_USAGE;
addr = hextoul(argv[1], &endp);
if (*argv[1] == 0 || *endp != 0)
- return -1;
+ return CMD_RET_USAGE;
if (mtd_arg_off_size(argc - 2, &argv[2], &dev, &offset, &len,
&maxsize, MTD_DEV_TYPE_NOR, flash->size))
- return -1;
+ return CMD_RET_FAILURE;
/* Consistency checking */
if (offset + len > flash->size) {
printf("ERROR: attempting %s past flash size (%#x)\n",
argv[0], flash->size);
- return 1;
+ return CMD_RET_FAILURE;
}
if (strncmp(argv[0], "read", 4) != 0 && flash->flash_is_unlocked &&
!flash->flash_is_unlocked(flash, offset, len)) {
printf("ERROR: flash area is locked\n");
- return 1;
+ return CMD_RET_FAILURE;
}
buf = map_physmem(addr, len, MAP_WRBACK);
if (!buf && addr) {
puts("Failed to map physical memory\n");
- return 1;
+ return CMD_RET_FAILURE;
}
if (strcmp(argv[0], "update") == 0) {
@@ -332,7 +332,7 @@
unmap_physmem(buf, len);
- return ret == 0 ? 0 : 1;
+ return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
}
static int do_spi_flash_erase(int argc, char *const argv[])
@@ -343,27 +343,27 @@
ulong size;
if (argc < 3)
- return -1;
+ return CMD_RET_USAGE;
if (mtd_arg_off(argv[1], &dev, &offset, &len, &maxsize,
MTD_DEV_TYPE_NOR, flash->size))
- return -1;
+ return CMD_RET_FAILURE;
ret = sf_parse_len_arg(argv[2], &size);
if (ret != 1)
- return -1;
+ return CMD_RET_USAGE;
/* Consistency checking */
if (offset + size > flash->size) {
printf("ERROR: attempting %s past flash size (%#x)\n",
argv[0], flash->size);
- return 1;
+ return CMD_RET_FAILURE;
}
if (flash->flash_is_unlocked &&
!flash->flash_is_unlocked(flash, offset, len)) {
printf("ERROR: flash area is locked\n");
- return 1;
+ return CMD_RET_FAILURE;
}
ret = spi_flash_erase(flash, offset, size);
@@ -373,7 +373,7 @@
else
printf("OK\n");
- return ret == 0 ? 0 : 1;
+ return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
}
static int do_spi_protect(int argc, char *const argv[])
@@ -579,21 +579,19 @@
/* need at least two arguments */
if (argc < 2)
- goto usage;
+ return CMD_RET_USAGE;
cmd = argv[1];
--argc;
++argv;
- if (strcmp(cmd, "probe") == 0) {
- ret = do_spi_flash_probe(argc, argv);
- goto done;
- }
+ if (strcmp(cmd, "probe") == 0)
+ return do_spi_flash_probe(argc, argv);
/* The remaining commands require a selected device */
if (!flash) {
puts("No SPI flash selected. Please run `sf probe'\n");
- return 1;
+ return CMD_RET_FAILURE;
}
if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0 ||
@@ -606,14 +604,9 @@
else if (IS_ENABLED(CONFIG_CMD_SF_TEST) && !strcmp(cmd, "test"))
ret = do_spi_flash_test(argc, argv);
else
- ret = -1;
+ ret = CMD_RET_USAGE;
-done:
- if (ret != -1)
- return ret;
-
-usage:
- return CMD_RET_USAGE;
+ return ret;
}
#ifdef CONFIG_SYS_LONGHELP
diff --git a/cmd/source.c b/cmd/source.c
index 94da5d8..92c7835 100644
--- a/cmd/source.c
+++ b/cmd/source.c
@@ -24,169 +24,6 @@
#include <asm/byteorder.h>
#include <asm/io.h>
-#if defined(CONFIG_FIT)
-/**
- * get_default_image() - Return default property from /images
- *
- * Return: Pointer to value of default property (or NULL)
- */
-static const char *get_default_image(const void *fit)
-{
- int images_noffset;
-
- images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
- if (images_noffset < 0)
- return NULL;
-
- return fdt_getprop(fit, images_noffset, FIT_DEFAULT_PROP, NULL);
-}
-#endif
-
-int image_source_script(ulong addr, const char *fit_uname, const char *confname)
-{
- ulong len;
-#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
- const struct legacy_img_hdr *hdr;
-#endif
- u32 *data;
- int verify;
- void *buf;
-#if defined(CONFIG_FIT)
- const void* fit_hdr;
- int noffset;
- const void *fit_data;
- size_t fit_len;
-#endif
-
- verify = env_get_yesno("verify");
-
- buf = map_sysmem(addr, 0);
- switch (genimg_get_format(buf)) {
-#if defined(CONFIG_LEGACY_IMAGE_FORMAT)
- case IMAGE_FORMAT_LEGACY:
- hdr = buf;
-
- if (!image_check_magic (hdr)) {
- puts ("Bad magic number\n");
- return 1;
- }
-
- if (!image_check_hcrc (hdr)) {
- puts ("Bad header crc\n");
- return 1;
- }
-
- if (verify) {
- if (!image_check_dcrc (hdr)) {
- puts ("Bad data crc\n");
- return 1;
- }
- }
-
- if (!image_check_type (hdr, IH_TYPE_SCRIPT)) {
- puts ("Bad image type\n");
- return 1;
- }
-
- /* get length of script */
- data = (u32 *)image_get_data (hdr);
-
- if ((len = uimage_to_cpu (*data)) == 0) {
- puts ("Empty Script\n");
- return 1;
- }
-
- /*
- * scripts are just multi-image files with one component, seek
- * past the zero-terminated sequence of image lengths to get
- * to the actual image data
- */
- while (*data++);
- break;
-#endif
-#if defined(CONFIG_FIT)
- case IMAGE_FORMAT_FIT:
- fit_hdr = buf;
- if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
- puts ("Bad FIT image format\n");
- return 1;
- }
-
- if (!fit_uname) {
- /* If confname is empty, use the default */
- if (confname && *confname)
- noffset = fit_conf_get_node(fit_hdr, confname);
- else
- noffset = fit_conf_get_node(fit_hdr, NULL);
- if (noffset < 0) {
- if (!confname)
- goto fallback;
- printf("Could not find config %s\n", confname);
- return 1;
- }
-
- if (verify && fit_config_verify(fit_hdr, noffset))
- return 1;
-
- noffset = fit_conf_get_prop_node(fit_hdr, noffset,
- FIT_SCRIPT_PROP,
- IH_PHASE_NONE);
- if (noffset < 0) {
- if (!confname)
- goto fallback;
- printf("Could not find script in %s\n", confname);
- return 1;
- }
- } else {
-fallback:
- if (!fit_uname || !*fit_uname)
- fit_uname = get_default_image(fit_hdr);
- if (!fit_uname) {
- puts("No FIT subimage unit name\n");
- return 1;
- }
-
- /* get script component image node offset */
- noffset = fit_image_get_node(fit_hdr, fit_uname);
- if (noffset < 0) {
- printf("Can't find '%s' FIT subimage\n",
- fit_uname);
- return 1;
- }
- }
-
- if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) {
- puts("Not a script image\n");
- return 1;
- }
-
- /* verify integrity */
- if (verify && !fit_image_verify(fit_hdr, noffset)) {
- puts("Bad Data Hash\n");
- return 1;
- }
-
- /* get script subimage data address and length */
- if (fit_image_get_data (fit_hdr, noffset, &fit_data, &fit_len)) {
- puts ("Could not find script subimage data\n");
- return 1;
- }
-
- data = (u32 *)fit_data;
- len = (ulong)fit_len;
- break;
-#endif
- default:
- puts ("Wrong image format for \"source\" command\n");
- return 1;
- }
-
- debug("** Script length: %ld\n", len);
- return run_command_list((char *)data, len, 0);
-}
-
-/**************************************************/
-#if defined(CONFIG_CMD_SOURCE)
static int do_source(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
@@ -213,7 +50,7 @@
}
printf ("## Executing script at %08lx\n", addr);
- rcode = image_source_script(addr, fit_uname, confname);
+ rcode = cmd_source_script(addr, fit_uname, confname);
return rcode;
}
@@ -235,4 +72,3 @@
source, 2, 0, do_source,
"run script from memory", source_help_text
);
-#endif
diff --git a/cmd/spi.c b/cmd/spi.c
index 454ebe3..f30018f 100644
--- a/cmd/spi.c
+++ b/cmd/spi.c
@@ -112,6 +112,9 @@
if ((flag & CMD_FLAG_REPEAT) == 0)
{
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
if (argc >= 2) {
mode = CONFIG_DEFAULT_SPI_MODE;
bus = dectoul(argv[1], &cp);
diff --git a/cmd/vbe.c b/cmd/vbe.c
index befaf07..6006903 100644
--- a/cmd/vbe.c
+++ b/cmd/vbe.c
@@ -79,10 +79,13 @@
static int do_vbe_state(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
- struct vbe_handoff *handoff;
+ struct vbe_handoff *handoff = NULL;
int i;
- handoff = bloblist_find(BLOBLISTT_VBE, sizeof(struct vbe_handoff));
+ if (IS_ENABLED(CONFIG_BLOBLIST)) {
+ handoff = bloblist_find(BLOBLISTT_VBE,
+ sizeof(struct vbe_handoff));
+ }
if (!handoff) {
printf("No VBE state\n");
return CMD_RET_FAILURE;
diff --git a/cmd/ximg.c b/cmd/ximg.c
index 1c40fd2..60ed2c9 100644
--- a/cmd/ximg.c
+++ b/cmd/ximg.c
@@ -27,9 +27,9 @@
#include <asm/cache.h>
#include <asm/io.h>
-#ifndef CONFIG_SYS_XIMG_LEN
+#ifndef CFG_SYS_XIMG_LEN
/* use 8MByte as default max gunzip size */
-#define CONFIG_SYS_XIMG_LEN 0x800000
+#define CFG_SYS_XIMG_LEN 0x800000
#endif
static int
@@ -52,7 +52,7 @@
size_t fit_len;
#endif
#ifdef CONFIG_GZIP
- uint unc_len = CONFIG_SYS_XIMG_LEN;
+ uint unc_len = CFG_SYS_XIMG_LEN;
#endif
uint8_t comp;
diff --git a/common/Kconfig b/common/Kconfig
index 8c71d3c..e3a5e1b 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -164,6 +164,16 @@
(e.g. NAND). This option makes the value of the 'silent'
environment variable take effect at relocation.
+config SILENT_CONSOLE_UNTIL_ENV
+ bool "Keep console silent until environment is loaded"
+ depends on SILENT_CONSOLE
+ help
+ This option makes sure U-Boot will never use the console unless the
+ environment from flash does not contain the 'silent' variable. If
+ set, the console is kept silent until after the environment was
+ loaded. Use this in combination with PRE_CONSOLE_BUFFER to print out
+ earlier messages after loading the environment when allowed.
+
config PRE_CONSOLE_BUFFER
bool "Buffer characters before the console is available"
help
@@ -594,24 +604,23 @@
endif # CYCLIC
config EVENT
- bool "General-purpose event-handling mechanism"
- default y if SANDBOX
+ bool
help
- This enables sending and processing of events, to allow interested
- parties to be alerted when something happens. This is an attempt to
- stem the flow of weak functions, hooks, functions in board_f.c
- and board_r.c and the Kconfig options below.
+ This adds a framework for general purpose sending and processing of
+ events, to allow interested parties to be alerted when something
+ happens. This is an attempt to stem the flow of weak functions,
+ hooks, functions in board_f.c and board_r.c and the Kconfig options
+ below.
See doc/develop/event.rst for more information.
if EVENT
config EVENT_DYNAMIC
- bool "Support event registration at runtime"
- default y if SANDBOX
+ bool
help
Enable this to support adding an event spy at runtime, without adding
- it to the EVENT_SPy() linker list. This increases code size slightly
+ it to the EVENT_SPY() linker list. This increases code size slightly
but provides more flexibility for boards and subsystems that need it.
config EVENT_DEBUG
@@ -865,7 +874,7 @@
config UPDATE_TFTP
bool "Auto-update using fitImage via TFTP"
- depends on FIT
+ depends on FIT && OF_LIBFDT && !MTD_NOR_FLASH
select UPDATE_COMMON
help
This option allows performing update of NOR with data in fitImage
@@ -874,16 +883,24 @@
config UPDATE_TFTP_CNT_MAX
int "The number of connection retries during auto-update"
default 0
- depends on UPDATE_TFTP
+ depends on UPDATE_TFTP || DFU_TFTP
config UPDATE_TFTP_MSEC_MAX
int "Delay in mSec to wait for the TFTP server during auto-update"
default 100
- depends on UPDATE_TFTP
+ depends on UPDATE_TFTP || DFU_TFTP
+
+config UPDATE_LOAD_ADDR
+ hex "Address in memory to load the update to"
+ depends on UPDATE_TFTP || DFU_TFTP
+ default 0x100000
+ help
+ This option defines the location in memory to be used to load the
+ update to, if 'loadaddr' is not set in the environment.
config UPDATE_FIT
bool "Firmware update using fitImage"
- depends on FIT
+ depends on FIT && OF_LIBFDT
depends on DFU
select UPDATE_COMMON
help
@@ -1089,3 +1106,15 @@
config IO_TRACE
bool
+
+config USB_HUB_DEBOUNCE_TIMEOUT
+ int "Timeout in milliseconds for USB HUB connection"
+ depends on USB
+ default 1000
+ help
+ Value in milliseconds of the USB connection timeout, the max delay to
+ wait the hub port status to be connected steadily after being powered
+ off and powered on in the usb hub driver.
+ This define allows to increase the HUB_DEBOUNCE_TIMEOUT default
+ value = 1s because some usb device needs around 1.5s to be initialized
+ and a 2s value should solve detection issue on problematic USB keys.
diff --git a/common/Makefile b/common/Makefile
index 20addfb..252e965 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -26,6 +26,7 @@
obj-$(CONFIG_USB_HOST) += usb.o usb_hub.o
obj-$(CONFIG_USB_GADGET) += usb.o usb_hub.o
obj-$(CONFIG_USB_STORAGE) += usb_storage.o
+obj-$(CONFIG_USB_ONBOARD_HUB) += usb_onboard_hub.o
# others
obj-$(CONFIG_CONSOLE_MUX) += iomux.o
@@ -38,7 +39,7 @@
obj-$(CONFIG_MENU) += menu.o
obj-$(CONFIG_UPDATE_COMMON) += update.o
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
-obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o
+obj-$(CONFIG_CMDLINE) += cli_getch.o cli_readline.o cli_simple.o
endif # !CONFIG_SPL_BUILD
@@ -93,8 +94,8 @@
endif
obj-y += cli.o
-obj-$(CONFIG_FSL_DDR_INTERACTIVE) += cli_simple.o cli_readline.o
-obj-$(CONFIG_STM32MP1_DDR_INTERACTIVE) += cli_simple.o cli_readline.o
+obj-$(CONFIG_FSL_DDR_INTERACTIVE) += cli_getch.o cli_simple.o cli_readline.o
+obj-$(CONFIG_STM32MP1_DDR_INTERACTIVE) += cli_getch.o cli_simple.o cli_readline.o
obj-$(CONFIG_DFU_OVER_USB) += dfu.o
obj-y += command.o
obj-$(CONFIG_$(SPL_TPL_)LOG) += log.o
diff --git a/common/autoboot.c b/common/autoboot.c
index ea44fdf..5d33199 100644
--- a/common/autoboot.c
+++ b/common/autoboot.c
@@ -40,11 +40,15 @@
static int stored_bootdelay;
static int menukey;
-#if !defined(CONFIG_AUTOBOOT_STOP_STR_CRYPT)
-#define CONFIG_AUTOBOOT_STOP_STR_CRYPT ""
+#if defined(CONFIG_AUTOBOOT_STOP_STR_CRYPT)
+#define AUTOBOOT_STOP_STR_CRYPT CONFIG_AUTOBOOT_STOP_STR_CRYPT
+#else
+#define AUTOBOOT_STOP_STR_CRYPT ""
#endif
-#if !defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
-#define CONFIG_AUTOBOOT_STOP_STR_SHA256 ""
+#if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
+#define AUTOBOOT_STOP_STR_SHA256 CONFIG_AUTOBOOT_STOP_STR_SHA256
+#else
+#define AUTOBOOT_STOP_STR_SHA256 ""
#endif
#ifdef CONFIG_AUTOBOOT_USE_MENUKEY
@@ -81,7 +85,7 @@
int err;
if (IS_ENABLED(CONFIG_AUTOBOOT_STOP_STR_ENABLE) && !crypt_env_str)
- crypt_env_str = CONFIG_AUTOBOOT_STOP_STR_CRYPT;
+ crypt_env_str = AUTOBOOT_STOP_STR_CRYPT;
if (!crypt_env_str)
return 0;
@@ -160,7 +164,7 @@
int ret;
if (sha_env_str == NULL)
- sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256;
+ sha_env_str = AUTOBOOT_STOP_STR_SHA256;
presskey = malloc_cache_aligned(DELAY_STOP_STR_MAX_LENGTH);
c = strstr(sha_env_str, ":");
@@ -422,7 +426,7 @@
return abort;
}
-static void process_fdt_options(const void *blob)
+static void process_fdt_options(void)
{
#ifdef CONFIG_TEXT_BASE
ulong addr;
@@ -474,7 +478,7 @@
s = env_get("bootcmd");
if (IS_ENABLED(CONFIG_OF_CONTROL))
- process_fdt_options(gd->fdt_blob);
+ process_fdt_options();
stored_bootdelay = bootdelay;
return s;
diff --git a/common/board_r.c b/common/board_r.c
index 42060ee..3618aca 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -756,9 +756,6 @@
initr_status_led,
#endif
/* PPC has a udelay(20) here dating from 2002. Why? */
-#if defined(CONFIG_GPIO_HOG)
- gpio_hog_probe_all,
-#endif
#ifdef CONFIG_BOARD_LATE_INIT
board_late_init,
#endif
diff --git a/common/cli.c b/common/cli.c
index a47d6a3..ba45dad 100644
--- a/common/cli.c
+++ b/common/cli.c
@@ -146,7 +146,7 @@
#if defined(CONFIG_CMD_RUN)
int do_run(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
- int i;
+ int i, ret;
if (argc < 2)
return CMD_RET_USAGE;
@@ -160,8 +160,9 @@
return 1;
}
- if (run_command(arg, flag | CMD_FLAG_ENV) != 0)
- return 1;
+ ret = run_command(arg, flag | CMD_FLAG_ENV);
+ if (ret)
+ return ret;
}
return 0;
}
diff --git a/common/cli_getch.c b/common/cli_getch.c
new file mode 100644
index 0000000..87c23ed
--- /dev/null
+++ b/common/cli_getch.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright 2022 Google LLC
+ */
+
+#include <common.h>
+#include <cli.h>
+
+/**
+ * enum cli_esc_state_t - indicates what to do with an escape character
+ *
+ * @ESC_REJECT: Invalid escape sequence, so the esc_save[] characters are
+ * returned from each subsequent call to cli_ch_esc()
+ * @ESC_SAVE: Character should be saved in esc_save until we have another one
+ * @ESC_CONVERTED: Escape sequence has been completed and the resulting
+ * character is available
+ */
+enum cli_esc_state_t {
+ ESC_REJECT,
+ ESC_SAVE,
+ ESC_CONVERTED
+};
+
+void cli_ch_init(struct cli_ch_state *cch)
+{
+ memset(cch, '\0', sizeof(*cch));
+}
+
+/**
+ * cli_ch_esc() - Process a character in an ongoing escape sequence
+ *
+ * @cch: State information
+ * @ichar: Character to process
+ * @actp: Returns the action to take
+ * Returns: Output character if *actp is ESC_CONVERTED, else 0
+ */
+static int cli_ch_esc(struct cli_ch_state *cch, int ichar,
+ enum cli_esc_state_t *actp)
+{
+ enum cli_esc_state_t act = ESC_REJECT;
+
+ switch (cch->esc_len) {
+ case 1:
+ if (ichar == '[' || ichar == 'O')
+ act = ESC_SAVE;
+ break;
+ case 2:
+ switch (ichar) {
+ case 'D': /* <- key */
+ ichar = CTL_CH('b');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^B handler */
+ case 'C': /* -> key */
+ ichar = CTL_CH('f');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^F handler */
+ case 'H': /* Home key */
+ ichar = CTL_CH('a');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^A handler */
+ case 'F': /* End key */
+ ichar = CTL_CH('e');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^E handler */
+ case 'A': /* up arrow */
+ ichar = CTL_CH('p');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^P handler */
+ case 'B': /* down arrow */
+ ichar = CTL_CH('n');
+ act = ESC_CONVERTED;
+ break; /* pass off to ^N handler */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '7':
+ case '8':
+ if (cch->esc_save[1] == '[') {
+ /* see if next character is ~ */
+ act = ESC_SAVE;
+ }
+ break;
+ }
+ break;
+ case 3:
+ switch (ichar) {
+ case '~':
+ switch (cch->esc_save[2]) {
+ case '3': /* Delete key */
+ ichar = CTL_CH('d');
+ act = ESC_CONVERTED;
+ break; /* pass to ^D handler */
+ case '1': /* Home key */
+ case '7':
+ ichar = CTL_CH('a');
+ act = ESC_CONVERTED;
+ break; /* pass to ^A handler */
+ case '4': /* End key */
+ case '8':
+ ichar = CTL_CH('e');
+ act = ESC_CONVERTED;
+ break; /* pass to ^E handler */
+ }
+ break;
+ case '0':
+ if (cch->esc_save[2] == '2')
+ act = ESC_SAVE;
+ break;
+ }
+ break;
+ case 4:
+ switch (ichar) {
+ case '0':
+ case '1':
+ act = ESC_SAVE;
+ break; /* bracketed paste */
+ }
+ break;
+ case 5:
+ if (ichar == '~') { /* bracketed paste */
+ ichar = 0;
+ act = ESC_CONVERTED;
+ }
+ }
+
+ *actp = act;
+
+ return act == ESC_CONVERTED ? ichar : 0;
+}
+
+int cli_ch_process(struct cli_ch_state *cch, int ichar)
+{
+ /*
+ * ichar=0x0 when error occurs in U-Boot getchar() or when the caller
+ * wants to check if there are more characters saved in the escape
+ * sequence
+ */
+ if (!ichar) {
+ if (cch->emitting) {
+ if (cch->emit_upto < cch->esc_len)
+ return cch->esc_save[cch->emit_upto++];
+ cch->emit_upto = 0;
+ cch->emitting = false;
+ }
+ return 0;
+ } else if (ichar == -ETIMEDOUT) {
+ /*
+ * If we are in an escape sequence but nothing has followed the
+ * Escape character, then the user probably just pressed the
+ * Escape key. Return it and clear the sequence.
+ */
+ if (cch->esc_len) {
+ cch->esc_len = 0;
+ return '\e';
+ }
+
+ /* Otherwise there is nothing to return */
+ return 0;
+ }
+
+ if (ichar == '\n' || ichar == '\r')
+ return '\n';
+
+ /* handle standard linux xterm esc sequences for arrow key, etc. */
+ if (cch->esc_len != 0) {
+ enum cli_esc_state_t act;
+
+ ichar = cli_ch_esc(cch, ichar, &act);
+
+ switch (act) {
+ case ESC_SAVE:
+ /* save this character and return nothing */
+ cch->esc_save[cch->esc_len++] = ichar;
+ ichar = 0;
+ break;
+ case ESC_REJECT:
+ /*
+ * invalid escape sequence, start returning the
+ * characters in it
+ */
+ cch->esc_save[cch->esc_len++] = ichar;
+ ichar = cch->esc_save[cch->emit_upto++];
+ cch->emitting = true;
+ break;
+ case ESC_CONVERTED:
+ /* valid escape sequence, return the resulting char */
+ cch->esc_len = 0;
+ break;
+ }
+ }
+
+ if (ichar == '\e') {
+ if (!cch->esc_len) {
+ cch->esc_save[cch->esc_len] = ichar;
+ cch->esc_len = 1;
+ } else {
+ puts("impossible condition #876\n");
+ cch->esc_len = 0;
+ }
+ return 0;
+ }
+
+ return ichar;
+}
diff --git a/common/cli_hush.c b/common/cli_hush.c
index a80b847..1ad7a50 100644
--- a/common/cli_hush.c
+++ b/common/cli_hush.c
@@ -1901,7 +1901,7 @@
last_return_code = -rcode - 2;
return -2; /* exit */
}
- last_return_code=(rcode == 0) ? 0 : 1;
+ last_return_code = rcode;
#endif
#ifndef __U_BOOT__
pi->num_progs = save_num_progs; /* restore number of programs */
@@ -3211,7 +3211,15 @@
printf("exit not allowed from main input shell.\n");
continue;
}
- break;
+ /*
+ * DANGER
+ * Return code -2 is special in this context,
+ * it indicates exit from inner pipe instead
+ * of return code itself, the return code is
+ * stored in 'last_return_code' variable!
+ * DANGER
+ */
+ return -2;
}
if (code == -1)
flag_repeat = 0;
@@ -3248,9 +3256,9 @@
#endif /* __U_BOOT__ */
{
struct in_str input;
+ int rcode;
#ifdef __U_BOOT__
char *p = NULL;
- int rcode;
if (!s)
return 1;
if (!*s)
@@ -3262,11 +3270,12 @@
setup_string_in_str(&input, p);
rcode = parse_stream_outer(&input, flag);
free(p);
- return rcode;
+ return rcode == -2 ? last_return_code : rcode;
} else {
#endif
setup_string_in_str(&input, s);
- return parse_stream_outer(&input, flag);
+ rcode = parse_stream_outer(&input, flag);
+ return rcode == -2 ? last_return_code : rcode;
#ifdef __U_BOOT__
}
#endif
@@ -3286,7 +3295,7 @@
setup_file_in_str(&input);
#endif
rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON);
- return rcode;
+ return rcode == -2 ? last_return_code : rcode;
}
#ifdef __U_BOOT__
diff --git a/common/cli_readline.c b/common/cli_readline.c
index d6444f5..709e9c3 100644
--- a/common/cli_readline.c
+++ b/common/cli_readline.c
@@ -62,7 +62,6 @@
#define putnstr(str, n) printf("%.*s", (int)n, str)
-#define CTL_CH(c) ((c) - 'a' + 1)
#define CTL_BACKSPACE ('\b')
#define DEL ((char)255)
#define DEL7 ((char)127)
@@ -252,156 +251,53 @@
static int cread_line(const char *const prompt, char *buf, unsigned int *len,
int timeout)
{
+ struct cli_ch_state s_cch, *cch = &s_cch;
unsigned long num = 0;
unsigned long eol_num = 0;
unsigned long wlen;
char ichar;
int insert = 1;
- int esc_len = 0;
- char esc_save[8];
int init_len = strlen(buf);
int first = 1;
+ cli_ch_init(cch);
+
if (init_len)
cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
while (1) {
- if (bootretry_tstc_timeout())
- return -2; /* timed out */
- if (first && timeout) {
- uint64_t etime = endtick(timeout);
+ /* Check for saved characters */
+ ichar = cli_ch_process(cch, 0);
- while (!tstc()) { /* while no incoming data */
- if (get_ticks() >= etime)
- return -2; /* timed out */
- schedule();
+ if (!ichar) {
+ if (bootretry_tstc_timeout())
+ return -2; /* timed out */
+ if (first && timeout) {
+ u64 etime = endtick(timeout);
+
+ while (!tstc()) { /* while no incoming data */
+ if (get_ticks() >= etime)
+ return -2; /* timed out */
+ schedule();
+ }
+ first = 0;
}
- first = 0;
+
+ ichar = getcmd_getch();
}
- ichar = getcmd_getch();
+ ichar = cli_ch_process(cch, ichar);
/* ichar=0x0 when error occurs in U-Boot getc */
if (!ichar)
continue;
- if ((ichar == '\n') || (ichar == '\r')) {
+ if (ichar == '\n') {
putc('\n');
break;
}
- /*
- * handle standard linux xterm esc sequences for arrow key, etc.
- */
- if (esc_len != 0) {
- enum { ESC_REJECT, ESC_SAVE, ESC_CONVERTED } act = ESC_REJECT;
-
- if (esc_len == 1) {
- if (ichar == '[' || ichar == 'O')
- act = ESC_SAVE;
- } else if (esc_len == 2) {
- switch (ichar) {
- case 'D': /* <- key */
- ichar = CTL_CH('b');
- act = ESC_CONVERTED;
- break; /* pass off to ^B handler */
- case 'C': /* -> key */
- ichar = CTL_CH('f');
- act = ESC_CONVERTED;
- break; /* pass off to ^F handler */
- case 'H': /* Home key */
- ichar = CTL_CH('a');
- act = ESC_CONVERTED;
- break; /* pass off to ^A handler */
- case 'F': /* End key */
- ichar = CTL_CH('e');
- act = ESC_CONVERTED;
- break; /* pass off to ^E handler */
- case 'A': /* up arrow */
- ichar = CTL_CH('p');
- act = ESC_CONVERTED;
- break; /* pass off to ^P handler */
- case 'B': /* down arrow */
- ichar = CTL_CH('n');
- act = ESC_CONVERTED;
- break; /* pass off to ^N handler */
- case '1':
- case '2':
- case '3':
- case '4':
- case '7':
- case '8':
- if (esc_save[1] == '[') {
- /* see if next character is ~ */
- act = ESC_SAVE;
- }
- break;
- }
- } else if (esc_len == 3) {
- switch (ichar) {
- case '~':
- switch (esc_save[2]) {
- case '3': /* Delete key */
- ichar = CTL_CH('d');
- act = ESC_CONVERTED;
- break; /* pass to ^D handler */
- case '1': /* Home key */
- case '7':
- ichar = CTL_CH('a');
- act = ESC_CONVERTED;
- break; /* pass to ^A handler */
- case '4': /* End key */
- case '8':
- ichar = CTL_CH('e');
- act = ESC_CONVERTED;
- break; /* pass to ^E handler */
- }
- break;
- case '0':
- if (esc_save[2] == '2')
- act = ESC_SAVE;
- break;
- }
- } else if (esc_len == 4) {
- switch (ichar) {
- case '0':
- case '1':
- act = ESC_SAVE;
- break; /* bracketed paste */
- }
- } else if (esc_len == 5) {
- if (ichar == '~') { /* bracketed paste */
- ichar = 0;
- act = ESC_CONVERTED;
- }
- }
- switch (act) {
- case ESC_SAVE:
- esc_save[esc_len++] = ichar;
- continue;
- case ESC_REJECT:
- esc_save[esc_len++] = ichar;
- cread_add_str(esc_save, esc_len, insert,
- &num, &eol_num, buf, *len);
- esc_len = 0;
- continue;
- case ESC_CONVERTED:
- esc_len = 0;
- break;
- }
- }
-
switch (ichar) {
- case 0x1b:
- if (esc_len == 0) {
- esc_save[esc_len] = ichar;
- esc_len = 1;
- } else {
- puts("impossible condition #876\n");
- esc_len = 0;
- }
- break;
-
case CTL_CH('a'):
BEGINNING_OF_LINE();
break;
@@ -470,8 +366,6 @@
{
char *hline;
- esc_len = 0;
-
if (ichar == CTL_CH('p'))
hline = hist_prev();
else
diff --git a/common/command.c b/common/command.c
index 41c91c6..846e16e 100644
--- a/common/command.c
+++ b/common/command.c
@@ -13,7 +13,9 @@
#include <command.h>
#include <console.h>
#include <env.h>
+#include <image.h>
#include <log.h>
+#include <mapmem.h>
#include <asm/global_data.h>
#include <linux/ctype.h>
@@ -66,7 +68,7 @@
return 1;
if (usage == NULL)
continue;
- printf("%-*s- %s\n", CONFIG_SYS_HELP_CMD_WIDTH,
+ printf("%-*s- %s\n", CFG_SYS_HELP_CMD_WIDTH,
cmd_array[i]->name, usage);
}
return 0;
@@ -654,3 +656,20 @@
return CMD_RET_SUCCESS;
}
+
+int cmd_source_script(ulong addr, const char *fit_uname, const char *confname)
+{
+ char *data;
+ void *buf;
+ uint len;
+ int ret;
+
+ buf = map_sysmem(addr, 0);
+ ret = image_locate_script(buf, 0, fit_uname, confname, &data, &len);
+ unmap_sysmem(buf);
+ if (ret)
+ return CMD_RET_FAILURE;
+
+ debug("** Script length: %d\n", len);
+ return run_command_list(data, len, 0);
+}
diff --git a/common/console.c b/common/console.c
index 10ab361..e4301a4 100644
--- a/common/console.c
+++ b/common/console.c
@@ -970,6 +970,11 @@
if (!IS_ENABLED(CONFIG_SILENT_CONSOLE))
return false;
+ if (IS_ENABLED(CONFIG_SILENT_CONSOLE_UNTIL_ENV) && !(gd->flags & GD_FLG_ENV_READY)) {
+ gd->flags |= GD_FLG_SILENT;
+ return false;
+ }
+
if (env_get("silent")) {
gd->flags |= GD_FLG_SILENT;
return false;
diff --git a/common/event.c b/common/event.c
index 231b9e6..c312556 100644
--- a/common/event.c
+++ b/common/event.c
@@ -123,7 +123,7 @@
ret = notify_static(&event);
if (ret)
- return log_msg_ret("dyn", ret);
+ return log_msg_ret("sta", ret);
if (CONFIG_IS_ENABLED(EVENT_DYNAMIC)) {
ret = notify_dynamic(&event);
diff --git a/common/menu.c b/common/menu.c
index 8fe0096..cdcdbb2 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -15,6 +15,8 @@
#include "menu.h"
+#define ansi 0
+
/*
* Internally, each item in a menu is represented by a struct menu_item.
*
@@ -425,15 +427,19 @@
return 1;
}
-void bootmenu_autoboot_loop(struct bootmenu_data *menu,
- enum bootmenu_key *key, int *esc)
+enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu,
+ struct cli_ch_state *cch)
{
+ enum bootmenu_key key = BKEY_NONE;
int i, c;
while (menu->delay > 0) {
- printf(ANSI_CURSOR_POSITION, menu->count + 5, 3);
+ if (ansi)
+ printf(ANSI_CURSOR_POSITION, menu->count + 5, 3);
printf("Hit any key to stop autoboot: %d ", menu->delay);
for (i = 0; i < 100; ++i) {
+ int ichar;
+
if (!tstc()) {
schedule();
mdelay(10);
@@ -443,22 +449,22 @@
menu->delay = -1;
c = getchar();
- switch (c) {
- case '\e':
- *esc = 1;
- *key = KEY_NONE;
+ ichar = cli_ch_process(cch, c);
+
+ switch (ichar) {
+ case '\0':
+ key = BKEY_NONE;
break;
- case '\r':
- *key = KEY_SELECT;
+ case '\n':
+ key = BKEY_SELECT;
break;
case 0x3: /* ^C */
- *key = KEY_QUIT;
+ key = BKEY_QUIT;
break;
default:
- *key = KEY_NONE;
+ key = BKEY_NONE;
break;
}
-
break;
}
@@ -468,93 +474,72 @@
--menu->delay;
}
- printf(ANSI_CURSOR_POSITION ANSI_CLEAR_LINE, menu->count + 5, 1);
+ if (ansi)
+ printf(ANSI_CURSOR_POSITION ANSI_CLEAR_LINE, menu->count + 5, 1);
if (menu->delay == 0)
- *key = KEY_SELECT;
+ key = BKEY_SELECT;
+
+ return key;
}
-void bootmenu_loop(struct bootmenu_data *menu,
- enum bootmenu_key *key, int *esc)
+enum bootmenu_key bootmenu_conv_key(int ichar)
{
+ enum bootmenu_key key;
+
+ switch (ichar) {
+ case '\n':
+ /* enter key was pressed */
+ key = BKEY_SELECT;
+ break;
+ case CTL_CH('c'):
+ case '\e':
+ /* ^C was pressed */
+ key = BKEY_QUIT;
+ break;
+ case CTL_CH('p'):
+ key = BKEY_UP;
+ break;
+ case CTL_CH('n'):
+ key = BKEY_DOWN;
+ break;
+ case '+':
+ key = BKEY_PLUS;
+ break;
+ case '-':
+ key = BKEY_MINUS;
+ break;
+ case ' ':
+ key = BKEY_SPACE;
+ break;
+ default:
+ key = BKEY_NONE;
+ break;
+ }
+
+ return key;
+}
+
+enum bootmenu_key bootmenu_loop(struct bootmenu_data *menu,
+ struct cli_ch_state *cch)
+{
+ enum bootmenu_key key;
int c;
- if (*esc == 1) {
- if (tstc()) {
+ c = cli_ch_process(cch, 0);
+ if (!c) {
+ while (!c && !tstc()) {
+ schedule();
+ mdelay(10);
+ c = cli_ch_process(cch, -ETIMEDOUT);
+ }
+ if (!c) {
c = getchar();
- } else {
- schedule();
- mdelay(10);
- if (tstc())
- c = getchar();
- else
- c = '\e';
+ c = cli_ch_process(cch, c);
}
- } else {
- while (!tstc()) {
- schedule();
- mdelay(10);
- }
- c = getchar();
}
- switch (*esc) {
- case 0:
- /* First char of ANSI escape sequence '\e' */
- if (c == '\e') {
- *esc = 1;
- *key = KEY_NONE;
- }
- break;
- case 1:
- /* Second char of ANSI '[' */
- if (c == '[') {
- *esc = 2;
- *key = KEY_NONE;
- } else {
- /* Alone ESC key was pressed */
- *key = KEY_QUIT;
- *esc = (c == '\e') ? 1 : 0;
- }
- break;
- case 2:
- case 3:
- /* Third char of ANSI (number '1') - optional */
- if (*esc == 2 && c == '1') {
- *esc = 3;
- *key = KEY_NONE;
- break;
- }
+ key = bootmenu_conv_key(c);
- *esc = 0;
-
- /* ANSI 'A' - key up was pressed */
- if (c == 'A')
- *key = KEY_UP;
- /* ANSI 'B' - key down was pressed */
- else if (c == 'B')
- *key = KEY_DOWN;
- /* other key was pressed */
- else
- *key = KEY_NONE;
-
- break;
- }
-
- /* enter key was pressed */
- if (c == '\r')
- *key = KEY_SELECT;
-
- /* ^C was pressed */
- if (c == 0x3)
- *key = KEY_QUIT;
-
- if (c == '+')
- *key = KEY_PLUS;
-
- if (c == '-')
- *key = KEY_MINUS;
-
- if (c == ' ')
- *key = KEY_SPACE;
+ return key;
}
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index a25d8fd..3c2af45 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -385,6 +385,7 @@
config SPL_STACK_R_MALLOC_SIMPLE_LEN
depends on SPL_STACK_R && SPL_SYS_MALLOC_SIMPLE
hex "Size of malloc_simple heap after switching to DRAM SPL stack"
+ default 0x400000 if ARCH_K3 && ARM64
default 0x100000
help
Specify the amount of the stack to use as memory pool for
diff --git a/common/spl/Kconfig.tpl b/common/spl/Kconfig.tpl
index e314b79..1874f9d 100644
--- a/common/spl/Kconfig.tpl
+++ b/common/spl/Kconfig.tpl
@@ -132,7 +132,7 @@
config TPL_MAX_SIZE
hex "Maximum size (in bytes) for the TPL stage"
default 0x2e000 if ROCKCHIP_RK3399
- default 0x8000 if ROCKCHIP_RK3288
+ default 0x8000 if ROCKCHIP_RK3288 || ROCKCHIP_RV1126
default 0x7000 if ROCKCHIP_RK322X || ROCKCHIP_RK3328 || ROCKCHIP_RK3368
default 0x2800 if ROCKCHIP_PX30
default 0x0
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 4668367..a630e79 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -786,9 +786,6 @@
}
}
- if (CONFIG_IS_ENABLED(GPIO_HOG))
- gpio_hog_probe_all();
-
#if CONFIG_IS_ENABLED(BOARD_INIT)
spl_board_init();
#endif
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 08da7fe..9ae3e5e 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -20,14 +20,6 @@
DECLARE_GLOBAL_DATA_PTR;
-#ifndef CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ
-#define CONFIG_SPL_LOAD_FIT_APPLY_OVERLAY_BUF_SZ (64 * 1024)
-#endif
-
-#ifndef CONFIG_SYS_BOOTM_LEN
-#define CONFIG_SYS_BOOTM_LEN (64 << 20)
-#endif
-
struct spl_fit_info {
const void *fit; /* Pointer to a valid FIT blob */
size_t ext_data_offset; /* Offset to FIT external data (end of FIT) */
@@ -408,7 +400,7 @@
if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY))
return 0;
- if (CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)) {
+#if CONFIG_IS_ENABLED(LOAD_FIT_APPLY_OVERLAY)
void *tmpbuffer = NULL;
for (; ; index++) {
@@ -462,7 +454,7 @@
free(tmpbuffer);
if (ret)
return ret;
- }
+#endif
/* Try to make space, so we can inject details on the loadables */
ret = fdt_shrink_to_minimum(spl_image->fdt_addr, 8192);
if (ret < 0)
@@ -599,6 +591,7 @@
debug("Ignoring compatible = %s property\n",
compatible);
}
+ return 0;
ret = fpga_load(devnum, (void *)fpga_image->load_addr,
fpga_image->size, BIT_FULL, flags);
diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c
index 5753bd2..8139a20 100644
--- a/common/spl/spl_ram.c
+++ b/common/spl/spl_ram.c
@@ -38,12 +38,13 @@
struct spl_boot_device *bootdev)
{
struct legacy_img_hdr *header;
+ int ret;
header = (struct legacy_img_hdr *)CONFIG_SPL_LOAD_FIT_ADDRESS;
if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) {
unsigned long addr = (unsigned long)header;
- int ret = image_pre_load(addr);
+ ret = image_pre_load(addr);
if (ret)
return ret;
@@ -64,7 +65,7 @@
debug("Found FIT\n");
load.bl_len = 1;
load.read = spl_ram_load_read;
- spl_load_simple_fit(spl_image, &load, 0, header);
+ ret = spl_load_simple_fit(spl_image, &load, 0, header);
} else {
ulong u_boot_pos = spl_get_image_pos();
@@ -85,10 +86,10 @@
}
header = (struct legacy_img_hdr *)map_sysmem(u_boot_pos, 0);
- spl_parse_image_header(spl_image, bootdev, header);
+ ret = spl_parse_image_header(spl_image, bootdev, header);
}
- return 0;
+ return ret;
}
#if CONFIG_IS_ENABLED(RAM_DEVICE)
SPL_LOAD_IMAGE_METHOD("RAM", 0, BOOT_DEVICE_RAM, spl_ram_load_image);
diff --git a/common/spl/spl_sata.c b/common/spl/spl_sata.c
index 12397f0..32746ce 100644
--- a/common/spl/spl_sata.c
+++ b/common/spl/spl_sata.c
@@ -17,11 +17,6 @@
#include <fat.h>
#include <image.h>
-#ifndef CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR
-/* Dummy value to make the compiler happy */
-#define CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR 0x100
-#endif
-
static int spl_sata_load_image_raw(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
struct blk_desc *stor_dev, unsigned long sector)
@@ -62,7 +57,7 @@
static int spl_sata_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
- int err = 0;
+ int err = -ENOSYS;
struct blk_desc *stor_dev;
/* try to recognize storage devices immediately */
@@ -77,16 +72,14 @@
CONFIG_SYS_SATA_FAT_BOOT_PARTITION))
#endif
{
- err = -ENOSYS;
-
- if (IS_ENABLED(CONFIG_SPL_FS_FAT)) {
- err = spl_load_image_fat(spl_image, bootdev, stor_dev,
- CONFIG_SYS_SATA_FAT_BOOT_PARTITION,
- CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
- } else if (IS_ENABLED(CONFIG_SPL_SATA_RAW_U_BOOT_USE_SECTOR)) {
- err = spl_sata_load_image_raw(spl_image, bootdev, stor_dev,
- CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR);
- }
+#ifdef CONFIG_SPL_FS_FAT
+ err = spl_load_image_fat(spl_image, bootdev, stor_dev,
+ CONFIG_SYS_SATA_FAT_BOOT_PARTITION,
+ CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
+#elif defined(CONFIG_SPL_SATA_RAW_U_BOOT_USE_SECTOR)
+ err = spl_sata_load_image_raw(spl_image, bootdev, stor_dev,
+ CONFIG_SPL_SATA_RAW_U_BOOT_SECTOR);
+#endif
}
if (err) {
puts("Error loading sata device\n");
diff --git a/common/update.c b/common/update.c
index 80f16af..3502713 100644
--- a/common/update.c
+++ b/common/update.c
@@ -10,14 +10,6 @@
#include <cpu_func.h>
#include <image.h>
-#if !(defined(CONFIG_FIT) && defined(CONFIG_OF_LIBFDT))
-#error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature"
-#endif
-
-#if defined(CONFIG_UPDATE_TFTP) && !defined(CONFIG_MTD_NOR_FLASH)
-#error "CONFIG_UPDATE_TFTP and !CONFIG_MTD_NOR_FLASH needed for legacy behaviour"
-#endif
-
#include <command.h>
#include <env.h>
#include <net.h>
@@ -31,19 +23,6 @@
/* env variable holding the location of the update file */
#define UPDATE_FILE_ENV "updatefile"
-/* set configuration defaults if needed */
-#ifndef CONFIG_UPDATE_LOAD_ADDR
-#define CONFIG_UPDATE_LOAD_ADDR 0x100000
-#endif
-
-#ifndef CONFIG_UPDATE_TFTP_MSEC_MAX
-#define CONFIG_UPDATE_TFTP_MSEC_MAX 100
-#endif
-
-#ifndef CONFIG_UPDATE_TFTP_CNT_MAX
-#define CONFIG_UPDATE_TFTP_CNT_MAX 0
-#endif
-
extern ulong tftp_timeout_ms;
extern int tftp_timeout_count_max;
#ifdef CONFIG_MTD_NOR_FLASH
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 95f1449..f7fd12c 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -47,7 +47,7 @@
#define HUB_SHORT_RESET_TIME 20
#define HUB_LONG_RESET_TIME 200
-#define HUB_DEBOUNCE_TIMEOUT 1000
+#define HUB_DEBOUNCE_TIMEOUT CONFIG_USB_HUB_DEBOUNCE_TIMEOUT
#define PORT_OVERCURRENT_MAX_SCAN_COUNT 3
diff --git a/common/usb_onboard_hub.c b/common/usb_onboard_hub.c
new file mode 100644
index 0000000..89e18a2
--- /dev/null
+++ b/common/usb_onboard_hub.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for onboard USB hubs
+ *
+ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
+ *
+ * Mostly inspired by Linux kernel v6.1 onboard_usb_hub driver
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <power/regulator.h>
+
+struct onboard_hub {
+ struct udevice *vdd;
+};
+
+static int usb_onboard_hub_probe(struct udevice *dev)
+{
+ struct onboard_hub *hub = dev_get_priv(dev);
+ int ret;
+
+ ret = device_get_supply_regulator(dev, "vdd-supply", &hub->vdd);
+ if (ret) {
+ dev_err(dev, "can't get vdd-supply: %d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_set_enable_if_allowed(hub->vdd, true);
+ if (ret)
+ dev_err(dev, "can't enable vdd-supply: %d\n", ret);
+
+ return ret;
+}
+
+static int usb_onboard_hub_remove(struct udevice *dev)
+{
+ struct onboard_hub *hub = dev_get_priv(dev);
+ int ret;
+
+ ret = regulator_set_enable_if_allowed(hub->vdd, false);
+ if (ret)
+ dev_err(dev, "can't disable vdd-supply: %d\n", ret);
+
+ return ret;
+}
+
+static const struct udevice_id usb_onboard_hub_ids[] = {
+ /* Use generic usbVID,PID dt-bindings (usb-device.yaml) */
+ { .compatible = "usb424,2514" }, /* USB2514B USB 2.0 */
+ { }
+};
+
+U_BOOT_DRIVER(usb_onboard_hub) = {
+ .name = "usb_onboard_hub",
+ .id = UCLASS_USB_HUB,
+ .probe = usb_onboard_hub_probe,
+ .remove = usb_onboard_hub_remove,
+ .of_match = usb_onboard_hub_ids,
+ .priv_auto = sizeof(struct onboard_hub),
+};
diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index 6727932..df4fdfa 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -6,7 +6,6 @@
CONFIG_DRAM_CLK=480
CONFIG_DRAM_EMR1=4
CONFIG_SYS_CLK_FREQ=912000000
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_I2C1_ENABLE=y
CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
diff --git a/configs/A10s-OLinuXino-M_defconfig b/configs/A10s-OLinuXino-M_defconfig
index d1e3b05..841fe0d 100644
--- a/configs/A10s-OLinuXino-M_defconfig
+++ b/configs/A10s-OLinuXino-M_defconfig
@@ -4,8 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=432
-CONFIG_MMC0_CD_PIN="PG1"
-CONFIG_MMC1_CD_PIN="PG13"
CONFIG_MMC_SUNXI_SLOT_EXTRA=1
CONFIG_USB1_VBUS_PIN="PB10"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/A13-OLinuXinoM_defconfig b/configs/A13-OLinuXinoM_defconfig
index f9d17b1..befe6d8 100644
--- a/configs/A13-OLinuXinoM_defconfig
+++ b/configs/A13-OLinuXinoM_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=408
CONFIG_DRAM_EMR1=0
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB1_VBUS_PIN="PG11"
# CONFIG_VIDEO_HDMI is not set
CONFIG_VIDEO_VGA_VIA_LCD=y
diff --git a/configs/A13-OLinuXino_defconfig b/configs/A13-OLinuXino_defconfig
index 8c90435..689ea53 100644
--- a/configs/A13-OLinuXino_defconfig
+++ b/configs/A13-OLinuXino_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=408
CONFIG_DRAM_EMR1=0
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB0_VBUS_DET="PG1"
CONFIG_USB1_VBUS_PIN="PG11"
CONFIG_AXP_GPIO=y
diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
index bccadcc..be49e93 100644
--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index 0a9de5e..43cd28c 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 38daf33..7c77f38 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_I2C1_ENABLE=y
CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
index d73e64c..0211699 100644
--- a/configs/A20-OLinuXino_MICRO-eMMC_defconfig
+++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_I2C1_ENABLE=y
CONFIG_VIDEO_VGA=y
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index 8a6bb88..895e8db 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -4,8 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
-CONFIG_MMC3_CD_PIN="PH11"
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_I2C1_ENABLE=y
CONFIG_VIDEO_VGA=y
diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig
index 5de6c2d..5bcc9f9 100644
--- a/configs/A20-Olimex-SOM-EVB_defconfig
+++ b/configs/A20-Olimex-SOM-EVB_defconfig
@@ -4,8 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
-CONFIG_MMC3_CD_PIN="PH0"
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="PH5"
diff --git a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
index 6e9bdc2..e588109 100644
--- a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
index e051745..592a79a 100644
--- a/configs/A20-Olimex-SOM204-EVB_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
diff --git a/configs/A33-OLinuXino_defconfig b/configs/A33-OLinuXino_defconfig
index 351a454..fc32a86 100644
--- a/configs/A33-OLinuXino_defconfig
+++ b/configs/A33-OLinuXino_defconfig
@@ -6,7 +6,6 @@
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=15291
CONFIG_DRAM_ODT_EN=y
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PB3"
diff --git a/configs/Ainol_AW1_defconfig b/configs/Ainol_AW1_defconfig
index 9a18af8..9ae3893 100644
--- a/configs/Ainol_AW1_defconfig
+++ b/configs/Ainol_AW1_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=123
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_AXP_GPIO=y
diff --git a/configs/Ampe_A76_defconfig b/configs/Ampe_A76_defconfig
index 7bf3dfc..1087512 100644
--- a/configs/Ampe_A76_defconfig
+++ b/configs/Ampe_A76_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=432
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB0_VBUS_PIN="PG12"
CONFIG_USB0_VBUS_DET="PG1"
CONFIG_USB0_ID_DET="PG2"
diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig
index 18ee81b..a5fe76a 100644
--- a/configs/Bananapi_M2_Ultra_defconfig
+++ b/configs/Bananapi_M2_Ultra_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_R40=y
CONFIG_DRAM_CLK=576
CONFIG_MACPWR="PA17"
-CONFIG_MMC0_CD_PIN="PH13"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB1_VBUS_PIN="PH23"
CONFIG_USB2_VBUS_PIN="PH23"
diff --git a/configs/Bananapi_m2m_defconfig b/configs/Bananapi_m2m_defconfig
index bad38a6..d26aa0b 100644
--- a/configs/Bananapi_m2m_defconfig
+++ b/configs/Bananapi_m2m_defconfig
@@ -6,7 +6,6 @@
CONFIG_DRAM_CLK=600
CONFIG_DRAM_ZQ=15291
CONFIG_DRAM_ODT_EN=y
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_ID_DET="PH8"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
index ab5e53f..0c23368 100644
--- a/configs/Cubieboard2_defconfig
+++ b/configs/Cubieboard2_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Cubieboard4_defconfig b/configs/Cubieboard4_defconfig
index 04ed79a..5eee23f 100644
--- a/configs/Cubieboard4_defconfig
+++ b/configs/Cubieboard4_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN9I=y
CONFIG_DRAM_CLK=672
-CONFIG_MMC0_CD_PIN="PH18"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
index c017b12..71743f7 100644
--- a/configs/Cubieboard_defconfig
+++ b/configs/Cubieboard_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
CONFIG_DRAM_CLK=480
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
index c85468e..184f305 100644
--- a/configs/Cubietruck_defconfig
+++ b/configs/Cubietruck_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_USB0_VBUS_PIN="PH17"
CONFIG_USB0_VBUS_DET="PH22"
CONFIG_USB0_ID_DET="PH19"
diff --git a/configs/Empire_electronix_d709_defconfig b/configs/Empire_electronix_d709_defconfig
index a9bbe8b..4bd3b56 100644
--- a/configs/Empire_electronix_d709_defconfig
+++ b/configs/Empire_electronix_d709_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_EMR1=0
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB0_VBUS_PIN="PG12"
CONFIG_USB0_VBUS_DET="PG1"
CONFIG_USB0_ID_DET="PG2"
diff --git a/configs/Empire_electronix_m712_defconfig b/configs/Empire_electronix_m712_defconfig
index fc1f26b..18873db 100644
--- a/configs/Empire_electronix_m712_defconfig
+++ b/configs/Empire_electronix_m712_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=408
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB0_VBUS_PIN="PG12"
CONFIG_USB0_VBUS_DET="PG1"
CONFIG_USB0_ID_DET="PG2"
diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
index 99df9cf..5d05f33 100644
--- a/configs/Itead_Ibox_A20_defconfig
+++ b/configs/Itead_Ibox_A20_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
index f97dc13..5294608 100644
--- a/configs/Lamobo_R1_defconfig
+++ b/configs/Lamobo_R1_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
CONFIG_MACPWR="PH23"
-CONFIG_MMC0_CD_PIN="PH10"
CONFIG_SATAPWR="PB3"
CONFIG_GMAC_TX_DELAY=4
CONFIG_AHCI=y
diff --git a/configs/Mele_M3_defconfig b/configs/Mele_M3_defconfig
index 77cb464..7b2d93c 100644
--- a/configs/Mele_M3_defconfig
+++ b/configs/Mele_M3_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_VIDEO_VGA=y
CONFIG_VIDEO_COMPOSITE=y
diff --git a/configs/Mele_M5_defconfig b/configs/Mele_M5_defconfig
index b07dbbd..90b181f 100644
--- a/configs/Mele_M5_defconfig
+++ b/configs/Mele_M5_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=122
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_VIDEO_COMPOSITE=y
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Merrii_A80_Optimus_defconfig b/configs/Merrii_A80_Optimus_defconfig
index c5d1f40..b9ccfcf 100644
--- a/configs/Merrii_A80_Optimus_defconfig
+++ b/configs/Merrii_A80_Optimus_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN9I=y
CONFIG_DRAM_CLK=672
-CONFIG_MMC0_CD_PIN="PH18"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
index 8757dcb..fe9ce80 100644
--- a/configs/Orangepi_mini_defconfig
+++ b/configs/Orangepi_mini_defconfig
@@ -5,8 +5,6 @@
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
CONFIG_MACPWR="PH23"
-CONFIG_MMC0_CD_PIN="PH10"
-CONFIG_MMC3_CD_PIN="PH11"
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_USB1_VBUS_PIN="PH26"
CONFIG_USB2_VBUS_PIN="PH22"
diff --git a/configs/P1010RDB-PA_36BIT_NAND_defconfig b/configs/P1010RDB-PA_36BIT_NAND_defconfig
index c12948a..e0ffb16 100644
--- a/configs/P1010RDB-PA_36BIT_NAND_defconfig
+++ b/configs/P1010RDB-PA_36BIT_NAND_defconfig
@@ -51,7 +51,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xd0034000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_DRIVERS_MISC=y
CONFIG_TPL_ENV_SUPPORT=y
diff --git a/configs/P1010RDB-PA_36BIT_SDCARD_defconfig b/configs/P1010RDB-PA_36BIT_SDCARD_defconfig
index e3b786d..0df2a55 100644
--- a/configs/P1010RDB-PA_36BIT_SDCARD_defconfig
+++ b/configs/P1010RDB-PA_36BIT_SDCARD_defconfig
@@ -48,7 +48,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig b/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig
index e6ce59e..086bfcb 100644
--- a/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig
+++ b/configs/P1010RDB-PA_36BIT_SPIFLASH_defconfig
@@ -50,7 +50,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1010RDB-PA_NAND_defconfig b/configs/P1010RDB-PA_NAND_defconfig
index 99b94a0..aa8aeda 100644
--- a/configs/P1010RDB-PA_NAND_defconfig
+++ b/configs/P1010RDB-PA_NAND_defconfig
@@ -50,7 +50,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xd0034000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_DRIVERS_MISC=y
CONFIG_TPL_ENV_SUPPORT=y
diff --git a/configs/P1010RDB-PA_SDCARD_defconfig b/configs/P1010RDB-PA_SDCARD_defconfig
index 9f2afcd..30ff3ad 100644
--- a/configs/P1010RDB-PA_SDCARD_defconfig
+++ b/configs/P1010RDB-PA_SDCARD_defconfig
@@ -47,7 +47,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1010RDB-PA_SPIFLASH_defconfig b/configs/P1010RDB-PA_SPIFLASH_defconfig
index 7c64fdc..d7d8219 100644
--- a/configs/P1010RDB-PA_SPIFLASH_defconfig
+++ b/configs/P1010RDB-PA_SPIFLASH_defconfig
@@ -49,7 +49,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1010RDB-PB_36BIT_NAND_defconfig b/configs/P1010RDB-PB_36BIT_NAND_defconfig
index 87953b8..6e05387 100644
--- a/configs/P1010RDB-PB_36BIT_NAND_defconfig
+++ b/configs/P1010RDB-PB_36BIT_NAND_defconfig
@@ -52,7 +52,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xd0034000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_DRIVERS_MISC=y
CONFIG_TPL_ENV_SUPPORT=y
diff --git a/configs/P1010RDB-PB_36BIT_SDCARD_defconfig b/configs/P1010RDB-PB_36BIT_SDCARD_defconfig
index 4dbf869..216e14c 100644
--- a/configs/P1010RDB-PB_36BIT_SDCARD_defconfig
+++ b/configs/P1010RDB-PB_36BIT_SDCARD_defconfig
@@ -49,7 +49,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig b/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig
index f5bcffb..35943d1 100644
--- a/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig
+++ b/configs/P1010RDB-PB_36BIT_SPIFLASH_defconfig
@@ -51,7 +51,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1010RDB-PB_NAND_defconfig b/configs/P1010RDB-PB_NAND_defconfig
index 82f29be..c2c851c 100644
--- a/configs/P1010RDB-PB_NAND_defconfig
+++ b/configs/P1010RDB-PB_NAND_defconfig
@@ -51,7 +51,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xd0034000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_DRIVERS_MISC=y
CONFIG_TPL_ENV_SUPPORT=y
diff --git a/configs/P1010RDB-PB_SDCARD_defconfig b/configs/P1010RDB-PB_SDCARD_defconfig
index 3dfb509..b8e0a92 100644
--- a/configs/P1010RDB-PB_SDCARD_defconfig
+++ b/configs/P1010RDB-PB_SDCARD_defconfig
@@ -48,7 +48,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1010RDB-PB_SPIFLASH_defconfig b/configs/P1010RDB-PB_SPIFLASH_defconfig
index f3d399f..f403e67 100644
--- a/configs/P1010RDB-PB_SPIFLASH_defconfig
+++ b/configs/P1010RDB-PB_SPIFLASH_defconfig
@@ -50,7 +50,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PBSIZE=276
CONFIG_CMD_IMLS=y
diff --git a/configs/P1020RDB-PC_36BIT_NAND_defconfig b/configs/P1020RDB-PC_36BIT_NAND_defconfig
index de04556..02f0f3c 100644
--- a/configs/P1020RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P1020RDB-PC_36BIT_NAND_defconfig
@@ -52,7 +52,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xf8fb4000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_ENV_SUPPORT=y
CONFIG_TPL_I2C=y
diff --git a/configs/P1020RDB-PC_36BIT_SDCARD_defconfig b/configs/P1020RDB-PC_36BIT_SDCARD_defconfig
index 2d201bf..84cc6bd 100644
--- a/configs/P1020RDB-PC_36BIT_SDCARD_defconfig
+++ b/configs/P1020RDB-PC_36BIT_SDCARD_defconfig
@@ -49,7 +49,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig b/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig
index a6b7a4a..427b67c 100644
--- a/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig
+++ b/configs/P1020RDB-PC_36BIT_SPIFLASH_defconfig
@@ -51,7 +51,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P1020RDB-PC_NAND_defconfig b/configs/P1020RDB-PC_NAND_defconfig
index cf47bd4..e1e6af7 100644
--- a/configs/P1020RDB-PC_NAND_defconfig
+++ b/configs/P1020RDB-PC_NAND_defconfig
@@ -51,7 +51,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xf8fb4000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_ENV_SUPPORT=y
CONFIG_TPL_I2C=y
diff --git a/configs/P1020RDB-PC_SDCARD_defconfig b/configs/P1020RDB-PC_SDCARD_defconfig
index 3a86a9e..d9477f1 100644
--- a/configs/P1020RDB-PC_SDCARD_defconfig
+++ b/configs/P1020RDB-PC_SDCARD_defconfig
@@ -48,7 +48,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P1020RDB-PC_SPIFLASH_defconfig b/configs/P1020RDB-PC_SPIFLASH_defconfig
index 9fe2b1d..f27c9c3 100644
--- a/configs/P1020RDB-PC_SPIFLASH_defconfig
+++ b/configs/P1020RDB-PC_SPIFLASH_defconfig
@@ -50,7 +50,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P1020RDB-PD_NAND_defconfig b/configs/P1020RDB-PD_NAND_defconfig
index 2f768c0..1d364fe 100644
--- a/configs/P1020RDB-PD_NAND_defconfig
+++ b/configs/P1020RDB-PD_NAND_defconfig
@@ -51,7 +51,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xf8fb4000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_ENV_SUPPORT=y
CONFIG_TPL_I2C=y
diff --git a/configs/P1020RDB-PD_SDCARD_defconfig b/configs/P1020RDB-PD_SDCARD_defconfig
index 6cb3be0..4dc2457 100644
--- a/configs/P1020RDB-PD_SDCARD_defconfig
+++ b/configs/P1020RDB-PD_SDCARD_defconfig
@@ -48,7 +48,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P1020RDB-PD_SPIFLASH_defconfig b/configs/P1020RDB-PD_SPIFLASH_defconfig
index 0eb2b3a..bf6d223 100644
--- a/configs/P1020RDB-PD_SPIFLASH_defconfig
+++ b/configs/P1020RDB-PD_SPIFLASH_defconfig
@@ -50,7 +50,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P2020RDB-PC_36BIT_NAND_defconfig b/configs/P2020RDB-PC_36BIT_NAND_defconfig
index c53c4c6..7646e90 100644
--- a/configs/P2020RDB-PC_36BIT_NAND_defconfig
+++ b/configs/P2020RDB-PC_36BIT_NAND_defconfig
@@ -52,7 +52,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xf8fb4000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_ENV_SUPPORT=y
CONFIG_TPL_I2C=y
diff --git a/configs/P2020RDB-PC_36BIT_SDCARD_defconfig b/configs/P2020RDB-PC_36BIT_SDCARD_defconfig
index 0ac7428..8151259 100644
--- a/configs/P2020RDB-PC_36BIT_SDCARD_defconfig
+++ b/configs/P2020RDB-PC_36BIT_SDCARD_defconfig
@@ -49,7 +49,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig b/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig
index 9da9ef0..3f106c6 100644
--- a/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig
+++ b/configs/P2020RDB-PC_36BIT_SPIFLASH_defconfig
@@ -51,7 +51,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P2020RDB-PC_NAND_defconfig b/configs/P2020RDB-PC_NAND_defconfig
index 4758e0e..11d59d1 100644
--- a/configs/P2020RDB-PC_NAND_defconfig
+++ b/configs/P2020RDB-PC_NAND_defconfig
@@ -51,7 +51,6 @@
CONFIG_TPL_RELOC_MALLOC_ADDR=0xf8fb4000
CONFIG_TPL_RELOC_MALLOC_SIZE=0xc000
CONFIG_SPL_NAND_SUPPORT=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_TPL=y
CONFIG_TPL_ENV_SUPPORT=y
CONFIG_TPL_I2C=y
diff --git a/configs/P2020RDB-PC_SDCARD_defconfig b/configs/P2020RDB-PC_SDCARD_defconfig
index 1584a8a..9416d93 100644
--- a/configs/P2020RDB-PC_SDCARD_defconfig
+++ b/configs/P2020RDB-PC_SDCARD_defconfig
@@ -48,7 +48,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/P2020RDB-PC_SPIFLASH_defconfig b/configs/P2020RDB-PC_SPIFLASH_defconfig
index 6acb0bc..74d26f1 100644
--- a/configs/P2020RDB-PC_SPIFLASH_defconfig
+++ b/configs/P2020RDB-PC_SPIFLASH_defconfig
@@ -50,7 +50,6 @@
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_I2C=y
CONFIG_SPL_MPC8XXX_INIT_DDR=y
-CONFIG_SPL_TARGET="u-boot-with-spl.bin"
CONFIG_HUSH_PARSER=y
# CONFIG_AUTO_COMPLETE is not set
CONFIG_SYS_PBSIZE=276
diff --git a/configs/Sinlinx_SinA31s_defconfig b/configs/Sinlinx_SinA31s_defconfig
index 238b007..59869b7 100644
--- a/configs/Sinlinx_SinA31s_defconfig
+++ b/configs/Sinlinx_SinA31s_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN6I=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=251
-CONFIG_MMC0_CD_PIN="PA4"
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_USB1_VBUS_PIN=""
CONFIG_USB2_VBUS_PIN=""
diff --git a/configs/Sinlinx_SinA33_defconfig b/configs/Sinlinx_SinA33_defconfig
index 4eb5300..cfb4329 100644
--- a/configs/Sinlinx_SinA33_defconfig
+++ b/configs/Sinlinx_SinA33_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A33=y
CONFIG_DRAM_CLK=552
CONFIG_DRAM_ZQ=15291
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_ID_DET="PH8"
CONFIG_VIDEO_LCD_MODE="x:1024,y:600,depth:18,pclk_khz:66000,le:90,ri:160,up:3,lo:127,hs:70,vs:20,sync:3,vmode:0"
diff --git a/configs/Sunchip_CX-A99_defconfig b/configs/Sunchip_CX-A99_defconfig
index bb62ae9..348140d 100644
--- a/configs/Sunchip_CX-A99_defconfig
+++ b/configs/Sunchip_CX-A99_defconfig
@@ -6,7 +6,6 @@
CONFIG_DRAM_CLK=600
CONFIG_DRAM_ZQ=3881915
CONFIG_DRAM_ODT_EN=y
-CONFIG_MMC0_CD_PIN="PH17"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PH15"
CONFIG_USB1_VBUS_PIN="PL7"
diff --git a/configs/UTOO_P66_defconfig b/configs/UTOO_P66_defconfig
index b021b0a..88a082c 100644
--- a/configs/UTOO_P66_defconfig
+++ b/configs/UTOO_P66_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_EMR1=0
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PB04"
CONFIG_USB0_VBUS_DET="PG01"
diff --git a/configs/Wobo_i5_defconfig b/configs/Wobo_i5_defconfig
index e0687bf..9e9bddb 100644
--- a/configs/Wobo_i5_defconfig
+++ b/configs/Wobo_i5_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=432
-CONFIG_MMC0_CD_PIN="PB3"
CONFIG_USB1_VBUS_PIN="PG12"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Yones_Toptech_BD1078_defconfig b/configs/Yones_Toptech_BD1078_defconfig
index f1ceb8b..4f2290c 100644
--- a/configs/Yones_Toptech_BD1078_defconfig
+++ b/configs/Yones_Toptech_BD1078_defconfig
@@ -4,8 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=408
-CONFIG_MMC0_CD_PIN="PH1"
-CONFIG_MMC1_CD_PIN="PH2"
CONFIG_MMC1_PINS_PH=y
CONFIG_MMC_SUNXI_SLOT_EXTRA=1
CONFIG_USB0_VBUS_PIN="PB9"
diff --git a/configs/Yones_Toptech_BS1078_V2_defconfig b/configs/Yones_Toptech_BS1078_V2_defconfig
index 6701ecc..b33c825 100644
--- a/configs/Yones_Toptech_BS1078_V2_defconfig
+++ b/configs/Yones_Toptech_BS1078_V2_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN6I=y
CONFIG_DRAM_CLK=420
CONFIG_DRAM_ZQ=251
-CONFIG_MMC0_CD_PIN="PA8"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PA15"
diff --git a/configs/am62ax_evm_a53_defconfig b/configs/am62ax_evm_a53_defconfig
index 0c2cf94..6e97fd4 100644
--- a/configs/am62ax_evm_a53_defconfig
+++ b/configs/am62ax_evm_a53_defconfig
@@ -20,7 +20,6 @@
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000
-CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
CONFIG_SPL_MAX_SIZE=0x58000
CONFIG_SPL_PAD_TO=0x0
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
diff --git a/configs/am62ax_evm_r5_defconfig b/configs/am62ax_evm_r5_defconfig
index 59d5f4f..0e48f0a 100644
--- a/configs/am62ax_evm_r5_defconfig
+++ b/configs/am62ax_evm_r5_defconfig
@@ -13,20 +13,25 @@
CONFIG_SPL_MMC=y
CONFIG_SPL_SERIAL=y
CONFIG_SPL_STACK_R_ADDR=0x82000000
-CONFIG_SPL_SIZE_LIMIT=0x40000
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x7145
+CONFIG_SPL_SIZE_LIMIT=0x3A7F0
+CONFIG_SPL_SIZE_LIMIT_PROVIDE_STACK=0x3500
CONFIG_SPL_FS_FAT=y
CONFIG_SPL_LIBDISK_SUPPORT=y
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x7000ffff
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x43c3a7f0
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_LOAD_FIT_ADDRESS=0x80080000
CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y
# CONFIG_DISPLAY_CPUINFO is not set
-CONFIG_SPL_MAX_SIZE=0x58000
+CONFIG_SPL_SIZE_LIMIT_SUBTRACT_GD=y
+CONFIG_SPL_SIZE_LIMIT_SUBTRACT_MALLOC=y
+CONFIG_SPL_MAX_SIZE=0x3B000
CONFIG_SPL_PAD_TO=0x0
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
-CONFIG_SPL_BSS_START_ADDR=0x43c37800
-CONFIG_SPL_BSS_MAX_SIZE=0x5000
+CONFIG_SPL_BSS_START_ADDR=0x43c3b000
+CONFIG_SPL_BSS_MAX_SIZE=0x3000
+CONFIG_SPL_SYS_REPORT_STACK_F_USAGE=y
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_SEPARATE_BSS=y
diff --git a/configs/am62x_evm_a53_defconfig b/configs/am62x_evm_a53_defconfig
index e6ffd16..273db2e 100644
--- a/configs/am62x_evm_a53_defconfig
+++ b/configs/am62x_evm_a53_defconfig
@@ -7,6 +7,7 @@
CONFIG_SOC_K3_AM625=y
CONFIG_K3_ATF_LOAD_ADDR=0x9e780000
CONFIG_TARGET_AM625_A53_EVM=y
+CONFIG_SPL_DM_SPI=y
CONFIG_DEFAULT_DEVICE_TREE="k3-am625-sk"
CONFIG_SPL_TEXT_BASE=0x80080000
CONFIG_SPL_MMC=y
@@ -14,6 +15,7 @@
CONFIG_SPL_STACK_R_ADDR=0x82000000
CONFIG_SPL_FS_FAT=y
CONFIG_SPL_LIBDISK_SUPPORT=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
@@ -21,7 +23,7 @@
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_LOAD_FIT=y
CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000
-CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern"
+CONFIG_BOOTCOMMAND="run findfdt; run envboot; run init_${boot}; run get_kern_${boot}; run get_fdt_${boot}; run get_overlay_${boot}; run run_kern; setenv fdtfile ti/${name_fdt}; run distro_bootcmd"
CONFIG_SPL_MAX_SIZE=0x58000
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
CONFIG_SPL_BSS_START_ADDR=0x80a00000
@@ -32,12 +34,10 @@
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1400
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME="u-boot.img"
CONFIG_SPL_DM_MAILBOX=y
-CONFIG_SPL_DM_SPI=y
CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_SPL_POWER_DOMAIN=y
# CONFIG_SPL_SPI_FLASH_TINY is not set
CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y
-CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI_LOAD=y
CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000
CONFIG_SPL_YMODEM_SUPPORT=y
@@ -57,6 +57,8 @@
CONFIG_CLK=y
CONFIG_SPL_CLK=y
CONFIG_CLK_TI_SCI=y
+CONFIG_DMA_CHANNELS=y
+CONFIG_TI_K3_NAVSS_UDMA=y
CONFIG_TI_SCI_PROTOCOL=y
CONFIG_DM_MAILBOX=y
CONFIG_K3_SEC_PROXY=y
@@ -71,7 +73,11 @@
CONFIG_SPI_FLASH_SOFT_RESET=y
CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_SPI_FLASH_S28HS512T=y
+CONFIG_SPI_FLASH_S28HX_T=y
+CONFIG_PHY_TI_DP83867=y
+CONFIG_PHY_FIXED=y
+CONFIG_TI_AM65_CPSW_NUSS=y
+CONFIG_PHY=y
CONFIG_PINCTRL=y
CONFIG_SPL_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
diff --git a/configs/am62x_evm_r5_defconfig b/configs/am62x_evm_r5_defconfig
index f95bc5f..7350882 100644
--- a/configs/am62x_evm_r5_defconfig
+++ b/configs/am62x_evm_r5_defconfig
@@ -7,6 +7,7 @@
CONFIG_NR_DRAM_BANKS=2
CONFIG_SOC_K3_AM625=y
CONFIG_TARGET_AM625_R5_EVM=y
+CONFIG_ENV_SIZE=0x20000
CONFIG_DM_GPIO=y
CONFIG_SPL_DM_SPI=y
CONFIG_DEFAULT_DEVICE_TREE="k3-am625-r5-sk"
@@ -18,10 +19,8 @@
CONFIG_SPL_SIZE_LIMIT=0x40000
CONFIG_SPL_FS_FAT=y
CONFIG_SPL_LIBDISK_SUPPORT=y
-CONFIG_SPL_SPI=y
CONFIG_SPL_SPI_FLASH_SUPPORT=y
-CONFIG_SPL_SPI_SUPPORT=y
-CONFIG_SF_DEFAULT_SPEED=25000000
+CONFIG_SPL_SPI=y
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x7000ffff
CONFIG_SPL_LOAD_FIT=y
@@ -42,10 +41,9 @@
CONFIG_SPL_EARLY_BSS=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x400
-CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000
CONFIG_SPL_DM_MAILBOX=y
-CONFIG_SPL_DM_RESET=y
CONFIG_SPL_DM_SPI_FLASH=y
+CONFIG_SPL_DM_RESET=y
CONFIG_SPL_POWER_DOMAIN=y
CONFIG_SPL_RAM_SUPPORT=y
CONFIG_SPL_RAM_DEVICE=y
@@ -53,6 +51,7 @@
# CONFIG_SPL_SPI_FLASH_TINY is not set
CONFIG_SPL_SPI_FLASH_SFDP_SUPPORT=y
CONFIG_SPL_SPI_LOAD=y
+CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000
CONFIG_SPL_YMODEM_SUPPORT=y
CONFIG_HUSH_PARSER=y
CONFIG_CMD_ASKENV=y
@@ -88,6 +87,14 @@
CONFIG_MMC_SDHCI_ADMA=y
CONFIG_SPL_MMC_SDHCI_ADMA=y
CONFIG_MMC_SDHCI_AM654=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SF_DEFAULT_MODE=0
+CONFIG_SF_DEFAULT_SPEED=25000000
+CONFIG_SPI_FLASH_SFDP_SUPPORT=y
+CONFIG_SPI_FLASH_SOFT_RESET=y
+CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_S28HX_T=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_GENERIC is not set
CONFIG_SPL_PINCTRL=y
@@ -101,23 +108,14 @@
CONFIG_RESET_TI_SCI=y
CONFIG_SPECIFY_CONSOLE_INDEX=y
CONFIG_DM_SERIAL=y
-CONFIG_DM_SPI=y
-CONFIG_CADENCE_QSPI=y
-CONFIG_DM_SPI_FLASH=y
-CONFIG_SF_DEFAULT_MODE=0
-CONFIG_SPI=y
-CONFIG_SPI_FLASH_SFDP_SUPPORT=y
-CONFIG_SPI_FLASH_SOFT_RESET=y
-CONFIG_SPI_FLASH_SOFT_RESET_ON_BOOT=y
-CONFIG_SPI_FLASH_SPANSION=y
-CONFIG_SPI_FLASH_S28HS512T=y
CONFIG_SOC_DEVICE=y
CONFIG_SOC_DEVICE_TI_K3=y
CONFIG_SOC_TI=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_CADENCE_QSPI=y
CONFIG_TIMER=y
CONFIG_SPL_TIMER=y
CONFIG_OMAP_TIMER=y
CONFIG_LIB_RATIONAL=y
CONFIG_SPL_LIB_RATIONAL=y
-CONFIG_ENV_SIZE=0x20000
-CONFIG_ENV_OFFSET=0x680000
diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig
index fe3346f..ad46a74 100644
--- a/configs/am65x_evm_a53_defconfig
+++ b/configs/am65x_evm_a53_defconfig
@@ -179,3 +179,4 @@
CONFIG_USB_GADGET_PRODUCT_NUM=0x6162
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_PHANDLE_CHECK_SEQ=y
diff --git a/configs/bananapi_m2_berry_defconfig b/configs/bananapi_m2_berry_defconfig
index 588eea2..f4edcf4 100644
--- a/configs/bananapi_m2_berry_defconfig
+++ b/configs/bananapi_m2_berry_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN8I_R40=y
CONFIG_DRAM_CLK=576
-CONFIG_MMC0_CD_PIN="PH13"
CONFIG_USB1_VBUS_PIN="PH23"
# CONFIG_HAS_ARMV7_SECURE_BASE is not set
CONFIG_AHCI=y
diff --git a/configs/bananapi_m2_zero_defconfig b/configs/bananapi_m2_zero_defconfig
index ac3f8f5..25617a8 100644
--- a/configs/bananapi_m2_zero_defconfig
+++ b/configs/bananapi_m2_zero_defconfig
@@ -4,5 +4,4 @@
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=408
-CONFIG_MMC0_CD_PIN=""
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig
index 5463b04..99dc2f7 100644
--- a/configs/bananapi_m64_defconfig
+++ b/configs/bananapi_m64_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN50I=y
CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y
-CONFIG_MMC0_CD_PIN="PH13"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUPPORT_EMMC_BOOT=y
diff --git a/configs/beelink_gs1_defconfig b/configs/beelink_gs1_defconfig
index 42925ea..de46d20 100644
--- a/configs/beelink_gs1_defconfig
+++ b/configs/beelink_gs1_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_LPDDR3=y
-CONFIG_MMC0_CD_PIN="PF6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_PSCI_RESET is not set
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/colorfly_e708_q1_defconfig b/configs/colorfly_e708_q1_defconfig
index 5d3636e..89f063b 100644
--- a/configs/colorfly_e708_q1_defconfig
+++ b/configs/colorfly_e708_q1_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN6I=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=251
-CONFIG_MMC0_CD_PIN="PA8"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PA15"
diff --git a/configs/difrnce_dit4350_defconfig b/configs/difrnce_dit4350_defconfig
index e1067b6..f54a83d 100644
--- a/configs/difrnce_dit4350_defconfig
+++ b/configs/difrnce_dit4350_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=408
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB0_VBUS_PIN="PG12"
CONFIG_USB0_VBUS_DET="PG1"
CONFIG_USB0_ID_DET="PG2"
diff --git a/configs/dockstar_defconfig b/configs/dockstar_defconfig
index a17d01f..d08182d 100644
--- a/configs/dockstar_defconfig
+++ b/configs/dockstar_defconfig
@@ -17,9 +17,6 @@
CONFIG_SYS_PROMPT="DockStar> "
CONFIG_IDENT_STRING="\nSeagate FreeAgent DockStar"
CONFIG_SYS_LOAD_ADDR=0x800000
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
-# CONFIG_SYS_MALLOC_F is not set
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="setenv bootargs ${console} ${mtdparts} ${bootargs_root}; ubi part root; ubifsmount ubi:root; ubifsload 0x800000 ${kernel}; ubifsload 0x1100000 ${initrd}; bootm 0x800000 0x1100000"
diff --git a/configs/dreamplug_defconfig b/configs/dreamplug_defconfig
index 6deb055..3cff503 100644
--- a/configs/dreamplug_defconfig
+++ b/configs/dreamplug_defconfig
@@ -17,9 +17,6 @@
CONFIG_IDENT_STRING="\nMarvell-DreamPlug"
CONFIG_SYS_LOAD_ADDR=0x800000
CONFIG_ENV_ADDR=0x100000
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
-# CONFIG_SYS_MALLOC_F is not set
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="setenv ethact ethernet-controller@72000; ${x_bootcmd_ethernet}; setenv ethact ethernet-controller@76000; ${x_bootcmd_ethernet}; ${x_bootcmd_usb}; ${x_bootcmd_kernel}; setenv bootargs ${x_bootargs} ${x_bootargs_root}; bootm 0x6400000;"
diff --git a/configs/dserve_dsrv9703c_defconfig b/configs/dserve_dsrv9703c_defconfig
index 60910c3..f5ff69d 100644
--- a/configs/dserve_dsrv9703c_defconfig
+++ b/configs/dserve_dsrv9703c_defconfig
@@ -3,7 +3,6 @@
CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-dserve-dsrv9703c"
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_USB0_ID_DET="PH4"
diff --git a/configs/evb-ast2600_defconfig b/configs/evb-ast2600_defconfig
index 2fac79b..3440062 100644
--- a/configs/evb-ast2600_defconfig
+++ b/configs/evb-ast2600_defconfig
@@ -120,3 +120,4 @@
CONFIG_SHA384=y
CONFIG_HEXDUMP=y
# CONFIG_EFI_LOADER is not set
+CONFIG_PHANDLE_CHECK_SEQ=y
diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig
index fcfb6aa..5c6b1d5 100644
--- a/configs/evb-rk3288_defconfig
+++ b/configs/evb-rk3288_defconfig
@@ -29,6 +29,7 @@
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_SPL_PAD_TO=0x7f8000
CONFIG_SPL_NO_BSS_LIMIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_STACK=0xff718000
CONFIG_SPL_STACK_R=y
diff --git a/configs/goflexhome_defconfig b/configs/goflexhome_defconfig
index 8ee1183..8dc2852 100644
--- a/configs/goflexhome_defconfig
+++ b/configs/goflexhome_defconfig
@@ -17,9 +17,6 @@
CONFIG_SYS_PROMPT="GoFlexHome> "
CONFIG_IDENT_STRING="\nSeagate GoFlex Home"
CONFIG_SYS_LOAD_ADDR=0x800000
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
-# CONFIG_SYS_MALLOC_F is not set
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="setenv bootargs ${console} ${mtdparts} ${bootargs_root}; ubi part root; ubifsmount ubi:root; ubifsload 0x800000 ${kernel}; bootm 0x800000"
diff --git a/configs/gt90h_v4_defconfig b/configs/gt90h_v4_defconfig
index 1a5fe06..f5e3a72 100644
--- a/configs/gt90h_v4_defconfig
+++ b/configs/gt90h_v4_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A23=y
CONFIG_DRAM_CLK=480
CONFIG_DRAM_ZQ=32767
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/iNet_3F_defconfig b/configs/iNet_3F_defconfig
index 436e3a8..5cc1a1d 100644
--- a/configs/iNet_3F_defconfig
+++ b/configs/iNet_3F_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN4I=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_EMR1=4
-CONFIG_MMC0_CD_PIN="PH1"
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_VIDEO_LCD_MODE="x:1024,y:768,depth:18,pclk_khz:100000,le:799,ri:260,up:15,lo:16,hs:1,vs:1,sync:3,vmode:0"
diff --git a/configs/iNet_3W_defconfig b/configs/iNet_3W_defconfig
index 6978f8b..38b2010 100644
--- a/configs/iNet_3W_defconfig
+++ b/configs/iNet_3W_defconfig
@@ -6,7 +6,6 @@
CONFIG_DRAM_CLK=408
CONFIG_DRAM_ZQ=127
CONFIG_DRAM_EMR1=4
-CONFIG_MMC0_CD_PIN="PH20"
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_VIDEO_LCD_MODE="x:1024,y:768,depth:24,pclk_khz:65000,le:159,ri:160,up:22,lo:15,hs:1,vs:1,sync:3,vmode:0"
diff --git a/configs/iNet_D978_rev2_defconfig b/configs/iNet_D978_rev2_defconfig
index 9a90252..e01e184 100644
--- a/configs/iNet_D978_rev2_defconfig
+++ b/configs/iNet_D978_rev2_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A33=y
CONFIG_DRAM_CLK=456
CONFIG_DRAM_ZQ=15291
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/icnova-a20-swac_defconfig b/configs/icnova-a20-swac_defconfig
index c759d7e..30c28f7 100644
--- a/configs/icnova-a20-swac_defconfig
+++ b/configs/icnova-a20-swac_defconfig
@@ -9,7 +9,6 @@
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
CONFIG_OLD_SUNXI_KERNEL_COMPAT=y
-CONFIG_MMC0_CD_PIN="PI5"
CONFIG_USB0_VBUS_PIN="PG11"
CONFIG_USB0_VBUS_DET="PH7"
CONFIG_USB1_VBUS_PIN="PG10"
diff --git a/configs/iconnect_defconfig b/configs/iconnect_defconfig
index f536dd3..94f4ee2 100644
--- a/configs/iconnect_defconfig
+++ b/configs/iconnect_defconfig
@@ -17,9 +17,6 @@
CONFIG_SYS_PROMPT="iConnect> "
CONFIG_IDENT_STRING=" Iomega iConnect"
CONFIG_SYS_LOAD_ADDR=0x800000
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
-# CONFIG_SYS_MALLOC_F is not set
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="setenv bootargs ${console} ${mtdparts} ${bootargs_root}; ubi part rootfs; ubifsmount ubi:rootfs; ubifsload 0x800000 ${kernel}; bootm 0x800000"
diff --git a/configs/inet86dz_defconfig b/configs/inet86dz_defconfig
index 3ade9fe..2035a34 100644
--- a/configs/inet86dz_defconfig
+++ b/configs/inet86dz_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A23=y
CONFIG_DRAM_CLK=552
CONFIG_DRAM_ZQ=63351
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/inet98v_rev2_defconfig b/configs/inet98v_rev2_defconfig
index bd6c45b..e4da6c1 100644
--- a/configs/inet98v_rev2_defconfig
+++ b/configs/inet98v_rev2_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=432
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB0_VBUS_PIN="PG12"
CONFIG_USB0_VBUS_DET="PG1"
CONFIG_USB0_ID_DET="PG2"
diff --git a/configs/inet_q972_defconfig b/configs/inet_q972_defconfig
index 1769256..85a3b4e 100644
--- a/configs/inet_q972_defconfig
+++ b/configs/inet_q972_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN6I=y
CONFIG_DRAM_CLK=384
CONFIG_DRAM_ZQ=251
-CONFIG_MMC0_CD_PIN="PA8"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PA15"
diff --git a/configs/khadas-edge-captain-rk3399_defconfig b/configs/khadas-edge-captain-rk3399_defconfig
index 754fd4e..f6e90bf 100644
--- a/configs/khadas-edge-captain-rk3399_defconfig
+++ b/configs/khadas-edge-captain-rk3399_defconfig
@@ -53,7 +53,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
diff --git a/configs/khadas-edge-rk3399_defconfig b/configs/khadas-edge-rk3399_defconfig
index 7518f7f..f74963c 100644
--- a/configs/khadas-edge-rk3399_defconfig
+++ b/configs/khadas-edge-rk3399_defconfig
@@ -52,7 +52,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
diff --git a/configs/khadas-edge-v-rk3399_defconfig b/configs/khadas-edge-v-rk3399_defconfig
index 4c4301a..3abfef1 100644
--- a/configs/khadas-edge-v-rk3399_defconfig
+++ b/configs/khadas-edge-v-rk3399_defconfig
@@ -53,7 +53,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
diff --git a/configs/leez-rk3399_defconfig b/configs/leez-rk3399_defconfig
index 5a958ee..bee55f8 100644
--- a/configs/leez-rk3399_defconfig
+++ b/configs/leez-rk3399_defconfig
@@ -48,7 +48,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
diff --git a/configs/licheepi_nano_defconfig b/configs/licheepi_nano_defconfig
index 12a43c1..b25c9ba 100644
--- a/configs/licheepi_nano_defconfig
+++ b/configs/licheepi_nano_defconfig
@@ -10,4 +10,3 @@
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_XTX=y
CONFIG_SPI=y
-# CONFIG_SYSRESET is not set
diff --git a/configs/mx6ull_14x14_evk_defconfig b/configs/mx6ull_14x14_evk_defconfig
index 65db621..881bc27 100644
--- a/configs/mx6ull_14x14_evk_defconfig
+++ b/configs/mx6ull_14x14_evk_defconfig
@@ -65,3 +65,7 @@
CONFIG_FSL_QSPI=y
CONFIG_SOFT_SPI=y
CONFIG_IMX_THERMAL=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_DM_RNG=y
+CONFIG_CMD_RNG=y
+CONFIG_FSL_DCP_RNG=y
diff --git a/configs/mx6ull_14x14_evk_plugin_defconfig b/configs/mx6ull_14x14_evk_plugin_defconfig
index 55ddd7e..5e67662 100644
--- a/configs/mx6ull_14x14_evk_plugin_defconfig
+++ b/configs/mx6ull_14x14_evk_plugin_defconfig
@@ -64,3 +64,7 @@
CONFIG_FSL_QSPI=y
CONFIG_SOFT_SPI=y
CONFIG_IMX_THERMAL=y
+CONFIG_ARCH_MISC_INIT=y
+CONFIG_DM_RNG=y
+CONFIG_CMD_RNG=y
+CONFIG_FSL_DCP_RNG=y
diff --git a/configs/nanopi-r4s-rk3399_defconfig b/configs/nanopi-r4s-rk3399_defconfig
index 40a45a0..0ef5486 100644
--- a/configs/nanopi-r4s-rk3399_defconfig
+++ b/configs/nanopi-r4s-rk3399_defconfig
@@ -49,7 +49,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index 37b7817..76655d7 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=408
CONFIG_MACPWR="PD6"
-CONFIG_MMC0_CD_PIN="PH13"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/neu2-io-rv1126_defconfig b/configs/neu2-io-rv1126_defconfig
new file mode 100644
index 0000000..e0816f8
--- /dev/null
+++ b/configs/neu2-io-rv1126_defconfig
@@ -0,0 +1,57 @@
+CONFIG_ARM=y
+CONFIG_SPL_SKIP_LOWLEVEL_INIT_ONLY=y
+CONFIG_TPL_SKIP_LOWLEVEL_INIT_ONLY=y
+CONFIG_COUNTER_FREQUENCY=24000000
+CONFIG_SYS_ARCH_TIMER=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_DEFAULT_DEVICE_TREE="rv1126-edgeble-neu2-io"
+CONFIG_ROCKCHIP_RV1126=y
+CONFIG_TARGET_RV1126_NEU2=y
+CONFIG_DEBUG_UART_BASE=0xff570000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_SYS_LOAD_ADDR=0xe00800
+CONFIG_DEBUG_UART=y
+CONFIG_SYS_MONITOR_LEN=614400
+CONFIG_FIT_VERBOSE=y
+CONFIG_DEFAULT_FDT_FILE="rv1126-edgeble-neu2-io.dtb"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
+CONFIG_SPL_PAD_TO=0x7f8000
+CONFIG_SPL_NO_BSS_LIMIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+# CONFIG_CMD_BOOTD is not set
+CONFIG_SYS_BOOTM_LEN=0x4000000
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+CONFIG_CMD_GPT=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_ISO_PARTITION is not set
+CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64
+CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MISC=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_PWM_ROCKCHIP=y
+# CONFIG_RAM_ROCKCHIP_DEBUG is not set
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYSRESET=y
+# CONFIG_TPL_SYSRESET is not set
+CONFIG_DM_THERMAL=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_LZO=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/nsa310s_defconfig b/configs/nsa310s_defconfig
index e7d6ffd..ab896ff 100644
--- a/configs/nsa310s_defconfig
+++ b/configs/nsa310s_defconfig
@@ -9,7 +9,6 @@
CONFIG_INITRD_TAG=y
CONFIG_SYS_KWD_CONFIG="board/zyxel/nsa310s/kwbimage.cfg"
CONFIG_TEXT_BASE=0x600000
-CONFIG_SYS_MALLOC_F_LEN=0x400
CONFIG_NR_DRAM_BANKS=2
CONFIG_TARGET_NSA310S=y
CONFIG_ENV_SIZE=0x20000
@@ -19,8 +18,6 @@
CONFIG_IDENT_STRING="\nZyXEL NSA310S/320S 1/2-Bay Power Media Server"
CONFIG_SYS_LOAD_ADDR=0x800000
CONFIG_DISTRO_DEFAULTS=y
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
CONFIG_BOOTDELAY=3
CONFIG_USE_PREBOOT=y
# CONFIG_DISPLAY_BOARDINFO is not set
diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig
index 7ce63ba..2ebca67 100644
--- a/configs/oceanic_5205_5inmfd_defconfig
+++ b/configs/oceanic_5205_5inmfd_defconfig
@@ -7,7 +7,6 @@
CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
CONFIG_DRAM_CLK=552
CONFIG_DRAM_ZQ=3881949
-CONFIG_MMC0_CD_PIN=""
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_3_defconfig b/configs/orangepi_3_defconfig
index ebecf49..125137b 100644
--- a/configs/orangepi_3_defconfig
+++ b/configs/orangepi_3_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_LPDDR3=y
-CONFIG_MMC0_CD_PIN="PF6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_BLUETOOTH_DT_DEVICE_FIXUP="brcm,bcm4345c5"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/orangepi_lite2_defconfig b/configs/orangepi_lite2_defconfig
index 75c97d6..577f743 100644
--- a/configs/orangepi_lite2_defconfig
+++ b/configs/orangepi_lite2_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_LPDDR3=y
-CONFIG_MMC0_CD_PIN="PF6"
# CONFIG_PSCI_RESET is not set
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/orangepi_one_plus_defconfig b/configs/orangepi_one_plus_defconfig
index 55a8b00..aa5f540 100644
--- a/configs/orangepi_one_plus_defconfig
+++ b/configs/orangepi_one_plus_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_LPDDR3=y
-CONFIG_MMC0_CD_PIN="PF6"
# CONFIG_PSCI_RESET is not set
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig
index ceef51b..72fc419 100644
--- a/configs/orangepi_zero2_defconfig
+++ b/configs/orangepi_zero2_defconfig
@@ -7,7 +7,6 @@
CONFIG_DRAM_SUN50I_H616_READ_TRAINING=y
CONFIG_DRAM_SUN50I_H616_WRITE_TRAINING=y
CONFIG_MACH_SUN50I_H616=y
-CONFIG_MMC0_CD_PIN="PF6"
CONFIG_R_I2C_ENABLE=y
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/orangepi_zero_plus2_defconfig b/configs/orangepi_zero_plus2_defconfig
index 9583d24..393cb0f 100644
--- a/configs/orangepi_zero_plus2_defconfig
+++ b/configs/orangepi_zero_plus2_defconfig
@@ -6,7 +6,6 @@
CONFIG_DRAM_CLK=672
CONFIG_DRAM_ZQ=3881977
# CONFIG_DRAM_ODT_EN is not set
-CONFIG_MMC0_CD_PIN="PH13"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_zero_plus2_h3_defconfig b/configs/orangepi_zero_plus2_h3_defconfig
index 55a2513..057f45e 100644
--- a/configs/orangepi_zero_plus2_h3_defconfig
+++ b/configs/orangepi_zero_plus2_h3_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=672
# CONFIG_DRAM_ODT_EN is not set
-CONFIG_MMC0_CD_PIN="PH13"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/parrot_r16_defconfig b/configs/parrot_r16_defconfig
index d56c450..72235cc 100644
--- a/configs/parrot_r16_defconfig
+++ b/configs/parrot_r16_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A33=y
CONFIG_DRAM_CLK=600
CONFIG_DRAM_ZQ=15291
-CONFIG_MMC0_CD_PIN="PD14"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_ID_DET="PD10"
CONFIG_USB1_VBUS_PIN="PD12"
diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig
index 7e7c2d7..9583d29 100644
--- a/configs/pine64-lts_defconfig
+++ b/configs/pine64-lts_defconfig
@@ -6,7 +6,6 @@
CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
CONFIG_DRAM_CLK=552
CONFIG_DRAM_ZQ=3881949
-CONFIG_MMC0_CD_PIN=""
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 09a4275..6dac609 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_LPDDR3=y
CONFIG_MACPWR="PC16"
-CONFIG_MMC0_CD_PIN="PF6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB3_VBUS_PIN="PL5"
CONFIG_SPL_SPI_SUNXI=y
diff --git a/configs/pinebook-pro-rk3399_defconfig b/configs/pinebook-pro-rk3399_defconfig
index dfbf5e7..c885cba 100644
--- a/configs/pinebook-pro-rk3399_defconfig
+++ b/configs/pinebook-pro-rk3399_defconfig
@@ -74,7 +74,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_DM_RESET=y
CONFIG_DM_RNG=y
CONFIG_RNG_ROCKCHIP=y
diff --git a/configs/pinephone-pro-rk3399_defconfig b/configs/pinephone-pro-rk3399_defconfig
new file mode 100644
index 0000000..eb979f6
--- /dev/null
+++ b/configs/pinephone-pro-rk3399_defconfig
@@ -0,0 +1,104 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_COUNTER_FREQUENCY=24000000
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x00200000
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_ENV_SIZE=0x8000
+CONFIG_ENV_OFFSET=0x3F8000
+CONFIG_DEFAULT_DEVICE_TREE="rk3399-pinephone-pro"
+CONFIG_ROCKCHIP_RK3399=y
+CONFIG_TARGET_PINEPHONE_PRO_RK3399=y
+CONFIG_DEBUG_UART_BASE=0xFF1A0000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI=y
+CONFIG_SYS_LOAD_ADDR=0x800800
+CONFIG_DEBUG_UART=y
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000
+CONFIG_BOOTDELAY=3
+CONFIG_USE_PREBOOT=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-pinephone-pro.dtb"
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
+CONFIG_SPL_MAX_SIZE=0x2e000
+CONFIG_SPL_PAD_TO=0x7f8000
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x400000
+CONFIG_SPL_BSS_MAX_SIZE=0x2000
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_STACK=0x400000
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000
+CONFIG_SPL_SPI_LOAD=y
+CONFIG_TPL=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TIME=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_DM_KEYBOARD=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_ROCKCHIP=y
+CONFIG_SF_DEFAULT_BUS=1
+CONFIG_SF_DEFAULT_SPEED=20000000
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PHY_ROCKCHIP_TYPEC=y
+CONFIG_DM_PMIC_FAN53555=y
+CONFIG_DM_REGULATOR_FAN53555=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_DM_RESET=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_ROCKCHIP=y
+CONFIG_BAUDRATE=1500000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_ROCKCHIP_SPI=y
+CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_DWC3=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_GENERIC=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_GENERIC=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_RTL8152=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_EDP=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/pogo_e02_defconfig b/configs/pogo_e02_defconfig
index 116e5d0..067fb9e 100644
--- a/configs/pogo_e02_defconfig
+++ b/configs/pogo_e02_defconfig
@@ -17,9 +17,6 @@
CONFIG_SYS_PROMPT="PogoE02> "
CONFIG_IDENT_STRING="\nPogo E02"
CONFIG_SYS_LOAD_ADDR=0x800000
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
-# CONFIG_SYS_MALLOC_F is not set
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="setenv bootargs $(bootargs_console); run bootcmd_usb; bootm 0x00800000 0x01100000"
diff --git a/configs/pogo_v4_defconfig b/configs/pogo_v4_defconfig
index 57ec6f1..3860ad3 100644
--- a/configs/pogo_v4_defconfig
+++ b/configs/pogo_v4_defconfig
@@ -9,7 +9,6 @@
CONFIG_INITRD_TAG=y
CONFIG_SYS_KWD_CONFIG="board/cloudengines/pogo_v4/kwbimage.cfg"
CONFIG_TEXT_BASE=0x600000
-CONFIG_SYS_MALLOC_F_LEN=0x400
CONFIG_TARGET_POGO_V4=y
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xC0000
@@ -18,8 +17,6 @@
CONFIG_IDENT_STRING="\nPogoplug V4"
CONFIG_SYS_LOAD_ADDR=0x800000
CONFIG_DISTRO_DEFAULTS=y
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
CONFIG_BOOTSTAGE=y
CONFIG_SHOW_BOOT_PROGRESS=y
CONFIG_BOOTDELAY=10
diff --git a/configs/polaroid_mid2407pxe03_defconfig b/configs/polaroid_mid2407pxe03_defconfig
index 17fffeb..023f880 100644
--- a/configs/polaroid_mid2407pxe03_defconfig
+++ b/configs/polaroid_mid2407pxe03_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A23=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=63351
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/polaroid_mid2809pxe04_defconfig b/configs/polaroid_mid2809pxe04_defconfig
index e542b71..2e9efd0 100644
--- a/configs/polaroid_mid2809pxe04_defconfig
+++ b/configs/polaroid_mid2809pxe04_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A23=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=63351
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/poleg_evb_defconfig b/configs/poleg_evb_defconfig
index b7e39eb..2d5bfa5 100644
--- a/configs/poleg_evb_defconfig
+++ b/configs/poleg_evb_defconfig
@@ -22,12 +22,26 @@
CONFIG_SYS_MAXARGS=32
CONFIG_SYS_CBSIZE=256
CONFIG_SYS_PBSIZE=280
+CONFIG_CMD_FUSE=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+CONFIG_CMD_WDT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
CONFIG_CMD_CACHE=y
+CONFIG_CMD_RNG=y
CONFIG_CMD_UUID=y
+CONFIG_CMD_HASH=y
+CONFIG_CMD_FAT=y
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
CONFIG_USE_IPADDR=y
CONFIG_IPADDR="192.168.0.2"
CONFIG_USE_NETMASK=y
@@ -35,16 +49,59 @@
CONFIG_USE_SERVERIP=y
CONFIG_SERVERIP="192.168.0.1"
CONFIG_CLK=y
+CONFIG_NPCM_AES=y
+CONFIG_NPCM_SHA=y
+CONFIG_NPCM_GPIO=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_NPCM=y
+CONFIG_MISC=y
+CONFIG_NPCM_HOST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_NPCM=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_PHY_BROADCOM=y
+CONFIG_PHY_FIXED=y
+CONFIG_DM_ETH=y
+CONFIG_PHY_GIGE=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_NET_NPCM750=y
+CONFIG_RGMII=y
+CONFIG_MII=y
+CONFIG_PHY=y
+CONFIG_PHY_NPCM_USB=y
CONFIG_PINCTRL=y
CONFIG_PINCONF=y
+CONFIG_PINCTRL_NPCM7XX=y
+CONFIG_DM_RESET=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_NPCM=y
CONFIG_DM_SERIAL=y
CONFIG_NPCM_SERIAL=y
CONFIG_SPI=y
CONFIG_DM_SPI=y
+CONFIG_NPCM_FIU_SPI=y
+CONFIG_NPCM_PSPI=y
CONFIG_SYSRESET=y
CONFIG_SYSRESET_WATCHDOG=y
CONFIG_TIMER=y
CONFIG_NPCM_TIMER=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_NPCM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_NPCM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Nuvoton"
+CONFIG_USB_GADGET_VENDOR_NUM=0x0416
+CONFIG_USB_GADGET_PRODUCT_NUM=0xffff
+CONFIG_CI_UDC=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+# CONFIG_WATCHDOG is not set
+CONFIG_WDT_NPCM=y
+CONFIG_LIB_HW_RAND=y
+CONFIG_SHA_HW_ACCEL=y
+CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS=1
+
diff --git a/configs/q8_a13_tablet_defconfig b/configs/q8_a13_tablet_defconfig
index f269b8a..36252e5 100644
--- a/configs/q8_a13_tablet_defconfig
+++ b/configs/q8_a13_tablet_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_MACH_SUN5I=y
CONFIG_DRAM_CLK=384
-CONFIG_MMC0_CD_PIN="PG0"
CONFIG_USB0_VBUS_PIN="PG12"
CONFIG_USB0_VBUS_DET="PG1"
CONFIG_USB0_ID_DET="PG2"
diff --git a/configs/q8_a23_tablet_800x480_defconfig b/configs/q8_a23_tablet_800x480_defconfig
index dda1a0c..3bfc5c5 100644
--- a/configs/q8_a23_tablet_800x480_defconfig
+++ b/configs/q8_a23_tablet_800x480_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A23=y
CONFIG_DRAM_CLK=432
CONFIG_DRAM_ZQ=63306
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/q8_a33_tablet_1024x600_defconfig b/configs/q8_a33_tablet_1024x600_defconfig
index 7925677..9166ec0 100644
--- a/configs/q8_a33_tablet_1024x600_defconfig
+++ b/configs/q8_a33_tablet_1024x600_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A33=y
CONFIG_DRAM_CLK=456
CONFIG_DRAM_ZQ=15291
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/q8_a33_tablet_800x480_defconfig b/configs/q8_a33_tablet_800x480_defconfig
index f3335f9..6114fcb 100644
--- a/configs/q8_a33_tablet_800x480_defconfig
+++ b/configs/q8_a33_tablet_800x480_defconfig
@@ -5,7 +5,6 @@
CONFIG_MACH_SUN8I_A33=y
CONFIG_DRAM_CLK=456
CONFIG_DRAM_ZQ=15291
-CONFIG_MMC0_CD_PIN="PB4"
CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH8"
diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig
index 9335233..2f46030 100644
--- a/configs/qemu_arm64_defconfig
+++ b/configs/qemu_arm64_defconfig
@@ -63,6 +63,7 @@
CONFIG_DEBUG_UART_PL011=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CMD_POWEROFF=y
CONFIG_SYSRESET_PSCI=y
CONFIG_TPM2_MMIO=y
CONFIG_USB=y
diff --git a/configs/qemu_arm_defconfig b/configs/qemu_arm_defconfig
index 6373185..f0ee546 100644
--- a/configs/qemu_arm_defconfig
+++ b/configs/qemu_arm_defconfig
@@ -65,6 +65,7 @@
CONFIG_DEBUG_UART_PL011=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYSRESET=y
+CONFIG_SYSRESET_CMD_POWEROFF=y
CONFIG_SYSRESET_PSCI=y
CONFIG_TPM2_MMIO=y
CONFIG_USB=y
diff --git a/configs/r8a77970_eagle_defconfig b/configs/r8a77970_eagle_defconfig
index fac4ab6..62192ad 100644
--- a/configs/r8a77970_eagle_defconfig
+++ b/configs/r8a77970_eagle_defconfig
@@ -14,6 +14,7 @@
CONFIG_RCAR_GEN3=y
CONFIG_TARGET_EAGLE=y
CONFIG_SYS_LOAD_ADDR=0x58000000
+CONFIG_LTO=y
CONFIG_REMAKE_ELF=y
CONFIG_SYS_MONITOR_LEN=1048576
CONFIG_FIT=y
diff --git a/configs/r8a77980_condor_defconfig b/configs/r8a77980_condor_defconfig
index 1983c8a..2e2bb55 100644
--- a/configs/r8a77980_condor_defconfig
+++ b/configs/r8a77980_condor_defconfig
@@ -2,7 +2,7 @@
CONFIG_COUNTER_FREQUENCY=16666666
CONFIG_ARCH_CPU_INIT=y
CONFIG_ARCH_RMOBILE=y
-CONFIG_TEXT_BASE=0x50000000
+CONFIG_TEXT_BASE=0x0
CONFIG_SYS_MALLOC_LEN=0x4000000
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_ENV_SIZE=0x40000
@@ -14,6 +14,7 @@
CONFIG_RCAR_GEN3=y
CONFIG_TARGET_CONDOR=y
CONFIG_SYS_LOAD_ADDR=0x58000000
+CONFIG_LTO=y
CONFIG_REMAKE_ELF=y
CONFIG_SYS_MONITOR_LEN=1048576
CONFIG_FIT=y
@@ -36,6 +37,7 @@
CONFIG_CMD_DFU=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
CONFIG_CMD_DHCP=y
@@ -63,7 +65,11 @@
CONFIG_RCAR_GPIO=y
CONFIG_DM_I2C=y
CONFIG_SYS_I2C_RCAR_I2C=y
-# CONFIG_MMC is not set
+CONFIG_DM_MMC=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_UHS_SUPPORT=y
+CONFIG_MMC_HS200_SUPPORT=y
+CONFIG_RENESAS_SDHI=y
CONFIG_MTD=y
CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_SPANSION=y
diff --git a/configs/r8a77990_ebisu_defconfig b/configs/r8a77990_ebisu_defconfig
index fe2a38d..00337e0 100644
--- a/configs/r8a77990_ebisu_defconfig
+++ b/configs/r8a77990_ebisu_defconfig
@@ -13,6 +13,7 @@
CONFIG_RCAR_GEN3=y
CONFIG_TARGET_EBISU=y
CONFIG_SYS_LOAD_ADDR=0x58000000
+CONFIG_LTO=y
CONFIG_REMAKE_ELF=y
CONFIG_SYS_MONITOR_LEN=1048576
CONFIG_FIT=y
diff --git a/configs/r8a77995_draak_defconfig b/configs/r8a77995_draak_defconfig
index 9ac70cb..e6517ea 100644
--- a/configs/r8a77995_draak_defconfig
+++ b/configs/r8a77995_draak_defconfig
@@ -13,6 +13,7 @@
CONFIG_RCAR_GEN3=y
CONFIG_TARGET_DRAAK=y
CONFIG_SYS_LOAD_ADDR=0x58000000
+CONFIG_LTO=y
CONFIG_REMAKE_ELF=y
CONFIG_SYS_MONITOR_LEN=1048576
CONFIG_FIT=y
diff --git a/configs/r8a779a0_falcon_defconfig b/configs/r8a779a0_falcon_defconfig
index 8cf2921..28fef6f 100644
--- a/configs/r8a779a0_falcon_defconfig
+++ b/configs/r8a779a0_falcon_defconfig
@@ -16,6 +16,7 @@
# CONFIG_PSCI_RESET is not set
CONFIG_ARMV8_PSCI=y
CONFIG_SYS_LOAD_ADDR=0x58000000
+CONFIG_LTO=y
CONFIG_REMAKE_ELF=y
CONFIG_SYS_MONITOR_LEN=1048576
CONFIG_FIT=y
diff --git a/configs/rcar3_ulcb_defconfig b/configs/rcar3_ulcb_defconfig
index 43361a2..1e96488 100644
--- a/configs/rcar3_ulcb_defconfig
+++ b/configs/rcar3_ulcb_defconfig
@@ -2,7 +2,7 @@
CONFIG_COUNTER_FREQUENCY=16666666
CONFIG_ARCH_CPU_INIT=y
CONFIG_ARCH_RMOBILE=y
-CONFIG_TEXT_BASE=0x50000000
+CONFIG_TEXT_BASE=0x0
CONFIG_SYS_MALLOC_LEN=0x4000000
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_ENV_SIZE=0x20000
@@ -13,6 +13,7 @@
CONFIG_RCAR_GEN3=y
CONFIG_TARGET_ULCB=y
CONFIG_SYS_LOAD_ADDR=0x58000000
+CONFIG_LTO=y
CONFIG_REMAKE_ELF=y
CONFIG_SYS_MONITOR_LEN=1048576
CONFIG_FIT=y
diff --git a/configs/ringneck-px30_defconfig b/configs/ringneck-px30_defconfig
new file mode 100644
index 0000000..dd332ec
--- /dev/null
+++ b/configs/ringneck-px30_defconfig
@@ -0,0 +1,129 @@
+CONFIG_ARM=y
+CONFIG_SKIP_LOWLEVEL_INIT=y
+CONFIG_COUNTER_FREQUENCY=24000000
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_TEXT_BASE=0x00200000
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_SPL_GPIO=y
+CONFIG_SPL_LIBCOMMON_SUPPORT=y
+CONFIG_SPL_LIBGENERIC_SUPPORT=y
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_DEFAULT_DEVICE_TREE="px30-ringneck-haikou"
+CONFIG_SPL_TEXT_BASE=0x00000000
+CONFIG_ROCKCHIP_PX30=y
+CONFIG_TARGET_RINGNECK_PX30=y
+CONFIG_TPL_LIBGENERIC_SUPPORT=y
+CONFIG_SPL_DRIVERS_MISC=y
+CONFIG_SPL_STACK_R_ADDR=0x600000
+CONFIG_DEBUG_UART_BASE=0xFF030000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_SYS_LOAD_ADDR=0x800800
+CONFIG_TPL_MAX_SIZE=0x20000
+CONFIG_DEBUG_UART=y
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x400000
+CONFIG_TPL_SYS_MALLOC_F_LEN=0x600
+# CONFIG_ANDROID_BOOT_IMAGE is not set
+CONFIG_FIT=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_SPL_LOAD_FIT=y
+CONFIG_DEFAULT_FDT_FILE="rockchip/px30-ringneck-haikou.dtb"
+# CONFIG_DISPLAY_CPUINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
+CONFIG_SPL_MAX_SIZE=0x20000
+CONFIG_SPL_PAD_TO=0x0
+CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
+CONFIG_SPL_BSS_START_ADDR=0x4000000
+CONFIG_SPL_BSS_MAX_SIZE=0x4000
+CONFIG_SPL_BOOTROM_SUPPORT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
+CONFIG_SPL_STACK=0x400000
+CONFIG_SPL_STACK_R=y
+CONFIG_SYS_SPL_MALLOC=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x200
+CONFIG_SPL_ATF=y
+# CONFIG_TPL_FRAMEWORK is not set
+# CONFIG_CMD_BOOTD is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_IMI is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_LZMADEC is not set
+# CONFIG_CMD_UNZIP is not set
+CONFIG_CMD_GPT=y
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_CMD_ITEST is not set
+# CONFIG_CMD_SETEXPR is not set
+# CONFIG_CMD_SLEEP is not set
+# CONFIG_SPL_DOS_PARTITION is not set
+# CONFIG_ISO_PARTITION is not set
+CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_OF_SPL_REMOVE_PROPS="interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_ENV_IS_IN_MMC=y
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_SPL_DM_SEQ_ALIAS=y
+CONFIG_REGMAP=y
+CONFIG_SPL_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_SPL_SYSCON=y
+CONFIG_BUTTON=y
+CONFIG_BUTTON_GPIO=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_FASTBOOT_BUF_ADDR=0x800800
+CONFIG_FASTBOOT_BUF_SIZE=0x04000000
+CONFIG_GPIO_HOG=y
+CONFIG_SPL_GPIO_HOG=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_MISC=y
+CONFIG_ROCKCHIP_OTP=y
+CONFIG_SUPPORT_EMMC_RPMB=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_PHY_TI_GENERIC=y
+CONFIG_PHY_GIGE=y
+CONFIG_ETH_DESIGNWARE=y
+CONFIG_GMAC_ROCKCHIP=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_PWM_ROCKCHIP=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_TPL_RAM=y
+CONFIG_ROCKCHIP_SDRAM_COMMON=y
+CONFIG_RAM_PX30_DDR4=y
+CONFIG_DM_RESET=y
+CONFIG_DM_RNG=y
+CONFIG_RNG_ROCKCHIP=y
+# CONFIG_SPECIFY_CONSOLE_INDEX is not set
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_SKIP_INIT=y
+CONFIG_SYS_NS16550_MEM32=y
+CONFIG_SOUND=y
+CONFIG_SYSRESET=y
+CONFIG_DM_THERMAL=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_SPL_TINY_MEMSET=y
+CONFIG_TPL_TINY_MEMSET=y
+CONFIG_LZO=y
+CONFIG_ERRNO_STR=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/roc-pc-mezzanine-rk3399_defconfig b/configs/roc-pc-mezzanine-rk3399_defconfig
index 6827c98..00239c2 100644
--- a/configs/roc-pc-mezzanine-rk3399_defconfig
+++ b/configs/roc-pc-mezzanine-rk3399_defconfig
@@ -22,6 +22,7 @@
# CONFIG_ANDROID_BOOT_IMAGE is not set
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-roc-pc-mezzanine.dtb"
CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
CONFIG_SPL_MAX_SIZE=0x2e000
CONFIG_SPL_PAD_TO=0x7f8000
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
@@ -50,6 +51,7 @@
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
@@ -67,7 +69,7 @@
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
# CONFIG_RAM_ROCKCHIP_DEBUG is not set
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_DM_RESET=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
diff --git a/configs/roc-pc-rk3399_defconfig b/configs/roc-pc-rk3399_defconfig
index 3e58db0..ed70ce0 100644
--- a/configs/roc-pc-rk3399_defconfig
+++ b/configs/roc-pc-rk3399_defconfig
@@ -23,6 +23,7 @@
CONFIG_USE_PREBOOT=y
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-roc-pc.dtb"
CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
CONFIG_SPL_MAX_SIZE=0x2e000
CONFIG_SPL_PAD_TO=0x7f8000
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
@@ -50,6 +51,7 @@
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_MISC=y
+CONFIG_ROCKCHIP_EFUSE=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
@@ -66,7 +68,7 @@
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
# CONFIG_RAM_ROCKCHIP_DEBUG is not set
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_DM_RESET=y
CONFIG_DM_RNG=y
CONFIG_RNG_ROCKCHIP=y
diff --git a/configs/rock-pi-4-rk3399_defconfig b/configs/rock-pi-4-rk3399_defconfig
index 7c49ccd..ac182ee 100644
--- a/configs/rock-pi-4-rk3399_defconfig
+++ b/configs/rock-pi-4-rk3399_defconfig
@@ -64,7 +64,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_DM_RESET=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
diff --git a/configs/rock-pi-4c-rk3399_defconfig b/configs/rock-pi-4c-rk3399_defconfig
index 4f61a0f..292436b 100644
--- a/configs/rock-pi-4c-rk3399_defconfig
+++ b/configs/rock-pi-4c-rk3399_defconfig
@@ -64,7 +64,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_DM_RESET=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig
index 5b8d678..3b4820c 100644
--- a/configs/rockpro64-rk3399_defconfig
+++ b/configs/rockpro64-rk3399_defconfig
@@ -9,6 +9,7 @@
CONFIG_DEFAULT_DEVICE_TREE="rk3399-rockpro64"
CONFIG_ROCKCHIP_RK3399=y
CONFIG_TARGET_ROCKPRO64_RK3399=y
+CONFIG_BOOTSTAGE_STASH_ADDR=0xff8e0000
CONFIG_DEBUG_UART_BASE=0xFF1A0000
CONFIG_DEBUG_UART_CLOCK=24000000
CONFIG_SPL_SPI_FLASH_SUPPORT=y
@@ -17,6 +18,12 @@
CONFIG_DEBUG_UART=y
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x300000
+CONFIG_BOOTSTAGE=y
+CONFIG_SPL_BOOTSTAGE=y
+CONFIG_TPL_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_SPL_BOOTSTAGE_RECORD_COUNT=10
+CONFIG_BOOTSTAGE_STASH=y
CONFIG_USE_PREBOOT=y
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-rockpro64.dtb"
CONFIG_DISPLAY_BOARDINFO_LATE=y
@@ -40,6 +47,7 @@
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_TIME=y
+CONFIG_CMD_BOOTSTAGE=y
CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
CONFIG_ENV_IS_IN_SPI_FLASH=y
@@ -71,7 +79,7 @@
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
-CONFIG_RAM_RK3399_LPDDR4=y
+CONFIG_RAM_ROCKCHIP_LPDDR4=y
CONFIG_DM_RESET=y
CONFIG_DM_RNG=y
CONFIG_RNG_ROCKCHIP=y
diff --git a/configs/sama7g5ek_mmc1_defconfig b/configs/sama7g5ek_mmc1_defconfig
index f004e44..ecb4dfc 100644
--- a/configs/sama7g5ek_mmc1_defconfig
+++ b/configs/sama7g5ek_mmc1_defconfig
@@ -79,3 +79,4 @@
CONFIG_MCHP_PIT64B_TIMER=y
CONFIG_OF_LIBFDT_OVERLAY=y
# CONFIG_EFI_LOADER_HII is not set
+CONFIG_PHANDLE_CHECK_SEQ=y
diff --git a/configs/sama7g5ek_mmc_defconfig b/configs/sama7g5ek_mmc_defconfig
index 5b42fc6..1d5bccd 100644
--- a/configs/sama7g5ek_mmc_defconfig
+++ b/configs/sama7g5ek_mmc_defconfig
@@ -79,3 +79,4 @@
CONFIG_MCHP_PIT64B_TIMER=y
CONFIG_OF_LIBFDT_OVERLAY=y
# CONFIG_EFI_LOADER_HII is not set
+CONFIG_PHANDLE_CHECK_SEQ=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index de799b5..34c342b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -13,6 +13,7 @@
CONFIG_FIT_RSASSA_PSS=y
CONFIG_FIT_CIPHER=y
CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
CONFIG_BOOTSTAGE=y
CONFIG_BOOTSTAGE_REPORT=y
CONFIG_BOOTSTAGE_FDT=y
@@ -72,6 +73,7 @@
CONFIG_CMD_I2C=y
CONFIG_CMD_LOADM=y
CONFIG_CMD_LSBLK=y
+CONFIG_CMD_MMC=y
CONFIG_CMD_MUX=y
CONFIG_CMD_OSD=y
CONFIG_CMD_PCI=y
@@ -130,7 +132,6 @@
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
CONFIG_ENV_IMPORT_FDT=y
-# CONFIG_BOOTDEV_ETH is not set
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
@@ -210,6 +211,7 @@
CONFIG_MMC_SDHCI=y
CONFIG_MTD=y
CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_BOOTDEV_SPI_FLASH=y
CONFIG_SPI_FLASH_ATMEL=y
CONFIG_SPI_FLASH_EON=y
CONFIG_SPI_FLASH_GIGADEVICE=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 88aaddf..477763d 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -11,6 +11,7 @@
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_FIT_VERBOSE=y
+CONFIG_LEGACY_IMAGE_FORMAT=y
CONFIG_BOOTSTAGE=y
CONFIG_BOOTSTAGE_REPORT=y
CONFIG_BOOTSTAGE_FDT=y
@@ -39,7 +40,9 @@
CONFIG_CMD_DEMO=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_GPT=y
+CONFIG_CMD_IDE=y
CONFIG_CMD_I2C=y
+CONFIG_CMD_MMC=y
CONFIG_CMD_OSD=y
CONFIG_CMD_PCI=y
CONFIG_CMD_REMOTEPROC=y
@@ -73,7 +76,6 @@
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
-# CONFIG_BOOTDEV_ETH is not set
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
@@ -89,6 +91,13 @@
CONFIG_ADC_SANDBOX=y
CONFIG_AXI=y
CONFIG_AXI_SANDBOX=y
+CONFIG_SYS_IDE_MAXBUS=1
+CONFIG_SYS_ATA_BASE_ADDR=0x100
+CONFIG_SYS_ATA_STRIDE=4
+CONFIG_SYS_ATA_DATA_OFFSET=0
+CONFIG_SYS_ATA_REG_OFFSET=1
+CONFIG_SYS_ATA_ALT_OFFSET=2
+CONFIG_SYS_ATA_IDE0_OFFSET=0
CONFIG_CLK=y
CONFIG_CLK_COMPOSITE_CCF=y
CONFIG_CLK_K210=y
@@ -129,6 +138,7 @@
CONFIG_I2C_EEPROM=y
CONFIG_MMC_SANDBOX=y
CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_BOOTDEV_SPI_FLASH=y
CONFIG_SPI_FLASH_ATMEL=y
CONFIG_SPI_FLASH_EON=y
CONFIG_SPI_FLASH_GIGADEVICE=y
@@ -209,6 +219,7 @@
CONFIG_RSA_VERIFY_WITH_PKEY=y
CONFIG_TPM=y
CONFIG_LZ4=y
+CONFIG_ZSTD=y
CONFIG_ERRNO_STR=y
# CONFIG_CMD_BOOTEFI_BOOTMGR is not set
CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig
index a122355..59e9a8d 100644
--- a/configs/sandbox_noinst_defconfig
+++ b/configs/sandbox_noinst_defconfig
@@ -236,6 +236,7 @@
CONFIG_RSA_VERIFY_WITH_PKEY=y
CONFIG_TPM=y
CONFIG_LZ4=y
+CONFIG_ZSTD=y
CONFIG_ERRNO_STR=y
CONFIG_UNIT_TEST=y
CONFIG_SPL_UNIT_TEST=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 4d70466..5316e0b 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -239,6 +239,7 @@
CONFIG_RSA_VERIFY_WITH_PKEY=y
CONFIG_TPM=y
CONFIG_LZ4=y
+CONFIG_ZSTD=y
CONFIG_ERRNO_STR=y
CONFIG_SPL_HEXDUMP=y
CONFIG_UNIT_TEST=y
diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig
index c94b059..1d434ec 100644
--- a/configs/sandbox_vpl_defconfig
+++ b/configs/sandbox_vpl_defconfig
@@ -254,6 +254,7 @@
CONFIG_RSA_VERIFY_WITH_PKEY=y
CONFIG_TPM=y
CONFIG_LZ4=y
+CONFIG_ZSTD=y
# CONFIG_VPL_LZMA is not set
CONFIG_ERRNO_STR=y
CONFIG_UNIT_TEST=y
diff --git a/configs/sheevaplug_defconfig b/configs/sheevaplug_defconfig
index 79f36c0..cb38a3f 100644
--- a/configs/sheevaplug_defconfig
+++ b/configs/sheevaplug_defconfig
@@ -16,9 +16,6 @@
CONFIG_DEFAULT_DEVICE_TREE="kirkwood-sheevaplug"
CONFIG_IDENT_STRING="\nMarvell-Sheevaplug"
CONFIG_SYS_LOAD_ADDR=0x800000
-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc8012000
-# CONFIG_SYS_MALLOC_F is not set
CONFIG_HAS_BOARD_SIZE_LIMIT=y
CONFIG_BOARD_SIZE_LIMIT=524288
CONFIG_BOOTDELAY=3
diff --git a/configs/snow_defconfig b/configs/snow_defconfig
index 6921c56..faa3a94 100644
--- a/configs/snow_defconfig
+++ b/configs/snow_defconfig
@@ -28,7 +28,11 @@
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x2050000
CONFIG_FIT=y
CONFIG_FIT_BEST_MATCH=y
+CONFIG_BOOTSTD_FULL=y
CONFIG_SILENT_CONSOLE=y
+CONFIG_BLOBLIST=y
+# CONFIG_SPL_BLOBLIST is not set
+CONFIG_BLOBLIST_ADDR=0x43d00000
# CONFIG_SPL_FRAMEWORK is not set
CONFIG_SPL_FOOTPRINT_LIMIT=y
CONFIG_SPL_MAX_FOOTPRINT=0x3800
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index fbbef7a..a5e1478 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -7,7 +7,6 @@
CONFIG_SUNXI_DRAM_LPDDR3_STOCK=y
CONFIG_DRAM_CLK=552
CONFIG_DRAM_ZQ=3881949
-CONFIG_MMC0_CD_PIN=""
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/starqltechn_defconfig b/configs/starqltechn_defconfig
index 7955076..7a64f2a 100644
--- a/configs/starqltechn_defconfig
+++ b/configs/starqltechn_defconfig
@@ -20,14 +20,14 @@
CONFIG_CMD_GPIO=y
CONFIG_CMD_BMP=y
# CONFIG_NET is not set
-# CONFIG_DM_STDIO is not set
CONFIG_CLK=y
CONFIG_MSM_GPIO=y
CONFIG_QCOM_PMIC_GPIO=y
CONFIG_PINCTRL=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_QCOM=y
-# CONFIG_REQUIRE_SERIAL_CONSOLE is not set
+CONFIG_REQUIRE_SERIAL_CONSOLE=y
+CONFIG_MSM_GENI_SERIAL=y
CONFIG_SPMI_MSM=y
CONFIG_VIDEO=y
CONFIG_SYS_WHITE_ON_BLACK=y
diff --git a/configs/stm32mp13_defconfig b/configs/stm32mp13_defconfig
index af6b183..ab82480 100644
--- a/configs/stm32mp13_defconfig
+++ b/configs/stm32mp13_defconfig
@@ -7,6 +7,7 @@
CONFIG_SYS_PROMPT="STM32MP> "
CONFIG_STM32MP13x=y
CONFIG_DDR_CACHEABLE_SIZE=0x10000000
+CONFIG_CMD_STM32KEY=y
CONFIG_TARGET_ST_STM32MP13x=y
CONFIG_ENV_OFFSET_REDUND=0x940000
# CONFIG_ARMV7_NONSEC is not set
@@ -26,6 +27,7 @@
CONFIG_CMD_MEMTEST=y
CONFIG_CMD_UNZIP=y
CONFIG_CMD_CLK=y
+CONFIG_CMD_FUSE=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_LSBLK=y
@@ -46,6 +48,7 @@
CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_DEV=-1
+CONFIG_ENV_MMC_USE_DT=y
CONFIG_CLK_SCMI=y
CONFIG_GPIO_HOG=y
CONFIG_DM_I2C=y
diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig
index 2d4b7cb..87e3b49 100644
--- a/configs/stm32mp15_basic_defconfig
+++ b/configs/stm32mp15_basic_defconfig
@@ -91,6 +91,7 @@
CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_DEV=-1
+CONFIG_ENV_MMC_USE_DT=y
# CONFIG_SPL_ENV_IS_NOWHERE is not set
# CONFIG_SPL_ENV_IS_IN_SPI_FLASH is not set
CONFIG_TFTP_TSIZE=y
@@ -166,6 +167,7 @@
CONFIG_DM_USB_GADGET=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_ONBOARD_HUB=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
CONFIG_USB_GADGET_VENDOR_NUM=0x0483
diff --git a/configs/stm32mp15_defconfig b/configs/stm32mp15_defconfig
index 22cf538..5dc0021 100644
--- a/configs/stm32mp15_defconfig
+++ b/configs/stm32mp15_defconfig
@@ -65,6 +65,7 @@
CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_DEV=-1
+CONFIG_ENV_MMC_USE_DT=y
CONFIG_TFTP_TSIZE=y
CONFIG_USE_SERVERIP=y
CONFIG_SERVERIP="192.168.1.1"
@@ -142,6 +143,7 @@
CONFIG_DM_USB_GADGET=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_ONBOARD_HUB=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
CONFIG_USB_GADGET_VENDOR_NUM=0x0483
diff --git a/configs/stm32mp15_trusted_defconfig b/configs/stm32mp15_trusted_defconfig
index e00c00f..c1ad4dd 100644
--- a/configs/stm32mp15_trusted_defconfig
+++ b/configs/stm32mp15_trusted_defconfig
@@ -66,6 +66,7 @@
CONFIG_ENV_UBI_VOLUME_REDUND="uboot_config_r"
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_DEV=-1
+CONFIG_ENV_MMC_USE_DT=y
CONFIG_TFTP_TSIZE=y
CONFIG_USE_SERVERIP=y
CONFIG_SERVERIP="192.168.1.1"
@@ -142,6 +143,7 @@
CONFIG_DM_USB_GADGET=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
+CONFIG_USB_ONBOARD_HUB=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="STMicroelectronics"
CONFIG_USB_GADGET_VENDOR_NUM=0x0483
diff --git a/configs/tanix_tx6_defconfig b/configs/tanix_tx6_defconfig
index 0390347..d734392 100644
--- a/configs/tanix_tx6_defconfig
+++ b/configs/tanix_tx6_defconfig
@@ -5,6 +5,5 @@
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_DDR3_1333=y
CONFIG_DRAM_CLK=648
-CONFIG_MMC0_CD_PIN="PF6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig
index de99f38..23e1f0e 100644
--- a/configs/tools-only_defconfig
+++ b/configs/tools-only_defconfig
@@ -3,10 +3,13 @@
CONFIG_ENV_SIZE=0x2000
CONFIG_DEFAULT_DEVICE_TREE="sandbox"
CONFIG_SYS_LOAD_ADDR=0x0
+# CONFIG_SANDBOX_SDL is not set
CONFIG_ANDROID_BOOT_IMAGE=y
CONFIG_FIT=y
CONFIG_TIMESTAMP=y
CONFIG_FIT_SIGNATURE=y
+# CONFIG_BOOTSTD_FULL is not set
+# CONFIG_BOOTMETH_VBE is not set
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="run distro_bootcmd"
# CONFIG_CMD_BOOTD is not set
@@ -27,7 +30,6 @@
CONFIG_SOUND=y
CONFIG_SYSRESET=y
CONFIG_TIMER=y
-CONFIG_VIDEO=y
# CONFIG_VIRTIO_MMIO is not set
# CONFIG_VIRTIO_PCI is not set
# CONFIG_VIRTIO_SANDBOX is not set
diff --git a/configs/x96_mate_defconfig b/configs/x96_mate_defconfig
index 4276f4f..38b82c3 100644
--- a/configs/x96_mate_defconfig
+++ b/configs/x96_mate_defconfig
@@ -4,7 +4,6 @@
CONFIG_SPL=y
CONFIG_DRAM_SUN50I_H616_READ_CALIBRATION=y
CONFIG_MACH_SUN50I_H616=y
-CONFIG_MMC0_CD_PIN="PF6"
CONFIG_R_I2C_ENABLE=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/disk/part.c b/disk/part.c
index 5ee60a7..d449635 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -770,3 +770,19 @@
sprintf(name, "%s%c%d", devtype, 'a' + dev_desc->devnum, part_num);
}
+
+int part_get_bootable(struct blk_desc *desc)
+{
+ struct disk_partition info;
+ int p;
+
+ for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
+ int ret;
+
+ ret = part_get_info(desc, p, &info);
+ if (!ret && info.bootable)
+ return p;
+ }
+
+ return 0;
+}
diff --git a/doc/README.davinci b/doc/README.davinci
index 326efa0..f368f99 100644
--- a/doc/README.davinci
+++ b/doc/README.davinci
@@ -58,7 +58,7 @@
device specific datasheet before setting up this variable. This information is
passed to the Linux kernel using the ATAG_REVISION atag.
-If "maxcpuclk" is not defined, the configuration CONFIG_DA850_EVM_MAX_CPU_CLK
+If "maxcpuclk" is not defined, the configuration CFG_DA850_EVM_MAX_CPU_CLK
is used to obtain this information.
Links
diff --git a/doc/README.fec_mxc b/doc/README.fec_mxc
index 2ccd428..a33f4a7 100644
--- a/doc/README.fec_mxc
+++ b/doc/README.fec_mxc
@@ -7,7 +7,7 @@
CONFIG_MII
Must be defined if CONFIG_FEC_MXC is defined.
-CONFIG_FEC_MXC_SWAP_PACKET
+CFG_FEC_MXC_SWAP_PACKET
Forced on iff MX28.
Swaps the bytes order of all words(4 byte units) in the packet.
This should not be specified by a board file. It is cpu specific.
diff --git a/doc/README.gpio b/doc/README.gpio
index 548ff37..d253f65 100644
--- a/doc/README.gpio
+++ b/doc/README.gpio
@@ -2,10 +2,8 @@
GPIO hog (CONFIG_GPIO_HOG)
--------
-All the GPIO hog are initialized in gpio_hog_probe_all() function called in
-board_r.c just before board_late_init() but you can also acces directly to
-the gpio with gpio_hog_lookup_name().
-
+All the GPIO hog are initialized using DM_FLAG_PROBE_AFTER_BIND DM flag
+after bind().
Example, for the device tree:
diff --git a/doc/README.gpt b/doc/README.gpt
index 91e397d..386ac2e 100644
--- a/doc/README.gpt
+++ b/doc/README.gpt
@@ -177,7 +177,7 @@
"name=u-boot,size=60MiB;name=boot,size=60Mib,bootable;name=rootfs,size=0"
It can be used to locate bootable disks with command
"part list <interface> <dev> -bootable <varname>",
- please check out doc/README.distro for use.
+ please check out doc/develop/distro.rst for use.
2. Define 'CONFIG_EFI_PARTITION' and 'CONFIG_CMD_GPT'
@@ -260,7 +260,7 @@
For created partition, the used partition type GUID is
PARTITION_BASIC_DATA_GUID (EBD0A0A2-B9E5-4433-87C0-68B6B72699C7).
-If you define 'CONFIG_PARTITION_TYPE_GUID', a optionnal parameter 'type'
+If you define 'CONFIG_PARTITION_TYPE_GUID', an optional parameter 'type'
can specify a other partition type guid:
"uuid_disk=...;name=u-boot,size=60MiB,uuid=...;
diff --git a/doc/README.socfpga b/doc/README.socfpga
index 4d73398..e5adb62 100644
--- a/doc/README.socfpga
+++ b/doc/README.socfpga
@@ -6,16 +6,6 @@
based SOCFPGA. To know more about the hardware itself, please refer to
www.altera.com.
-
-socfpga_dw_mmc
---------------
-
-Here are macro and detailed configuration required to enable DesignWare SDMMC
-controller support within SOCFPGA
-
-#define CONFIG_SYS_MMC_MAX_BLK_COUNT 256
--> Using smaller max blk cnt to avoid flooding the limited stack in OCRAM
-
---------------------------------------------------------------------
Cyclone 5 / Arria 5 generating the handoff header files for U-Boot SPL
---------------------------------------------------------------------
diff --git a/doc/README.uniphier b/doc/README.uniphier
index badfacd..af746f6 100644
--- a/doc/README.uniphier
+++ b/doc/README.uniphier
@@ -336,7 +336,7 @@
--------------------------
UniPhier SoC family boot the kernel in a generic manner as described in
-doc/README.distro .
+doc/develop/distro.rst.
To boot the kernel, you need to deploy necesssary components to a file
system on one of your block devices (eMMC, NAND, USB drive, etc.).
diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst
index 7611f07..1ad8a89 100644
--- a/doc/android/fastboot.rst
+++ b/doc/android/fastboot.rst
@@ -28,6 +28,7 @@
- ``oem partconf`` - this executes ``mmc partconf %x <arg> 0`` to configure eMMC
with <arg> = boot_ack boot_partition
- ``oem bootbus`` - this executes ``mmc bootbus %x %s`` to configure eMMC
+- ``oem run`` - this executes an arbitrary U-Boot command
Support for both eMMC and NAND devices is included.
@@ -227,6 +228,23 @@
Starting kernel ...
+Running Shell Commands
+^^^^^^^^^^^^^^^^^^^^^^
+
+Normally, arbitrary U-Boot command execution is not enabled. This is so
+fastboot can be used to update systems using verified boot. However, such
+functionality can be useful for production or when verified boot is not in use.
+Enable ``CONFIG_FASTBOOT_OEM_RUN`` to use this functionality. This will enable
+``oem run`` command, which can be used with the fastboot client. For example,
+to print "Hello at 115200 baud" (or whatever ``CONFIG_BAUDRATE`` is), run::
+
+ $ fastboot oem run:'echo Hello at $baudrate baud'
+
+You can run any command you would normally run on the U-Boot command line,
+including multiple commands (using e.g. ``;`` or ``&&``) and control structures
+(``if``, ``while``, etc.). The exit code of ``fastboot`` will reflect the exit
+code of the command you ran.
+
References
----------
diff --git a/doc/board/emulation/qemu-x86.rst b/doc/board/emulation/qemu-x86.rst
index db842f2..e7dd4e9 100644
--- a/doc/board/emulation/qemu-x86.rst
+++ b/doc/board/emulation/qemu-x86.rst
@@ -57,7 +57,8 @@
U-Boot uses 'distro_bootcmd' by default when booting on x86 QEMU. This tries to
load a boot script, kernel, and ramdisk from several different interfaces. For
the default boot order, see 'qemu-x86.h'. For more information, see
-'README.distro'. Most Linux distros can be booted by writing a uboot script.
+'doc/develop/distro.rst'. Most Linux distros can be booted by writing a uboot
+script.
For example, Debian (stretch) can be booted by creating a script file named
'boot.txt' with the contents::
diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst
index 8edbf04..23e2db4 100644
--- a/doc/board/google/chromebook_coral.rst
+++ b/doc/board/google/chromebook_coral.rst
@@ -259,7 +259,7 @@
U-Boot (running from start_from_spl.S) starts running in RAM and uses the same
stack as SPL. It does various init activities before relocation. Notably
-arch_cpu_init_dm() sets up the pin muxing for the chip using a very large table
+fsp_setup_pinctrl() sets up the pin muxing for the chip using a very large table
in the device tree.
PCI auto-config is not used before relocation, but CONFIG_PCI of course is
diff --git a/doc/board/intel/edison.rst b/doc/board/intel/edison.rst
index 5a65673..782d75a 100644
--- a/doc/board/intel/edison.rst
+++ b/doc/board/intel/edison.rst
@@ -90,7 +90,7 @@
.. code-block:: none
- lsusb | egrep "8087|8086"
+ lsusb | grep -E "8087|8086"
Bus 001 Device 004: ID 8086:e005 Intel Corp.
If you see a device with the same ID as above, the board is waiting for your
diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst
index 4ca7b00..28c837a 100644
--- a/doc/board/rockchip/rockchip.rst
+++ b/doc/board/rockchip/rockchip.rst
@@ -27,6 +27,7 @@
- Engicam PX30.Core C.TOUCH 2.0 10.1 (px30-core-ctouch2-of10-px30)
- Engicam PX30.Core EDIMM2.2 Starter Kit (px30-core-edimm2.2-px30)
- Firefly Core-PX30-JD4 (firefly-px30)
+ - Theobroma Systems PX30-µQ7 SoM - Ringneck (ringneck-px30)
* rk3036
- Rockchip Evb-RK3036 (evb-rk3036)
- Kylin (kylin_rk3036)
@@ -89,6 +90,9 @@
- Rockchip Evb-rv1108 (evb-rv1108)
- Elgin-R1 (elgin-rv1108)
+* rv1126
+ - Edgeble Neural Compute Module 2 SoM - Neu2/Neu2k (neu2-io-r1126)
+
Building
--------
diff --git a/doc/board/st/stm32mp1.rst b/doc/board/st/stm32mp1.rst
index 3759df3..3f70634 100644
--- a/doc/board/st/stm32mp1.rst
+++ b/doc/board/st/stm32mp1.rst
@@ -478,7 +478,7 @@
+-------+--------+---------+------------------------+------------------------+
And the 4th partition (Rootfs) is marked bootable with a file extlinux.conf
-following the Generic Distribution feature (doc/README.distro for use).
+following the Generic Distribution feature (doc/develop/distro.rst for use).
The size of fip or ssbl partition must be enough for the associated binary file,
4MB and 2MB are default values.
@@ -620,7 +620,7 @@
STM32MP> env print ethaddr
## Error: "ethaddr" not defined
-3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 1=locked)::
+3) check lock status of fuse 57 & 58 (at 0x39, 0=unlocked, 0x40000000=locked)::
STM32MP> fuse sense 0 0x10000039 2
Sensing bank 0:
@@ -640,11 +640,11 @@
3) Lock OTP::
- STM32MP> fuse prog 0 0x10000039 1 1
+ STM32MP> fuse prog 0 0x10000039 0x40000000 0x40000000
STM32MP> fuse sense 0 0x10000039 2
Sensing bank 0:
- Word 0x10000039: 00000001 00000001
+ Word 0x10000039: 40000000 40000000
4) next REBOOT, in the trace::
diff --git a/doc/board/tbs/tbs2910.rst b/doc/board/tbs/tbs2910.rst
index e97f2b6..9d4be61 100644
--- a/doc/board/tbs/tbs2910.rst
+++ b/doc/board/tbs/tbs2910.rst
@@ -181,7 +181,7 @@
'distro_bootcmd': It will first try to boot from the microSD slot, then the
SD slot, then the internal eMMC, then the SATA interface and finally the USB
interface. For more information on how to configure your distribution to boot,
-see 'README.distro'.
+see 'doc/develop/distro.rst'.
Links:
------
diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst
index 1ccc494..281aabf 100644
--- a/doc/develop/bootstd.rst
+++ b/doc/develop/bootstd.rst
@@ -71,8 +71,14 @@
filesystems that might contain things related to an operating system.
For example, an MMC bootdev provides access to the individual partitions on the
-MMC device. It scans through these to find filesystems, then provides a list of
-these for consideration.
+MMC device. It scans through these to find filesystems with the boot flag set,
+then provides a list of these for consideration.
+
+Some bootdevs are not visible until a bus is enumerated, e.g. flash sticks
+attached via USB. To deal with this, each bootdev has an associated 'hunter'
+which can hunt for bootdevs of a particular uclass type. For example, the SCSI
+bootdev scans the SCSI bus looking for devices, creating a bootdev for each
+Logical Unit Number (LUN) that it finds.
Bootmeth
@@ -175,7 +181,10 @@
available.
A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this
-function for each media device uclass, in a few lines of code.
+function for each media device uclass, in a few lines of code. For many types
+ot bootdevs, the `get_bootflow` member can be NULL, indicating that the default
+handler is used. This is called `default_get_bootflow()` and it only works with
+block devices.
Bootdev drivers
@@ -183,41 +192,16 @@
A bootdev driver is typically fairly simple. Here is one for mmc::
- static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
- struct bootflow *bflow)
- {
- struct udevice *mmc_dev = dev_get_parent(dev);
- struct udevice *blk;
- int ret;
-
- ret = mmc_get_blk(mmc_dev, &blk);
- /*
- * If there is no media, indicate that no more partitions should be
- * checked
- */
- if (ret == -EOPNOTSUPP)
- ret = -ESHUTDOWN;
- if (ret)
- return log_msg_ret("blk", ret);
- assert(blk);
- ret = bootdev_find_in_blk(dev, blk, iter, bflow);
- if (ret)
- return log_msg_ret("find", ret);
-
- return 0;
- }
-
static int mmc_bootdev_bind(struct udevice *dev)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
- ucp->prio = BOOTDEVP_0_INTERNAL_FAST;
+ ucp->prio = BOOTDEVP_2_INTERNAL_FAST;
return 0;
}
struct bootdev_ops mmc_bootdev_ops = {
- .get_bootflow = mmc_get_bootflow,
};
static const struct udevice_id mmc_bootdev_ids[] = {
@@ -233,15 +217,77 @@
.of_match = mmc_bootdev_ids,
};
-The implementation of the `get_bootflow()` method is simply to obtain the
-block device and call a bootdev helper function to do the rest. The
+You may notice that the `get_bootflow` memory is not provided, so is NULL. This
+means that `default_get_bootflow()` is used. This simply obtains the
+block device and calls a bootdev helper function to do the rest. The
implementation of `bootdev_find_in_blk()` checks the partition table, and
attempts to read a file from a filesystem on the partition number given by the
-`@iter->part` parameter.
+`@iter->part` parameter. If there are any bootable partitions in the table,
+then only bootable partitions are considered.
-Each bootdev has a priority, which indicates the order in which it is used.
-Faster bootdevs are used first, since they are more likely to be able to boot
-the device quickly.
+Each bootdev has a priority, which indicates the order in which it is used,
+if `boot_targets` is not used. Faster bootdevs are used first, since they are
+more likely to be able to boot the device quickly.
+
+
+Environment Variables
+---------------------
+
+Various environment variables are used by standard boot. These allow the board
+to control where things are placed when booting the OS. You should ensure that
+your boards sets values for these.
+
+fdtfile
+ Name of the flattened device tree (FDT) file to load, e.g.
+ "rockchip/rk3399-rockpro64.dtb"
+
+fdtaddr_addr_r
+ Address at which to load the FDT, e.g. 0x01f00000
+
+fdtoverlay_addr_r (needed if overlays are used)
+ Address at which to load the overlay for the FDT, e.g. 0x02000000
+
+kernel_addr_r
+ Address at which to load the kernel, e.g. 0x02080000
+
+kernel_comp_addr_r
+ Address to which to decompress the kernel, e.g. 0x08000000
+
+kernel_comp_size
+ Size of available space for decompressed kernel, e.g. 0x2000000
+
+pxefile_addr_r
+ Address at which to load the PXE file, e.g. 0x00600000
+
+ramdisk_addr_r
+ Address at which to load the ramdisk, e.g. 0x06000000
+
+scriptaddr
+ Address at which to load the U-Boot script, e.g. 0x00500000
+
+script_offset_f
+ SPI flash offset from which to load the U-Boot script, e.g. 0xffe000
+
+script_size_f
+ Size of the script to load, e.g. 0x2000
+
+Some variables are set by script bootmeth:
+
+devtype
+ Device type being used for boot, e.g. mmc
+
+devnum
+ Device number being used for boot, e.g. 1
+
+distro_bootpart
+ Partition being used for boot, e.g. 2
+
+prefix
+ Directory containing the script
+
+mmc_bootdev
+ Device number being used for boot (e.g. 1). This is only used by MMC on
+ sunxi boards.
Device hierarchy
@@ -259,13 +305,22 @@
bootdev 1 [ ] mmc_bootdev | | `-- sdhci@7e300000.bootdev
The bootdev device is typically created automatically in the media uclass'
-`post_bind()` method by calling `bootdev_setup_for_dev()`. The code typically
-something like this::
+`post_bind()` method by calling `bootdev_setup_for_dev()` or
+`bootdev_setup_sibling_blk()`. The code typically something like this::
+ /* dev is the Ethernet device */
ret = bootdev_setup_for_dev(dev, "eth_bootdev");
if (ret)
return log_msg_ret("bootdev", ret);
+or::
+
+ /* blk is the block device (child of MMC device)
+ ret = bootdev_setup_sibling_blk(blk, "mmc_bootdev");
+ if (ret)
+ return log_msg_ret("bootdev", ret);
+
+
Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev`
is the ethernet device. This function is safe to call even if standard boot is
not enabled, since it does nothing in that case. It can be added to all uclasses
@@ -337,6 +392,10 @@
option also. For example, `CONFIG_BOOTMETH_DISTRO` enables support for distro
boot from a disk.
+To enable all feature sof standard boot, use `CONFIG_BOOTSTD_FULL`. This
+includes the full set of commands, more error messages when things go wrong and
+bootmeth ordering with the bootmeths environment variable.
+
Available bootmeth drivers
--------------------------
@@ -345,7 +404,8 @@
- distro boot from a disk (syslinux)
- distro boot from a network (PXE)
- - EFI boot using bootefi
+ - U-Boot scripts from disk, network or SPI flash
+ - EFI boot using bootefi from disk
- VBE
- EFI boot using boot manager
@@ -412,26 +472,49 @@
devices and one or more bootmeth devices.
Once these are ready, typically a `bootflow scan` command is issued. This kicks
-of the iteration process, which involves looking through the bootdevs and their
-partitions one by one to find bootflows.
+of the iteration process, which involves hunting for bootdevs and looking
+through the bootdevs and their partitions one by one to find bootflows.
-Iteration is kicked off using `bootflow_scan_first()`, which calls
-`bootflow_scan_bootdev()`.
+Iteration is kicked off using `bootflow_scan_first()`.
The iterator is set up with `bootflow_iter_init()`. This simply creates an
empty one with the given flags. Flags are used to control whether each
iteration is displayed, whether to return iterations even if they did not result
in a valid bootflow, whether to iterate through just a single bootdev, etc.
-Then the ordering of bootdevs is determined, by `bootdev_setup_iter_order()`. By
-default, the bootdevs are used in the order specified by the `boot_targets`
-environment variable (e.g. "mmc2 mmc0 usb"). If that is missing then their
-sequence order is used, as determined by the `/aliases` node, or failing that
-their order in the devicetree. For BOOTSTD_FULL, if there is a `bootdev-order`
-property in the bootstd node, then this is used as a final fallback. In any
-case, the iterator ends up with a `dev_order` array containing the bootdevs that
-are going to be used, with `num_devs` set to the number of bootdevs and
-`cur_dev` starting at 0.
+Then the iterator is set up to according to the parameters given:
+
+- When `dev` is provided, then a single bootdev is scanned. In this case,
+ `BOOTFLOWF_SKIP_GLOBAL` and `BOOTFLOWF_SINGLE_DEV` are set. No hunters are
+ used in this case
+
+- Otherwise, when `label` is provided, then a single label or named bootdev is
+ scanned. In this case `BOOTFLOWF_SKIP_GLOBAL` is set and there are three
+ options (with an effect on the `iter_incr()` function described later):
+
+ - If `label` indicates a numeric bootdev number (e.g. "2") then
+ `BOOTFLOW_METHF_SINGLE_DEV` is set. In this case, moving to the next bootdev
+ simple stops, since there is only one. No hunters are used.
+ - If `label` indicates a particular media device (e.g. "mmc1") then
+ `BOOTFLOWF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev
+ processes just the children of the media device. Hunters are used, in this
+ example just the "mmc" hunter.
+ - If `label` indicates a media uclass (e.g. "mmc") then
+ `BOOTFLOWF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass
+ are used. Hunters are used, in this example just the "mmc" hunter
+
+- Otherwise, none of the above flags is set and iteration is set up to work
+ through `boot_targets` environment variable (or `bootdev-order` device tree
+ property) in order, running the relevant hunter first. In this case
+ `cur_label` is used to indicate the label being processed. If there is no list
+ of labels, then all bootdevs are processed in order of priority, running the
+ hunters as it goes.
+
+With the above it is therefore possible to iterate in a variety of ways.
+
+No attempt is made to determine the ordering of bootdevs, since this cannot be
+known in advance if we are using the hunters. Any hunter might discover a new
+bootdev and disturb the original ordering.
Next, the ordering of bootmeths is determined, by `bootmeth_setup_iter_order()`.
By default the ordering is again by sequence number, i.e. the `/aliases` node,
@@ -446,21 +529,21 @@
first. Once all have been used, these bootmeths are dropped from the iteration.
When there are no global bootmeths, `cur_method` is set to 0.
-At this point the iterator is ready to use, with the first bootdev and bootmeth
-selected. Most of the other fields are 0. This means that the current partition
+At this point the iterator is ready to use, with the first bootmeth selected.
+Most of the other fields are 0. This means that the current partition
is 0, which is taken to mean the whole device, since partition numbers start at
1. It also means that `max_part` is 0, i.e. the maximum partition number we know
about is 0, meaning that, as far as we know, there is no partition table on this
bootdev.
-With the iterator ready, `bootflow_scan_bootdev()` checks whether the current
+With the iterator ready, `bootflow_scan_first()` checks whether the current
settings produce a valid bootflow. This is handled by `bootflow_check()`, which
either returns 0 (if it got something) or an error if not (more on that later).
If the `BOOTFLOWF_ALL` iterator flag is set, even errors are returned as
incomplete bootflows, but normally an error results in moving onto the next
iteration.
-Note that `bootflow_check()` handles global bootmeths explicitly, but calling
+Note that `bootflow_check()` handles global bootmeths explicitly, by calling
`bootmeth_get_bootflow()` on each one. The `doing_global` flag indicates when
the iterator is in that state.
@@ -468,7 +551,7 @@
checking it. In fact it sits in a loop doing that repeatedly until it finds
something it wants to return.
-The actual 'moving on' part is implemented in `iter_incr()`. This is a very
+The actual 'moving on' part is implemented in `iter_incr()`. This is a fairly
simple function. It increments the first counter. If that hits its maximum, it
sets it to zero and increments the second counter. You can think of all the
counters together as a number with three digits which increment in order, with
@@ -522,6 +605,12 @@
The changeover of the value of `doing_global` from true to false is handled in
`iter_incr()` as well.
+Note that the value in the `bootdev` column above is not actually stored - it is
+just for illustration. In practice, `iter_incr()` uses the flags to determine
+whether to move to the next bootdev in the uclass, the next child of the media
+device, the next label, or the next priority level, depending on the flag
+settings (see `BOOTFLOW_METHF_SINGLE_DEV`, etc. above).
+
There is no expectation that iteration will actually finish. Quite often a
valid bootflow is found early on. With `bootflow scan -b`, that causes the
bootflow to be immediately booted. Assuming it is successful, the iteration never
@@ -567,9 +656,9 @@
Going down a level, what does the bootdev do in its `get_bootflow()` method?
Let us consider the MMC bootdev. In that case the call to
-`bootdev_get_bootflow()` ends up in `mmc_get_bootflow()`. It locates the parent
-device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds the block
-device associated with it. It then calls the helper function
+`bootdev_get_bootflow()` ends up in `default_get_bootflow()`. It locates the
+parent device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds
+the block device associated with it. It then calls the helper function
`bootdev_find_in_blk()` to do all the work. This is common with just about any
bootdev that is based on a media device.
@@ -586,7 +675,9 @@
Note: At present a filesystem is needed for the bootmeth to be called on block
devices, simply because we don't have any examples where this is not the case.
-This feature can be added as needed.
+This feature can be added as needed. Note that sandbox is a special case, since
+in that case the host filesystem can be accessed even though the block device
+is NULL.
If we take the example of the `bootmeth_distro` driver, this call ends up at
`distro_read_bootflow()`. It has the filesystem ready, so tries various
@@ -594,9 +685,9 @@
all goes well the bootflow ends up in the `BOOTFLOWST_READY` state.
At this point, we fall back from the bootmeth driver, to
-`bootdev_find_in_blk()`, then back to `mmc_get_bootflow()`, then to
+`bootdev_find_in_blk()`, then back to `default_get_bootflow()`, then to
`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller,
-either `bootflow_scan_bootdev()` or `bootflow_scan_next()`. In either case,
+either `bootflow_scan_first()` or `bootflow_scan_next()`. In either case,
the bootflow is returned as the result of this iteration, assuming it made it to
the `BOOTFLOWST_READY` state.
@@ -625,9 +716,9 @@
the commands. All tests use sandbox so can be run on a standard Linux computer
and in U-Boot's CI.
-For testing, a DOS-formatted disk image is used with a single FAT partition on
-it. This is created in `setup_bootflow_image()`, with a canned one from the
-source tree used if it cannot be created (e.g. in CI).
+For testing, a DOS-formatted disk image is used with a FAT partition on it and
+a second unused partition. This is created in `setup_bootflow_image()`, with a
+canned one from the source tree used if it cannot be created (e.g. in CI).
Bootflow internals
diff --git a/doc/develop/driver-model/nvme.rst b/doc/develop/driver-model/nvme.rst
index fd0c0f0..7551813 100644
--- a/doc/develop/driver-model/nvme.rst
+++ b/doc/develop/driver-model/nvme.rst
@@ -27,7 +27,7 @@
------------
There is an NVMe uclass driver (driver name "nvme"), an NVMe host controller
driver (driver name "nvme") and an NVMe namespace block driver (driver name
-"nvme-blk"). The host controller driver is supposed to probe the hardware and
+"nvme_blk"). The host controller driver is supposed to probe the hardware and
do necessary initialization to put the controller into a ready state at which
it is able to scan all available namespaces attached to it. Scanning namespace
is triggered by the NVMe uclass driver and the actual work is done in the NVMe
diff --git a/doc/develop/environment.rst b/doc/develop/environment.rst
index 0b86faf..e178346 100644
--- a/doc/develop/environment.rst
+++ b/doc/develop/environment.rst
@@ -18,7 +18,7 @@
U_BOOT_ENV_CALLBACK macro in your board or driver code.
These callbacks are associated with variables in one of two ways. The
-static list can be added to by defining CONFIG_ENV_CALLBACK_LIST_STATIC
+static list can be added to by defining CFG_ENV_CALLBACK_LIST_STATIC
in the board configuration to a string that defines a list of
associations. The list must be in the following format::
diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst
new file mode 100644
index 0000000..32dd7f0
--- /dev/null
+++ b/doc/develop/expo.rst
@@ -0,0 +1,188 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Expo menu
+=========
+
+U-Boot provides a menu implementation for use with selecting bootflows and
+changing U-Boot settings. This is in early stages of development.
+
+Motivation
+----------
+
+U-Boot already has a text-based menu system accessed via the
+:doc:`../usage/cmd/bootmenu`. This works using environment variables, or via
+some EFI-specific hacks.
+
+The command makes use of a lower-level `menu` implementation, which is quite
+flexible and can be used to make menu hierarchies.
+
+However this system is not flexible enough for use with standard boot. It does
+not support a graphical user interface and cannot currently support anything
+more than a very simple list of items. While it does support multiple menus in
+hierarchies, these are implemented by the caller. See for example `eficonfig.c`.
+
+Another challenge with the current menu implementation is that it controls
+the event loop, such that bootmenu_loop() does not return until a key is
+pressed. This makes it difficult to implement dynamic displays or to do other
+things while the menu is running, such as searching for more bootflows.
+
+For these reasons an attempt has been made to develop a more flexible system
+which can handle menus as well as other elements. This is called 'expo', short
+for exposition, in an attempt to avoid common words like display, screen, menu
+and the like. The primary goal is to support Verified Boot for Embedded (VBE),
+although it is available to any boot method, using the 'bootflow menu' command.
+
+Efforts have been made to use common code with the existing menu, including
+key processing in particular.
+
+Previous work looked at integrating Nuklear into U-Boot. This works fine and
+could provide a way to provide a more flexible UI, perhaps with expo dealing
+with the interface to Nuklear. But this is quite a big step and it may be years
+before this becomes desirable, if at all. For now, U-Boot only needs a fairly
+simple set of menus and options, so rendering them directly is fairly
+straightforward.
+
+Concepts
+--------
+
+The creator of the expo is here called a `controller` and it controls most
+aspects of the expo. This is the code that you must write to use expo.
+
+An `expo` is a set of scenes which can be presented to the user one at a time,
+to show information and obtain input from the user.
+
+A `scene` is a collection of objects which are displayed together on the screen.
+Only one scene is visible at a time and scenes do not share objects.
+
+A `scene object` is something that appears in the scene, such as some text, an
+image or a menu. Objects can be positioned and hidden.
+
+A `menu object` contains a title, a set of `menu items` and a pointer to the
+current item. Menu items consist of a keypress (indicating what to press to
+select the item), label and description. All three are shown in a single line
+within the menu. Items can also have a preview image, which is shown when the
+item is highlighted.
+
+All components have a name. This is purely for debugging, so it is easy to see
+what object is referred to. Of course the ID numbers can help as well, but they
+are less easy to distinguish.
+
+While the expo implementation provides support for handling keypresses and
+rendering on the display or serial port, it does not actually deal with reading
+input from the user, nor what should be done when a particular menu item is
+selected. This is deliberate since having the event loop outside the expo is
+more flexible, particularly in a single-threaded environment like U-Boot.
+
+Everything within an expo has a unique ID number. This is done so that it is
+easy to refer to things after the expo has been created. The expectation is that
+the controller declares an enum containing all of the elements in the expo,
+passing the ID of each object as it is created. When a menu item is selected,
+its ID is returned. When a object's font or position needs to change, the ID is
+passed to expo functions to indicate which object it is. It is possible for expo
+to auto-allocate IDs, but this is not recommended. The use of IDs is a
+convenience, removing the need for the controller to store pointers to objects,
+or even the IDs of objects. Programmatic creation of many items in a loop can be
+handled by allocating space in the enum for a maximum number of items, then
+adding the loop count to the enum values to obtain unique IDs.
+
+All text strings are stored in a structure attached to the expo, referenced by
+a text ID. This makes it easier at some point to implement multiple languages or
+to support Unicode strings.
+
+Menu objects do not have their own text and image objects. Instead they simply
+refer to objects which have been created. So a menu item is just a collection
+of IDs of text and image objects. When adding a menu item you must create these
+objects first, then create the menu item, passing in the relevant IDs.
+
+Creating an expo
+----------------
+
+To create an expo, use `expo_new()` followed by `scene_new()` to create a scene.
+Then add objects to the scene, using functions like `scene_txt_str()` and
+`scene_menu()`. For every menu item, add text and image objects, then create
+the menu item with `scene_menuitem()`, referring to those objects.
+
+Layout
+------
+
+Individual objects can be positioned using `scene_obj_set_pos()`. Menu items
+cannot be positioned manually: this is done by `scene_arrange()` which is called
+automatically when something changes. The menu itself determines the position of
+its items.
+
+Rendering
+---------
+
+Rendering is performed by calling `expo_render()`. This uses either the
+vidconsole, if present, or the serial console in `text mode`. Expo handles
+presentation automatically in either case, without any change in how the expo is
+created.
+
+For the vidconsole, Truetype fonts can be used if enabled, to enhance the
+quality of the display. For text mode, each menu item is shown in a single line,
+allowing easy selection using arrow keys.
+
+Input
+-----
+
+The controller is responsible for collecting keyboard input. A good way to do
+this is to use `cli_ch_process()`, since it handles conversion of escape
+sequences into keys. However, expo has some special menu-key codes for
+navigating the interface. These are defined in `enum bootmenu_key` and include
+`BKEY_UP` for moving up and `BKEY_SELECT` for selecting an item. You can use
+`bootmenu_conv_key()` to convert an ASCII key into one of these.
+
+Once a keypress is decoded, call `expo_send_key()` to send it to the expo. This
+may cause an update to the expo state and may produce an action.
+
+Actions
+-------
+
+Call `expo_action_get()` in the event loop to check for any actions that the
+expo wants to report. These can include selecting a particular menu item, or
+quitting the menu. Processing of these is the responsibility of your controller.
+
+Event loop
+----------
+
+Expo is intended to be used in an event loop. For an example loop, see
+`bootflow_menu_run()`. It is possible to perform other work in your event loop,
+such as scanning devices for more bootflows.
+
+Themes
+------
+
+Expo does not itself support themes. The bootflow_menu implement supposed a
+basic theme, applying font sizes to the various text objects in the expo.
+
+API documentation
+-----------------
+
+.. kernel-doc:: include/expo.h
+
+Future ideas
+------------
+
+Some ideas for future work:
+
+- Default menu item and a timeout
+- Higher-level / automatic / more flexible layout of objects
+- Image formats other than BMP
+- Use of ANSI sequences to control a serial terminal
+- Colour selection
+- Better support for handling lots of settings, e.g. with multiple menus and
+ radio/option widgets
+- Mouse support
+- Integrate Nuklear, NxWidgets or some other library for a richer UI
+- Optimise rendering by only updating the display with changes since last render
+- Use expo to replace the existing menu implementation
+- Add a Kconfig option to drop the names to save code / data space
+- Add a Kconfig option to disable vidconsole support to save code / data space
+- Support both graphical and text menus at the same time on different devices
+- Implement proper measurement of object bounding boxes, to permit more exact
+ layout. This would tidy up the layout when Truetype is not used
+- Support unicode
+- Support curses for proper serial-terminal menus
+
+.. Simon Glass <sjg@chromium.org>
+.. 7-Oct-22
diff --git a/doc/develop/index.rst b/doc/develop/index.rst
index 97c526e..79d7736 100644
--- a/doc/develop/index.rst
+++ b/doc/develop/index.rst
@@ -34,6 +34,7 @@
distro
driver-model/index
environment
+ expo
event
global_data
logging
diff --git a/doc/develop/trace.rst b/doc/develop/trace.rst
index b22e068..5c7802d 100644
--- a/doc/develop/trace.rst
+++ b/doc/develop/trace.rst
@@ -185,7 +185,7 @@
this timer include high resolution timers, PWMs or profile timers if
available. Most modern SOCs have a suitable timer for this. Make sure
that you mark this timer (and anything it calls) with
-__attribute__((no_instrument_function)) so that the trace library can
+notrace so that the trace library can
use it without causing an infinite loop.
diff --git a/doc/usage/cmd/bdinfo.rst b/doc/usage/cmd/bdinfo.rst
new file mode 100644
index 0000000..6b3cde2
--- /dev/null
+++ b/doc/usage/cmd/bdinfo.rst
@@ -0,0 +1,119 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2023, Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+
+bdinfo command
+==============
+
+Synopsis
+--------
+
+::
+
+ bdinfo
+
+Description
+-----------
+
+The *bdinfo* command prints information about the board.
+
+Example
+=======
+
+::
+
+ => bdinfo
+ boot_params = 0x0000000000000000
+ DRAM bank = 0x0000000000000000
+ -> start = 0x0000000040000000
+ -> size = 0x0000000100000000
+ flashstart = 0x0000000000000000
+ flashsize = 0x0000000004000000
+ flashoffset = 0x00000000000e87f8
+ baudrate = 115200 bps
+ relocaddr = 0x000000013fefb000
+ reloc off = 0x000000013fefb000
+ Build = 64-bit
+ current eth = virtio-net#32
+ ethaddr = 52:52:52:52:52:52
+ IP addr = 10.0.2.15
+ fdt_blob = 0x000000013edbadb0
+ new_fdt = 0x000000013edbadb0
+ fdt_size = 0x0000000000100000
+ lmb_dump_all:
+ memory.cnt = 0x1
+ memory[0] [0x40000000-0x13fffffff], 0x100000000 bytes flags: 0
+ reserved.cnt = 0x2
+ reserved[0] [0x13ddb3000-0x13fffffff], 0x0224d000 bytes flags: 0
+ reserved[1] [0x13edb6930-0x13fffffff], 0x012496d0 bytes flags: 0
+ devicetree = board
+ arch_number = 0x0000000000000000
+ TLB addr = 0x000000013fff0000
+ irq_sp = 0x000000013edbada0
+ sp start = 0x000000013edbada0
+ Early malloc usage: 3a8 / 2000
+ =>
+
+boot_params
+ address of the memory area for boot parameters
+
+DRAM bank
+ index, start address and end address of a memory bank
+
+baudrate
+ baud rate of the serial console
+
+relocaddr
+ address to which U-Boot has relocated itself
+
+reloc off
+ relocation offset, difference between *relocaddr* and the text base
+
+Build
+ bitness of the system
+
+current eth
+ name of the active network device
+
+IP addr
+ network address, value of the environment variable *ipaddr*
+
+fdt_blob
+ address of U-Boot's own device tree, NULL if none
+
+new_fdt
+ location of the relocated device tree
+
+fdt_size
+ space reserved for relocated device space
+
+lmb_dump_all
+ available memory and memory reservations
+
+devicetree
+ source of the device-tree
+
+arch_number
+ unique id for the board
+
+TLB addr
+ address of the translation lookaside buffer
+
+irq_sp
+ address of the IRQ stack pointer
+
+sp start
+ initial stack pointer address
+
+Early malloc usage
+ amount of memory used in the early malloc memory and its maximum size
+ as defined by CONFIGSYS_MALLOC_F_LEN
+
+Configuration
+-------------
+
+The bdinfo command is available if CONFIG_CMD_BDI=y.
+
+Return code
+-----------
+
+The return code $? is 0 (true).
diff --git a/doc/usage/cmd/blkcache.rst b/doc/usage/cmd/blkcache.rst
new file mode 100644
index 0000000..d3b2254
--- /dev/null
+++ b/doc/usage/cmd/blkcache.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2023, Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
+
+blkcache command
+================
+
+Synopsis
+--------
+
+::
+
+ blkcache show
+ blkcache configure <blocks> <entries>
+
+Description
+-----------
+
+The *blkcache* command is used to control the size of the block cache and to
+display statistics.
+
+The block cache buffers data read from block devices. This speeds up the access
+to file-systems.
+
+show
+ show and reset statistics
+
+configure
+ set the maximum number of cache entries and the maximum number of blocks per
+ entry
+
+blocks
+ maximum number of blocks per cache entry. The block size is device specific.
+ The initial value is 8.
+
+entries
+ maximum number of entries in the cche. The initial value is 32.
+
+Example
+-------
+
+.. code-block::
+
+ => blkcache show
+ hits: 296
+ misses: 149
+ entries: 7
+ max blocks/entry: 8
+ max cache entries: 32
+ => blkcache show
+ hits: 0
+ misses: 0
+ entries: 7
+ max blocks/entry: 8
+ max cache entries: 32
+ => blkcache configure 16 64
+ changed to max of 64 entries of 16 blocks each
+ => blkcache show
+ hits: 0
+ misses: 0
+ entries: 0
+ max blocks/entry: 16
+ max cache entries: 64
+ =>
+
+Configuration
+-------------
+
+The blkcache command is only available if CONFIG_CMD_BLOCK_CACHE=y.
+
+Return code
+-----------
+
+If the command succeeds, the return code $? is set 0 (true). In case of an
+error the return code is set to 1 (false).
diff --git a/doc/usage/cmd/bootdev.rst b/doc/usage/cmd/bootdev.rst
index 5e02e32..6c68d0b 100644
--- a/doc/usage/cmd/bootdev.rst
+++ b/doc/usage/cmd/bootdev.rst
@@ -8,9 +8,10 @@
::
- bootdev list [-p] - list all available bootdevs (-p to probe)\n"
- bootdev select <bm> - select a bootdev by name\n"
- bootdev info [-p] - show information about a bootdev";
+ bootdev list [-p] - list all available bootdevs (-p to probe)
+ bootdev hunt [-l|<spec>] - use hunt drivers to find bootdevs
+ bootdev select <bm> - select a bootdev by name
+ bootdev info [-p] - show information about a bootdev
Description
-----------
@@ -63,6 +64,17 @@
with `.bootdev`
+bootdev hunt
+~~~~~~~~~~~~
+
+This hunts for new bootdevs, or shows a list of hunters.
+
+Use `-l` to list the available bootdev hunters.
+
+To run hunters, specify the name of the hunter to run, e.g. "mmc". If no
+name is provided, all hunters are run.
+
+
bootdev select
~~~~~~~~~~~~~~~~~
@@ -83,7 +95,7 @@
this:
========= =======================
-Name mmc@7e202000.bootdev
+Name `mmc@7e202000.bootdev`
Sequence 0
Status Probed
Uclass mmc
@@ -128,6 +140,34 @@
Uclass: mmc
Bootflows: 1 (1 valid)
+This shows using one of the available hunters, then listing them::
+
+ => bootdev hunt usb
+ Hunting with: usb
+ Bus usb@1: scanning bus usb@1 for devices...
+ 3 USB Device(s) found
+ => bootdev hunt -l
+ Prio Used Uclass Hunter
+ ---- ---- --------------- ---------------
+ 6 ethernet eth_bootdev
+ 1 simple_bus (none)
+ 5 ide ide_bootdev
+ 2 mmc mmc_bootdev
+ 4 nvme nvme_bootdev
+ 4 scsi scsi_bootdev
+ 4 spi_flash sf_bootdev
+ 5 * usb usb_bootdev
+ 4 virtio virtio_bootdev
+ (total hunters: 9)
+ => usb stor
+ Device 0: Vendor: sandbox Rev: 1.0 Prod: flash
+ Type: Hard Disk
+ Capacity: 4.0 MB = 0.0 GB (8192 x 512)
+ Device 1: Vendor: sandbox Rev: 1.0 Prod: flash
+ Type: Hard Disk
+ Capacity: 0.0 MB = 0.0 GB (1 x 512)
+ =>
+
Return value
------------
diff --git a/doc/usage/cmd/bootflow.rst b/doc/usage/cmd/bootflow.rst
index aa12dc2..cad09bb 100644
--- a/doc/usage/cmd/bootflow.rst
+++ b/doc/usage/cmd/bootflow.rst
@@ -8,7 +8,7 @@
::
- bootflow scan [-abel] [bootdev]
+ bootflow scan [-abelGH] [bootdev]
bootflow list [-e]
bootflow select [<num|name>]
bootflow info [-d]
@@ -57,6 +57,16 @@
is happening during scanning. Use it with the `-b` flag to see which
bootdev and bootflows are being tried.
+-G
+ Skip global bootmeths when scanning. By default these are tried first, but
+ this flag disables them.
+
+-H
+ Don't use bootdev hunters. By default these are used before each boot
+ priority or label is tried, to see if more bootdevs can be discovered, but
+ this flag disables that process.
+
+
The optional argument specifies a particular bootdev to scan. This can either be
the name of a bootdev or its sequence number (both shown with `bootdev list`).
Alternatively a convenience label can be used, like `mmc0`, which is the type of
@@ -145,6 +155,7 @@
Filename /extlinux/extlinux.conf
Buffer 3db7ad48
Size 232 (562 bytes)
+FDT: <NULL>
Error 0
========= ===============================
@@ -169,6 +180,10 @@
Size
Size of the bootflow file
+FDT:
+ Filename of the device tree, if supported. The EFI bootmeth uses this to
+ remember the filename to load. If `<NULL>` then there is none.
+
Error
Error number returned from scanning for the bootflow. This is 0 if the
bootflow is in the 'loaded' state, or a negative error value on error. You
diff --git a/doc/usage/cmd/dm.rst b/doc/usage/cmd/dm.rst
index 7bc1962..236cd02 100644
--- a/doc/usage/cmd/dm.rst
+++ b/doc/usage/cmd/dm.rst
@@ -12,7 +12,7 @@
dm devres
dm drivers
dm static
- dm tree
+ dm tree [-s]
dm uclass
Description
@@ -123,6 +123,9 @@
Shows the device name as well as the tree structure, since child devices are
shown attached to their parent.
+If -s is given, the top-level devices (those which are children of the root
+device) are shown sorted in order of uclass ID, so it is easier to find a
+particular device type.
dm uclass
~~~~~~~~~
diff --git a/doc/usage/cmd/exit.rst b/doc/usage/cmd/exit.rst
index 769223c..3edb128 100644
--- a/doc/usage/cmd/exit.rst
+++ b/doc/usage/cmd/exit.rst
@@ -37,4 +37,6 @@
Return value
------------
-$? is always set to 0 (true).
+$? is default set to 0 (true). In case zero or positive integer parameter
+is passed to the command, the return value is the parameter value. In case
+negative integer parameter is passed to the command, the return value is 0.
diff --git a/doc/usage/cmd/part.rst b/doc/usage/cmd/part.rst
new file mode 100644
index 0000000..8d2a280
--- /dev/null
+++ b/doc/usage/cmd/part.rst
@@ -0,0 +1,154 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+part command
+===============
+
+Synopis
+-------
+
+::
+
+ part uuid <interface> <dev>:<part> [varname]
+ part list <interface> <dev> [flags] [varname]
+ part start <interface> <dev> <part> <varname>
+ part size <interface> <dev> <part> <varname>
+ part number <interface> <dev> <part> <varname>
+ part type <interface> <dev>:<part> [varname]
+ part types
+
+Description
+-----------
+
+The `part` command is used to manage disk partition related commands.
+
+The 'part uuid' command prints or sets an environment variable to partition UUID
+
+ interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+ dev
+ device number
+ part
+ partition number
+ varname
+ an optional environment variable to store the current partition UUID value into.
+
+The 'part list' command prints or sets an environment variable to the list of partitions
+
+ interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+ dev
+ device number
+ part
+ partition number
+ flags
+ -bootable
+ lists only bootable partitions
+ varname
+ an optional environment variable to store the list of partitions value into.
+
+The 'part start' commnad sets an environment variable to the start of the partition (in blocks),
+part can be either partition number or partition name.
+
+ interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+ dev
+ device number
+ part
+ partition number
+ varname
+ a variable to store the current start of the partition value into.
+
+The 'part size' command sets an environment variable to the size of the partition (in blocks),
+part can be either partition number or partition name.
+
+ interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+ dev
+ device number
+ part
+ partition number
+ varname
+ a variable to store the current size of the partition value into.
+
+The 'part number' command sets an environment variable to the partition number using the partition name,
+part must be specified as partition name.
+
+ interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+ dev
+ device number
+ part
+ partition number
+ varname
+ a variable to store the current partition number value into
+
+The 'part type' command prints or sets an environment variable to the partition type UUID.
+
+ interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+ dev
+ device number
+ part
+ partition number
+ varname
+ a variable to store the current partition type UUID value into
+
+The 'part types' command list supported partition table types.
+
+Examples
+--------
+
+::
+
+ => host bind 0 ./test_gpt_disk_image.bin
+ => part uuid host 0:1
+ 24156b69-3378-497f-bb3e-b982223de528
+ => part uuid host 0:1 varname
+ => env print varname
+ varname=24156b69-3378-497f-bb3e-b982223de528
+ =>
+ => part list host 0
+
+ Partition Map for HOST device 0 -- Partition Type: EFI
+
+ Part Start LBA End LBA Name
+ Attributes
+ Type GUID
+ Partition GUID
+ 1 0x00000800 0x00000fff "second"
+ attrs: 0x0000000000000000
+ type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+ (data)
+ guid: 24156b69-3378-497f-bb3e-b982223de528
+ 2 0x00001000 0x00001bff "first"
+ attrs: 0x0000000000000000
+ type: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+ (data)
+ guid: 5272ee44-29ab-4d46-af6c-4b45ac67d3b7
+ =>
+ => part start host 0 2 varname
+ => env print varname
+ varname=1000
+ =>
+ => part size host 0 2 varname
+ => env print varname
+ varname=c00
+ =>
+ => part number host 0 2 varname
+ => env print varname
+ varname=0x2
+ =>
+ => part type host 0:1
+ ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+ => part type host 0:1 varname
+ => env print varname
+ varname=ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
+ =>
+ => part types
+ Supported partition tables: EFI, AMIGA, DOS, ISO, MAC
+
+Return value
+------------
+
+The return value $? is set to 0 (true) if the command succededd. If an
+error occurs, the return value $? is set to 1 (false).
diff --git a/doc/usage/cmd/source.rst b/doc/usage/cmd/source.rst
new file mode 100644
index 0000000..61a4505
--- /dev/null
+++ b/doc/usage/cmd/source.rst
@@ -0,0 +1,193 @@
+.. SPDX-License-Identifier: GPL-2.0+
+.. Copyright 2022, Heinrich Schuchardt <xypron.glpk@gmx.de>
+
+source command
+==============
+
+Synopsis
+--------
+
+::
+
+ source [<addr>][:[<image>]|#[<config>]]
+
+Description
+-----------
+
+The *source* command is used to execute a script file from memory.
+
+Two formats for script files exist:
+
+* legacy U-Boot image format
+* Flat Image Tree (FIT)
+
+The benefit of the FIT images is that they can be signed and verifed as
+decribed in :download:`signature.txt <../../uImage.FIT/signature.txt>`.
+
+Both formats can be created with the mkimage tool.
+
+addr
+ location of the script file in memory, defaults to CONFIG_SYS_LOAD_ADDR.
+
+image
+ name of an image in a FIT file
+
+config
+ name of a configuration in a FIT file. A hash sign following white space
+ starts a comment. Hence, if no *addr* is specified, the hash sign has to be
+ escaped with a backslash or the argument must be quoted.
+
+If both *image* and *config* are omitted, the default configuration is used, or
+if no configuration is defined, the default image.
+
+Examples
+--------
+
+FIT image
+'''''''''
+
+For creating a FIT image an image tree source file (\*.its) is needed. Here is
+an example (source.its).
+
+.. code-block::
+
+ /dts-v1/;
+
+ / {
+ description = "FIT image to test the source command";
+ #address-cells = <1>;
+
+ images {
+ default = "script-1";
+
+ script-1 {
+ data = "echo 1";
+ type = "script";
+ compression = "none";
+ };
+
+ script-2 {
+ data = "echo 2";
+ type = "script";
+ compression = "none";
+ };
+ };
+
+ configurations {
+ default = "conf-2";
+
+ conf-1 {
+ script = "script-1";
+ };
+
+ conf-2 {
+ script = "script-2";
+ };
+ };
+ };
+
+The FIT image file (boot.itb) is created with:
+
+.. code-block:: bash
+
+ mkimage -f source.its boot.itb
+
+In U-Boot the script can be loaded and execute like this
+
+.. code-block::
+
+ => load host 0:1 $loadaddr boot.itb
+ 1552 bytes read in 0 ms
+ => source $loadaddr#conf-1
+ ## Executing script at 00000000
+ 1
+ => source $loadaddr#conf-2
+ ## Executing script at 00000000
+ 2
+ => source $loadaddr:script-1
+ ## Executing script at 00000000
+ 1
+ => source $loadaddr:script-2
+ ## Executing script at 00000000
+ 2
+ => source $loadaddr
+ ## Executing script at 00000000
+ 2
+ => source \#conf-1
+ ## Executing script at 00000000
+ 1
+ => source '#conf-1'
+ ## Executing script at 00000000
+ 1
+ => source ':script-1'
+ ## Executing script at 00000000
+ 1
+ => source
+ ## Executing script at 00000000
+ 2
+ =>
+
+Instead of specifying command line instructions directly in the *data* property
+of the image tree source file another file can be included. Here is a minimal
+example which encapsulates the file boot.txt:
+
+.. code-block::
+
+ /dts-v1/;
+ / {
+ description = "";
+ images {
+ script {
+ data = /incbin/("./boot.txt");
+ type = "script";
+ };
+ };
+ };
+
+Legacy U-Boot image
+'''''''''''''''''''
+
+A script file using the legacy U-Boot image file format can be created based on
+a text file. Let's use this example text file (boot.txt):
+
+.. code-block:: bash
+
+ echo Hello from a script
+ echo -------------------
+
+The boot scripts (boot.scr) is created with:
+
+.. code-block:: bash
+
+ mkimage -T script -n 'Test script' -d boot.txt boot.scr
+
+The script can be execute in U-boot like this:
+
+.. code-block::
+
+ => load host 0:1 $loadaddr boot.scr
+ 122 bytes read in 0 ms
+ => source $loadaddr
+ ## Executing script at 00000000
+ Hello from a script
+ -------------------
+ => source
+ ## Executing script at 00000000
+ Hello from a script
+ -------------------
+ =>
+
+Configuration
+-------------
+
+The source command is only available if CONFIG_CMD_SOURCE=y.
+The FIT image file format requires CONFIG_FIT=y.#
+The legacy U-Boot image file format requires CONFIG_LEGACY_IMAGE_FORMAT=y.
+On hardened systems support for the legacy U-Boot image format should be
+disabled as these images cannot be signed and verified.
+
+Return value
+------------
+
+If the scripts is executed successfully, the return value $? is 0 (true).
+Otherwise it is 1 (false).
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index bbd40a6..7d4a1cb 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -23,6 +23,8 @@
cmd/addrmap
cmd/askenv
cmd/base
+ cmd/bdinfo
+ cmd/blkcache
cmd/bootd
cmd/bootdev
cmd/bootefi
@@ -61,6 +63,7 @@
cmd/mbr
cmd/md
cmd/mmc
+ cmd/part
cmd/pause
cmd/pinmux
cmd/printenv
@@ -74,6 +77,7 @@
cmd/setexpr
cmd/size
cmd/sound
+ cmd/source
cmd/temperature
cmd/tftpput
cmd/true
diff --git a/doc/usage/netconsole.rst b/doc/usage/netconsole.rst
index 0156f02..2aa3b9c 100644
--- a/doc/usage/netconsole.rst
+++ b/doc/usage/netconsole.rst
@@ -9,7 +9,7 @@
switched independently.
The default buffer size can be overridden by setting
-CONFIG_NETCONSOLE_BUFFER_SIZE.
+CFG_NETCONSOLE_BUFFER_SIZE.
We use an environment variable 'ncip' to set the IP address and the
port of the destination. The format is <ip_addr>:<port>. If <port> is
diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c
index 85efc11..1fba707 100644
--- a/drivers/adc/stm32-adc.c
+++ b/drivers/adc/stm32-adc.c
@@ -33,8 +33,11 @@
#define STM32H7_ADRDY BIT(0)
/* STM32H7_ADC_CR - bit fields */
+#define STM32H7_ADCAL BIT(31)
+#define STM32H7_ADCALDIF BIT(30)
#define STM32H7_DEEPPWD BIT(29)
#define STM32H7_ADVREGEN BIT(28)
+#define STM32H7_ADCALLIN BIT(16)
#define STM32H7_BOOST BIT(8)
#define STM32H7_ADSTART BIT(2)
#define STM32H7_ADDIS BIT(1)
@@ -65,14 +68,56 @@
const struct stm32_adc_cfg *cfg;
};
+static void stm32_adc_enter_pwr_down(struct udevice *dev)
+{
+ struct stm32_adc *adc = dev_get_priv(dev);
+
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+ /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+}
+
+static int stm32_adc_exit_pwr_down(struct udevice *dev)
+{
+ struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int ret;
+ u32 val;
+
+ /* return immediately if ADC is not in deep power down mode */
+ if (!(readl(adc->regs + STM32H7_ADC_CR) & STM32H7_DEEPPWD))
+ return 0;
+
+ /* Exit deep power down, then enable ADC voltage regulator */
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
+
+ if (common->rate > STM32H7_BOOST_CLKRATE)
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
+
+ /* Wait for startup time */
+ if (!adc->cfg->has_vregready) {
+ udelay(20);
+ return 0;
+ }
+
+ ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
+ val & STM32MP1_VREGREADY,
+ STM32_ADC_TIMEOUT_US);
+ if (ret < 0) {
+ stm32_adc_enter_pwr_down(dev);
+ dev_err(dev, "Failed to enable vreg: %d\n", ret);
+ }
+
+ return ret;
+}
+
static int stm32_adc_stop(struct udevice *dev)
{
struct stm32_adc *adc = dev_get_priv(dev);
setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADDIS);
- clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
- /* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
- setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
+ stm32_adc_enter_pwr_down(dev);
adc->active_channel = -1;
return 0;
@@ -81,30 +126,13 @@
static int stm32_adc_start_channel(struct udevice *dev, int channel)
{
struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
- struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
struct stm32_adc *adc = dev_get_priv(dev);
int ret;
u32 val;
- /* Exit deep power down, then enable ADC voltage regulator */
- clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_DEEPPWD);
- setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADVREGEN);
- if (common->rate > STM32H7_BOOST_CLKRATE)
- setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_BOOST);
-
- /* Wait for startup time */
- if (!adc->cfg->has_vregready) {
- udelay(20);
- } else {
- ret = readl_poll_timeout(adc->regs + STM32H7_ADC_ISR, val,
- val & STM32MP1_VREGREADY,
- STM32_ADC_TIMEOUT_US);
- if (ret < 0) {
- stm32_adc_stop(dev);
- dev_err(dev, "Failed to enable vreg: %d\n", ret);
- return ret;
- }
- }
+ ret = stm32_adc_exit_pwr_down(dev);
+ if (ret < 0)
+ return ret;
/* Only use single ended channels */
writel(0, adc->regs + STM32H7_ADC_DIFSEL);
@@ -162,6 +190,64 @@
return 0;
}
+/**
+ * Fixed timeout value for ADC calibration.
+ * worst cases:
+ * - low clock frequency (0.12 MHz min)
+ * - maximum prescalers
+ * Calibration requires:
+ * - 16384 ADC clock cycle for the linear calibration
+ * - 20 ADC clock cycle for the offset calibration
+ *
+ * Set to 100ms for now
+ */
+#define STM32H7_ADC_CALIB_TIMEOUT_US 100000
+
+static int stm32_adc_selfcalib(struct udevice *dev)
+{
+ struct stm32_adc *adc = dev_get_priv(dev);
+ int ret;
+ u32 val;
+
+ /*
+ * Select calibration mode:
+ * - Offset calibration for single ended inputs
+ * - No linearity calibration. Done in next step.
+ */
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
+
+ /* Start calibration, then wait for completion */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL);
+ ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val,
+ !(val & STM32H7_ADCAL), 100,
+ STM32H7_ADC_CALIB_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "calibration failed\n");
+ goto out;
+ }
+
+ /*
+ * Select calibration mode, then start calibration:
+ * - Offset calibration for differential input
+ * - Linearity calibration (needs to be done only once for single/diff)
+ * will run simultaneously with offset calibration.
+ */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
+
+ /* Start calibration, then wait for completion */
+ setbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCAL);
+ ret = readl_poll_sleep_timeout(adc->regs + STM32H7_ADC_CR, val,
+ !(val & STM32H7_ADCAL), 100,
+ STM32H7_ADC_CALIB_TIMEOUT_US);
+ if (ret)
+ dev_err(dev, "calibration failed\n");
+
+out:
+ clrbits_le32(adc->regs + STM32H7_ADC_CR, STM32H7_ADCALDIF | STM32H7_ADCALLIN);
+
+ return ret;
+}
+
static int stm32_adc_get_legacy_chan_count(struct udevice *dev)
{
int ret;
@@ -272,7 +358,7 @@
struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
struct stm32_adc_common *common = dev_get_priv(dev_get_parent(dev));
struct stm32_adc *adc = dev_get_priv(dev);
- int offset;
+ int offset, ret;
offset = dev_read_u32_default(dev, "reg", -ENODATA);
if (offset < 0) {
@@ -287,7 +373,19 @@
uc_pdata->vdd_microvolts = common->vref_uv;
uc_pdata->vss_microvolts = 0;
- return stm32_adc_chan_of_init(dev);
+ ret = stm32_adc_chan_of_init(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = stm32_adc_exit_pwr_down(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = stm32_adc_selfcalib(dev);
+ if (ret)
+ stm32_adc_enter_pwr_down(dev);
+
+ return ret;
}
static const struct adc_ops stm32_adc_ops = {
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index a063b22..3fe53d6 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -135,6 +135,7 @@
config SATA_SIL
bool "Enable Silicon Image SIL3131 / SIL3132 / SIL3124 SATA driver support"
+ depends on PCI
select AHCI
select LIBATA
help
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index de6131f..272c48b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -675,6 +675,12 @@
/* Read id from sata */
port = pccb->target;
+ /* If this port number is not valid, give up */
+ if (!(uc_priv->port_map & (1 << port))) {
+ debug("Port %x not valid in map %x\n", port, uc_priv->port_map);
+ return -ENODEV;
+ }
+
if (ahci_device_data_io(uc_priv, port, (u8 *)&fis, sizeof(fis),
(u8 *)tmpid, ATA_ID_WORDS * 2, 0)) {
debug("scsi_ahci: SCSI inquiry command failure.\n");
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index eaa58d8..1ad9b6c 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <ata.h>
#include <blk.h>
+#include <bootdev.h>
#include <dm.h>
#include <ide.h>
#include <log.h>
@@ -443,9 +444,6 @@
device = dev_desc->devnum;
dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */
-#ifndef CONFIG_BLK
- dev_desc->block_read = atapi_read;
-#endif
memset(ccb, 0, sizeof(ccb));
memset(iobuf, 0, sizeof(iobuf));
@@ -692,6 +690,7 @@
void ide_init(void)
{
+ struct udevice *dev;
unsigned char c;
int i, bus;
@@ -759,29 +758,14 @@
ide_dev_desc[i].log2blksz =
LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz));
ide_dev_desc[i].lba = 0;
-#ifndef CONFIG_BLK
- ide_dev_desc[i].block_read = ide_read;
- ide_dev_desc[i].block_write = ide_write;
-#endif
if (!ide_bus_ok[IDE_BUS(i)])
continue;
ide_ident(&ide_dev_desc[i]);
dev_print(&ide_dev_desc[i]);
-
-#ifndef CONFIG_BLK
- if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) {
- /* initialize partition type */
- part_init(&ide_dev_desc[i]);
- }
-#endif
}
schedule();
-#ifdef CONFIG_BLK
- struct udevice *dev;
-
uclass_first_device(UCLASS_IDE, &dev);
-#endif
}
__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words)
@@ -830,17 +814,10 @@
}
}
-#ifdef CONFIG_BLK
ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
void *buffer)
-#else
-ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- void *buffer)
-#endif
{
-#ifdef CONFIG_BLK
struct blk_desc *block_dev = dev_get_uclass_plat(dev);
-#endif
int device = block_dev->devnum;
ulong n = 0;
unsigned char c;
@@ -957,17 +934,10 @@
return n;
}
-#ifdef CONFIG_BLK
ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
const void *buffer)
-#else
-ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt,
- const void *buffer)
-#endif
{
-#ifdef CONFIG_BLK
struct blk_desc *block_dev = dev_get_uclass_plat(dev);
-#endif
int device = block_dev->devnum;
ulong n = 0;
unsigned char c;
@@ -1056,7 +1026,6 @@
}
#endif
-#ifdef CONFIG_BLK
static int ide_blk_probe(struct udevice *udev)
{
struct blk_desc *desc = dev_get_uclass_plat(udev);
@@ -1087,6 +1056,45 @@
.probe = ide_blk_probe,
};
+static int ide_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_5_SCAN_SLOW;
+
+ return 0;
+}
+
+static int ide_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ ide_init();
+
+ return 0;
+}
+
+struct bootdev_ops ide_bootdev_ops = {
+};
+
+static const struct udevice_id ide_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-ide" },
+ { }
+};
+
+U_BOOT_DRIVER(ide_bootdev) = {
+ .name = "ide_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &ide_bootdev_ops,
+ .bind = ide_bootdev_bind,
+ .of_match = ide_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(ide_bootdev_hunter) = {
+ .prio = BOOTDEVP_5_SCAN_SLOW,
+ .uclass = UCLASS_IDE,
+ .hunt = ide_bootdev_hunt,
+ .drv = DM_DRIVER_REF(ide_bootdev),
+};
+
static int ide_probe(struct udevice *udev)
{
struct udevice *blk_dev;
@@ -1118,6 +1126,10 @@
ret = blk_probe_or_unbind(blk_dev);
if (ret)
return ret;
+
+ ret = bootdev_setup_for_dev(udev, "ide_bootdev");
+ if (ret)
+ return log_msg_ret("bootdev", ret);
}
}
@@ -1141,11 +1153,3 @@
.name = "ide",
.id = UCLASS_IDE,
};
-#else
-U_BOOT_LEGACY_BLK(ide) = {
- .uclass_idname = "ide",
- .uclass_id = UCLASS_IDE,
- .max_devs = CONFIG_SYS_IDE_MAXDEVICE,
- .desc = ide_dev_desc,
-};
-#endif
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index a72d8fe..f719f4e 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -17,3 +17,4 @@
obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o
obj-$(CONFIG_ROCKCHIP_RK3568) += clk_rk3568.o
obj-$(CONFIG_ROCKCHIP_RV1108) += clk_rv1108.o
+obj-$(CONFIG_ROCKCHIP_RV1126) += clk_rv1126.o
diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c
index 5d46744..33a7348 100644
--- a/drivers/clk/rockchip/clk_px30.c
+++ b/drivers/clk/rockchip/clk_px30.c
@@ -1415,6 +1415,9 @@
case SCLK_GMAC_RMII:
/* Required to successfully probe the Designware GMAC driver */
return 0;
+ case PCLK_WDT_NS:
+ /* Required to successfully probe the Designware watchdog driver */
+ return 0;
}
debug("%s: unsupported clk %ld\n", __func__, clk->id);
diff --git a/drivers/clk/rockchip/clk_rv1126.c b/drivers/clk/rockchip/clk_rv1126.c
new file mode 100644
index 0000000..3ed2936
--- /dev/null
+++ b/drivers/clk/rockchip/clk_rv1126.c
@@ -0,0 +1,1889 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ * Author: Finley Xiao <finley.xiao@rock-chips.com>
+ */
+
+#include <common.h>
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rv1126.h>
+#include <asm/arch-rockchip/grf_rv1126.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <dm/device-internal.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/rockchip,rv1126-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define RV1126_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \
+{ \
+ .rate = _rate##U, \
+ .aclk_div = _aclk_div, \
+ .pclk_div = _pclk_div, \
+}
+
+#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
+
+static struct rockchip_cpu_rate_table rv1126_cpu_rates[] = {
+ RV1126_CPUCLK_RATE(1200000000, 1, 5),
+ RV1126_CPUCLK_RATE(1008000000, 1, 5),
+ RV1126_CPUCLK_RATE(816000000, 1, 3),
+ RV1126_CPUCLK_RATE(600000000, 1, 3),
+ RV1126_CPUCLK_RATE(408000000, 1, 1),
+};
+
+static struct rockchip_pll_rate_table rv1126_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ RK3036_PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0),
+ RK3036_PLL_RATE(1400000000, 3, 350, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1100000000, 3, 275, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+ RK3036_PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0),
+ RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+ RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0),
+ RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0),
+ RK3036_PLL_RATE(594000000, 1, 99, 4, 1, 1, 0),
+ RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0),
+ RK3036_PLL_RATE(200000000, 1, 100, 6, 2, 1, 0),
+ RK3036_PLL_RATE(100000000, 1, 100, 6, 4, 1, 0),
+ { /* sentinel */ },
+};
+
+static struct rockchip_pll_clock rv1126_pll_clks[] = {
+ [APLL] = PLL(pll_rk3328, PLL_APLL, RV1126_PLL_CON(0),
+ RV1126_MODE_CON, 0, 10, 0, rv1126_pll_rates),
+ [DPLL] = PLL(pll_rk3328, PLL_DPLL, RV1126_PLL_CON(8),
+ RV1126_MODE_CON, 2, 10, 0, NULL),
+ [CPLL] = PLL(pll_rk3328, PLL_CPLL, RV1126_PLL_CON(16),
+ RV1126_MODE_CON, 4, 10, 0, rv1126_pll_rates),
+ [HPLL] = PLL(pll_rk3328, PLL_HPLL, RV1126_PLL_CON(24),
+ RV1126_MODE_CON, 6, 10, 0, rv1126_pll_rates),
+ [GPLL] = PLL(pll_rk3328, PLL_GPLL, RV1126_PMU_PLL_CON(0),
+ RV1126_PMU_MODE, 0, 10, 0, rv1126_pll_rates),
+};
+
+static ulong rv1126_gpll_set_rate(struct rv1126_clk_priv *priv,
+ struct rv1126_pmuclk_priv *pmu_priv,
+ ulong rate);
+/*
+ *
+ * rational_best_approximation(31415, 10000,
+ * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+static void rational_best_approximation(unsigned long given_numerator,
+ unsigned long given_denominator,
+ unsigned long max_numerator,
+ unsigned long max_denominator,
+ unsigned long *best_numerator,
+ unsigned long *best_denominator)
+{
+ unsigned long n, d, n0, d0, n1, d1;
+
+ n = given_numerator;
+ d = given_denominator;
+ n0 = 0;
+ d1 = 0;
+ n1 = 1;
+ d0 = 1;
+ for (;;) {
+ unsigned long t, a;
+
+ if (n1 > max_numerator || d1 > max_denominator) {
+ n1 = n0;
+ d1 = d0;
+ break;
+ }
+ if (d == 0)
+ break;
+ t = d;
+ a = n / d;
+ d = n % d;
+ n = t;
+ t = n0 + a * n1;
+ n0 = n1;
+ n1 = t;
+ t = d0 + a * d1;
+ d0 = d1;
+ d1 = t;
+ }
+ *best_numerator = n1;
+ *best_denominator = d1;
+}
+
+static ulong rv1126_gpll_get_pmuclk(struct rv1126_pmuclk_priv *priv)
+{
+ return rockchip_pll_get_rate(&rv1126_pll_clks[GPLL],
+ priv->pmucru, GPLL);
+}
+
+static ulong rv1126_gpll_set_pmuclk(struct rv1126_pmuclk_priv *pmu_priv, ulong rate)
+{
+ struct udevice *cru_dev;
+ struct rv1126_clk_priv *priv;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_CLK,
+ DM_DRIVER_GET(rockchip_rv1126_cru),
+ &cru_dev);
+ if (ret) {
+ printf("%s: could not find cru device\n", __func__);
+ return ret;
+ }
+ priv = dev_get_priv(cru_dev);
+
+ if (rv1126_gpll_set_rate(priv, pmu_priv, rate)) {
+ printf("%s: failed to set gpll rate %lu\n", __func__, rate);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static ulong rv1126_rtc32k_get_pmuclk(struct rv1126_pmuclk_priv *priv)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ unsigned long m, n;
+ u32 fracdiv;
+
+ fracdiv = readl(&pmucru->pmu_clksel_con[13]);
+ m = fracdiv & CLK_RTC32K_FRAC_NUMERATOR_MASK;
+ m >>= CLK_RTC32K_FRAC_NUMERATOR_SHIFT;
+ n = fracdiv & CLK_RTC32K_FRAC_DENOMINATOR_MASK;
+ n >>= CLK_RTC32K_FRAC_DENOMINATOR_SHIFT;
+
+ return OSC_HZ * m / n;
+}
+
+static ulong rv1126_rtc32k_set_pmuclk(struct rv1126_pmuclk_priv *priv,
+ ulong rate)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ unsigned long m, n, val;
+
+ rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
+ RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
+
+ rational_best_approximation(rate, OSC_HZ,
+ GENMASK(16 - 1, 0),
+ GENMASK(16 - 1, 0),
+ &m, &n);
+ val = m << CLK_RTC32K_FRAC_NUMERATOR_SHIFT | n;
+ writel(val, &pmucru->pmu_clksel_con[13]);
+
+ return rv1126_rtc32k_get_pmuclk(priv);
+}
+
+static ulong rv1126_i2c_get_pmuclk(struct rv1126_pmuclk_priv *priv,
+ ulong clk_id)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ u32 div, con;
+
+ switch (clk_id) {
+ case CLK_I2C0:
+ con = readl(&pmucru->pmu_clksel_con[2]);
+ div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT;
+ break;
+ case CLK_I2C2:
+ con = readl(&pmucru->pmu_clksel_con[3]);
+ div = (con & CLK_I2C1_DIV_MASK) >> CLK_I2C1_DIV_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_i2c_set_pmuclk(struct rv1126_pmuclk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+
+ switch (clk_id) {
+ case CLK_I2C0:
+ rk_clrsetreg(&pmucru->pmu_clksel_con[2], CLK_I2C0_DIV_MASK,
+ (src_clk_div - 1) << CLK_I2C0_DIV_SHIFT);
+ break;
+ case CLK_I2C2:
+ rk_clrsetreg(&pmucru->pmu_clksel_con[3], CLK_I2C2_DIV_MASK,
+ (src_clk_div - 1) << CLK_I2C2_DIV_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rv1126_i2c_get_pmuclk(priv, clk_id);
+}
+
+static ulong rv1126_pwm_get_pmuclk(struct rv1126_pmuclk_priv *priv,
+ ulong clk_id)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ u32 div, sel, con;
+
+ switch (clk_id) {
+ case CLK_PWM0:
+ con = readl(&pmucru->pmu_clksel_con[6]);
+ sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT;
+ div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT;
+ if (sel == CLK_PWM0_SEL_XIN24M)
+ return OSC_HZ;
+ break;
+ case CLK_PWM1:
+ con = readl(&pmucru->pmu_clksel_con[6]);
+ sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM1_SEL_SHIFT;
+ div = (con & CLK_PWM1_DIV_MASK) >> CLK_PWM1_DIV_SHIFT;
+ if (sel == CLK_PWM1_SEL_XIN24M)
+ return OSC_HZ;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_pwm_set_pmuclk(struct rv1126_pmuclk_priv *priv,
+ ulong clk_id, ulong rate)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ int src_clk_div;
+
+ switch (clk_id) {
+ case CLK_PWM0:
+ if (rate == OSC_HZ) {
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM0_SEL_MASK,
+ CLK_PWM0_SEL_XIN24M << CLK_PWM0_SEL_SHIFT);
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM0_DIV_MASK, 0);
+ } else {
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM0_DIV_MASK,
+ (src_clk_div - 1) << CLK_PWM0_DIV_SHIFT);
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM0_SEL_MASK,
+ CLK_PWM0_SEL_GPLL << CLK_PWM0_SEL_SHIFT);
+ }
+ break;
+ case CLK_PWM1:
+ if (rate == OSC_HZ) {
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM1_SEL_MASK,
+ CLK_PWM1_SEL_XIN24M << CLK_PWM1_SEL_SHIFT);
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM1_DIV_MASK, 0);
+ } else {
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM1_DIV_MASK,
+ (src_clk_div - 1) << CLK_PWM1_DIV_SHIFT);
+ rk_clrsetreg(&pmucru->pmu_clksel_con[6],
+ CLK_PWM1_SEL_MASK,
+ CLK_PWM1_SEL_GPLL << CLK_PWM1_SEL_SHIFT);
+ }
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rv1126_pwm_get_pmuclk(priv, clk_id);
+}
+
+static ulong rv1126_spi_get_pmuclk(struct rv1126_pmuclk_priv *priv)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ u32 div, con;
+
+ con = readl(&pmucru->pmu_clksel_con[9]);
+ div = (con & CLK_SPI0_DIV_MASK) >> CLK_SPI0_DIV_SHIFT;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_spi_set_pmuclk(struct rv1126_pmuclk_priv *priv,
+ ulong rate)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+
+ rk_clrsetreg(&pmucru->pmu_clksel_con[9],
+ CLK_SPI0_SEL_MASK | CLK_SPI0_DIV_MASK,
+ CLK_SPI0_SEL_GPLL << CLK_SPI0_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_SPI0_DIV_SHIFT);
+
+ return rv1126_spi_get_pmuclk(priv);
+}
+
+static ulong rv1126_pdpmu_get_pmuclk(struct rv1126_pmuclk_priv *priv)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ u32 div, con;
+
+ con = readl(&pmucru->pmu_clksel_con[1]);
+ div = (con & PCLK_PDPMU_DIV_MASK) >> PCLK_PDPMU_DIV_SHIFT;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_pdpmu_set_pmuclk(struct rv1126_pmuclk_priv *priv,
+ ulong rate)
+{
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+
+ rk_clrsetreg(&pmucru->pmu_clksel_con[1],
+ PCLK_PDPMU_DIV_MASK,
+ (src_clk_div - 1) << PCLK_PDPMU_DIV_SHIFT);
+
+ return rv1126_pdpmu_get_pmuclk(priv);
+}
+
+static ulong rv1126_pmuclk_get_rate(struct clk *clk)
+{
+ struct rv1126_pmuclk_priv *priv = dev_get_priv(clk->dev);
+ ulong rate = 0;
+
+ if (!priv->gpll_hz) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ debug("%s %ld\n", __func__, clk->id);
+ switch (clk->id) {
+ case PLL_GPLL:
+ rate = rv1126_gpll_get_pmuclk(priv);
+ break;
+ case CLK_RTC32K:
+ rate = rv1126_rtc32k_get_pmuclk(priv);
+ break;
+ case CLK_I2C0:
+ case CLK_I2C2:
+ rate = rv1126_i2c_get_pmuclk(priv, clk->id);
+ break;
+ case CLK_PWM0:
+ case CLK_PWM1:
+ rate = rv1126_pwm_get_pmuclk(priv, clk->id);
+ break;
+ case CLK_SPI0:
+ rate = rv1126_spi_get_pmuclk(priv);
+ break;
+ case PCLK_PDPMU:
+ rate = rv1126_pdpmu_get_pmuclk(priv);
+ break;
+ default:
+ debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
+ return -ENOENT;
+ }
+
+ return rate;
+}
+
+static ulong rv1126_pmuclk_set_rate(struct clk *clk, ulong rate)
+{
+ struct rv1126_pmuclk_priv *priv = dev_get_priv(clk->dev);
+ ulong ret = 0;
+
+ if (!priv->gpll_hz) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ debug("%s %ld %ld\n", __func__, clk->id, rate);
+ switch (clk->id) {
+ case PLL_GPLL:
+ ret = rv1126_gpll_set_pmuclk(priv, rate);
+ break;
+ case CLK_RTC32K:
+ ret = rv1126_rtc32k_set_pmuclk(priv, rate);
+ break;
+ case CLK_I2C0:
+ case CLK_I2C2:
+ ret = rv1126_i2c_set_pmuclk(priv, clk->id, rate);
+ break;
+ case CLK_PWM0:
+ case CLK_PWM1:
+ ret = rv1126_pwm_set_pmuclk(priv, clk->id, rate);
+ break;
+ case CLK_SPI0:
+ ret = rv1126_spi_set_pmuclk(priv, rate);
+ break;
+ case PCLK_PDPMU:
+ ret = rv1126_pdpmu_set_pmuclk(priv, rate);
+ break;
+ default:
+ debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
+ return -ENOENT;
+ }
+
+ return ret;
+}
+
+static int rv1126_rtc32k_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct rv1126_pmuclk_priv *priv = dev_get_priv(clk->dev);
+ struct rv1126_pmucru *pmucru = priv->pmucru;
+
+ if (parent->id == CLK_OSC0_DIV32K)
+ rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
+ RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT);
+ else
+ rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK,
+ RTC32K_SEL_OSC1_32K << RTC32K_SEL_SHIFT);
+
+ return 0;
+}
+
+static int rv1126_pmuclk_set_parent(struct clk *clk, struct clk *parent)
+{
+ switch (clk->id) {
+ case CLK_RTC32K:
+ return rv1126_rtc32k_set_parent(clk, parent);
+ default:
+ debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
+ return -ENOENT;
+ }
+}
+
+static struct clk_ops rv1126_pmuclk_ops = {
+ .get_rate = rv1126_pmuclk_get_rate,
+ .set_rate = rv1126_pmuclk_set_rate,
+ .set_parent = rv1126_pmuclk_set_parent,
+};
+
+static int rv1126_pmuclk_probe(struct udevice *dev)
+{
+ struct rv1126_pmuclk_priv *priv = dev_get_priv(dev);
+
+ priv->gpll_hz = rv1126_gpll_get_pmuclk(priv);
+
+ return 0;
+}
+
+static int rv1126_pmuclk_of_to_plat(struct udevice *dev)
+{
+ struct rv1126_pmuclk_priv *priv = dev_get_priv(dev);
+
+ priv->pmucru = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static int rv1126_pmuclk_bind(struct udevice *dev)
+{
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+ int ret;
+
+ ret = offsetof(struct rv1126_pmucru, pmu_softrst_con[0]);
+ ret = rockchip_reset_bind(dev, ret, 2);
+ if (ret)
+ debug("Warning: software reset driver bind faile\n");
+#endif
+ return 0;
+}
+
+static const struct udevice_id rv1126_pmuclk_ids[] = {
+ { .compatible = "rockchip,rv1126-pmucru" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rv1126_pmucru) = {
+ .name = "rockchip_rv1126_pmucru",
+ .id = UCLASS_CLK,
+ .of_match = rv1126_pmuclk_ids,
+ .priv_auto = sizeof(struct rv1126_pmuclk_priv),
+ .of_to_plat = rv1126_pmuclk_of_to_plat,
+ .ops = &rv1126_pmuclk_ops,
+ .bind = rv1126_pmuclk_bind,
+ .probe = rv1126_pmuclk_probe,
+};
+
+static int rv1126_armclk_set_clk(struct rv1126_clk_priv *priv, ulong hz)
+{
+ struct rv1126_cru *cru = priv->cru;
+ const struct rockchip_cpu_rate_table *rate;
+ ulong old_rate;
+
+ rate = rockchip_get_cpu_settings(rv1126_cpu_rates, hz);
+ if (!rate) {
+ printf("%s unsupported rate\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * set up dependent divisors for DBG and ACLK clocks.
+ */
+ old_rate = rockchip_pll_get_rate(&rv1126_pll_clks[APLL],
+ priv->cru, APLL);
+ if (old_rate > hz) {
+ if (rockchip_pll_set_rate(&rv1126_pll_clks[APLL],
+ priv->cru, APLL, hz))
+ return -EINVAL;
+ rk_clrsetreg(&cru->clksel_con[1],
+ CORE_DBG_DIV_MASK | CORE_ACLK_DIV_MASK,
+ rate->pclk_div << CORE_DBG_DIV_SHIFT |
+ rate->aclk_div << CORE_ACLK_DIV_SHIFT);
+ } else if (old_rate < hz) {
+ rk_clrsetreg(&cru->clksel_con[1],
+ CORE_DBG_DIV_MASK | CORE_ACLK_DIV_MASK,
+ rate->pclk_div << CORE_DBG_DIV_SHIFT |
+ rate->aclk_div << CORE_ACLK_DIV_SHIFT);
+ if (rockchip_pll_set_rate(&rv1126_pll_clks[APLL],
+ priv->cru, APLL, hz))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static ulong rv1126_pdcore_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 con, div;
+
+ con = readl(&cru->clksel_con[0]);
+ div = (con & CORE_HCLK_DIV_MASK) >> CORE_HCLK_DIV_SHIFT;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_pdcore_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+
+ rk_clrsetreg(&cru->clksel_con[0], CORE_HCLK_DIV_MASK,
+ (src_clk_div - 1) << CORE_HCLK_DIV_SHIFT);
+
+ return rv1126_pdcore_get_clk(priv);
+}
+
+static ulong rv1126_pdbus_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 con, div, sel, parent;
+
+ switch (clk_id) {
+ case ACLK_PDBUS:
+ con = readl(&cru->clksel_con[2]);
+ div = (con & ACLK_PDBUS_DIV_MASK) >> ACLK_PDBUS_DIV_SHIFT;
+ sel = (con & ACLK_PDBUS_SEL_MASK) >> ACLK_PDBUS_SEL_SHIFT;
+ if (sel == ACLK_PDBUS_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == ACLK_PDBUS_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+ break;
+ case HCLK_PDBUS:
+ con = readl(&cru->clksel_con[2]);
+ div = (con & HCLK_PDBUS_DIV_MASK) >> HCLK_PDBUS_DIV_SHIFT;
+ sel = (con & HCLK_PDBUS_SEL_MASK) >> HCLK_PDBUS_SEL_SHIFT;
+ if (sel == HCLK_PDBUS_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == HCLK_PDBUS_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+ break;
+ case PCLK_PDBUS:
+ case PCLK_WDT:
+ con = readl(&cru->clksel_con[3]);
+ div = (con & PCLK_PDBUS_DIV_MASK) >> PCLK_PDBUS_DIV_SHIFT;
+ sel = (con & PCLK_PDBUS_SEL_MASK) >> PCLK_PDBUS_SEL_SHIFT;
+ if (sel == PCLK_PDBUS_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == PCLK_PDBUS_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_pdbus_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
+ ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div, clk_sel;
+
+ switch (clk_id) {
+ case ACLK_PDBUS:
+ if (CPLL_HZ % rate) {
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ clk_sel = ACLK_PDBUS_SEL_GPLL;
+ } else {
+ src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ clk_sel = ACLK_PDBUS_SEL_CPLL;
+ }
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[2],
+ ACLK_PDBUS_SEL_MASK | ACLK_PDBUS_DIV_MASK,
+ clk_sel << ACLK_PDBUS_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_PDBUS_DIV_SHIFT);
+ break;
+ case HCLK_PDBUS:
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[2],
+ HCLK_PDBUS_SEL_MASK | HCLK_PDBUS_DIV_MASK,
+ HCLK_PDBUS_SEL_GPLL << HCLK_PDBUS_SEL_SHIFT |
+ (src_clk_div - 1) << HCLK_PDBUS_DIV_SHIFT);
+ break;
+ case PCLK_PDBUS:
+ case PCLK_WDT:
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[3],
+ PCLK_PDBUS_SEL_MASK | PCLK_PDBUS_DIV_MASK,
+ PCLK_PDBUS_SEL_GPLL << PCLK_PDBUS_SEL_SHIFT |
+ (src_clk_div - 1) << PCLK_PDBUS_DIV_SHIFT);
+ break;
+
+ default:
+ printf("do not support this pdbus freq\n");
+ return -EINVAL;
+ }
+
+ return rv1126_pdbus_get_clk(priv, clk_id);
+}
+
+static ulong rv1126_pdphp_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 con, div, parent;
+
+ switch (clk_id) {
+ case ACLK_PDPHP:
+ con = readl(&cru->clksel_con[53]);
+ div = (con & ACLK_PDPHP_DIV_MASK) >> ACLK_PDPHP_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ case HCLK_PDPHP:
+ con = readl(&cru->clksel_con[53]);
+ div = (con & HCLK_PDPHP_DIV_MASK) >> HCLK_PDPHP_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_pdphp_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
+ ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+
+ switch (clk_id) {
+ case ACLK_PDPHP:
+ rk_clrsetreg(&cru->clksel_con[53],
+ ACLK_PDPHP_SEL_MASK | ACLK_PDPHP_DIV_MASK,
+ ACLK_PDPHP_SEL_GPLL << ACLK_PDPHP_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_PDPHP_DIV_SHIFT);
+ break;
+ case HCLK_PDPHP:
+ rk_clrsetreg(&cru->clksel_con[53],
+ HCLK_PDPHP_DIV_MASK,
+ (src_clk_div - 1) << HCLK_PDPHP_DIV_SHIFT);
+ break;
+ default:
+ printf("do not support this pdphp freq\n");
+ return -EINVAL;
+ }
+
+ return rv1126_pdphp_get_clk(priv, clk_id);
+}
+
+static ulong rv1126_pdaudio_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 con, div;
+
+ con = readl(&cru->clksel_con[26]);
+ div = (con & HCLK_PDAUDIO_DIV_MASK) >> HCLK_PDAUDIO_DIV_SHIFT;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_pdaudio_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+
+ rk_clrsetreg(&cru->clksel_con[26], HCLK_PDAUDIO_DIV_MASK,
+ (src_clk_div - 1) << HCLK_PDAUDIO_DIV_SHIFT);
+
+ return rv1126_pdaudio_get_clk(priv);
+}
+
+static ulong rv1126_i2c_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, con;
+
+ switch (clk_id) {
+ case CLK_I2C1:
+ con = readl(&cru->clksel_con[5]);
+ div = (con & CLK_I2C1_DIV_MASK) >> CLK_I2C1_DIV_SHIFT;
+ break;
+ case CLK_I2C3:
+ con = readl(&cru->clksel_con[5]);
+ div = (con & CLK_I2C3_DIV_MASK) >> CLK_I2C3_DIV_SHIFT;
+ break;
+ case CLK_I2C4:
+ con = readl(&cru->clksel_con[6]);
+ div = (con & CLK_I2C4_DIV_MASK) >> CLK_I2C4_DIV_SHIFT;
+ break;
+ case CLK_I2C5:
+ con = readl(&cru->clksel_con[6]);
+ div = (con & CLK_I2C5_DIV_MASK) >> CLK_I2C5_DIV_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_i2c_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
+ ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+
+ switch (clk_id) {
+ case CLK_I2C1:
+ rk_clrsetreg(&cru->clksel_con[5], CLK_I2C1_DIV_MASK,
+ (src_clk_div - 1) << CLK_I2C1_DIV_SHIFT);
+ break;
+ case CLK_I2C3:
+ rk_clrsetreg(&cru->clksel_con[5], CLK_I2C3_DIV_MASK,
+ (src_clk_div - 1) << CLK_I2C3_DIV_SHIFT);
+ break;
+ case CLK_I2C4:
+ rk_clrsetreg(&cru->clksel_con[6], CLK_I2C4_DIV_MASK,
+ (src_clk_div - 1) << CLK_I2C4_DIV_SHIFT);
+ break;
+ case CLK_I2C5:
+ rk_clrsetreg(&cru->clksel_con[6], CLK_I2C5_DIV_MASK,
+ (src_clk_div - 1) << CLK_I2C5_DIV_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rv1126_i2c_get_clk(priv, clk_id);
+}
+
+static ulong rv1126_spi_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, con;
+
+ con = readl(&cru->clksel_con[8]);
+ div = (con & CLK_SPI1_DIV_MASK) >> CLK_SPI1_DIV_SHIFT;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_spi_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+
+ rk_clrsetreg(&cru->clksel_con[8],
+ CLK_SPI1_SEL_MASK | CLK_SPI1_DIV_MASK,
+ CLK_SPI1_SEL_GPLL << CLK_SPI1_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_SPI1_DIV_SHIFT);
+
+ return rv1126_spi_get_clk(priv);
+}
+
+static ulong rv1126_pwm_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con;
+
+ con = readl(&cru->clksel_con[9]);
+ sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT;
+ div = (con & CLK_PWM2_DIV_MASK) >> CLK_PWM2_DIV_SHIFT;
+ if (sel == CLK_PWM2_SEL_XIN24M)
+ return OSC_HZ;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong rv1126_pwm_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ if (rate == OSC_HZ) {
+ rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_SEL_MASK,
+ CLK_PWM2_SEL_XIN24M << CLK_PWM2_SEL_SHIFT);
+ rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_DIV_MASK, 0);
+ } else {
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+ rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_DIV_MASK,
+ (src_clk_div - 1) << CLK_PWM2_DIV_SHIFT);
+ rk_clrsetreg(&cru->clksel_con[9], CLK_PWM2_SEL_MASK,
+ CLK_PWM2_SEL_GPLL << CLK_PWM2_SEL_SHIFT);
+ }
+
+ return rv1126_pwm_get_clk(priv);
+}
+
+static ulong rv1126_saradc_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, con;
+
+ con = readl(&cru->clksel_con[20]);
+ div = (con & CLK_SARADC_DIV_MASK) >> CLK_SARADC_DIV_SHIFT;
+
+ return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong rv1126_saradc_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(OSC_HZ, rate);
+ assert(src_clk_div - 1 <= 2047);
+ rk_clrsetreg(&cru->clksel_con[20], CLK_SARADC_DIV_MASK,
+ (src_clk_div - 1) << CLK_SARADC_DIV_SHIFT);
+
+ return rv1126_saradc_get_clk(priv);
+}
+
+static ulong rv1126_crypto_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ switch (clk_id) {
+ case CLK_CRYPTO_CORE:
+ con = readl(&cru->clksel_con[7]);
+ div = (con & CLK_CRYPTO_CORE_DIV_MASK) >> CLK_CRYPTO_CORE_DIV_SHIFT;
+ sel = (con & CLK_CRYPTO_CORE_SEL_MASK) >> CLK_CRYPTO_CORE_SEL_SHIFT;
+ if (sel == CLK_CRYPTO_CORE_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == CLK_CRYPTO_CORE_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+ break;
+ case CLK_CRYPTO_PKA:
+ con = readl(&cru->clksel_con[7]);
+ div = (con & CLK_CRYPTO_PKA_DIV_MASK) >> CLK_CRYPTO_PKA_DIV_SHIFT;
+ sel = (con & CLK_CRYPTO_PKA_SEL_MASK) >> CLK_CRYPTO_PKA_SEL_SHIFT;
+ if (sel == CLK_CRYPTO_PKA_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == CLK_CRYPTO_PKA_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+ break;
+ case ACLK_CRYPTO:
+ con = readl(&cru->clksel_con[4]);
+ div = (con & ACLK_CRYPTO_DIV_MASK) >> ACLK_CRYPTO_DIV_SHIFT;
+ sel = (con & ACLK_CRYPTO_SEL_MASK) >> ACLK_CRYPTO_SEL_SHIFT;
+ if (sel == ACLK_CRYPTO_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == ACLK_CRYPTO_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_crypto_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
+ ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+
+ switch (clk_id) {
+ case CLK_CRYPTO_CORE:
+ rk_clrsetreg(&cru->clksel_con[7],
+ CLK_CRYPTO_CORE_SEL_MASK |
+ CLK_CRYPTO_CORE_DIV_MASK,
+ CLK_CRYPTO_CORE_SEL_GPLL <<
+ CLK_CRYPTO_CORE_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_CRYPTO_CORE_DIV_SHIFT);
+ break;
+ case CLK_CRYPTO_PKA:
+ rk_clrsetreg(&cru->clksel_con[7],
+ CLK_CRYPTO_PKA_SEL_MASK |
+ CLK_CRYPTO_PKA_DIV_MASK,
+ CLK_CRYPTO_PKA_SEL_GPLL <<
+ CLK_CRYPTO_PKA_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_CRYPTO_PKA_DIV_SHIFT);
+ break;
+ case ACLK_CRYPTO:
+ rk_clrsetreg(&cru->clksel_con[4],
+ ACLK_CRYPTO_SEL_MASK | ACLK_CRYPTO_DIV_MASK,
+ ACLK_CRYPTO_SEL_GPLL << ACLK_CRYPTO_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_CRYPTO_DIV_SHIFT);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rv1126_crypto_get_clk(priv, clk_id);
+}
+
+static ulong rv1126_mmc_get_clk(struct rv1126_clk_priv *priv, ulong clk_id)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, con_id;
+
+ switch (clk_id) {
+ case HCLK_SDMMC:
+ case CLK_SDMMC:
+ con_id = 55;
+ break;
+ case HCLK_SDIO:
+ case CLK_SDIO:
+ con_id = 56;
+ break;
+ case HCLK_EMMC:
+ case CLK_EMMC:
+ case SCLK_EMMC_SAMPLE:
+ con_id = 57;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ con = readl(&cru->clksel_con[con_id]);
+ div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
+ sel = (con & EMMC_SEL_MASK) >> EMMC_SEL_SHIFT;
+ if (sel == EMMC_SEL_GPLL)
+ return DIV_TO_RATE(priv->gpll_hz, div) / 2;
+ else if (sel == EMMC_SEL_CPLL)
+ return DIV_TO_RATE(priv->cpll_hz, div) / 2;
+ else if (sel == EMMC_SEL_XIN24M)
+ return DIV_TO_RATE(OSC_HZ, div) / 2;
+
+ return -ENOENT;
+}
+
+static ulong rv1126_mmc_set_clk(struct rv1126_clk_priv *priv, ulong clk_id,
+ ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+ u32 con_id;
+
+ switch (clk_id) {
+ case HCLK_SDMMC:
+ case CLK_SDMMC:
+ con_id = 55;
+ break;
+ case HCLK_SDIO:
+ case CLK_SDIO:
+ con_id = 56;
+ break;
+ case HCLK_EMMC:
+ case CLK_EMMC:
+ con_id = 57;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ /* Select clk_sdmmc/emmc source from GPLL by default */
+ /* mmc clock defaulg div 2 internal, need provide double in cru */
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, rate);
+
+ if (src_clk_div > 127) {
+ /* use 24MHz source for 400KHz clock */
+ src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, rate);
+ rk_clrsetreg(&cru->clksel_con[con_id],
+ EMMC_SEL_MASK | EMMC_DIV_MASK,
+ EMMC_SEL_XIN24M << EMMC_SEL_SHIFT |
+ (src_clk_div - 1) << EMMC_DIV_SHIFT);
+ } else {
+ rk_clrsetreg(&cru->clksel_con[con_id],
+ EMMC_SEL_MASK | EMMC_DIV_MASK,
+ EMMC_SEL_GPLL << EMMC_SEL_SHIFT |
+ (src_clk_div - 1) << EMMC_DIV_SHIFT);
+ }
+
+ return rv1126_mmc_get_clk(priv, clk_id);
+}
+
+static ulong rv1126_sfc_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[58]);
+ div = (con & SCLK_SFC_DIV_MASK) >> SCLK_SFC_DIV_SHIFT;
+ sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT;
+ if (sel == SCLK_SFC_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == SCLK_SFC_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_sfc_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ rk_clrsetreg(&cru->clksel_con[58],
+ SCLK_SFC_SEL_MASK | SCLK_SFC_DIV_MASK,
+ SCLK_SFC_SEL_GPLL << SCLK_SFC_SEL_SHIFT |
+ (src_clk_div - 1) << SCLK_SFC_DIV_SHIFT);
+
+ return rv1126_sfc_get_clk(priv);
+}
+
+static ulong rv1126_nand_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[59]);
+ div = (con & CLK_NANDC_DIV_MASK) >> CLK_NANDC_DIV_SHIFT;
+ sel = (con & CLK_NANDC_SEL_MASK) >> CLK_NANDC_SEL_SHIFT;
+ if (sel == CLK_NANDC_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == CLK_NANDC_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_nand_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ rk_clrsetreg(&cru->clksel_con[59],
+ CLK_NANDC_SEL_MASK | CLK_NANDC_DIV_MASK,
+ CLK_NANDC_SEL_GPLL << CLK_NANDC_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_NANDC_DIV_SHIFT);
+
+ return rv1126_nand_get_clk(priv);
+}
+
+static ulong rv1126_aclk_vop_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[45]);
+ div = (con & ACLK_PDVO_DIV_MASK) >> ACLK_PDVO_DIV_SHIFT;
+ sel = (con & ACLK_PDVO_SEL_MASK) >> ACLK_PDVO_SEL_SHIFT;
+ if (sel == ACLK_PDVO_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == ACLK_PDVO_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_aclk_vop_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[45],
+ ACLK_PDVO_SEL_MASK | ACLK_PDVO_DIV_MASK,
+ ACLK_PDVO_SEL_GPLL << ACLK_PDVO_SEL_SHIFT |
+ (src_clk_div - 1) << ACLK_PDVO_DIV_SHIFT);
+
+ return rv1126_aclk_vop_get_clk(priv);
+}
+
+static ulong rv1126_dclk_vop_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[47]);
+ div = (con & DCLK_VOP_DIV_MASK) >> DCLK_VOP_DIV_SHIFT;
+ sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT;
+ if (sel == DCLK_VOP_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == DCLK_VOP_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_dclk_vop_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ ulong pll_rate, now, best_rate = 0;
+ u32 i, div, best_div = 0, best_sel = 0;
+
+ for (i = 0; i <= DCLK_VOP_SEL_CPLL; i++) {
+ switch (i) {
+ case DCLK_VOP_SEL_GPLL:
+ pll_rate = priv->gpll_hz;
+ break;
+ case DCLK_VOP_SEL_CPLL:
+ pll_rate = priv->cpll_hz;
+ break;
+ default:
+ printf("do not support this vop pll sel\n");
+ return -EINVAL;
+ }
+
+ div = DIV_ROUND_UP(pll_rate, rate);
+ if (div > 255)
+ continue;
+ now = pll_rate / div;
+ if (abs(rate - now) < abs(rate - best_rate)) {
+ best_rate = now;
+ best_div = div;
+ best_sel = i;
+ }
+ debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n",
+ pll_rate, best_rate, best_div, best_sel);
+ }
+
+ if (best_rate) {
+ rk_clrsetreg(&cru->clksel_con[47],
+ DCLK_VOP_SEL_MASK | DCLK_VOP_DIV_MASK,
+ best_sel << DCLK_VOP_SEL_SHIFT |
+ (best_div - 1) << DCLK_VOP_DIV_SHIFT);
+ } else {
+ printf("do not support this vop freq %lu\n", rate);
+ return -EINVAL;
+ }
+
+ return rv1126_dclk_vop_get_clk(priv);
+}
+
+static ulong rv1126_scr1_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[3]);
+ div = (con & CLK_SCR1_DIV_MASK) >> CLK_SCR1_DIV_SHIFT;
+ sel = (con & CLK_SCR1_SEL_MASK) >> CLK_SCR1_SEL_SHIFT;
+ if (sel == CLK_SCR1_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == CLK_SCR1_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_scr1_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[3],
+ CLK_SCR1_SEL_MASK | CLK_SCR1_DIV_MASK,
+ CLK_SCR1_SEL_GPLL << CLK_SCR1_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_SCR1_DIV_SHIFT);
+
+ return rv1126_scr1_get_clk(priv);
+}
+
+static ulong rv1126_gmac_src_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[63]);
+ div = (con & CLK_GMAC_SRC_DIV_MASK) >> CLK_GMAC_SRC_DIV_SHIFT;
+ sel = (con & CLK_GMAC_SRC_SEL_MASK) >> CLK_GMAC_SRC_SEL_SHIFT;
+ if (sel == CLK_GMAC_SRC_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else if (sel == CLK_GMAC_SRC_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_gmac_src_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[63],
+ CLK_GMAC_SRC_SEL_MASK | CLK_GMAC_SRC_DIV_MASK,
+ CLK_GMAC_SRC_SEL_CPLL << CLK_GMAC_SRC_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_GMAC_SRC_DIV_SHIFT);
+
+ return rv1126_gmac_src_get_clk(priv);
+}
+
+static ulong rv1126_gmac_out_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[61]);
+ div = (con & CLK_GMAC_OUT_DIV_MASK) >> CLK_GMAC_OUT_DIV_SHIFT;
+ sel = (con & CLK_GMAC_OUT_SEL_MASK) >> CLK_GMAC_OUT_SEL_SHIFT;
+ if (sel == CLK_GMAC_OUT_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else if (sel == CLK_GMAC_OUT_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_gmac_out_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->cpll_hz, rate);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[61],
+ CLK_GMAC_OUT_SEL_MASK | CLK_GMAC_OUT_DIV_MASK,
+ CLK_GMAC_OUT_SEL_CPLL << CLK_GMAC_OUT_SEL_SHIFT |
+ (src_clk_div - 1) << CLK_GMAC_OUT_DIV_SHIFT);
+
+ return rv1126_gmac_out_get_clk(priv);
+}
+
+static ulong rv1126_gmac_tx_rx_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 con, sel, div_sel;
+
+ con = readl(&cru->gmac_con);
+ sel = (con & GMAC_MODE_SEL_MASK) >> GMAC_MODE_SEL_SHIFT;
+
+ if (sel == GMAC_RGMII_MODE) {
+ if (rate == 2500000)
+ div_sel = RGMII_CLK_DIV50;
+ else if (rate == 25000000)
+ div_sel = RGMII_CLK_DIV5;
+ else
+ div_sel = RGMII_CLK_DIV0;
+ rk_clrsetreg(&cru->gmac_con, RGMII_CLK_SEL_MASK,
+ div_sel << RGMII_CLK_SEL_SHIFT);
+ } else if (sel == GMAC_RMII_MODE) {
+ if (rate == 2500000)
+ div_sel = RMII_CLK_DIV20;
+ else
+ div_sel = RMII_CLK_DIV2;
+ rk_clrsetreg(&cru->gmac_con, RMII_CLK_SEL_MASK,
+ div_sel << RMII_CLK_SEL_SHIFT);
+ }
+
+ return 0;
+}
+
+static ulong rv1126_pclk_gmac_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, con, parent;
+
+ parent = rv1126_pdphp_get_clk(priv, ACLK_PDPHP);
+
+ con = readl(&cru->clksel_con[63]);
+ div = (con & PCLK_GMAC_DIV_MASK) >> PCLK_GMAC_DIV_SHIFT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_dclk_decom_get_clk(struct rv1126_clk_priv *priv)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 div, sel, con, parent;
+
+ con = readl(&cru->clksel_con[25]);
+ div = (con & DCLK_DECOM_DIV_MASK) >> DCLK_DECOM_DIV_SHIFT;
+ sel = (con & DCLK_DECOM_SEL_MASK) >> DCLK_DECOM_SEL_SHIFT;
+ if (sel == DCLK_DECOM_SEL_GPLL)
+ parent = priv->gpll_hz;
+ else if (sel == DCLK_DECOM_SEL_CPLL)
+ parent = priv->cpll_hz;
+ else
+ return -ENOENT;
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong rv1126_dclk_decom_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct rv1126_cru *cru = priv->cru;
+ u32 src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, rate);
+ assert(src_clk_div - 1 <= 127);
+ rk_clrsetreg(&cru->clksel_con[25],
+ DCLK_DECOM_SEL_MASK | DCLK_DECOM_DIV_MASK,
+ DCLK_DECOM_SEL_GPLL << DCLK_DECOM_SEL_SHIFT |
+ (src_clk_div - 1) << DCLK_DECOM_DIV_SHIFT);
+
+ return rv1126_dclk_decom_get_clk(priv);
+}
+
+static ulong rv1126_clk_get_rate(struct clk *clk)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong rate = 0;
+
+ if (!priv->gpll_hz) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ switch (clk->id) {
+ case PLL_APLL:
+ case ARMCLK:
+ rate = rockchip_pll_get_rate(&rv1126_pll_clks[APLL], priv->cru,
+ APLL);
+ break;
+ case PLL_CPLL:
+ rate = rockchip_pll_get_rate(&rv1126_pll_clks[CPLL], priv->cru,
+ CPLL);
+ break;
+ case PLL_HPLL:
+ rate = rockchip_pll_get_rate(&rv1126_pll_clks[HPLL], priv->cru,
+ HPLL);
+ break;
+ case PLL_DPLL:
+ rate = rockchip_pll_get_rate(&rv1126_pll_clks[DPLL], priv->cru,
+ DPLL);
+ break;
+ case HCLK_PDCORE_NIU:
+ rate = rv1126_pdcore_get_clk(priv);
+ break;
+ case ACLK_PDBUS:
+ case HCLK_PDBUS:
+ case PCLK_PDBUS:
+ case PCLK_WDT:
+ rate = rv1126_pdbus_get_clk(priv, clk->id);
+ break;
+ case ACLK_PDPHP:
+ case HCLK_PDPHP:
+ rate = rv1126_pdphp_get_clk(priv, clk->id);
+ break;
+ case HCLK_PDAUDIO:
+ rate = rv1126_pdaudio_get_clk(priv);
+ break;
+ case CLK_I2C1:
+ case CLK_I2C3:
+ case CLK_I2C4:
+ case CLK_I2C5:
+ rate = rv1126_i2c_get_clk(priv, clk->id);
+ break;
+ case CLK_SPI1:
+ rate = rv1126_spi_get_clk(priv);
+ break;
+ case CLK_PWM2:
+ rate = rv1126_pwm_get_clk(priv);
+ break;
+ case CLK_SARADC:
+ rate = rv1126_saradc_get_clk(priv);
+ break;
+ case CLK_CRYPTO_CORE:
+ case CLK_CRYPTO_PKA:
+ case ACLK_CRYPTO:
+ rate = rv1126_crypto_get_clk(priv, clk->id);
+ break;
+ case CLK_SDMMC:
+ case HCLK_SDMMC:
+ case CLK_SDIO:
+ case HCLK_SDIO:
+ case CLK_EMMC:
+ case HCLK_EMMC:
+ case SCLK_EMMC_SAMPLE:
+ rate = rv1126_mmc_get_clk(priv, clk->id);
+ break;
+ case SCLK_SFC:
+ rate = rv1126_sfc_get_clk(priv);
+ break;
+ case CLK_NANDC:
+ rate = rv1126_nand_get_clk(priv);
+ break;
+ case ACLK_PDVO:
+ case ACLK_VOP:
+ rate = rv1126_aclk_vop_get_clk(priv);
+ break;
+ case DCLK_VOP:
+ rate = rv1126_dclk_vop_get_clk(priv);
+ break;
+ case CLK_SCR1_CORE:
+ rate = rv1126_scr1_get_clk(priv);
+ break;
+ case CLK_GMAC_SRC:
+ rate = rv1126_gmac_src_get_clk(priv);
+ break;
+ case CLK_GMAC_ETHERNET_OUT:
+ rate = rv1126_gmac_out_get_clk(priv);
+ break;
+ case PCLK_GMAC:
+ rate = rv1126_pclk_gmac_get_clk(priv);
+ break;
+ case DCLK_DECOM:
+ rate = rv1126_dclk_decom_get_clk(priv);
+ break;
+ default:
+ debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
+ return -ENOENT;
+ }
+
+ return rate;
+};
+
+static ulong rv1126_clk_set_rate(struct clk *clk, ulong rate)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong ret = 0;
+
+ if (!priv->gpll_hz) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ switch (clk->id) {
+ case PLL_APLL:
+ case ARMCLK:
+ if (priv->armclk_hz)
+ rv1126_armclk_set_clk(priv, rate);
+ priv->armclk_hz = rate;
+ break;
+ case PLL_CPLL:
+ ret = rockchip_pll_set_rate(&rv1126_pll_clks[CPLL], priv->cru,
+ CPLL, rate);
+ break;
+ case PLL_HPLL:
+ ret = rockchip_pll_set_rate(&rv1126_pll_clks[HPLL], priv->cru,
+ HPLL, rate);
+ break;
+ case ACLK_PDBUS:
+ case HCLK_PDBUS:
+ case PCLK_PDBUS:
+ case PCLK_WDT:
+ ret = rv1126_pdbus_set_clk(priv, clk->id, rate);
+ break;
+ case ACLK_PDPHP:
+ case HCLK_PDPHP:
+ ret = rv1126_pdphp_set_clk(priv, clk->id, rate);
+ break;
+ case HCLK_PDCORE_NIU:
+ ret = rv1126_pdcore_set_clk(priv, rate);
+ break;
+ case HCLK_PDAUDIO:
+ ret = rv1126_pdaudio_set_clk(priv, rate);
+ break;
+ case CLK_I2C1:
+ case CLK_I2C3:
+ case CLK_I2C4:
+ case CLK_I2C5:
+ ret = rv1126_i2c_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_SPI1:
+ ret = rv1126_spi_set_clk(priv, rate);
+ break;
+ case CLK_PWM2:
+ ret = rv1126_pwm_set_clk(priv, rate);
+ break;
+ case CLK_SARADC:
+ ret = rv1126_saradc_set_clk(priv, rate);
+ break;
+ case CLK_CRYPTO_CORE:
+ case CLK_CRYPTO_PKA:
+ case ACLK_CRYPTO:
+ ret = rv1126_crypto_set_clk(priv, clk->id, rate);
+ break;
+ case CLK_SDMMC:
+ case HCLK_SDMMC:
+ case CLK_SDIO:
+ case HCLK_SDIO:
+ case CLK_EMMC:
+ case HCLK_EMMC:
+ ret = rv1126_mmc_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_SFC:
+ ret = rv1126_sfc_set_clk(priv, rate);
+ break;
+ case CLK_NANDC:
+ ret = rv1126_nand_set_clk(priv, rate);
+ break;
+ case ACLK_PDVO:
+ case ACLK_VOP:
+ ret = rv1126_aclk_vop_set_clk(priv, rate);
+ break;
+ case DCLK_VOP:
+ ret = rv1126_dclk_vop_set_clk(priv, rate);
+ break;
+ case CLK_SCR1_CORE:
+ ret = rv1126_scr1_set_clk(priv, rate);
+ break;
+ case CLK_GMAC_SRC:
+ ret = rv1126_gmac_src_set_clk(priv, rate);
+ break;
+ case CLK_GMAC_ETHERNET_OUT:
+ ret = rv1126_gmac_out_set_clk(priv, rate);
+ break;
+ case CLK_GMAC_TX_RX:
+ ret = rv1126_gmac_tx_rx_set_clk(priv, rate);
+ break;
+ case DCLK_DECOM:
+ ret = rv1126_dclk_decom_set_clk(priv, rate);
+ break;
+ default:
+ debug("%s: Unsupported CLK#%ld\n", __func__, clk->id);
+ return -ENOENT;
+ }
+
+ return ret;
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int rv1126_gmac_src_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rv1126_grf *grf = priv->grf;
+
+ if (parent->id == CLK_GMAC_SRC_M0)
+ rk_clrsetreg(&grf->iofunc_con1, GMAC_SRC_SEL_MASK,
+ GMAC_SRC_SEL_M0 << GMAC_SRC_SEL_SHIFT);
+ else if (parent->id == CLK_GMAC_SRC_M1)
+ rk_clrsetreg(&grf->iofunc_con1, GMAC_SRC_SEL_MASK,
+ GMAC_SRC_SEL_M1 << GMAC_SRC_SEL_SHIFT);
+
+ return 0;
+}
+
+static int rv1126_gmac_src_m0_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rv1126_cru *cru = priv->cru;
+
+ if (parent->id == CLK_GMAC_DIV)
+ rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M0_SEL_MASK,
+ GMAC_SRC_M0_SEL_INT << GMAC_SRC_M0_SEL_SHIFT);
+ else
+ rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M0_SEL_MASK,
+ GMAC_SRC_M0_SEL_EXT << GMAC_SRC_M0_SEL_SHIFT);
+
+ return 0;
+}
+
+static int rv1126_gmac_src_m1_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rv1126_cru *cru = priv->cru;
+
+ if (parent->id == CLK_GMAC_DIV)
+ rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M1_SEL_MASK,
+ GMAC_SRC_M1_SEL_INT << GMAC_SRC_M1_SEL_SHIFT);
+ else
+ rk_clrsetreg(&cru->gmac_con, GMAC_SRC_M1_SEL_MASK,
+ GMAC_SRC_M1_SEL_EXT << GMAC_SRC_M1_SEL_SHIFT);
+
+ return 0;
+}
+
+static int rv1126_gmac_tx_rx_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(clk->dev);
+ struct rv1126_cru *cru = priv->cru;
+
+ if (parent->id == RGMII_MODE_CLK)
+ rk_clrsetreg(&cru->gmac_con, GMAC_MODE_SEL_MASK,
+ GMAC_RGMII_MODE << GMAC_MODE_SEL_SHIFT);
+ else
+ rk_clrsetreg(&cru->gmac_con, GMAC_MODE_SEL_MASK,
+ GMAC_RMII_MODE << GMAC_MODE_SEL_SHIFT);
+
+ return 0;
+}
+
+static int rv1126_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ switch (clk->id) {
+ case CLK_GMAC_SRC:
+ return rv1126_gmac_src_set_parent(clk, parent);
+ case CLK_GMAC_SRC_M0:
+ return rv1126_gmac_src_m0_set_parent(clk, parent);
+ case CLK_GMAC_SRC_M1:
+ return rv1126_gmac_src_m1_set_parent(clk, parent);
+ case CLK_GMAC_TX_RX:
+ return rv1126_gmac_tx_rx_set_parent(clk, parent);
+ default:
+ return -ENOENT;
+ }
+
+ return 0;
+}
+#endif
+
+static struct clk_ops rv1126_clk_ops = {
+ .get_rate = rv1126_clk_get_rate,
+ .set_rate = rv1126_clk_set_rate,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .set_parent = rv1126_clk_set_parent,
+#endif
+};
+
+static ulong rv1126_gpll_set_rate(struct rv1126_clk_priv *priv,
+ struct rv1126_pmuclk_priv *pmu_priv,
+ ulong rate)
+{
+ ulong emmc_rate, sfc_rate, nandc_rate;
+ bool restore = false;
+
+ if (priv->gpll_hz != OSC_HZ) {
+ emmc_rate = rv1126_mmc_get_clk(priv, CLK_EMMC);
+ sfc_rate = rv1126_sfc_get_clk(priv);
+ nandc_rate = rv1126_nand_get_clk(priv);
+ debug("%s emmc=%lu, sfc=%lu, nandc=%lu\n", __func__,
+ emmc_rate, sfc_rate, nandc_rate);
+ restore = true;
+ }
+
+ /*
+ * the child div is big enough for gpll 1188MHz,
+ * even maskrom has change some clocks.
+ */
+ if (rockchip_pll_set_rate(&rv1126_pll_clks[GPLL],
+ pmu_priv->pmucru, GPLL, rate))
+ return -EINVAL;
+ pmu_priv->gpll_hz = rate;
+ priv->gpll_hz = rate;
+
+ if (restore) {
+ rv1126_mmc_set_clk(priv, CLK_EMMC, emmc_rate);
+ rv1126_sfc_set_clk(priv, sfc_rate);
+ rv1126_nand_set_clk(priv, nandc_rate);
+ }
+
+ return 0;
+}
+
+static int rv1126_gpll_set_clk(struct rv1126_clk_priv *priv, ulong rate)
+{
+ struct udevice *pmucru_dev;
+ struct rv1126_pmuclk_priv *pmu_priv;
+ int ret;
+
+ ret = uclass_get_device_by_driver(UCLASS_CLK,
+ DM_DRIVER_GET(rockchip_rv1126_pmucru),
+ &pmucru_dev);
+ if (ret) {
+ printf("%s: could not find pmucru device\n", __func__);
+ return ret;
+ }
+ pmu_priv = dev_get_priv(pmucru_dev);
+ priv->gpll_hz = pmu_priv->gpll_hz;
+
+ if (rv1126_gpll_set_rate(priv, pmu_priv, rate)) {
+ printf("%s: failed to set gpll rate %lu\n", __func__, rate);
+ return -EINVAL;
+ }
+
+ rv1126_pdpmu_set_pmuclk(pmu_priv, PCLK_PDPMU_HZ);
+ rv1126_rtc32k_set_pmuclk(pmu_priv, CLK_OSC0_DIV_HZ);
+
+ return 0;
+}
+
+static void rv1126_clk_init(struct rv1126_clk_priv *priv)
+{
+ int ret;
+
+ priv->sync_kernel = false;
+ if (!priv->armclk_enter_hz) {
+ priv->armclk_enter_hz =
+ rockchip_pll_get_rate(&rv1126_pll_clks[APLL],
+ priv->cru, APLL);
+ priv->armclk_init_hz = priv->armclk_enter_hz;
+ }
+
+ if (priv->armclk_init_hz != APLL_HZ) {
+ ret = rv1126_armclk_set_clk(priv, APLL_HZ);
+ if (!ret)
+ priv->armclk_init_hz = APLL_HZ;
+ }
+ if (priv->cpll_hz != CPLL_HZ) {
+ ret = rockchip_pll_set_rate(&rv1126_pll_clks[CPLL], priv->cru,
+ CPLL, CPLL_HZ);
+ if (!ret)
+ priv->cpll_hz = CPLL_HZ;
+ }
+ if (priv->hpll_hz != HPLL_HZ) {
+ ret = rockchip_pll_set_rate(&rv1126_pll_clks[HPLL], priv->cru,
+ HPLL, HPLL_HZ);
+ if (!ret)
+ priv->hpll_hz = HPLL_HZ;
+ }
+ if (priv->gpll_hz != GPLL_HZ)
+ rv1126_gpll_set_clk(priv, GPLL_HZ);
+
+ rv1126_pdbus_set_clk(priv, ACLK_PDBUS, ACLK_PDBUS_HZ);
+ rv1126_pdbus_set_clk(priv, HCLK_PDBUS, HCLK_PDBUS_HZ);
+ rv1126_pdbus_set_clk(priv, PCLK_PDBUS, PCLK_PDBUS_HZ);
+ rv1126_pdphp_set_clk(priv, ACLK_PDPHP, ACLK_PDPHP_HZ);
+ rv1126_pdphp_set_clk(priv, HCLK_PDPHP, HCLK_PDPHP_HZ);
+ rv1126_pdcore_set_clk(priv, HCLK_PDCORE_HZ);
+ rv1126_pdaudio_set_clk(priv, HCLK_PDAUDIO_HZ);
+}
+
+static int rv1126_clk_probe(struct udevice *dev)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+ if (IS_ERR(priv->grf))
+ return PTR_ERR(priv->grf);
+
+ rv1126_clk_init(priv);
+
+ /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
+ ret = clk_set_defaults(dev, 1);
+ if (ret)
+ debug("%s clk_set_defaults failed %d\n", __func__, ret);
+ else
+ priv->sync_kernel = true;
+
+ return 0;
+}
+
+static int rv1126_clk_of_to_plat(struct udevice *dev)
+{
+ struct rv1126_clk_priv *priv = dev_get_priv(dev);
+
+ priv->cru = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static int rv1126_clk_bind(struct udevice *dev)
+{
+ int ret;
+ struct udevice *sys_child;
+ struct sysreset_reg *priv;
+
+ /* The reset driver does not have a device node, so bind it here */
+ ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+ &sys_child);
+ if (ret) {
+ debug("Warning: No sysreset driver: ret=%d\n", ret);
+ } else {
+ priv = malloc(sizeof(struct sysreset_reg));
+ priv->glb_srst_fst_value = offsetof(struct rv1126_cru,
+ glb_srst_fst);
+ priv->glb_srst_snd_value = offsetof(struct rv1126_cru,
+ glb_srst_snd);
+ dev_set_priv(sys_child, priv);
+ }
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+ ret = offsetof(struct rv1126_cru, softrst_con[0]);
+ ret = rockchip_reset_bind(dev, ret, 15);
+ if (ret)
+ debug("Warning: software reset driver bind faile\n");
+#endif
+ return 0;
+}
+
+static const struct udevice_id rv1126_clk_ids[] = {
+ { .compatible = "rockchip,rv1126-cru" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_rv1126_cru) = {
+ .name = "rockchip_rv1126_cru",
+ .id = UCLASS_CLK,
+ .of_match = rv1126_clk_ids,
+ .priv_auto = sizeof(struct rv1126_clk_priv),
+ .of_to_plat = rv1126_clk_of_to_plat,
+ .ops = &rv1126_clk_ops,
+ .bind = rv1126_clk_bind,
+ .probe = rv1126_clk_probe,
+};
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 8c81b1a..136ba89 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -16,6 +16,7 @@
static const struct ccu_clk_gate a64_gates[] = {
[CLK_PLL_PERIPH0] = GATE(0x028, BIT(31)),
+ [CLK_BUS_MIPI_DSI] = GATE(0x060, BIT(1)),
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
@@ -28,6 +29,11 @@
[CLK_BUS_OHCI0] = GATE(0x060, BIT(28)),
[CLK_BUS_OHCI1] = GATE(0x060, BIT(29)),
+ [CLK_BUS_TCON0] = GATE(0x064, BIT(3)),
+ [CLK_BUS_TCON1] = GATE(0x064, BIT(4)),
+ [CLK_BUS_HDMI] = GATE(0x064, BIT(11)),
+ [CLK_BUS_DE] = GATE(0x064, BIT(12)),
+
[CLK_BUS_PIO] = GATE(0x068, BIT(5)),
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
@@ -48,6 +54,15 @@
[CLK_USB_HSIC_12M] = GATE(0x0cc, BIT(11)),
[CLK_USB_OHCI0] = GATE(0x0cc, BIT(16)),
[CLK_USB_OHCI1] = GATE(0x0cc, BIT(17)),
+
+ [CLK_DE] = GATE(0x104, BIT(31)),
+ [CLK_TCON0] = GATE(0x118, BIT(31)),
+ [CLK_TCON1] = GATE(0x11c, BIT(31)),
+
+ [CLK_HDMI] = GATE(0x150, BIT(31)),
+ [CLK_HDMI_DDC] = GATE(0x154, BIT(31)),
+
+ [CLK_DSI_DPHY] = GATE(0x168, BIT(15)),
};
static const struct ccu_reset a64_resets[] = {
@@ -55,6 +70,7 @@
[RST_USB_PHY1] = RESET(0x0cc, BIT(1)),
[RST_USB_HSIC] = RESET(0x0cc, BIT(2)),
+ [RST_BUS_MIPI_DSI] = RESET(0x2c0, BIT(1)),
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
@@ -67,6 +83,12 @@
[RST_BUS_OHCI0] = RESET(0x2c0, BIT(28)),
[RST_BUS_OHCI1] = RESET(0x2c0, BIT(29)),
+ [RST_BUS_TCON0] = RESET(0x2c4, BIT(3)),
+ [RST_BUS_TCON1] = RESET(0x2c4, BIT(4)),
+ [RST_BUS_HDMI0] = RESET(0x2c4, BIT(10)),
+ [RST_BUS_HDMI1] = RESET(0x2c4, BIT(11)),
+ [RST_BUS_DE] = RESET(0x2c4, BIT(12)),
+
[RST_BUS_I2C0] = RESET(0x2d8, BIT(0)),
[RST_BUS_I2C1] = RESET(0x2d8, BIT(1)),
[RST_BUS_I2C2] = RESET(0x2d8, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
index 3562da6..d5af37b 100644
--- a/drivers/clk/sunxi/clk_a83t.c
+++ b/drivers/clk/sunxi/clk_a83t.c
@@ -14,6 +14,7 @@
#include <linux/bitops.h>
static struct ccu_clk_gate a83t_gates[] = {
+ [CLK_BUS_MIPI_DSI] = GATE(0x060, BIT(1)),
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
@@ -25,6 +26,11 @@
[CLK_BUS_EHCI1] = GATE(0x060, BIT(27)),
[CLK_BUS_OHCI0] = GATE(0x060, BIT(29)),
+ [CLK_BUS_TCON0] = GATE(0x064, BIT(4)),
+ [CLK_BUS_TCON1] = GATE(0x064, BIT(5)),
+ [CLK_BUS_HDMI] = GATE(0x064, BIT(11)),
+ [CLK_BUS_DE] = GATE(0x064, BIT(12)),
+
[CLK_BUS_PIO] = GATE(0x068, BIT(5)),
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
@@ -44,6 +50,15 @@
[CLK_USB_HSIC] = GATE(0x0cc, BIT(10)),
[CLK_USB_HSIC_12M] = GATE(0x0cc, BIT(11)),
[CLK_USB_OHCI0] = GATE(0x0cc, BIT(16)),
+
+ [CLK_TCON0] = GATE(0x118, BIT(31)),
+ [CLK_TCON1] = GATE(0x11c, BIT(31)),
+
+ [CLK_HDMI] = GATE(0x150, BIT(31)),
+ [CLK_HDMI_SLOW] = GATE(0x154, BIT(31)),
+
+ [CLK_MIPI_DSI0] = GATE(0x168, BIT(31)),
+ [CLK_MIPI_DSI1] = GATE(0x16c, BIT(31)),
};
static struct ccu_reset a83t_resets[] = {
@@ -51,6 +66,7 @@
[RST_USB_PHY1] = RESET(0x0cc, BIT(1)),
[RST_USB_HSIC] = RESET(0x0cc, BIT(2)),
+ [RST_BUS_MIPI_DSI] = RESET(0x2c0, BIT(1)),
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
@@ -62,6 +78,12 @@
[RST_BUS_EHCI1] = RESET(0x2c0, BIT(27)),
[RST_BUS_OHCI0] = RESET(0x2c0, BIT(29)),
+ [RST_BUS_TCON0] = RESET(0x2c4, BIT(4)),
+ [RST_BUS_TCON1] = RESET(0x2c4, BIT(5)),
+ [RST_BUS_HDMI0] = RESET(0x2c4, BIT(10)),
+ [RST_BUS_HDMI1] = RESET(0x2c4, BIT(11)),
+ [RST_BUS_DE] = RESET(0x2c4, BIT(12)),
+
[RST_BUS_I2C0] = RESET(0x2d8, BIT(0)),
[RST_BUS_I2C1] = RESET(0x2d8, BIT(1)),
[RST_BUS_I2C2] = RESET(0x2d8, BIT(2)),
diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
index 17ab3b5..213ab51 100644
--- a/drivers/clk/sunxi/clk_h3.c
+++ b/drivers/clk/sunxi/clk_h3.c
@@ -32,6 +32,11 @@
[CLK_BUS_OHCI2] = GATE(0x060, BIT(30)),
[CLK_BUS_OHCI3] = GATE(0x060, BIT(31)),
+ [CLK_BUS_TCON0] = GATE(0x064, BIT(3)),
+ [CLK_BUS_TCON1] = GATE(0x064, BIT(4)),
+ [CLK_BUS_HDMI] = GATE(0x064, BIT(11)),
+ [CLK_BUS_DE] = GATE(0x064, BIT(12)),
+
[CLK_BUS_PIO] = GATE(0x068, BIT(5)),
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
@@ -55,6 +60,12 @@
[CLK_USB_OHCI1] = GATE(0x0cc, BIT(17)),
[CLK_USB_OHCI2] = GATE(0x0cc, BIT(18)),
[CLK_USB_OHCI3] = GATE(0x0cc, BIT(19)),
+
+ [CLK_DE] = GATE(0x104, BIT(31)),
+ [CLK_TCON0] = GATE(0x118, BIT(31)),
+
+ [CLK_HDMI] = GATE(0x150, BIT(31)),
+ [CLK_HDMI_DDC] = GATE(0x154, BIT(31)),
};
static struct ccu_reset h3_resets[] = {
@@ -79,6 +90,12 @@
[RST_BUS_OHCI2] = RESET(0x2c0, BIT(30)),
[RST_BUS_OHCI3] = RESET(0x2c0, BIT(31)),
+ [RST_BUS_TCON0] = RESET(0x2c4, BIT(3)),
+ [RST_BUS_TCON1] = RESET(0x2c4, BIT(4)),
+ [RST_BUS_HDMI0] = RESET(0x2c4, BIT(10)),
+ [RST_BUS_HDMI1] = RESET(0x2c4, BIT(11)),
+ [RST_BUS_DE] = RESET(0x2c4, BIT(12)),
+
[RST_BUS_EPHY] = RESET(0x2c8, BIT(2)),
[RST_BUS_I2C0] = RESET(0x2d8, BIT(0)),
diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
index 041bc5e..24eb972 100644
--- a/drivers/clk/sunxi/clk_h6.c
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -18,6 +18,9 @@
[CLK_APB1] = GATE_DUMMY,
+ [CLK_DE] = GATE(0x600, BIT(31)),
+ [CLK_BUS_DE] = GATE(0x60c, BIT(0)),
+
[CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
[CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
[CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
@@ -55,9 +58,21 @@
[CLK_BUS_XHCI] = GATE(0xa8c, BIT(5)),
[CLK_BUS_EHCI3] = GATE(0xa8c, BIT(7)),
[CLK_BUS_OTG] = GATE(0xa8c, BIT(8)),
+
+ [CLK_HDMI] = GATE(0xb00, BIT(31)),
+ [CLK_HDMI_SLOW] = GATE(0xb04, BIT(31)),
+ [CLK_HDMI_CEC] = GATE(0xb10, BIT(31)),
+ [CLK_BUS_HDMI] = GATE(0xb1c, BIT(0)),
+ [CLK_BUS_TCON_TOP] = GATE(0xb5c, BIT(0)),
+ [CLK_TCON_LCD0] = GATE(0xb60, BIT(31)),
+ [CLK_BUS_TCON_LCD0] = GATE(0xb7c, BIT(0)),
+ [CLK_TCON_TV0] = GATE(0xb80, BIT(31)),
+ [CLK_BUS_TCON_TV0] = GATE(0xb9c, BIT(0)),
};
static struct ccu_reset h6_resets[] = {
+ [RST_BUS_DE] = RESET(0x60c, BIT(16)),
+
[RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
[RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
[RST_BUS_MMC2] = RESET(0x84c, BIT(18)),
@@ -89,6 +104,12 @@
[RST_BUS_XHCI] = RESET(0xa8c, BIT(21)),
[RST_BUS_EHCI3] = RESET(0xa8c, BIT(23)),
[RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
+
+ [RST_BUS_HDMI] = RESET(0xb1c, BIT(16)),
+ [RST_BUS_HDMI_SUB] = RESET(0xb1c, BIT(17)),
+ [RST_BUS_TCON_TOP] = RESET(0xb5c, BIT(16)),
+ [RST_BUS_TCON_LCD0] = RESET(0xb7c, BIT(16)),
+ [RST_BUS_TCON_TV0] = RESET(0xb9c, BIT(16)),
};
const struct ccu_desc h6_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c
index 964636d..88d6bf3 100644
--- a/drivers/clk/sunxi/clk_h616.c
+++ b/drivers/clk/sunxi/clk_h616.c
@@ -17,6 +17,9 @@
[CLK_APB1] = GATE_DUMMY,
+ [CLK_DE] = GATE(0x600, BIT(31)),
+ [CLK_BUS_DE] = GATE(0x60c, BIT(0)),
+
[CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
[CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
[CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
@@ -64,9 +67,21 @@
[CLK_BUS_EHCI2] = GATE(0xa8c, BIT(6)),
[CLK_BUS_EHCI3] = GATE(0xa8c, BIT(7)),
[CLK_BUS_OTG] = GATE(0xa8c, BIT(8)),
+
+ [CLK_HDMI] = GATE(0xb00, BIT(31)),
+ [CLK_HDMI_SLOW] = GATE(0xb04, BIT(31)),
+ [CLK_HDMI_CEC] = GATE(0xb10, BIT(31)),
+ [CLK_BUS_HDMI] = GATE(0xb1c, BIT(0)),
+ [CLK_BUS_TCON_TOP] = GATE(0xb5c, BIT(0)),
+ [CLK_TCON_TV0] = GATE(0xb80, BIT(31)),
+ [CLK_TCON_TV1] = GATE(0xb84, BIT(31)),
+ [CLK_BUS_TCON_TV0] = GATE(0xb9c, BIT(0)),
+ [CLK_BUS_TCON_TV1] = GATE(0xb9c, BIT(1)),
};
static struct ccu_reset h616_resets[] = {
+ [RST_BUS_DE] = RESET(0x60c, BIT(16)),
+
[RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
[RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
[RST_BUS_MMC2] = RESET(0x84c, BIT(18)),
@@ -107,6 +122,12 @@
[RST_BUS_EHCI2] = RESET(0xa8c, BIT(22)),
[RST_BUS_EHCI3] = RESET(0xa8c, BIT(23)),
[RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
+
+ [RST_BUS_HDMI] = RESET(0xb1c, BIT(16)),
+ [RST_BUS_HDMI_SUB] = RESET(0xb1c, BIT(17)),
+ [RST_BUS_TCON_TOP] = RESET(0xb5c, BIT(16)),
+ [RST_BUS_TCON_TV0] = RESET(0xb9c, BIT(16)),
+ [RST_BUS_TCON_TV1] = RESET(0xb9c, BIT(17)),
};
const struct ccu_desc h616_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
index ef743d6..630e80d 100644
--- a/drivers/clk/sunxi/clk_r40.c
+++ b/drivers/clk/sunxi/clk_r40.c
@@ -14,6 +14,7 @@
#include <linux/bitops.h>
static struct ccu_clk_gate r40_gates[] = {
+ [CLK_BUS_MIPI_DSI] = GATE(0x060, BIT(1)),
[CLK_BUS_MMC0] = GATE(0x060, BIT(8)),
[CLK_BUS_MMC1] = GATE(0x060, BIT(9)),
[CLK_BUS_MMC2] = GATE(0x060, BIT(10)),
@@ -30,7 +31,15 @@
[CLK_BUS_OHCI1] = GATE(0x060, BIT(30)),
[CLK_BUS_OHCI2] = GATE(0x060, BIT(31)),
+ [CLK_BUS_HDMI0] = GATE(0x064, BIT(10)),
+ [CLK_BUS_HDMI1] = GATE(0x064, BIT(11)),
+ [CLK_BUS_DE] = GATE(0x064, BIT(12)),
[CLK_BUS_GMAC] = GATE(0x064, BIT(17)),
+ [CLK_BUS_TCON_LCD0] = GATE(0x064, BIT(26)),
+ [CLK_BUS_TCON_LCD1] = GATE(0x064, BIT(27)),
+ [CLK_BUS_TCON_TV0] = GATE(0x064, BIT(28)),
+ [CLK_BUS_TCON_TV1] = GATE(0x064, BIT(29)),
+ [CLK_BUS_TCON_TOP] = GATE(0x064, BIT(30)),
[CLK_BUS_PIO] = GATE(0x068, BIT(5)),
@@ -59,6 +68,17 @@
[CLK_USB_OHCI0] = GATE(0x0cc, BIT(16)),
[CLK_USB_OHCI1] = GATE(0x0cc, BIT(17)),
[CLK_USB_OHCI2] = GATE(0x0cc, BIT(18)),
+
+ [CLK_DE] = GATE(0x104, BIT(31)),
+ [CLK_TCON_LCD0] = GATE(0x110, BIT(31)),
+ [CLK_TCON_LCD1] = GATE(0x114, BIT(31)),
+ [CLK_TCON_TV0] = GATE(0x118, BIT(31)),
+ [CLK_TCON_TV1] = GATE(0x11c, BIT(31)),
+
+ [CLK_HDMI] = GATE(0x150, BIT(31)),
+ [CLK_HDMI_SLOW] = GATE(0x154, BIT(31)),
+
+ [CLK_DSI_DPHY] = GATE(0x168, BIT(15)),
};
static struct ccu_reset r40_resets[] = {
@@ -66,6 +86,7 @@
[RST_USB_PHY1] = RESET(0x0cc, BIT(1)),
[RST_USB_PHY2] = RESET(0x0cc, BIT(2)),
+ [RST_BUS_MIPI_DSI] = RESET(0x2c0, BIT(1)),
[RST_BUS_MMC0] = RESET(0x2c0, BIT(8)),
[RST_BUS_MMC1] = RESET(0x2c0, BIT(9)),
[RST_BUS_MMC2] = RESET(0x2c0, BIT(10)),
@@ -82,7 +103,15 @@
[RST_BUS_OHCI1] = RESET(0x2c0, BIT(30)),
[RST_BUS_OHCI2] = RESET(0x2c0, BIT(31)),
+ [RST_BUS_HDMI0] = RESET(0x2c4, BIT(10)),
+ [RST_BUS_HDMI1] = RESET(0x2c4, BIT(11)),
+ [RST_BUS_DE] = RESET(0x2c4, BIT(12)),
[RST_BUS_GMAC] = RESET(0x2c4, BIT(17)),
+ [RST_BUS_TCON_LCD0] = RESET(0x2c4, BIT(26)),
+ [RST_BUS_TCON_LCD1] = RESET(0x2c4, BIT(27)),
+ [RST_BUS_TCON_TV0] = RESET(0x2c4, BIT(28)),
+ [RST_BUS_TCON_TV1] = RESET(0x2c4, BIT(29)),
+ [RST_BUS_TCON_TOP] = RESET(0x2c4, BIT(30)),
[RST_BUS_I2C0] = RESET(0x2d8, BIT(0)),
[RST_BUS_I2C1] = RESET(0x2d8, BIT(1)),
diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c
index f2fd11e..6524c13 100644
--- a/drivers/clk/sunxi/clk_v3s.c
+++ b/drivers/clk/sunxi/clk_v3s.c
@@ -20,6 +20,9 @@
[CLK_BUS_SPI0] = GATE(0x060, BIT(20)),
[CLK_BUS_OTG] = GATE(0x060, BIT(24)),
+ [CLK_BUS_TCON0] = GATE(0x064, BIT(4)),
+ [CLK_BUS_DE] = GATE(0x064, BIT(12)),
+
[CLK_BUS_PIO] = GATE(0x068, BIT(5)),
[CLK_BUS_I2C0] = GATE(0x06c, BIT(0)),
@@ -31,6 +34,9 @@
[CLK_SPI0] = GATE(0x0a0, BIT(31)),
[CLK_USB_PHY0] = GATE(0x0cc, BIT(8)),
+
+ [CLK_DE] = GATE(0x104, BIT(31)),
+ [CLK_TCON0] = GATE(0x118, BIT(31)),
};
static struct ccu_reset v3s_resets[] = {
@@ -42,6 +48,9 @@
[RST_BUS_SPI0] = RESET(0x2c0, BIT(20)),
[RST_BUS_OTG] = RESET(0x2c0, BIT(24)),
+ [RST_BUS_TCON0] = RESET(0x2c4, BIT(4)),
+ [RST_BUS_DE] = RESET(0x2c4, BIT(12)),
+
[RST_BUS_I2C0] = RESET(0x2d8, BIT(0)),
[RST_BUS_I2C1] = RESET(0x2d8, BIT(1)),
[RST_BUS_UART0] = RESET(0x2d8, BIT(16)),
diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 8fde77c..6fc8854 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -109,13 +109,14 @@
causes USB host controllers to not be stopped when booting the OS.
config DM_EVENT
- bool "Support events with driver model"
- depends on DM && EVENT
- default y if SANDBOX
+ bool
+ depends on DM
+ select EVENT
help
This enables support for generating events related to driver model
operations, such as prbing or removing a device. Subsystems can
- register a 'spy' function that is called when the event occurs.
+ register a 'spy' function that is called when the event occurs. Such
+ subsystems must select this option.
config SPL_DM_DEVICE_REMOVE
bool "Support device removal in SPL"
diff --git a/drivers/core/dump.c b/drivers/core/dump.c
index 1c1f7e4..3e77832 100644
--- a/drivers/core/dump.c
+++ b/drivers/core/dump.c
@@ -5,19 +5,41 @@
#include <common.h>
#include <dm.h>
+#include <malloc.h>
#include <mapmem.h>
+#include <sort.h>
#include <dm/root.h>
#include <dm/util.h>
#include <dm/uclass-internal.h>
-static void show_devices(struct udevice *dev, int depth, int last_flag)
+/**
+ * struct sort_info - information used for sorting
+ *
+ * @dev: List of devices
+ * @alloced: Maximum number of devices in @dev
+ */
+struct sort_info {
+ struct udevice **dev;
+ int size;
+};
+
+static int h_cmp_uclass_id(const void *d1, const void *d2)
+{
+ const struct udevice *const *dev1 = d1;
+ const struct udevice *const *dev2 = d2;
+
+ return device_get_uclass_id(*dev1) - device_get_uclass_id(*dev2);
+}
+
+static void show_devices(struct udevice *dev, int depth, int last_flag,
+ struct udevice **devs)
{
int i, is_last;
struct udevice *child;
u32 flags = dev_get_flags(dev);
/* print the first 20 characters to not break the tree-format. */
- printf(IS_ENABLED(CONFIG_SPL_BUILD) ? " %s %d [ %c ] %s " :
+ printf(CONFIG_IS_ENABLED(USE_TINY_PRINTF) ? " %s %d [ %c ] %s " :
" %-10.10s %3d [ %c ] %-20.20s ", dev->uclass->uc_drv->name,
dev_get_uclass_index(dev, NULL),
flags & DM_FLAG_ACTIVATED ? '+' : ' ', dev->driver->name);
@@ -39,21 +61,52 @@
printf("%s\n", dev->name);
- device_foreach_child(child, dev) {
- is_last = list_is_last(&child->sibling_node, &dev->child_head);
- show_devices(child, depth + 1, (last_flag << 1) | is_last);
+ if (devs) {
+ int count;
+ int i;
+
+ count = 0;
+ device_foreach_child(child, dev)
+ devs[count++] = child;
+ qsort(devs, count, sizeof(struct udevice *), h_cmp_uclass_id);
+
+ for (i = 0; i < count; i++) {
+ show_devices(devs[i], depth + 1,
+ (last_flag << 1) | (i == count - 1),
+ devs + count);
+ }
+ } else {
+ device_foreach_child(child, dev) {
+ is_last = list_is_last(&child->sibling_node,
+ &dev->child_head);
+ show_devices(child, depth + 1,
+ (last_flag << 1) | is_last, NULL);
+ }
}
}
-void dm_dump_tree(void)
+void dm_dump_tree(bool sort)
{
struct udevice *root;
root = dm_root();
if (root) {
+ int dev_count, uclasses;
+ struct udevice **devs = NULL;
+
+ dm_get_stats(&dev_count, &uclasses);
+
printf(" Class Index Probed Driver Name\n");
printf("-----------------------------------------------------------\n");
- show_devices(root, -1, 0);
+ if (sort) {
+ devs = calloc(dev_count, sizeof(struct udevice *));
+ if (!devs) {
+ printf("(out of memory)\n");
+ return;
+ }
+ }
+ show_devices(root, -1, 0, devs);
+ free(devs);
}
}
diff --git a/drivers/core/root.c b/drivers/core/root.c
index f24ddfa..c4fb485 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -363,20 +363,22 @@
static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only)
{
- u32 mask = DM_FLAG_PROBE_AFTER_BIND;
- u32 flags = dev_get_flags(dev);
+ ofnode node = dev_ofnode(dev);
struct udevice *child;
int ret;
- if (pre_reloc_only)
- mask |= DM_FLAG_PRE_RELOC;
+ if (pre_reloc_only &&
+ (!ofnode_valid(node) || !ofnode_pre_reloc(node)) &&
+ !(dev->driver->flags & DM_FLAG_PRE_RELOC))
+ goto probe_children;
- if ((flags & mask) == mask) {
+ if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) {
ret = device_probe(dev);
if (ret)
return ret;
}
+probe_children:
list_for_each_entry(child, &dev->child_head, sibling_node)
dm_probe_devices(child, pre_reloc_only);
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig
index 2187433..3bf0410 100644
--- a/drivers/cpu/Kconfig
+++ b/drivers/cpu/Kconfig
@@ -23,7 +23,6 @@
config CPU_MICROBLAZE
bool "Enable Microblaze CPU driver"
depends on CPU && MICROBLAZE
- select EVENT
select DM_EVENT
select XILINX_MICROBLAZE0_PVR
help
diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig
index b04c701..91a51cc 100644
--- a/drivers/crypto/fsl/Kconfig
+++ b/drivers/crypto/fsl/Kconfig
@@ -73,3 +73,13 @@
reseeded from the TRNG every time random data is generated.
endif
+
+config FSL_DCP_RNG
+ bool "Enable Random Number Generator support"
+ depends on DM_RNG
+ default n
+ help
+ Enable support for the hardware based random number generator
+ module of the DCP. It uses the True Random Number Generator (TRNG)
+ and a Pseudo-Random Number Generator (PRNG) to achieve a true
+ randomness and cryptographic strength.
diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile
index f9c3cce..7a2543e 100644
--- a/drivers/crypto/fsl/Makefile
+++ b/drivers/crypto/fsl/Makefile
@@ -7,4 +7,5 @@
obj-$(CONFIG_CMD_BLOB)$(CONFIG_IMX_CAAM_DEK_ENCAP) += fsl_blob.o
obj-$(CONFIG_RSA_FREESCALE_EXP) += fsl_rsa.o
obj-$(CONFIG_FSL_CAAM_RNG) += rng.o
+obj-$(CONFIG_FSL_DCP_RNG) += dcp_rng.o
obj-$(CONFIG_FSL_MFGPROT) += fsl_mfgprot.o
diff --git a/drivers/crypto/fsl/dcp_rng.c b/drivers/crypto/fsl/dcp_rng.c
new file mode 100644
index 0000000..3170696
--- /dev/null
+++ b/drivers/crypto/fsl/dcp_rng.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RNG driver for Freescale RNGC
+ *
+ * Copyright 2022 NXP
+ *
+ * Based on RNGC driver in drivers/char/hw_random/imx-rngc.c in Linux
+ */
+
+#include <common.h>
+#include <cpu_func.h>
+#include <dm.h>
+#include <rng.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <dm/root.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+
+#define DCP_RNG_MAX_FIFO_STORE_SIZE 4
+#define RNGC_VER_ID 0x0
+#define RNGC_COMMAND 0x4
+#define RNGC_CONTROL 0x8
+#define RNGC_STATUS 0xC
+#define RNGC_ERROR 0x10
+#define RNGC_FIFO 0x14
+
+/* the fields in the ver id register */
+#define RNGC_TYPE_SHIFT 28
+
+/* the rng_type field */
+#define RNGC_TYPE_RNGB 0x1
+#define RNGC_TYPE_RNGC 0x2
+
+#define RNGC_CMD_CLR_ERR 0x20
+#define RNGC_CMD_SEED 0x2
+
+#define RNGC_CTRL_AUTO_SEED 0x10
+
+#define RNGC_STATUS_ERROR 0x10000
+#define RNGC_STATUS_FIFO_LEVEL_MASK 0xf00
+#define RNGC_STATUS_FIFO_LEVEL_SHIFT 8
+#define RNGC_STATUS_SEED_DONE 0x20
+#define RNGC_STATUS_ST_DONE 0x10
+
+#define RNGC_ERROR_STATUS_STAT_ERR 0x8
+
+#define RNGC_TIMEOUT 3000000U /* 3 sec */
+
+struct imx_rngc_priv {
+ unsigned long base;
+};
+
+static int rngc_read(struct udevice *dev, void *data, size_t len)
+{
+ struct imx_rngc_priv *priv = dev_get_priv(dev);
+ u8 buffer[DCP_RNG_MAX_FIFO_STORE_SIZE];
+ u32 status, level;
+ size_t size;
+
+ while (len) {
+ status = readl(priv->base + RNGC_STATUS);
+
+ /* is there some error while reading this random number? */
+ if (status & RNGC_STATUS_ERROR)
+ break;
+ /* how many random numbers are in FIFO? [0-16] */
+ level = (status & RNGC_STATUS_FIFO_LEVEL_MASK) >>
+ RNGC_STATUS_FIFO_LEVEL_SHIFT;
+
+ if (level) {
+ /* retrieve a random number from FIFO */
+ *(u32 *)buffer = readl(priv->base + RNGC_FIFO);
+ size = min(len, sizeof(u32));
+ memcpy(data, buffer, size);
+ data += size;
+ len -= size;
+ }
+ }
+
+ return len ? -EIO : 0;
+}
+
+static int rngc_init(struct imx_rngc_priv *priv)
+{
+ u32 cmd, ctrl, status, err_reg = 0;
+ unsigned long long timeval = 0;
+ unsigned long long timeout = RNGC_TIMEOUT;
+
+ /* clear error */
+ cmd = readl(priv->base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_CLR_ERR, priv->base + RNGC_COMMAND);
+
+ /* create seed, repeat while there is some statistical error */
+ do {
+ /* seed creation */
+ cmd = readl(priv->base + RNGC_COMMAND);
+ writel(cmd | RNGC_CMD_SEED, priv->base + RNGC_COMMAND);
+
+ udelay(1);
+ timeval += 1;
+
+ status = readl(priv->base + RNGC_STATUS);
+ err_reg = readl(priv->base + RNGC_ERROR);
+
+ if (status & (RNGC_STATUS_SEED_DONE | RNGC_STATUS_ST_DONE))
+ break;
+
+ if (timeval > timeout) {
+ debug("rngc timed out\n");
+ return -ETIMEDOUT;
+ }
+ } while (err_reg == RNGC_ERROR_STATUS_STAT_ERR);
+
+ if (err_reg)
+ return -EIO;
+
+ /*
+ * enable automatic seeding, the rngc creates a new seed automatically
+ * after serving 2^20 random 160-bit words
+ */
+ ctrl = readl(priv->base + RNGC_CONTROL);
+ ctrl |= RNGC_CTRL_AUTO_SEED;
+ writel(ctrl, priv->base + RNGC_CONTROL);
+ return 0;
+}
+
+static int rngc_probe(struct udevice *dev)
+{
+ struct imx_rngc_priv *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
+ u32 ver_id;
+ u8 rng_type;
+ int ret;
+
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ priv->base = addr;
+ ver_id = readl(priv->base + RNGC_VER_ID);
+ rng_type = ver_id >> RNGC_TYPE_SHIFT;
+ /*
+ * This driver supports only RNGC and RNGB. (There's a different
+ * driver for RNGA.)
+ */
+ if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = rngc_init(priv);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ printf("%s error = %d\n", __func__, ret);
+ return ret;
+}
+
+static const struct dm_rng_ops rngc_ops = {
+ .read = rngc_read,
+};
+
+static const struct udevice_id rngc_dt_ids[] = {
+ { .compatible = "fsl,imx25-rngb" },
+ { }
+};
+
+U_BOOT_DRIVER(dcp_rng) = {
+ .name = "dcp_rng",
+ .id = UCLASS_RNG,
+ .of_match = rngc_dt_ids,
+ .ops = &rngc_ops,
+ .probe = rngc_probe,
+ .priv_auto = sizeof(struct imx_rngc_priv),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index ee822ed..ceb66dd 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -328,7 +328,7 @@
caam = &caam_st;
#endif
unsigned long long timeval = 0;
- unsigned long long timeout = CONFIG_USEC_DEQ_TIMEOUT;
+ unsigned long long timeout = CFG_USEC_DEQ_TIMEOUT;
struct result op;
int ret = 0;
@@ -743,8 +743,8 @@
* creating PAMU entries corresponding to these.
* For normal build, these are set in set_liodns().
*/
- liodn_ns = CONFIG_SPL_JR0_LIODN_NS & JRNSLIODN_MASK;
- liodn_s = CONFIG_SPL_JR0_LIODN_S & JRSLIODN_MASK;
+ liodn_ns = CFG_SPL_JR0_LIODN_NS & JRNSLIODN_MASK;
+ liodn_s = CFG_SPL_JR0_LIODN_S & JRSLIODN_MASK;
liodnr = sec_in32(&sec->jrliodnr[caam->jrid].ls) &
~(JRNSLIODN_MASK | JRSLIODN_MASK);
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index 3eb7be7..4e4c4af 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -15,7 +15,7 @@
#define JR_SIZE 4
/* Timeout currently defined as 10 sec */
-#define CONFIG_USEC_DEQ_TIMEOUT 10000000U
+#define CFG_USEC_DEQ_TIMEOUT 10000000U
#define DEFAULT_JR_ID 0
#define DEFAULT_JR_LIODN 0
diff --git a/drivers/ddr/fsl/ctrl_regs.c b/drivers/ddr/fsl/ctrl_regs.c
index 759921b..8f8c2c8 100644
--- a/drivers/ddr/fsl/ctrl_regs.c
+++ b/drivers/ddr/fsl/ctrl_regs.c
@@ -822,7 +822,7 @@
twot_en = popts->twot_en;
}
- sdram_type = CONFIG_FSL_SDRAM_TYPE;
+ sdram_type = CFG_FSL_SDRAM_TYPE;
dyn_pwr = popts->dynamic_power;
dbw = popts->data_bus_width;
@@ -926,7 +926,7 @@
rcw_en = 1;
/* DDR4 can have address parity for UDIMM and discrete */
- if ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) &&
+ if ((CFG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) &&
(!popts->registered_dimm_en)) {
ap_en = 0;
} else {
@@ -1188,7 +1188,7 @@
* handled by register chip and RCW settings.
*/
if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
- ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
+ ((CFG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
!popts->registered_dimm_en)) {
if (mclk_ps >= 935) {
/* for DDR4-1600/1866/2133 */
@@ -1223,7 +1223,7 @@
}
if ((ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN) &&
- ((CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
+ ((CFG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4) ||
!popts->registered_dimm_en)) {
if (mclk_ps >= 935) {
/* for DDR4-1600/1866/2133 */
@@ -1983,7 +1983,7 @@
tcksrx = max(5U, picos_to_mclk(ctrl_num, 10000));
if (ddr->ddr_sdram_cfg_2 & SDRAM_CFG2_AP_EN &&
- CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4) {
+ CFG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4) {
/* for DDR4 only */
par_lat = (ddr->ddr_sdram_rcw_2 & 0xf) + 1;
debug("PAR_LAT = %u for mclk_ps = %d\n", par_lat, mclk_ps);
diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c
index 9555b9a..7cff823 100644
--- a/drivers/ddr/fsl/options.c
+++ b/drivers/ddr/fsl/options.c
@@ -753,7 +753,7 @@
defined(CONFIG_SYS_FSL_DDR4)
const struct dynamic_odt *pdodt = odt_unknown;
#endif
-#if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
+#if (CFG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
ulong ddr_freq;
#endif
@@ -1024,7 +1024,7 @@
if (hwconfig_sub_f("fsl_ddr", "parity", buf)) {
if (hwconfig_subarg_cmp_f("fsl_ddr", "parity", "on", buf)) {
if (popts->registered_dimm_en ||
- (CONFIG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4))
+ (CFG_FSL_SDRAM_TYPE == SDRAM_TYPE_DDR4))
popts->ap_en = 1;
}
}
@@ -1302,7 +1302,7 @@
popts->package_3ds = pdimm->package_3ds;
-#if (CONFIG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
+#if (CFG_FSL_SDRAM_TYPE != SDRAM_TYPE_DDR4)
ddr_freq = get_ddr_freq(ctrl_num) / 1000000;
if (popts->registered_dimm_en) {
popts->rcw_override = 1;
diff --git a/drivers/ddr/marvell/a38x/Makefile b/drivers/ddr/marvell/a38x/Makefile
index 8251d6d..fcfb615 100644
--- a/drivers/ddr/marvell/a38x/Makefile
+++ b/drivers/ddr/marvell/a38x/Makefile
@@ -17,3 +17,11 @@
obj-$(CONFIG_SPL_BUILD) += mv_ddr_spd.o
obj-$(CONFIG_SPL_BUILD) += mv_ddr_topology.o
obj-$(CONFIG_SPL_BUILD) += xor.o
+
+ifdef CONFIG_DDR4
+ obj-$(CONFIG_SPL_BUILD) += mv_ddr4_mpr_pda_if.o
+ obj-$(CONFIG_SPL_BUILD) += mv_ddr4_training.o
+ obj-$(CONFIG_SPL_BUILD) += mv_ddr4_training_calibration.o
+ obj-$(CONFIG_SPL_BUILD) += mv_ddr4_training_db.o
+ obj-$(CONFIG_SPL_BUILD) += mv_ddr4_training_leveling.o
+endif
diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c b/drivers/ddr/marvell/a38x/ddr3_debug.c
index f5fc964..9e499cf 100644
--- a/drivers/ddr/marvell/a38x/ddr3_debug.c
+++ b/drivers/ddr/marvell/a38x/ddr3_debug.c
@@ -30,6 +30,12 @@
u8 debug_training_access = DEBUG_LEVEL_ERROR;
u8 debug_training_device = DEBUG_LEVEL_ERROR;
+#if defined(CONFIG_DDR4)
+u8 debug_tap_tuning = DEBUG_LEVEL_ERROR;
+u8 debug_calibration = DEBUG_LEVEL_ERROR;
+u8 debug_ddr4_centralization = DEBUG_LEVEL_ERROR;
+u8 debug_dm_tuning = DEBUG_LEVEL_ERROR;
+#endif /* CONFIG_DDR4 */
void mv_ddr_user_log_level_set(enum ddr_lib_debug_block block)
{
@@ -70,6 +76,17 @@
else
is_reg_dump = 0;
break;
+#if defined(CONFIG_DDR4)
+ case DEBUG_TAP_TUNING_ENGINE:
+ debug_tap_tuning = level;
+ break;
+ case DEBUG_BLOCK_CALIBRATION:
+ debug_calibration = level;
+ break;
+ case DEBUG_BLOCK_DDR4_CENTRALIZATION:
+ debug_ddr4_centralization = level;
+ break;
+#endif /* CONFIG_DDR4 */
case DEBUG_BLOCK_ALL:
default:
debug_training_static = level;
@@ -80,6 +97,11 @@
debug_training_hw_alg = level;
debug_training_access = level;
debug_training_device = level;
+#if defined(CONFIG_DDR4)
+ debug_tap_tuning = level;
+ debug_calibration = level;
+ debug_ddr4_centralization = level;
+#endif /* CONFIG_DDR4 */
}
}
#endif /* SILENT_LIB */
@@ -209,11 +231,13 @@
case MV_DDR_FREQ_LOW_FREQ:
return "MV_DDR_FREQ_LOW_FREQ";
+#if !defined(CONFIG_DDR4)
case MV_DDR_FREQ_400:
return "400";
case MV_DDR_FREQ_533:
return "533";
+#endif /* CONFIG_DDR4 */
case MV_DDR_FREQ_667:
return "667";
@@ -227,6 +251,7 @@
case MV_DDR_FREQ_1066:
return "1066";
+#if !defined(CONFIG_DDR4)
case MV_DDR_FREQ_311:
return "311";
@@ -247,6 +272,7 @@
case MV_DDR_FREQ_1000:
return "MV_DDR_FREQ_1000";
+#endif /* CONFIG_DDR4 */
default:
return "Unknown Frequency";
@@ -463,6 +489,7 @@
(training_result[WRITE_LEVELING_TF]
[if_id])));
}
+#if !defined(CONFIG_DDR4)
if (mask_tune_func & READ_LEVELING_TF_MASK_BIT) {
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
("\tRL TF: %s\n",
@@ -470,6 +497,7 @@
(training_result[READ_LEVELING_TF]
[if_id])));
}
+#endif /* CONFIG_DDR4 */
if (mask_tune_func & WRITE_LEVELING_SUPP_TF_MASK_BIT) {
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
("\tWL TF Supp: %s\n",
@@ -499,6 +527,43 @@
(training_result[CENTRALIZATION_TX]
[if_id])));
}
+#if defined(CONFIG_DDR4)
+ if (mask_tune_func & SW_READ_LEVELING_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tSW RL TF: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[SW_READ_LEVELING]
+ [if_id])));
+ }
+ if (mask_tune_func & RECEIVER_CALIBRATION_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tRX CAL: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[RECEIVER_CALIBRATION]
+ [if_id])));
+ }
+ if (mask_tune_func & WL_PHASE_CORRECTION_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tWL PHASE CORRECT: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[WL_PHASE_CORRECTION]
+ [if_id])));
+ }
+ if (mask_tune_func & DQ_VREF_CALIBRATION_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tDQ VREF CAL: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[DQ_VREF_CALIBRATION]
+ [if_id])));
+ }
+ if (mask_tune_func & DQ_MAPPING_MASK_BIT) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("\tDQ MAP: %s\n",
+ ddr3_tip_convert_tune_result
+ (training_result[DQ_MAPPING]
+ [if_id])));
+ }
+#endif /* CONFIG_DDR4 */
}
return MV_OK;
@@ -512,6 +577,9 @@
{
u8 if_id = 0, csindex = 0, bus_id = 0, idx = 0;
u32 reg_data;
+#if defined(CONFIG_DDR4)
+ u32 reg_data1;
+#endif /* CONFIG_DDR4 */
u32 read_data[MAX_INTERFACE_NUM];
unsigned int max_cs = mv_ddr_cs_num_get();
struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
@@ -524,7 +592,13 @@
printf("CS%d , ", csindex);
printf("\n");
VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+#if defined(CONFIG_DDR4)
+ printf("DminTx, AreaTx, DminRx, AreaRx, WL_tot, WL_ADLL, WL_PH, RL_Tot, RL_ADLL, RL_PH, RL_Smp, CenTx, CenRx, Vref, DQVref,");
+ for (idx = 0; idx < 11; idx++)
+ printf("DC-Pad%d,", idx);
+#else /* CONFIG_DDR4 */
printf("VWTx, VWRx, WL_tot, WL_ADLL, WL_PH, RL_Tot, RL_ADLL, RL_PH, RL_Smp, Cen_tx, Cen_rx, Vref, DQVref,");
+#endif /* CONFIG_DDR4 */
printf("\t\t");
for (idx = 0; idx < 11; idx++)
printf("PBSTx-Pad%d,", idx);
@@ -565,6 +639,40 @@
for (bus_id = 0; bus_id < MAX_BUS_NUM; bus_id++) {
printf("\n");
VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id);
+#if defined(CONFIG_DDR4)
+ /* DminTx, areaTX */
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ RESULT_PHY_REG +
+ csindex, ®_data);
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ dmin_phy_reg_table
+ [csindex * 5 + bus_id][0],
+ DDR_PHY_CONTROL,
+ dmin_phy_reg_table
+ [csindex * 5 + bus_id][1],
+ ®_data1);
+ printf("%d,%d,", 2 * (reg_data1 & 0xFF),
+ reg_data);
+ /* DminRx, areaRX */
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ RESULT_PHY_REG +
+ csindex + 4, ®_data);
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ dmin_phy_reg_table
+ [csindex * 5 + bus_id][0],
+ DDR_PHY_CONTROL,
+ dmin_phy_reg_table
+ [csindex * 5 + bus_id][1],
+ ®_data1);
+ printf("%d,%d,", 2 * (reg_data1 >> 8),
+ reg_data);
+#else /* CONFIG_DDR4 */
ddr3_tip_bus_read(dev_num, if_id,
ACCESS_TYPE_UNICAST,
bus_id, DDR_PHY_DATA,
@@ -572,6 +680,7 @@
csindex, ®_data);
printf("%d,%d,", (reg_data & 0x1f),
((reg_data & 0x3e0) >> 5));
+#endif /* CONFIG_DDR4 */
/* WL */
ddr3_tip_bus_read(dev_num, if_id,
ACCESS_TYPE_UNICAST,
@@ -628,6 +737,17 @@
/* DQVref */
/* Need to add the Read Function from device */
printf("%d,", 0);
+#if defined(CONFIG_DDR4)
+ printf("\t\t");
+ for (idx = 0; idx < 11; idx++) {
+ ddr3_tip_bus_read(dev_num, if_id,
+ ACCESS_TYPE_UNICAST,
+ bus_id, DDR_PHY_DATA,
+ 0xd0 + 12 * csindex +
+ idx, ®_data);
+ printf("%d,", (reg_data & 0x3f));
+ }
+#endif /* CONFIG_DDR4 */
printf("\t\t");
for (idx = 0; idx < 11; idx++) {
ddr3_tip_bus_read(dev_num, if_id,
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c
index f878b45..27eb3ac 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.c
+++ b/drivers/ddr/marvell/a38x/ddr3_init.c
@@ -6,7 +6,11 @@
#include "ddr3_init.h"
#include "mv_ddr_common.h"
+#if defined(CONFIG_DDR4)
+static char *ddr_type = "DDR4";
+#else /* CONFIG_DDR4 */
static char *ddr_type = "DDR3";
+#endif /* CONFIG_DDR4 */
/*
* generic_init_controller controls D-unit configuration:
@@ -61,6 +65,13 @@
mv_ddr_mc_init();
if (!is_manual_cal_done) {
+#if defined(CONFIG_DDR4)
+ status = mv_ddr4_calibration_adjust(0, 1, 0);
+ if (status != MV_OK) {
+ printf("%s: failed (0x%x)\n", __func__, status);
+ return status;
+ }
+#endif
}
@@ -120,6 +131,19 @@
params.g_zpodt_ctrl = TUNE_TRAINING_PARAMS_P_ODT_CTRL;
params.g_znodt_ctrl = TUNE_TRAINING_PARAMS_N_ODT_CTRL;
+#if defined(CONFIG_DDR4)
+ params.g_zpodt_data = TUNE_TRAINING_PARAMS_P_ODT_DATA_DDR4;
+ params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_DDR4;
+ params.g_rtt_nom = TUNE_TRAINING_PARAMS_RTT_NOM_DDR4;
+ params.g_dic = TUNE_TRAINING_PARAMS_DIC_DDR4;
+ if (cs_num == 1) {
+ params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_1CS;
+ params.g_rtt_park = TUNE_TRAINING_PARAMS_RTT_PARK_1CS;
+ } else {
+ params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_2CS;
+ params.g_rtt_park = TUNE_TRAINING_PARAMS_RTT_PARK_2CS;
+ }
+#else /* CONFIG_DDR4 */
params.g_zpodt_data = TUNE_TRAINING_PARAMS_P_ODT_DATA;
params.g_dic = TUNE_TRAINING_PARAMS_DIC;
params.g_rtt_nom = TUNE_TRAINING_PARAMS_RTT_NOM;
@@ -130,6 +154,7 @@
params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_2CS;
params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS;
}
+#endif /* CONFIG_DDR4 */
if (ck_delay > 0)
params.ck_delay = ck_delay;
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h b/drivers/ddr/marvell/a38x/ddr3_init.h
index 055516b..ba9f788 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.h
+++ b/drivers/ddr/marvell/a38x/ddr3_init.h
@@ -137,6 +137,10 @@
extern u32 nominal_avs;
extern u32 extension_avs;
+#if defined(CONFIG_DDR4)
+/* if 1, SSTL & POD have same Vref and workaround is required */
+extern u8 vref_calibration_wa;
+#endif /* CONFIG_DDR4 */
/* Prototypes */
int ddr3_init(void);
@@ -152,6 +156,13 @@
int ddr3_tip_reg_write(u32 dev_num, u32 reg_addr, u32 data);
int ddr3_tip_reg_read(u32 dev_num, u32 reg_addr, u32 *data, u32 reg_mask);
int ddr3_silicon_get_ddr_target_freq(u32 *ddr_freq);
+#if defined(CONFIG_DDR4)
+int mv_ddr4_mode_regs_init(u8 dev_num);
+int mv_ddr4_sdram_config(u32 dev_num);
+int mv_ddr4_phy_config(u32 dev_num);
+int mv_ddr4_calibration_adjust(u32 dev_num, u8 vref_en, u8 pod_only);
+int mv_ddr4_training_main_flow(u32 dev_num);
+#endif /* CONFIG_DDR4 */
int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]);
int print_ph(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]);
@@ -188,5 +199,8 @@
unsigned int mv_ddr_misl_phy_drv_ctrl_n_get(void);
unsigned int mv_ddr_misl_phy_odt_p_get(void);
unsigned int mv_ddr_misl_phy_odt_n_get(void);
+#if defined(CONFIG_DDR4)
+void refresh(void);
+#endif
#endif /* _DDR3_INIT_H */
diff --git a/drivers/ddr/marvell/a38x/ddr3_logging_def.h b/drivers/ddr/marvell/a38x/ddr3_logging_def.h
index ad9da1c..a809213 100644
--- a/drivers/ddr/marvell/a38x/ddr3_logging_def.h
+++ b/drivers/ddr/marvell/a38x/ddr3_logging_def.h
@@ -73,6 +73,27 @@
#endif
#endif
+#ifdef CONFIG_DDR4
+#ifdef SILENT_LIB
+#define DEBUG_TAP_TUNING_ENGINE(level, s)
+#define DEBUG_CALIBRATION(level, s)
+#define DEBUG_DDR4_CENTRALIZATION(level, s)
+#define DEBUG_DM_TUNING(level, s)
+#else /* SILENT_LIB */
+#define DEBUG_TAP_TUNING_ENGINE(level, s) \
+ if (level >= debug_tap_tuning) \
+ printf s
+#define DEBUG_CALIBRATION(level, s) \
+ if (level >= debug_calibration) \
+ printf s
+#define DEBUG_DDR4_CENTRALIZATION(level, s) \
+ if (level >= debug_ddr4_centralization) \
+ printf s
+#define DEBUG_DM_TUNING(level, s) \
+ if (level >= debug_dm_tuning) \
+ printf s
+#endif /* SILENT_LIB */
+#endif /* CONFIG_DDR4 */
/* Logging defines */
enum mv_ddr_debug_level {
@@ -94,6 +115,12 @@
DEBUG_BLOCK_DEVICE,
DEBUG_BLOCK_ACCESS,
DEBUG_STAGES_REG_DUMP,
+#if defined(CONFIG_DDR4)
+ DEBUG_TAP_TUNING_ENGINE,
+ DEBUG_BLOCK_CALIBRATION,
+ DEBUG_BLOCK_DDR4_CENTRALIZATION,
+ DEBUG_DM_TUNING,
+#endif /* CONFIG_DDR4 */
/* All excluding IP and REG_DUMP, should be enabled separatelly */
DEBUG_BLOCK_ALL
};
diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c
index 0ddd5ae..790b01d 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training.c
@@ -25,7 +25,11 @@
/* in case of ddr4 do not run ddr3_tip_write_additional_odt_setting function - mc odt always 'on'
* in ddr4 case the terminations are rttWR and rttPARK and the odt must be always 'on' 0x1498 = 0xf
*/
+#if defined(CONFIG_DDR4)
+u32 odt_config = 0;
+#else
u32 odt_config = 1;
+#endif
u32 nominal_avs;
u32 extension_avs;
@@ -85,7 +89,11 @@
READ_LEVELING_MASK_BIT |
SET_TARGET_FREQ_MASK_BIT |
WRITE_LEVELING_TF_MASK_BIT |
+#if defined(CONFIG_DDR4)
+ SW_READ_LEVELING_MASK_BIT |
+#else /* CONFIG_DDR4 */
READ_LEVELING_TF_MASK_BIT |
+#endif /* CONFIG_DDR4 */
CENTRALIZATION_RX_MASK_BIT |
CENTRALIZATION_TX_MASK_BIT);
@@ -102,6 +110,10 @@
u32 if_id, enum mv_ddr_freq frequency);
static int ddr3_tip_set_timing(u32 dev_num, enum hws_access_type access_type,
u32 if_id, enum mv_ddr_freq frequency);
+#if defined(CONFIG_DDR4)
+static int ddr4_tip_set_timing(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum mv_ddr_freq frequency);
+#endif /* CONFIG_DDR4 */
static u8 mem_size_config[MV_DDR_DIE_CAP_LAST] = {
0x2, /* 512Mbit */
@@ -173,12 +185,24 @@
};
/* MR cmd and addr definitions */
+#if defined(CONFIG_DDR4)
+struct mv_ddr_mr_data mr_data[] = {
+ {MRS0_CMD, DDR4_MR0_REG},
+ {MRS1_CMD, DDR4_MR1_REG},
+ {MRS2_CMD, DDR4_MR2_REG},
+ {MRS3_CMD, DDR4_MR3_REG},
+ {MRS4_CMD, DDR4_MR4_REG},
+ {MRS5_CMD, DDR4_MR5_REG},
+ {MRS6_CMD, DDR4_MR6_REG}
+};
+#else
struct mv_ddr_mr_data mr_data[] = {
{MRS0_CMD, MR0_REG},
{MRS1_CMD, MR1_REG},
{MRS2_CMD, MR2_REG},
{MRS3_CMD, MR3_REG}
};
+#endif
/* inverse pads */
static int ddr3_tip_pad_inv(void)
@@ -664,6 +688,11 @@
calibration_update_control << 3, 0x3 << 3));
}
+#if defined(CONFIG_DDR4)
+ /* dev_num, vref_en, pod_only */
+ CHECK_STATUS(mv_ddr4_mode_regs_init(dev_num));
+ CHECK_STATUS(mv_ddr4_sdram_config(dev_num));
+#endif /* CONFIG_DDR4 */
if (delay_enable != 0) {
adll_tap = MEGA / (mv_ddr_freq_get(freq) * 64);
@@ -1325,6 +1354,20 @@
/* disable ODT in case of dll off */
if (is_dll_off == 1) {
+#if defined(CONFIG_DDR4)
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, access_type, PARAM_NOT_CARE,
+ 0x1974, &g_rtt_nom_cs0, MASK_ALL_BITS));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x1974, 0, (0x7 << 8)));
+ CHECK_STATUS(ddr3_tip_if_read
+ (dev_num, access_type, PARAM_NOT_CARE,
+ 0x1A74, &g_rtt_nom_cs1, MASK_ALL_BITS));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x1A74, 0, (0x7 << 8)));
+#else /* CONFIG_DDR4 */
CHECK_STATUS(ddr3_tip_if_write
(dev_num, access_type, if_id,
0x1874, 0, 0x244));
@@ -1337,6 +1380,7 @@
CHECK_STATUS(ddr3_tip_if_write
(dev_num, access_type, if_id,
0x18a4, 0, 0x244));
+#endif /* CONFIG_DDR4 */
}
/* DFS - Enter Self-Refresh */
@@ -1404,6 +1448,16 @@
/* Restore original RTT values if returning from DLL OFF mode */
if (is_dll_off == 1) {
+#if defined(CONFIG_DDR4)
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x1974, g_rtt_nom_cs0, (0x7 << 8)));
+ CHECK_STATUS(ddr3_tip_if_write
+ (dev_num, access_type, if_id,
+ 0x1A74, g_rtt_nom_cs1, (0x7 << 8)));
+
+ mv_ddr4_mode_regs_init(dev_num);
+#else /* CONFIG_DDR4 */
CHECK_STATUS(ddr3_tip_if_write
(dev_num, access_type, if_id, 0x1874,
g_dic | g_rtt_nom, 0x266));
@@ -1416,6 +1470,7 @@
CHECK_STATUS(ddr3_tip_if_write
(dev_num, access_type, if_id, 0x18a4,
g_dic | g_rtt_nom, 0x266));
+#endif /* CONFIG_DDR4 */
}
/* Reset divider_b assert -> de-assert */
@@ -1669,8 +1724,13 @@
t_rtp = GET_MAX_VALUE(t_ckclk * 4, mv_ddr_speed_bin_timing_get(speed_bin_index,
SPEED_BIN_TRTP));
t_mod = GET_MAX_VALUE(t_ckclk * 12, 15000);
+#if defined(CONFIG_DDR4)
+ t_wtr = GET_MAX_VALUE(t_ckclk * 2, mv_ddr_speed_bin_timing_get(speed_bin_index,
+ SPEED_BIN_TWTR));
+#else /* CONFIG_DDR4 */
t_wtr = GET_MAX_VALUE(t_ckclk * 4, mv_ddr_speed_bin_timing_get(speed_bin_index,
SPEED_BIN_TWTR));
+#endif /* CONFIG_DDR4 */
t_ras = time_to_nclk(mv_ddr_speed_bin_timing_get(speed_bin_index,
SPEED_BIN_TRAS),
t_ckclk);
@@ -1758,10 +1818,70 @@
DDR_TIMING_TPD_MASK << DDR_TIMING_TPD_OFFS |
DDR_TIMING_TXPDLL_MASK << DDR_TIMING_TXPDLL_OFFS));
+#if defined(CONFIG_DDR4)
+ ddr4_tip_set_timing(dev_num, access_type, if_id, frequency);
+#endif /* CONFIG_DDR4 */
return MV_OK;
}
+#if defined(CONFIG_DDR4)
+static int ddr4_tip_set_timing(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, enum mv_ddr_freq frequency)
+{
+ u32 t_rrd_l = 0, t_wtr_l = 0, t_ckclk = 0, t_mod = 0, t_ccd = 0;
+ u32 page_size = 0, val = 0, mask = 0;
+ enum mv_ddr_speed_bin speed_bin_index;
+ enum mv_ddr_die_capacity memory_size;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u32 freq = mv_ddr_freq_get(frequency);
+
+ speed_bin_index = tm->interface_params[if_id].speed_bin_index;
+ memory_size = tm->interface_params[if_id].memory_size;
+ page_size = mv_ddr_page_size_get(tm->interface_params[if_id].bus_width, memory_size);
+
+ t_ckclk = (MEGA / freq);
+
+ t_rrd_l = (page_size == 1) ? mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TRRDL1K) :
+ mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TRRDL2K);
+ t_rrd_l = GET_MAX_VALUE(t_ckclk * 4, t_rrd_l);
+
+ t_wtr_l = mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TWTRL);
+ t_wtr_l = GET_MAX_VALUE(t_ckclk * 4, t_wtr_l);
+
+ t_rrd_l = time_to_nclk(t_rrd_l, t_ckclk);
+ t_wtr_l = time_to_nclk(t_wtr_l, t_ckclk);
+
+ val = (((t_rrd_l - 1) & DDR4_TRRD_L_MASK) << DDR4_TRRD_L_OFFS) |
+ (((t_wtr_l - 1) & DDR4_TWTR_L_MASK) << DDR4_TWTR_L_OFFS);
+ mask = (DDR4_TRRD_L_MASK << DDR4_TRRD_L_OFFS) |
+ (DDR4_TWTR_L_MASK << DDR4_TWTR_L_OFFS);
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DRAM_LONG_TIMING_REG, val, mask));
+
+ val = 0;
+ mask = 0;
+ t_mod = mv_ddr_speed_bin_timing_get(speed_bin_index, SPEED_BIN_TMOD);
+ t_mod = GET_MAX_VALUE(t_ckclk * 24, t_mod);
+ t_mod = time_to_nclk(t_mod, t_ckclk);
+
+ val = (((t_mod - 1) & SDRAM_TIMING_HIGH_TMOD_MASK) << SDRAM_TIMING_HIGH_TMOD_OFFS) |
+ ((((t_mod - 1) >> 4) & SDRAM_TIMING_HIGH_TMOD_HIGH_MASK) << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS);
+ mask = (SDRAM_TIMING_HIGH_TMOD_MASK << SDRAM_TIMING_HIGH_TMOD_OFFS) |
+ (SDRAM_TIMING_HIGH_TMOD_HIGH_MASK << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS);
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ SDRAM_TIMING_HIGH_REG, val, mask));
+
+ t_ccd = 6;
+
+ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
+ DDR_TIMING_REG,
+ ((t_ccd - 1) & DDR_TIMING_TCCD_MASK) << DDR_TIMING_TCCD_OFFS,
+ DDR_TIMING_TCCD_MASK << DDR_TIMING_TCCD_OFFS));
+
+ return MV_OK;
+}
+#endif /* CONFIG_DDR4 */
/*
* Write CS Result
@@ -2245,6 +2365,7 @@
}
}
+#if !defined(CONFIG_DDR4)
for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
if (mask_tune_func & PBS_RX_MASK_BIT) {
training_stage = PBS_RX;
@@ -2284,6 +2405,7 @@
}
/* Set to 0 after each loop to avoid illegal value may be used */
effective_cs = 0;
+#endif /* CONFIG_DDR4 */
if (mask_tune_func & SET_TARGET_FREQ_MASK_BIT) {
training_stage = SET_TARGET_FREQ;
@@ -2367,6 +2489,7 @@
}
}
+#if !defined(CONFIG_DDR4)
if (mask_tune_func & DM_PBS_TX_MASK_BIT) {
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("DM_PBS_TX_MASK_BIT\n"));
}
@@ -2412,6 +2535,7 @@
}
/* Set to 0 after each loop to avoid illegal value may be used */
effective_cs = 0;
+#endif /* CONFIG_DDR4 */
for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
if (mask_tune_func & WRITE_LEVELING_SUPP_TF_MASK_BIT) {
@@ -2434,7 +2558,12 @@
/* Set to 0 after each loop to avoid illegal value may be used */
effective_cs = 0;
+#if defined(CONFIG_DDR4)
+ for (effective_cs = 0; effective_cs < max_cs; effective_cs++)
+ CHECK_STATUS(mv_ddr4_training_main_flow(dev_num));
+#endif /* CONFIG_DDR4 */
+#if !defined(CONFIG_DDR4)
for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
if (mask_tune_func & CENTRALIZATION_TX_MASK_BIT) {
training_stage = CENTRALIZATION_TX;
@@ -2455,6 +2584,7 @@
}
/* Set to 0 after each loop to avoid illegal value may be used */
effective_cs = 0;
+#endif /* CONFIG_DDR4 */
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("restore registers to default\n"));
/* restore register values */
@@ -2895,3 +3025,4 @@
return odt_n;
}
+
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_bist.c b/drivers/ddr/marvell/a38x/ddr3_training_bist.c
index d388a17..3f072eb 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_bist.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training_bist.c
@@ -459,7 +459,11 @@
(ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS),
(ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS));
+#if defined(CONFIG_DDR4)
+ if (pattern == PATTERN_ZERO || pattern == PATTERN_ONE)
+#else
if (pattern == PATTERN_00 || pattern == PATTERN_FF)
+#endif
ddr3_tip_load_pattern_to_odpg(0, access_type, 0, pattern, offset);
else
mv_ddr_load_dm_pattern_to_odpg(access_type, pattern, dm_dir);
@@ -507,7 +511,11 @@
ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
mv_ddr_odpg_bist_prepare(pattern, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE,
bist_offset, cs, pattern_table[pattern].num_of_phases_tx,
+#if defined(CONFIG_DDR4)
+ (pattern == PATTERN_ZERO) ? DM_DIR_DIRECT : DM_DIR_INVERSE);
+#else
(pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE);
+#endif
for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) {
/* change target odpg address */
@@ -539,7 +547,11 @@
/* fill memory with vref pattern to increment addr using odpg bist */
mv_ddr_odpg_bist_prepare(PATTERN_VREF, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE,
bist_offset, cs, pattern_table[pattern].num_of_phases_tx,
+#if defined(CONFIG_DDR4)
+ (pattern == PATTERN_ZERO) ? DM_DIR_DIRECT : DM_DIR_INVERSE);
+#else
(pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE);
+#endif
for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) {
ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_MULTICAST, 0,
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
index be9f985..e75e45c 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c
@@ -16,7 +16,11 @@
#define CENTRAL_RX 1
#define NUM_OF_CENTRAL_TYPES 2
+#if defined(CONFIG_DDR4) /* DDR4 16/32-bit */
+u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7_INV;
+#else /* DDR3 16/32-bit */
u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7;
+#endif /* CONFIG_64BIT */
u32 start_if = 0, end_if = (MAX_INTERFACE_NUM - 1);
u8 bus_end_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_db.c b/drivers/ddr/marvell/a38x/ddr3_training_db.c
index 6aa7b60..47ba911 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_db.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training_db.c
@@ -25,6 +25,98 @@
static inline u32 pattern_table_get_isi_word(u8 index);
static inline u32 pattern_table_get_isi_word16(u8 index);
+#if defined(CONFIG_DDR4)
+u8 pattern_killer_map[KILLER_PATTERN_LENGTH * 2] = {
+ 0x01,
+ 0x00,
+ 0x01,
+ 0xff,
+ 0xfe,
+ 0xfe,
+ 0x01,
+ 0xfe,
+ 0x01,
+ 0xfe,
+ 0x01,
+ 0x01,
+ 0xfe,
+ 0x01,
+ 0xfe,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x01,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xfe,
+ 0xfe,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0xfe,
+ 0x00,
+ 0xfe,
+ 0xfe,
+ 0x00,
+ 0xff,
+ 0xff,
+ 0x01,
+ 0x01,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xff
+};
+static inline u32 pattern_table_get_killer_word_4(u8 dqs, u8 index)
+{
+ u8 byte;
+
+ if (index >= (KILLER_PATTERN_LENGTH * 2)) {
+ printf("error: %s: invalid index [%u] found\n", __func__, index);
+ return 0;
+ }
+
+ byte = pattern_killer_map[index];
+
+ switch (byte) {
+ case 0x01:
+ byte = 1 << dqs;
+ break;
+ case 0xfe:
+ byte = 0xff & ~(1 << dqs);
+ break;
+ default:
+ break;
+ }
+
+ return byte | (byte << 8) | (byte << 16) | (byte << 24);
+}
+#else /* !CONFIG_DDR4 */
/* List of allowed frequency listed in order of enum mv_ddr_freq */
static unsigned int freq_val[MV_DDR_FREQ_LAST] = {
0, /*MV_DDR_FREQ_LOW_FREQ */
@@ -302,6 +394,7 @@
12155,
13090,
};
+#endif /* CONFIG_DDR4 */
enum {
PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
@@ -388,6 +481,7 @@
0xfe
};
+#if !defined(CONFIG_DDR4)
static struct mv_ddr_page_element page_tbl[] = {
/* 8-bit, 16-bit page size */
{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 512M */
@@ -521,6 +615,7 @@
return byte | (byte << 8) | (byte << 16) | (byte << 24);
}
+#endif /* !CONFIG_DDR4 */
static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
{
@@ -651,6 +746,7 @@
return 0xffffffff;
}
+#if !defined(CONFIG_DDR4)
static inline u32 pattern_table_get_static_pbs_word(u8 index)
{
u16 temp;
@@ -659,6 +755,7 @@
return temp | (temp << 8) | (temp << 16) | (temp << 24);
}
+#endif /* !CONFIG_DDR4 */
u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
{
@@ -670,26 +767,36 @@
switch (type) {
case PATTERN_PBS1:
case PATTERN_PBS2:
+#if !defined(CONFIG_DDR4)
if (index == 0 || index == 2 || index == 5 ||
index == 7)
pattern = PATTERN_55;
else
pattern = PATTERN_AA;
break;
+#endif /* !CONFIG_DDR4 */
case PATTERN_PBS3:
+#if !defined(CONFIG_DDR4)
if (0 == (index & 1))
pattern = PATTERN_55;
else
pattern = PATTERN_AA;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_RL:
+#if !defined(CONFIG_DDR4)
if (index < 6)
pattern = PATTERN_00;
else
pattern = PATTERN_80;
+#else /* CONFIG_DDR4 */
+ pattern = PATTERN_00;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_STATIC_PBS:
+#if !defined(CONFIG_DDR4)
pattern = pattern_table_get_static_pbs_word(index);
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_KILLER_DQ0:
case PATTERN_KILLER_DQ1:
@@ -699,14 +806,22 @@
case PATTERN_KILLER_DQ5:
case PATTERN_KILLER_DQ6:
case PATTERN_KILLER_DQ7:
+#if !defined(CONFIG_DDR4)
pattern = pattern_table_get_killer_word(
+#else /* CONFIG_DDR4 */
+ pattern = pattern_table_get_killer_word_4(
+#endif /* !CONFIG_DDR4 */
(u8)(type - PATTERN_KILLER_DQ0), index);
break;
case PATTERN_RL2:
+#if !defined(CONFIG_DDR4)
if (index < 6)
pattern = PATTERN_00;
else
pattern = PATTERN_01;
+#else /* !CONFIG_DDR4 */
+ pattern = PATTERN_FF;
+#endif /* CONFIG_DDR4 */
break;
case PATTERN_TEST:
if (index > 1 && index < 6)
@@ -749,6 +864,46 @@
case PATTERN_ISI_XTALK_FREE:
pattern = pattern_table_get_isi_word(index);
break;
+#if defined(CONFIG_DDR4)
+ case PATTERN_KILLER_DQ0_INV:
+ case PATTERN_KILLER_DQ1_INV:
+ case PATTERN_KILLER_DQ2_INV:
+ case PATTERN_KILLER_DQ3_INV:
+ case PATTERN_KILLER_DQ4_INV:
+ case PATTERN_KILLER_DQ5_INV:
+ case PATTERN_KILLER_DQ6_INV:
+ case PATTERN_KILLER_DQ7_INV:
+ pattern = ~pattern_table_get_killer_word_4(
+ (u8)(type - PATTERN_KILLER_DQ0_INV), index);
+ break;
+ case PATTERN_RESONANCE_1T:
+ case PATTERN_RESONANCE_2T:
+ case PATTERN_RESONANCE_3T:
+ case PATTERN_RESONANCE_4T:
+ case PATTERN_RESONANCE_5T:
+ case PATTERN_RESONANCE_6T:
+ case PATTERN_RESONANCE_7T:
+ case PATTERN_RESONANCE_8T:
+ case PATTERN_RESONANCE_9T:
+ {
+ u8 t_num = (u8)(type - PATTERN_RESONANCE_1T);
+ u8 t_end = (59 / t_num) * t_num;
+ if (index < t_end)
+ pattern = ((index % (t_num * 2)) >= t_num) ? 0xffffffff : 0x00000000;
+ else
+ pattern = ((index % 2) == 0) ? 0xffffffff : 0x00000000;
+ }
+ break;
+ case PATTERN_ZERO:
+ pattern = PATTERN_00;
+ break;
+ case PATTERN_ONE:
+ pattern = PATTERN_FF;
+ break;
+ case PATTERN_VREF_INV:
+ pattern = ~pattern_table_get_vref_word(index);
+ break;
+#endif /* CONFIG_DDR4 */
default:
printf("error: %s: unsupported pattern type [%d] found\n",
__func__, (int)type);
@@ -761,16 +916,24 @@
case PATTERN_PBS1:
case PATTERN_PBS2:
case PATTERN_PBS3:
+#if !defined(CONFIG_DDR4)
pattern = PATTERN_55AA;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_RL:
+#if !defined(CONFIG_DDR4)
if (index < 3)
pattern = PATTERN_00;
else
pattern = PATTERN_80;
+#else /* CONFIG_DDR4 */
+ pattern = PATTERN_00;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_STATIC_PBS:
+#if !defined(CONFIG_DDR4)
pattern = PATTERN_00FF;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_KILLER_DQ0:
case PATTERN_KILLER_DQ1:
@@ -784,25 +947,40 @@
(u8)(type - PATTERN_KILLER_DQ0), index);
break;
case PATTERN_RL2:
+#if !defined(CONFIG_DDR4)
if (index < 3)
pattern = PATTERN_00;
else
pattern = PATTERN_01;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_TEST:
+#if !defined(CONFIG_DDR4)
if ((index == 0) || (index == 3))
pattern = 0x00000000;
else
pattern = 0xFFFFFFFF;
+#else /* CONFIG_DDR4 */
+ if ((index > 1) && (index < 6))
+ pattern = PATTERN_20;
+ else
+ pattern = PATTERN_00;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_FULL_SSO0:
+#if !defined(CONFIG_DDR4)
pattern = 0x0000ffff;
break;
+#endif /* !CONFIG_DDR4 */
case PATTERN_FULL_SSO1:
case PATTERN_FULL_SSO2:
case PATTERN_FULL_SSO3:
pattern = pattern_table_get_sso_word(
+#if !defined(CONFIG_DDR4)
(u8)(type - PATTERN_FULL_SSO1), index);
+#else /* CONFIG_DDR4 */
+ (u8)(type - PATTERN_FULL_SSO0), index);
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_VREF:
pattern = pattern_table_get_vref_word16(index);
@@ -832,6 +1010,40 @@
case PATTERN_ISI_XTALK_FREE:
pattern = pattern_table_get_isi_word16(index);
break;
+#if defined(CONFIG_DDR4)
+ case PATTERN_KILLER_DQ0_INV:
+ case PATTERN_KILLER_DQ1_INV:
+ case PATTERN_KILLER_DQ2_INV:
+ case PATTERN_KILLER_DQ3_INV:
+ case PATTERN_KILLER_DQ4_INV:
+ case PATTERN_KILLER_DQ5_INV:
+ case PATTERN_KILLER_DQ6_INV:
+ case PATTERN_KILLER_DQ7_INV:
+ pattern = ~pattern_table_get_killer_word16(
+ (u8)(type - PATTERN_KILLER_DQ0_INV), index);
+ break;
+ case PATTERN_RESONANCE_1T:
+ case PATTERN_RESONANCE_2T:
+ case PATTERN_RESONANCE_3T:
+ case PATTERN_RESONANCE_4T:
+ case PATTERN_RESONANCE_5T:
+ case PATTERN_RESONANCE_6T:
+ case PATTERN_RESONANCE_7T:
+ case PATTERN_RESONANCE_8T:
+ case PATTERN_RESONANCE_9T:
+ {
+ u8 t_num = (u8)(type - PATTERN_RESONANCE_1T);
+ u8 t_end = (59 / t_num) * t_num;
+ if (index < t_end)
+ pattern = ((index % (t_num * 2)) >= t_num) ? 0xffffffff : 0x00000000;
+ else
+ pattern = ((index % 2) == 0) ? 0xffffffff : 0x00000000;
+ }
+ break;
+ case PATTERN_VREF_INV:
+ pattern = ~pattern_table_get_vref_word16(index);
+ break;
+#endif /* CONFIG_DDR4 */
default:
if (((int)type == 29) || ((int)type == 30))
break;
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip.h b/drivers/ddr/marvell/a38x/ddr3_training_ip.h
index 056c214..37d21f2 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_ip.h
+++ b/drivers/ddr/marvell/a38x/ddr3_training_ip.h
@@ -42,6 +42,13 @@
#define WRITE_LEVELING_LF_MASK_BIT 0x02000000
/* DDR4 Specific Training Mask bits */
+#if defined (CONFIG_DDR4)
+#define RECEIVER_CALIBRATION_MASK_BIT 0x04000000
+#define WL_PHASE_CORRECTION_MASK_BIT 0x08000000
+#define DQ_VREF_CALIBRATION_MASK_BIT 0x10000000
+#define DQ_MAPPING_MASK_BIT 0x20000000
+#define DM_TUNING_MASK_BIT 0x40000000
+#endif /* CONFIG_DDR4 */
enum hws_result {
TEST_FAILED = 0,
@@ -63,6 +70,9 @@
WRITE_LEVELING,
LOAD_PATTERN_2,
READ_LEVELING,
+#if defined(CONFIG_DDR4)
+ SW_READ_LEVELING,
+#endif /* CONFIG_DDR4 */
WRITE_LEVELING_SUPP,
PBS_RX,
PBS_TX,
@@ -78,6 +88,13 @@
TX_EMPHASIS,
LOAD_PATTERN_HIGH,
PER_BIT_READ_LEVELING_TF,
+#if defined(CONFIG_DDR4)
+ RECEIVER_CALIBRATION,
+ WL_PHASE_CORRECTION,
+ DQ_VREF_CALIBRATION,
+ DM_TUNING,
+ DQ_MAPPING,
+#endif /* CONFIG_DDR4 */
WRITE_LEVELING_LF,
MAX_STAGE_LIMIT
};
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h
index e28b7ec..7b24c1f 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h
+++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h
@@ -7,6 +7,66 @@
#define _DDR3_TRAINING_IP_DB_H_
enum hws_pattern {
+#if defined(CONFIG_DDR4) /* DDR4 16/32-bit */
+ PATTERN_PBS1,/*0*/
+ PATTERN_PBS2,
+ PATTERN_PBS3,
+ PATTERN_TEST,
+ PATTERN_RL,
+ PATTERN_RL2,
+ PATTERN_STATIC_PBS,
+ PATTERN_KILLER_DQ0,
+ PATTERN_KILLER_DQ1,
+ PATTERN_KILLER_DQ2,
+ PATTERN_KILLER_DQ3,/*10*/
+ PATTERN_KILLER_DQ4,
+ PATTERN_KILLER_DQ5,
+ PATTERN_KILLER_DQ6,
+ PATTERN_KILLER_DQ7,
+ PATTERN_KILLER_DQ0_INV,
+ PATTERN_KILLER_DQ1_INV,
+ PATTERN_KILLER_DQ2_INV,
+ PATTERN_KILLER_DQ3_INV,
+ PATTERN_KILLER_DQ4_INV,
+ PATTERN_KILLER_DQ5_INV,/*20*/
+ PATTERN_KILLER_DQ6_INV,
+ PATTERN_KILLER_DQ7_INV,
+ PATTERN_VREF,
+ PATTERN_VREF_INV,
+ PATTERN_FULL_SSO0,
+ PATTERN_FULL_SSO1,
+ PATTERN_FULL_SSO2,
+ PATTERN_FULL_SSO3,
+ PATTERN_ZERO,
+ PATTERN_ONE,
+ PATTERN_LAST,
+ PATTERN_SSO_FULL_XTALK_DQ0,
+ PATTERN_SSO_FULL_XTALK_DQ1,/*30*/
+ PATTERN_SSO_FULL_XTALK_DQ2,
+ PATTERN_SSO_FULL_XTALK_DQ3,
+ PATTERN_SSO_FULL_XTALK_DQ4,
+ PATTERN_SSO_FULL_XTALK_DQ5,
+ PATTERN_SSO_FULL_XTALK_DQ6,
+ PATTERN_SSO_FULL_XTALK_DQ7,
+ PATTERN_SSO_XTALK_FREE_DQ0,
+ PATTERN_SSO_XTALK_FREE_DQ1,
+ PATTERN_SSO_XTALK_FREE_DQ2,
+ PATTERN_SSO_XTALK_FREE_DQ3,/*40*/
+ PATTERN_SSO_XTALK_FREE_DQ4,
+ PATTERN_SSO_XTALK_FREE_DQ5,
+ PATTERN_SSO_XTALK_FREE_DQ6,
+ PATTERN_SSO_XTALK_FREE_DQ7,
+ PATTERN_ISI_XTALK_FREE,
+ PATTERN_RESONANCE_1T,
+ PATTERN_RESONANCE_2T,
+ PATTERN_RESONANCE_3T,
+ PATTERN_RESONANCE_4T,
+ PATTERN_RESONANCE_5T,/*50*/
+ PATTERN_RESONANCE_6T,
+ PATTERN_RESONANCE_7T,
+ PATTERN_RESONANCE_8T,
+ PATTERN_RESONANCE_9T
+#else /* DDR3 16/32-bit */
PATTERN_PBS1,
PATTERN_PBS2,
PATTERN_PBS3,
@@ -45,6 +105,7 @@
PATTERN_SSO_XTALK_FREE_DQ6,
PATTERN_SSO_XTALK_FREE_DQ7,
PATTERN_ISI_XTALK_FREE
+#endif /* CONFIG_64BIT */
};
enum mv_wl_supp_mode {
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c
index 102f9bd..2567dc3 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c
@@ -205,6 +205,137 @@
/* Note: actual start_address is "<< 3" of defined address */
};
+#if defined(CONFIG_DDR4)
+struct pattern_info pattern_table_16[] = {
+ /*
+ * num tx phases, tx burst, delay between, rx pattern,
+ * start_address, pattern_len
+ */
+ {0x1, 0x1, 2, 0x1, 0x0000, 2}, /* PATTERN_PBS1*/
+ {0x1, 0x1, 2, 0x1, 0x0080, 2}, /* PATTERN_PBS2*/
+ {0x1, 0x1, 2, 0x1, 0x0100, 2}, /* PATTERN_PBS3*/
+ {0x1, 0x1, 2, 0x1, 0x0180, 2}, /* PATTERN_TEST*/
+ {0x1, 0x1, 2, 0x1, 0x0200, 2}, /* PATTERN_RL*/
+ {0x1, 0x1, 2, 0x1, 0x0280, 2}, /* PATTERN_RL2*/
+ {0xf, 0x7, 2, 0x7, 0x0680, 16}, /* PATTERN_STATIC_PBS*/
+ {0xf, 0x7, 2, 0x7, 0x0A80, 16}, /* PATTERN_KILLER_DQ0*/
+ {0xf, 0x7, 2, 0x7, 0x0E80, 16}, /* PATTERN_KILLER_DQ1*/
+ {0xf, 0x7, 2, 0x7, 0x1280, 16}, /* PATTERN_KILLER_DQ2*/
+ {0xf, 0x7, 2, 0x7, 0x1680, 16}, /* PATTERN_KILLER_DQ3*/
+ {0xf, 0x7, 2, 0x7, 0x1A80, 16}, /* PATTERN_KILLER_DQ4*/
+ {0xf, 0x7, 2, 0x7, 0x1E80, 16}, /* PATTERN_KILLER_DQ5*/
+ {0xf, 0x7, 2, 0x7, 0x2280, 16}, /* PATTERN_KILLER_DQ6*/
+ {0xf, 0x7, 2, 0x7, 0x2680, 16}, /* PATTERN_KILLER_DQ7*/
+ {0xf, 0x7, 2, 0x7, 0x2A80, 16}, /* PATTERN_KILLER_DQ0_INV*/
+ {0xf, 0x7, 2, 0x7, 0x2E80, 16}, /* PATTERN_KILLER_DQ1_INV*/
+ {0xf, 0x7, 2, 0x7, 0x3280, 16}, /* PATTERN_KILLER_DQ2_INV*/
+ {0xf, 0x7, 2, 0x7, 0x3680, 16}, /* PATTERN_KILLER_DQ3_INV*/
+ {0xf, 0x7, 2, 0x7, 0x3A80, 16}, /* PATTERN_KILLER_DQ4_INV*/
+ {0xf, 0x7, 2, 0x7, 0x3E80, 16}, /* PATTERN_KILLER_DQ5_INV*/
+ {0xf, 0x7, 2, 0x7, 0x4280, 16}, /* PATTERN_KILLER_DQ6_INV*/
+ {0xf, 0x7, 2, 0x7, 0x4680, 16}, /* PATTERN_KILLER_DQ7_INV*/
+ {0xf, 0x7, 2, 0x7, 0x4A80, 16}, /* PATTERN_VREF*/
+ {0xf, 0x7, 2, 0x7, 0x4E80, 16}, /* PATTERN_VREF_INV*/
+ {0xf, 0x7, 2, 0x7, 0x5280, 16}, /* PATTERN_FULL_SSO_0T*/
+ {0xf, 0x7, 2, 0x7, 0x5680, 16}, /* PATTERN_FULL_SSO_1T*/
+ {0xf, 0x7, 2, 0x7, 0x5A80, 16}, /* PATTERN_FULL_SSO_2T*/
+ {0xf, 0x7, 2, 0x7, 0x5E80, 16}, /* PATTERN_FULL_SSO_3T*/
+ {0xf, 0x7, 2, 0x7, 0x6280, 16}, /* PATTERN_ZERO */
+ {0xf, 0x7, 2, 0x7, 0x6680, 16}, /* PATTERN_ONE */
+ {0xf, 0x7, 2, 0x7, 0x6A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ0*/
+ {0xf, 0x7, 2, 0x7, 0x6E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1*/
+ {0xf, 0x7, 2, 0x7, 0x7280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ2*/
+ {0xf, 0x7, 2, 0x7, 0x7680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ3*/
+ {0xf, 0x7, 2, 0x7, 0x7A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ4*/
+ {0xf, 0x7, 2, 0x7, 0x7E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ5*/
+ {0xf, 0x7, 2, 0x7, 0x8280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ6*/
+ {0xf, 0x7, 2, 0x7, 0x8680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ7*/
+ {0xf, 0x7, 2, 0x7, 0x8A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ0*/
+ {0xf, 0x7, 2, 0x7, 0x8E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ1*/
+ {0xf, 0x7, 2, 0x7, 0x9280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ2*/
+ {0xf, 0x7, 2, 0x7, 0x9680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ3*/
+ {0xf, 0x7, 2, 0x7, 0x9A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ4*/
+ {0xf, 0x7, 2, 0x7, 0x9E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ5*/
+ {0xf, 0x7, 2, 0x7, 0xA280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ6*/
+ {0xf, 0x7, 2, 0x7, 0xA680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ7*/
+ {0xf, 0x7, 2, 0x7, 0xAA80, 16}, /* PATTERN_ISI_XTALK_FREE*/
+ {0xf, 0x7, 2, 0x7, 0xAE80, 16}, /* PATTERN_RESONANCE_1T*/
+ {0xf, 0x7, 2, 0x7, 0xB280, 16}, /* PATTERN_RESONANCE_2T*/
+ {0xf, 0x7, 2, 0x7, 0xB680, 16}, /* PATTERN_RESONANCE_3T*/
+ {0xf, 0x7, 2, 0x7, 0xBA80, 16}, /* PATTERN_RESONANCE_4T*/
+ {0xf, 0x7, 2, 0x7, 0xBE80, 16}, /* PATTERN_RESONANCE_5T*/
+ {0xf, 0x7, 2, 0x7, 0xC280, 16}, /* PATTERN_RESONANCE_6T*/
+ {0xf, 0x7, 2, 0x7, 0xC680, 16}, /* PATTERN_RESONANCE_7T*/
+ {0xf, 0x7, 2, 0x7, 0xca80, 16}, /* PATTERN_RESONANCE_8T*/
+ {0xf, 0x7, 2, 0x7, 0xce80, 16} /* PATTERN_RESONANCE_9T*/
+ /* Note: actual start_address is "<< 3" of defined address */
+};
+
+struct pattern_info pattern_table_32[] = {
+ /*
+ * num tx phases, tx burst, delay between, rx pattern,
+ * start_address, pattern_len
+ */
+ {0x3, 0x3, 2, 0x3, 0x0000, 4}, /* PATTERN_PBS1*/
+ {0x3, 0x3, 2, 0x3, 0x0020, 4}, /* PATTERN_PBS2*/
+ {0x3, 0x3, 2, 0x3, 0x0040, 4}, /* PATTERN_PBS3*/
+ {0x3, 0x3, 2, 0x3, 0x0060, 4}, /* PATTERN_TEST*/
+ {0x3, 0x3, 2, 0x3, 0x0080, 4}, /* PATTERN_RL*/
+ {0x3, 0x3, 2, 0x3, 0x00a0, 4}, /* PATTERN_RL2*/
+ {0x1f, 0xf, 2, 0xf, 0x00c0, 32}, /* PATTERN_STATIC_PBS*/
+ {0x1f, 0xf, 2, 0xf, 0x00e0, 32}, /* PATTERN_KILLER_DQ0*/
+ {0x1f, 0xf, 2, 0xf, 0x0100, 32}, /* PATTERN_KILLER_DQ1*/
+ {0x1f, 0xf, 2, 0xf, 0x0120, 32}, /* PATTERN_KILLER_DQ2*/
+ {0x1f, 0xf, 2, 0xf, 0x0140, 32}, /* PATTERN_KILLER_DQ3*/
+ {0x1f, 0xf, 2, 0xf, 0x0160, 32}, /* PATTERN_KILLER_DQ4*/
+ {0x1f, 0xf, 2, 0xf, 0x0180, 32}, /* PATTERN_KILLER_DQ5*/
+ {0x1f, 0xf, 2, 0xf, 0x01a0, 32}, /* PATTERN_KILLER_DQ6*/
+ {0x1f, 0xf, 2, 0xf, 0x01c0, 32}, /* PATTERN_KILLER_DQ7*/
+ {0x1f, 0xf, 2, 0xf, 0x01e0, 32}, /* PATTERN_KILLER_DQ0_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x0200, 32}, /* PATTERN_KILLER_DQ1_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x0220, 32}, /* PATTERN_KILLER_DQ2_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x0240, 32}, /* PATTERN_KILLER_DQ3_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x0260, 32}, /* PATTERN_KILLER_DQ4_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x0280, 32}, /* PATTERN_KILLER_DQ5_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x02a0, 32}, /* PATTERN_KILLER_DQ6_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x02c0, 32}, /* PATTERN_KILLER_DQ7_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x02e0, 32}, /* PATTERN_VREF*/
+ {0x1f, 0xf, 2, 0xf, 0x0300, 32}, /* PATTERN_VREF_INV*/
+ {0x1f, 0xf, 2, 0xf, 0x0320, 32}, /* PATTERN_FULL_SSO_0T*/
+ {0x1f, 0xf, 2, 0xf, 0x0340, 32}, /* PATTERN_FULL_SSO_1T*/
+ {0x1f, 0xf, 2, 0xf, 0x0360, 32}, /* PATTERN_FULL_SSO_2T*/
+ {0x1f, 0xf, 2, 0xf, 0x0380, 32}, /* PATTERN_FULL_SSO_3T*/
+ {0x1f, 0xf, 2, 0xf, 0x6280, 32}, /* PATTERN_ZERO */
+ {0x1f, 0xf, 2, 0xf, 0x6680, 32}, /* PATTERN_ONE */
+ {0x1f, 0xf, 2, 0xf, 0x6A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0*/
+ {0x1f, 0xf, 2, 0xf, 0x6E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1*/
+ {0x1f, 0xf, 2, 0xf, 0x7280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2*/
+ {0x1f, 0xf, 2, 0xf, 0x7680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3*/
+ {0x1f, 0xf, 2, 0xf, 0x7A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4*/
+ {0x1f, 0xf, 2, 0xf, 0x7E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5*/
+ {0x1f, 0xf, 2, 0xf, 0x8280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6*/
+ {0x1f, 0xf, 2, 0xf, 0x8680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7*/
+ {0x1f, 0xf, 2, 0xf, 0x8A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0*/
+ {0x1f, 0xf, 2, 0xf, 0x8E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1*/
+ {0x1f, 0xf, 2, 0xf, 0x9280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2*/
+ {0x1f, 0xf, 2, 0xf, 0x9680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3*/
+ {0x1f, 0xf, 2, 0xf, 0x9A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4*/
+ {0x1f, 0xf, 2, 0xf, 0x9E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5*/
+ {0x1f, 0xf, 2, 0xf, 0xA280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6*/
+ {0x1f, 0xf, 2, 0xf, 0xA680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7*/
+ {0x1f, 0xf, 2, 0xf, 0xAA80, 32}, /* PATTERN_ISI_XTALK_FREE*/
+ {0x1f, 0xf, 2, 0xf, 0xAE80, 32}, /* PATTERN_RESONANCE_1T*/
+ {0x1f, 0xf, 2, 0xf, 0xB280, 32}, /* PATTERN_RESONANCE_2T*/
+ {0x1f, 0xf, 2, 0xf, 0xB680, 32}, /* PATTERN_RESONANCE_3T*/
+ {0x1f, 0xf, 2, 0xf, 0xBA80, 32}, /* PATTERN_RESONANCE_4T*/
+ {0x1f, 0xf, 2, 0xf, 0xBE80, 32}, /* PATTERN_RESONANCE_5T*/
+ {0x1f, 0xf, 2, 0xf, 0xC280, 32}, /* PATTERN_RESONANCE_6T*/
+ {0x1f, 0xf, 2, 0xf, 0xC680, 32}, /* PATTERN_RESONANCE_7T*/
+ {0x1f, 0xf, 2, 0xf, 0xca80, 32}, /* PATTERN_RESONANCE_8T*/
+ {0x1f, 0xf, 2, 0xf, 0xce80, 32} /* PATTERN_RESONANCE_9T*/
+ /* Note: actual start_address is "<< 3" of defined address */
+};
+#else /* CONFIG_DDR4 */
struct pattern_info pattern_table_16[] = {
/*
* num tx phases, tx burst, delay between, rx pattern,
@@ -294,6 +425,7 @@
{0x1f, 0xF, 2, 0xf, 0xA280, 32} /* PATTERN_ISI_XTALK_FREE */
/* Note: actual start_address is "<< 3" of defined address */
};
+#endif /* CONFIG_DDR4 */
u32 train_dev_num;
enum hws_ddr_cs traintrain_cs_type;
@@ -309,7 +441,12 @@
enum hws_edge_compare train_edge_compare;
u32 train_cs_num;
u32 train_if_acess, train_if_id, train_pup_access;
+#if defined(CONFIG_DDR4)
+/* The counter was increased for DDR4 because of A390 DB-GP DDR4 failure */
+u32 max_polling_for_done = 100000000;
+#else /* CONFIG_DDR4 */
u32 max_polling_for_done = 1000000;
+#endif /* CONFIG_DDR4 */
u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search,
enum hws_training_result result_type,
@@ -561,6 +698,10 @@
ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
+#if defined(CONFIG_DDR4)
+ if (tm->debug_level != DEBUG_LEVEL_ERROR)
+ refresh();
+#endif
return MV_OK;
}
@@ -837,6 +978,10 @@
}
}
}
+#if defined(CONFIG_DDR4)
+ if (tm->debug_level != DEBUG_LEVEL_ERROR)
+ refresh();
+#endif
return MV_OK;
}
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h
index 55832a5..16a5951 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h
+++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h
@@ -46,6 +46,11 @@
MR_CMD1,
MR_CMD2,
MR_CMD3,
+#if defined(CONFIG_DDR4)
+ MR_CMD4,
+ MR_CMD5,
+ MR_CMD6,
+#endif
MR_LAST
};
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_leveling.c b/drivers/ddr/marvell/a38x/ddr3_training_leveling.c
index 6523281..55abbad 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_leveling.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training_leveling.c
@@ -1667,6 +1667,59 @@
RL_BEHIND
};
+#if defined(CONFIG_DDR4)
+static int mpr_rd_frmt_config(
+ enum mv_ddr_mpr_ps ps,
+ enum mv_ddr_mpr_op op,
+ enum mv_ddr_mpr_rd_frmt rd_frmt,
+ u8 cs_bitmask, u8 dis_auto_refresh)
+{
+ u32 val, mask;
+ u8 cs_bitmask_inv;
+
+
+ if (dis_auto_refresh == 1) {
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_CTRL_CTRL_REG,
+ ODPG_CTRL_AUTO_REFRESH_DIS << ODPG_CTRL_AUTO_REFRESH_OFFS,
+ ODPG_CTRL_AUTO_REFRESH_MASK << ODPG_CTRL_AUTO_REFRESH_OFFS);
+ } else {
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_CTRL_CTRL_REG,
+ ODPG_CTRL_AUTO_REFRESH_ENA << ODPG_CTRL_AUTO_REFRESH_OFFS,
+ ODPG_CTRL_AUTO_REFRESH_MASK << ODPG_CTRL_AUTO_REFRESH_OFFS);
+ }
+
+ /* configure MPR Location for MPR write and read accesses within the selected page */
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, DDR4_MPR_WR_REG,
+ DDR4_MPR_LOC3 << DDR4_MPR_LOC_OFFS,
+ DDR4_MPR_LOC_MASK << DDR4_MPR_LOC_OFFS);
+
+ /* configure MPR page selection, operation and read format */
+ val = ps << DDR4_MPR_PS_OFFS |
+ op << DDR4_MPR_OP_OFFS |
+ rd_frmt << DDR4_MPR_RF_OFFS;
+ mask = DDR4_MPR_PS_MASK << DDR4_MPR_PS_OFFS |
+ DDR4_MPR_OP_MASK << DDR4_MPR_OP_OFFS |
+ DDR4_MPR_RF_MASK << DDR4_MPR_RF_OFFS;
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, DDR4_MR3_REG, val, mask);
+
+ /* prepare cs bitmask in active low format */
+ cs_bitmask_inv = ~cs_bitmask & SDRAM_OP_CMD_ALL_CS_MASK;
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, SDRAM_OP_REG,
+ CMD_DDR3_DDR4_MR3 << SDRAM_OP_CMD_OFFS |
+ cs_bitmask_inv << SDRAM_OP_CMD_CS_OFFS(0),
+ SDRAM_OP_CMD_MASK << SDRAM_OP_CMD_OFFS |
+ SDRAM_OP_CMD_ALL_CS_MASK << SDRAM_OP_CMD_CS_OFFS(0));
+
+ if (ddr3_tip_if_polling(0, ACCESS_TYPE_UNICAST, 0,
+ CMD_NORMAL, SDRAM_OP_CMD_MASK, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS)) {
+ printf("error: %s failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* CONFIG_DDR4 */
int mv_ddr_rl_dqs_burst(u32 dev_num, u32 if_id, u32 freq)
{
@@ -1690,6 +1743,19 @@
u32 reg_val, reg_mask;
uintptr_t test_addr = TEST_ADDR;
+#if defined(CONFIG_DDR4)
+ int status;
+ u8 cs_bitmask = tm->interface_params[0].as_bus_params[0].cs_bitmask;
+ u8 curr_cs_bitmask_inv;
+
+ /* enable MPR for all existing chip-selects */
+ status = mpr_rd_frmt_config(DDR4_MPR_PAGE0,
+ DDR4_MPR_OP_ENA,
+ DDR4_MPR_RF_SERIAL,
+ cs_bitmask, 1);
+ if (status)
+ return status;
+#endif /* CONFIG_DDR4 */
/* initialization */
if (mv_ddr_is_ecc_ena()) {
@@ -1728,6 +1794,48 @@
/* search for dqs edges per subphy */
if_id = 0;
for (effective_cs = 0; effective_cs < max_cs; effective_cs++) {
+#if defined(CONFIG_DDR4)
+ /* enable read preamble training mode for chip-select under test */
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR4_MR4_REG,
+ DDR4_RPT_ENA << DDR4_RPT_OFFS,
+ DDR4_RPT_MASK << DDR4_RPT_OFFS);
+ /* prepare current cs bitmask in active low format */
+ curr_cs_bitmask_inv = ~(1 << effective_cs) & SDRAM_OP_CMD_ALL_CS_MASK;
+ reg_val = curr_cs_bitmask_inv << SDRAM_OP_CMD_CS_OFFS(0) |
+ CMD_DDR4_MR4 << SDRAM_OP_CMD_OFFS;
+ reg_mask = SDRAM_OP_CMD_ALL_CS_MASK << SDRAM_OP_CMD_CS_OFFS(0) |
+ SDRAM_OP_CMD_MASK << SDRAM_OP_CMD_OFFS;
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_OP_REG, reg_val, reg_mask);
+ if (ddr3_tip_if_polling(0, ACCESS_TYPE_UNICAST, 0,
+ CMD_NORMAL, SDRAM_OP_CMD_MASK, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS)) {
+ printf("error: %s failed\n", __func__);
+ return -1;
+ }
+
+ /* disable preamble training mode for existing chip-selects not under test */
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR4_MR4_REG,
+ DDR4_RPT_DIS << DDR4_RPT_OFFS,
+ DDR4_RPT_MASK << DDR4_RPT_OFFS);
+ /* prepare bitmask for existing chip-selects not under test in active low format */
+ reg_val = ((~(curr_cs_bitmask_inv & cs_bitmask) & SDRAM_OP_CMD_ALL_CS_MASK) <<
+ SDRAM_OP_CMD_CS_OFFS(0)) |
+ CMD_DDR4_MR4 << SDRAM_OP_CMD_OFFS;
+ reg_mask = SDRAM_OP_CMD_ALL_CS_MASK << SDRAM_OP_CMD_CS_OFFS(0) |
+ SDRAM_OP_CMD_MASK << SDRAM_OP_CMD_OFFS;
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_OP_REG, reg_val, reg_mask);
+ if (ddr3_tip_if_polling(0, ACCESS_TYPE_UNICAST, 0,
+ CMD_NORMAL, SDRAM_OP_CMD_MASK, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS)) {
+ printf("error: %s failed\n", __func__);
+ return -1;
+ }
+
+#endif /* CONFIG_DDR4 */
pass_lock_num = init_pass_lock_num;
ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG,
@@ -1948,6 +2056,33 @@
CHECK_STATUS(ddr3_tip_write_additional_odt_setting(dev_num, if_id));
}
+#if defined(CONFIG_DDR4)
+ /* disable read preamble training mode for all existing chip-selects */
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR4_MR4_REG,
+ DDR4_RPT_DIS << DDR4_RPT_OFFS,
+ DDR4_RPT_MASK << DDR4_RPT_OFFS);
+ reg_val = (~cs_bitmask & SDRAM_OP_CMD_ALL_CS_MASK) << SDRAM_OP_CMD_CS_OFFS(0) |
+ CMD_DDR4_MR4 << SDRAM_OP_CMD_OFFS;
+ reg_mask = SDRAM_OP_CMD_ALL_CS_MASK << SDRAM_OP_CMD_CS_OFFS(0) |
+ SDRAM_OP_CMD_MASK << SDRAM_OP_CMD_OFFS;
+ ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ SDRAM_OP_REG, reg_val, reg_mask);
+ if (ddr3_tip_if_polling(0, ACCESS_TYPE_UNICAST, 0,
+ CMD_NORMAL, SDRAM_OP_CMD_MASK, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS)) {
+ printf("error: %s failed\n", __func__);
+ return -1;
+ }
+
+ /* disable MPR for all existing chip-selects */
+ status = mpr_rd_frmt_config(DDR4_MPR_PAGE0,
+ DDR4_MPR_OP_DIS,
+ DDR4_MPR_RF_SERIAL,
+ cs_bitmask, 0);
+ if (status)
+ return status;
+#endif /* CONFIG_DDR4 */
/* reset read fifo assertion */
ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG,
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_mpr_pda_if.c b/drivers/ddr/marvell/a38x/mv_ddr4_mpr_pda_if.c
new file mode 100644
index 0000000..f742b5a
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_mpr_pda_if.c
@@ -0,0 +1,674 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#if defined(CONFIG_DDR4)
+
+/* DDR4 MPR/PDA Interface */
+#include "ddr3_init.h"
+#include "mv_ddr4_mpr_pda_if.h"
+#include "mv_ddr4_training.h"
+#include "mv_ddr_training_db.h"
+#include "mv_ddr_common.h"
+#include "mv_ddr_regs.h"
+
+static u8 dram_to_mc_dq_map[MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+static int dq_map_enable;
+
+static u32 mv_ddr4_tx_odt_get(void)
+{
+ u16 odt = 0xffff, rtt = 0xffff;
+
+ if (g_odt_config & 0xe0000)
+ rtt = mv_ddr4_rtt_nom_to_odt(g_rtt_nom);
+ else if (g_odt_config & 0x10000)
+ rtt = mv_ddr4_rtt_wr_to_odt(g_rtt_wr);
+ else
+ return odt;
+
+ return (odt * rtt) / (odt + rtt);
+}
+
+/*
+ * mode registers initialization function
+ * replaces all MR writes in DDR3 init function
+ */
+int mv_ddr4_mode_regs_init(u8 dev_num)
+{
+ int status;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum hws_access_type access_type = ACCESS_TYPE_UNICAST;
+ u32 if_id;
+ u32 cl, cwl;
+ u32 val, mask;
+ u32 t_wr, t_ckclk;
+ /* design GL params to be set outside */
+ u32 dic = 0;
+ u32 ron = 30; /* znri */
+ u32 rodt = mv_ddr4_tx_odt_get(); /* effective rtt */
+ /* vref percentage presented as 100 x percentage value (e.g., 6000 = 100 x 60%) */
+ u32 vref = ((ron + rodt / 2) * 10000) / (ron + rodt);
+ u32 range = (vref >= 6000) ? 0 : 1; /* if vref is >= 60%, use upper range */
+ u32 tap;
+ u32 refresh_mode;
+
+ if (range == 0)
+ tap = (vref - 6000) / 65;
+ else
+ tap = (vref - 4500) / 65;
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ cl = tm->interface_params[if_id].cas_l;
+ cwl = tm->interface_params[if_id].cas_wl;
+ t_ckclk = MEGA / mv_ddr_freq_get(tm->interface_params[if_id].memory_freq);
+ t_wr = time_to_nclk(mv_ddr_speed_bin_timing_get(tm->interface_params[if_id].speed_bin_index,
+ SPEED_BIN_TWR), t_ckclk) - 1;
+
+ /* TODO: replace hard-coded values with appropriate defines */
+ /* DDR4 MR0 */
+ /*
+ * [6:4,2] bits to be taken from S@R frequency and speed bin
+ * rtt_nom to be taken from the algorithm definition
+ * dic to be taken fro the algorithm definition -
+ * set to 0x1 (for driver rzq/5 = 48 ohm) or
+ * set to 0x0 (for driver rzq/7 = 34 ohm)
+ */
+ /* set dll reset, 0x1900[8] to 0x1 */
+ /* set tm, 0x1900[7] to 0x0 */
+ /* set rbt, 0x1900[3] to 0x0 */
+ /* set bl, 0x1900[1:0] to 0x0 */
+ val = ((cl_mask_table[cl] & 0x1) << 2) |
+ (((cl_mask_table[cl] & 0xe) >> 1) << 4) |
+ (twr_mask_table[t_wr + 1] << 9) |
+ (0x1 << 8) | (0x0 << 7) | (0x0 << 3) | 0x0;
+ mask = (0x1 << 2) | (0x7 << 4) | (0x7 << 9) |
+ (0x1 << 8) | (0x1 << 7) | (0x1 << 3) | 0x3;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR0_REG,
+ val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* DDR4 MR1 */
+ /* set rtt nom to 0 if rtt park is activated (not zero) */
+ if ((g_rtt_park >> 6) != 0x0)
+ g_rtt_nom = 0;
+ /* set tdqs, 0x1904[11] to 0x0 */
+ /* set al, 0x1904[4:3] to 0x0 */
+ /* dic, 0x1904[2:1] */
+ /* dll enable */
+ val = g_rtt_nom | (0x0 << 11) | (0x0 << 3) | (dic << 1) | 0x1;
+ mask = (0x7 << 8) | (0x1 << 11) | (0x3 << 3) | (0x3 << 1) | 0x1;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR1_REG,
+ val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* DDR4 MR2 */
+ /* set rtt wr, 0x1908[10,9] to 0x0 */
+ /* set wr crc, 0x1908[12] to 0x0 */
+ /* cwl */
+ val = g_rtt_wr | (0x0 << 12) | (cwl_mask_table[cwl] << 3);
+ mask = (0x3 << 9) | (0x1 << 12) | (0x7 << 3);
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR2_REG,
+ val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* DDR4 MR3 */
+ /* set fgrm, 0x190C[8:6] to 0x0 */
+ /* set gd, 0x190C[3] to 0x0 */
+ refresh_mode = (tm->interface_params[if_id].interface_temp == MV_DDR_TEMP_HIGH) ? 1 : 0;
+
+ val = (refresh_mode << 6) | (0x0 << 3);
+ mask = (0x7 << 6) | (0x1 << 3);
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR3_REG,
+ val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* DDR4 MR4 */
+ /*
+ * set wp, 0x1910[12] to 0x0
+ * set rp, 0x1910[11] to 0x0
+ * set rp training, 0x1910[10] to 0x0
+ * set sra, 0x1910[9] to 0x0
+ * set cs2cmd, 0x1910[8:6] to 0x0
+ * set mpd, 0x1910[1] to 0x0
+ */
+ mask = (0x1 << 12) | (0x1 << 11) | (0x1 << 10) | (0x1 << 9) | (0x7 << 6) | (0x1 << 1);
+ val = (0x0 << 12) | (0x1 << 11) | (0x0 << 10) | (0x0 << 9) | (0x0 << 6) | (0x0 << 1);
+
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR4_REG,
+ val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* DDR4 MR5 */
+ /*
+ * set rdbi, 0x1914[12] to 0x0 during init sequence (may be enabled with
+ * op cmd mrs - bug in z1, to be fixed in a0)
+ * set wdbi, 0x1914[11] to 0x0
+ * set dm, 0x1914[10] to 0x1
+ * set ca_pl, 0x1914[2:0] to 0x0
+ * set odt input buffer during power down mode, 0x1914[5] to 0x1
+ */
+ mask = (0x1 << 12) | (0x1 << 11) | (0x1 << 10) | (0x7 << 6) | (0x1 << 5) | 0x7;
+ val = (0x0 << 12) | (0x0 << 11) | (0x1 << 10) | g_rtt_park | (0x1 << 5) | 0x0;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR5_REG,
+ val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* DDR4 MR6 */
+ /*
+ * set t_ccd_l, 0x1918[12:10] to 0x0, 0x2, or 0x4 (z1 supports only even
+ * values, to be fixed in a0)
+ * set vdq te, 0x1918[7] to 0x0
+ * set vdq tv, 0x1918[5:0] to vref training value
+ */
+ mask = (0x7 << 10) | (0x1 << 7) | (0x1 << 6) | 0x3f;
+ val = (0x2 << 10) | (0x0 << 7) | (range << 6) | tap;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR6_REG,
+ val, mask);
+ if (status != MV_OK)
+ return status;
+ }
+
+ return MV_OK;
+}
+
+/* enter mpr read mode */
+static int mv_ddr4_mpr_read_mode_enable(u8 dev_num, u32 mpr_num, u32 page_num,
+ enum mv_ddr4_mpr_read_format read_format)
+{
+ /*
+ * enable MPR page 2 mpr mode in DDR4 MR3
+ * read_format: 0 for serial, 1 for parallel, and 2 for staggered
+ * TODO: add support for cs, multicast or unicast, and if id
+ */
+ int status;
+ u32 val, mask, if_id = 0;
+
+ if (page_num != 0) {
+ /* serial is the only read format if the page is other than 0 */
+ read_format = MV_DDR4_MPR_READ_SERIAL;
+ }
+
+ val = (page_num << 0) | (0x1 << 2) | (read_format << 11);
+ mask = (0x3 << 0) | (0x1 << 2) | (0x3 << 11);
+
+ /* cs0 */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DDR4_MR3_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* op cmd: cs0, cs1 are on, cs2, cs3 are off */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, SDRAM_OP_REG,
+ (0x9 | (0xc << 8)) , (0x1f | (0xf << 8)));
+ if (status != MV_OK)
+ return status;
+
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_mpr_read_mode_enable: DDR3 poll failed(MPR3)\n"));
+ }
+
+ return MV_OK;
+}
+
+/* exit mpr read or write mode */
+static int mv_ddr4_mpr_mode_disable(u8 dev_num)
+{
+ /* TODO: add support for cs, multicast or unicast, and if id */
+ int status;
+ u32 val, mask, if_id = 0;
+
+ /* exit mpr */
+ val = 0x0 << 2;
+ mask = 0x1 << 2;
+ /* cs0 */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DDR4_MR3_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* op cmd: cs0, cs1 are on, cs2, cs3 are off */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, SDRAM_OP_REG,
+ (0x9 | (0xc << 8)) , (0x1f | (0xf << 8)));
+ if (status != MV_OK)
+ return status;
+
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_mpr_mode_disable: DDR3 poll failed(MPR3)\n"));
+ }
+
+ return MV_OK;
+}
+
+/* translate dq read value per dram dq pin */
+static int mv_ddr4_dq_decode(u8 dev_num, u32 *data)
+{
+ u32 subphy_num, dq_num;
+ u32 dq_val = 0, raw_data, idx;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u32 subphy_max = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+
+ /* suppose the third word is stable */
+ raw_data = data[2];
+
+ /* skip ecc supbhy; TODO: check to add support for ecc */
+ if (subphy_max % 2)
+ subphy_max -= 1;
+
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ for (dq_num = 0; dq_num < BUS_WIDTH_IN_BITS; dq_num++) {
+ idx = (dram_to_mc_dq_map[subphy_num][dq_num] + (subphy_num * BUS_WIDTH_IN_BITS));
+ dq_val |= (((raw_data & (1 << idx)) >> idx) << ((subphy_num * BUS_WIDTH_IN_BITS) + dq_num));
+ }
+ }
+
+ /* update burst words[0..7] with correct mapping */
+ for (idx = 0; idx < EXT_ACCESS_BURST_LENGTH; idx++)
+ data[idx] = dq_val;
+
+ return MV_OK;
+}
+
+/*
+ * read mpr value per requested format and type
+ * note: for parallel decoded read, data is presented as stored in mpr on dram side,
+ * for all others, data to be presneted "as is" (i.e. per dq order from high to low
+ * and bus pins connectivity).
+ */
+int mv_ddr4_mpr_read(u8 dev_num, u32 mpr_num, u32 page_num,
+ enum mv_ddr4_mpr_read_format read_format,
+ enum mv_ddr4_mpr_read_type read_type,
+ u32 *data)
+{
+ /* TODO: add support for multiple if_id, dev num, and cs */
+ u32 word_idx, if_id = 0;
+ volatile unsigned long *addr = NULL;
+
+ /* enter mpr read mode */
+ mv_ddr4_mpr_read_mode_enable(dev_num, mpr_num, page_num, read_format);
+
+ /* set pattern type*/
+ ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DDR4_MPR_WR_REG,
+ mpr_num << 8, 0x3 << 8);
+
+ for (word_idx = 0; word_idx < EXT_ACCESS_BURST_LENGTH; word_idx++) {
+ data[word_idx] = *addr;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("mv_ddr4_mpr_read: addr 0x%08lx, data 0x%08x\n",
+ (unsigned long)addr, data[word_idx]));
+ addr++;
+ }
+
+ /* exit mpr read mode */
+ mv_ddr4_mpr_mode_disable(dev_num);
+
+ /* decode mpr read value (only parallel mode supported) */
+ if ((read_type == MV_DDR4_MPR_READ_DECODED) && (read_format == MV_DDR4_MPR_READ_PARALLEL)) {
+ if (dq_map_enable == 1) {
+ mv_ddr4_dq_decode(dev_num, data);
+ } else {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_mpr_read: run mv_ddr4_dq_pins_mapping()\n"));
+ return MV_FAIL;
+ }
+ }
+
+ return MV_OK;
+}
+
+/* enter mpr write mode */
+static int mv_ddr4_mpr_write_mode_enable(u8 dev_num, u32 mpr_location, u32 page_num, u32 data)
+{
+ /*
+ * enable MPR page 2 mpr mode in DDR4 MR3
+ * TODO: add support for cs, multicast or unicast, and if id
+ */
+ int status;
+ u32 if_id = 0, val = 0, mask;
+
+ val = (page_num << 0) | (0x1 << 2);
+ mask = (0x3 << 0) | (0x1 << 2);
+ /* cs0 */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DDR4_MR3_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* cs0 */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DDR4_MPR_WR_REG,
+ (mpr_location << 8) | data, 0x3ff);
+ if (status != MV_OK)
+ return status;
+
+ /* op cmd: cs0, cs1 are on, cs2, cs3 are off */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, SDRAM_OP_REG,
+ (0x13 | 0xc << 8) , (0x1f | (0xf << 8)));
+ if (status != MV_OK)
+ return status;
+
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_mpr_write_mode_enable: DDR3 poll failed(MPR3)\n"));
+ }
+
+ return MV_OK;
+}
+
+/* write mpr value */
+int mv_ddr4_mpr_write(u8 dev_num, u32 mpr_location, u32 mpr_num, u32 page_num, u32 data)
+{
+ /* enter mpr write mode */
+ mv_ddr4_mpr_write_mode_enable(dev_num, mpr_location, page_num, data);
+
+ /* TODO: implement this function */
+
+ /* TODO: exit mpr write mode */
+
+ return MV_OK;
+}
+
+/*
+ * map physical on-board connection of dram dq pins to ddr4 controller pins
+ * note: supports only 32b width
+ * TODO: add support for 64-bit bus width and ecc subphy
+ */
+int mv_ddr4_dq_pins_mapping(u8 dev_num)
+{
+ static int run_once;
+ u8 dq_val[MAX_BUS_NUM][BUS_WIDTH_IN_BITS] = { {0} };
+ u32 mpr_pattern[MV_DDR4_MPR_READ_PATTERN_NUM][EXT_ACCESS_BURST_LENGTH] = { {0} };
+ u32 subphy_num, dq_num, mpr_type;
+ u8 subphy_pattern[3];
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u32 subphy_max = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+
+ if (run_once)
+ return MV_OK;
+ else
+ run_once++;
+
+ /* clear dq mapping */
+ memset(dram_to_mc_dq_map, 0, sizeof(dram_to_mc_dq_map));
+
+ /* stage 1: read page 0 mpr0..2 raw patterns */
+ for (mpr_type = 0; mpr_type < MV_DDR4_MPR_READ_PATTERN_NUM; mpr_type++)
+ mv_ddr4_mpr_read(dev_num, mpr_type, 0, MV_DDR4_MPR_READ_PARALLEL,
+ MV_DDR4_MPR_READ_RAW, mpr_pattern[mpr_type]);
+
+ /* stage 2: map every dq for each subphy to 3-bit value, create local database */
+ /* skip ecc supbhy; TODO: check to add support for ecc */
+ if (subphy_max % 2)
+ subphy_max -= 1;
+
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ /* extract pattern for each subphy */
+ for (mpr_type = 0; mpr_type < MV_DDR4_MPR_READ_PATTERN_NUM; mpr_type++)
+ subphy_pattern[mpr_type] = ((mpr_pattern[mpr_type][2] >> (subphy_num * 8)) & 0xff);
+
+ for (dq_num = 0; dq_num < BUS_WIDTH_IN_BITS; dq_num++)
+ for (mpr_type = 0; mpr_type < MV_DDR4_MPR_READ_PATTERN_NUM; mpr_type++)
+ dq_val[subphy_num][dq_num] += (((subphy_pattern[mpr_type] >> dq_num) & 1) *
+ (1 << mpr_type));
+ }
+
+ /* stage 3: map dram dq to mc dq and update database */
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ for (dq_num = 0; dq_num < BUS_WIDTH_IN_BITS; dq_num++)
+ dram_to_mc_dq_map[subphy_num][7 - dq_val[subphy_num][dq_num]] = dq_num;
+ }
+
+ /* set dq_map_enable */
+ dq_map_enable = 1;
+
+ return MV_OK;
+}
+
+/* enter to or exit from dram vref training mode */
+int mv_ddr4_vref_training_mode_ctrl(u8 dev_num, u8 if_id, enum hws_access_type access_type, int enable)
+{
+ int status;
+ u32 val, mask;
+
+ /* DDR4 MR6 */
+ /*
+ * set t_ccd_l, 0x1918[12:10] to 0x0, 0x2, or 0x4 (z1 supports only even
+ * values, to be fixed in a0)
+ * set vdq te, 0x1918[7] to 0x0
+ * set vdq tv, 0x1918[5:0] to vref training value
+ */
+
+ val = (((enable == 1) ? 1 : 0) << 7);
+ mask = (0x1 << 7);
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR6_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* write DDR4 MR6 cs configuration; only cs0, cs1 supported */
+ if (effective_cs == 0)
+ val = 0xe;
+ else
+ val = 0xd;
+ val <<= 8;
+ /* write DDR4 MR6 command */
+ val |= 0x12;
+ mask = (0xf << 8) | 0x1f;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, SDRAM_OP_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_vref_training_mode_ctrl: Polling command failed\n"));
+ }
+
+ return MV_OK;
+}
+
+/* set dram vref tap value */
+int mv_ddr4_vref_tap_set(u8 dev_num, u8 if_id, enum hws_access_type access_type,
+ u32 taps_num, enum mv_ddr4_vref_tap_state state)
+{
+ int status;
+ u32 range, vdq_tv;
+
+ /* disable and then enable the training with a new range */
+ if ((state == MV_DDR4_VREF_TAP_BUSY) && ((taps_num + MV_DDR4_VREF_STEP_SIZE) >= 23) &&
+ (taps_num < 23))
+ state = MV_DDR4_VREF_TAP_FLIP;
+
+ if (taps_num < 23) {
+ range = 1;
+ vdq_tv = taps_num;
+ } else {
+ range = 0;
+ vdq_tv = taps_num - 23;
+ }
+
+ if ((state == MV_DDR4_VREF_TAP_FLIP) | (state == MV_DDR4_VREF_TAP_START)) {
+ /* 0 to disable */
+ status = mv_ddr4_vref_set(dev_num, if_id, access_type, range, vdq_tv, 0);
+ if (status != MV_OK)
+ return status;
+ /* 1 to enable */
+ status = (mv_ddr4_vref_set(dev_num, if_id, access_type, range, vdq_tv, 1));
+ if (status != MV_OK)
+ return status;
+ } else if (state == MV_DDR4_VREF_TAP_END) {
+ /* 1 to enable */
+ status = (mv_ddr4_vref_set(dev_num, if_id, access_type, range, vdq_tv, 1));
+ if (status != MV_OK)
+ return status;
+ /* 0 to disable */
+ status = mv_ddr4_vref_set(dev_num, if_id, access_type, range, vdq_tv, 0);
+ if (status != MV_OK)
+ return status;
+ } else {
+ /* 1 to enable */
+ status = (mv_ddr4_vref_set(dev_num, if_id, access_type, range, vdq_tv, 1));
+ if (status != MV_OK)
+ return status;
+ }
+
+ return MV_OK;
+}
+
+/* set dram vref value */
+int mv_ddr4_vref_set(u8 dev_num, u8 if_id, enum hws_access_type access_type,
+ u32 range, u32 vdq_tv, u8 vdq_training_ena)
+{
+ int status;
+ u32 read_data;
+ u32 val, mask;
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("mv_ddr4_vref_set: range %d, vdq_tv %d\n", range, vdq_tv));
+
+ /* DDR4 MR6 */
+ /*
+ * set t_ccd_l, 0x1918[12:10] to 0x0, 0x2, or 0x4 (z1 supports only even
+ * values, to be fixed in a0)
+ * set vdq te, 0x1918[7] to 0x0
+ * set vdq tr, 0x1918[6] to 0x0 to disable or 0x1 to enable
+ * set vdq tv, 0x1918[5:0] to vref training value
+ */
+ val = (vdq_training_ena << 7) | (range << 6) | vdq_tv;
+ mask = (0x0 << 7) | (0x1 << 6) | 0x3f;
+
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR6_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ ddr3_tip_if_read(dev_num, access_type, if_id, DDR4_MR6_REG, &read_data, 0xffffffff);
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("mv_ddr4_vref_set: MR6 = 0x%x\n", read_data));
+
+ /* write DDR4 MR6 cs configuration; only cs0, cs1 supported */
+ if (effective_cs == 0)
+ val = 0xe;
+ else
+ val = 0xd;
+ val <<= 8;
+ /* write DDR4 MR6 command */
+ val |= 0x12;
+ mask = (0xf << 8) | 0x1f;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, SDRAM_OP_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1F, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_vref_set: Polling command failed\n"));
+ }
+
+ return MV_OK;
+}
+
+/* pda - load pattern to odpg */
+int mv_ddr4_pda_pattern_odpg_load(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, u32 subphy_mask, u32 cs_num)
+{
+ int status;
+ u32 pattern_len_count = 0;
+ u32 data_low[KILLER_PATTERN_LENGTH] = {0};
+ u32 data_high[KILLER_PATTERN_LENGTH] = {0};
+ u32 val, mask, subphy_num;
+
+ /*
+ * set 0x1630[10:5] bits to 0x3 (0x1 for 16-bit bus width)
+ * set 0x1630[14:11] bits to 0x3 (0x1 for 16-bit bus width)
+ */
+ val = (cs_num << 26) | (0x1 << 25) | (0x3 << 11) | (0x3 << 5) | 0x1;
+ mask = (0x3 << 26) | (0x1 << 25) | (0x3f << 11) | (0x3f << 5) | 0x1;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, ODPG_DATA_CTRL_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ if (subphy_mask != 0xf) {
+ for (subphy_num = 0; subphy_num < 4; subphy_num++)
+ if (((subphy_mask >> subphy_num) & 0x1) == 0)
+ data_low[0] = (data_low[0] | (0xff << (subphy_num * 8)));
+ } else
+ data_low[0] = 0;
+
+ for (pattern_len_count = 0; pattern_len_count < 4; pattern_len_count++) {
+ data_low[pattern_len_count] = data_low[0];
+ data_high[pattern_len_count] = data_low[0];
+ }
+
+ for (pattern_len_count = 0; pattern_len_count < 4 ; pattern_len_count++) {
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, ODPG_DATA_WR_DATA_LOW_REG,
+ data_low[pattern_len_count], MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, ODPG_DATA_WR_DATA_HIGH_REG,
+ data_high[pattern_len_count], MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, ODPG_DATA_WR_ADDR_REG,
+ pattern_len_count, MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+ }
+
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, ODPG_DATA_BUFFER_OFFS_REG,
+ 0x0, MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+
+ return MV_OK;
+}
+
+/* enable or disable pda */
+int mv_ddr4_pda_ctrl(u8 dev_num, u8 if_id, u8 cs_num, int enable)
+{
+ /*
+ * if enable is 0, exit
+ * mrs to be directed to all dram devices
+ * a calling function responsible to change odpg to 0x0
+ */
+
+ int status;
+ enum hws_access_type access_type = ACCESS_TYPE_UNICAST;
+ u32 val, mask;
+
+ /* per dram addressability enable */
+ val = ((enable == 1) ? 1 : 0);
+ val <<= 4;
+ mask = 0x1 << 4;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, DDR4_MR3_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ /* write DDR4 MR3 cs configuration; only cs0, cs1 supported */
+ if (cs_num == 0)
+ val = 0xe;
+ else
+ val = 0xd;
+ val <<= 8;
+ /* write DDR4 MR3 command */
+ val |= 0x9;
+ mask = (0xf << 8) | 0x1f;
+ status = ddr3_tip_if_write(dev_num, access_type, if_id, SDRAM_OP_REG, val, mask);
+ if (status != MV_OK)
+ return status;
+
+ if (enable == 0) {
+ /* check odpg access is done */
+ if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK)
+ return MV_FAIL;
+ }
+
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, SDRAM_OP_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_pda_ctrl: Polling command failed\n"));
+
+ return MV_OK;
+}
+#endif /* CONFIG_DDR4 */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_mpr_pda_if.h b/drivers/ddr/marvell/a38x/mv_ddr4_mpr_pda_if.h
new file mode 100644
index 0000000..347a1b2
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_mpr_pda_if.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR4_MPR_PDA_IF_H
+#define _MV_DDR4_MPR_PDA_IF_H
+
+#include "ddr3_init.h"
+#include "mv_ddr_common.h"
+
+#define MV_DDR4_VREF_STEP_SIZE 3
+#define MV_DDR4_VREF_MIN_RANGE 1
+#define MV_DDR4_VREF_MAX_RANGE 73
+#define MV_DDR4_VREF_MAX_COUNT (((MV_DDR4_VREF_MAX_RANGE - MV_DDR4_VREF_MIN_RANGE) / MV_DDR4_VREF_STEP_SIZE) + 2)
+
+#define MV_DDR4_MPR_READ_PATTERN_NUM 3
+
+enum mv_ddr4_mpr_read_format {
+ MV_DDR4_MPR_READ_SERIAL,
+ MV_DDR4_MPR_READ_PARALLEL,
+ MV_DDR4_MPR_READ_STAGGERED,
+ MV_DDR4_MPR_READ_RSVD_TEMP
+};
+
+enum mv_ddr4_mpr_read_type {
+ MV_DDR4_MPR_READ_RAW,
+ MV_DDR4_MPR_READ_DECODED
+};
+
+enum mv_ddr4_vref_tap_state {
+ MV_DDR4_VREF_TAP_START,
+ MV_DDR4_VREF_TAP_BUSY,
+ MV_DDR4_VREF_TAP_FLIP,
+ MV_DDR4_VREF_TAP_END
+};
+
+int mv_ddr4_mode_regs_init(u8 dev_num);
+int mv_ddr4_mpr_read(u8 dev_num, u32 mpr_num, u32 page_num,
+ enum mv_ddr4_mpr_read_format read_format,
+ enum mv_ddr4_mpr_read_type read_type,
+ u32 *data);
+int mv_ddr4_mpr_write(u8 dev_num, u32 mpr_location, u32 mpr_num,
+ u32 page_num, u32 data);
+int mv_ddr4_dq_pins_mapping(u8 dev_num);
+int mv_ddr4_vref_training_mode_ctrl(u8 dev_num, u8 if_id,
+ enum hws_access_type access_type,
+ int enable);
+int mv_ddr4_vref_tap_set(u8 dev_num, u8 if_id,
+ enum hws_access_type access_type,
+ u32 taps_num,
+ enum mv_ddr4_vref_tap_state state);
+int mv_ddr4_vref_set(u8 dev_num, u8 if_id, enum hws_access_type access_type,
+ u32 range, u32 vdq_tv, u8 vdq_training_ena);
+int mv_ddr4_pda_pattern_odpg_load(u32 dev_num, enum hws_access_type access_type,
+ u32 if_id, u32 subphy_mask, u32 cs_num);
+int mv_ddr4_pda_ctrl(u8 dev_num, u8 if_id, u8 cs_num, int enable);
+
+#endif /* _MV_DDR4_MPR_PDA_IF_H */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training.c b/drivers/ddr/marvell/a38x/mv_ddr4_training.c
new file mode 100644
index 0000000..cefc2e8
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_training.c
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#if defined(CONFIG_DDR4)
+
+/* DDR4 training service API and data structures */
+
+#include "ddr3_init.h"
+#include "mv_ddr4_training.h"
+#include "mv_ddr4_mpr_pda_if.h"
+#include "mv_ddr4_training_leveling.h"
+#include "mv_ddr4_training_calibration.h"
+#include "mv_ddr_regs.h"
+
+/* 1 for wa and sstl and pod to get the same vref value */
+u8 vref_calibration_wa = 1;
+
+static int a39x_z1_config(u32 dev_num);
+
+/* vref values for vcommon */
+static u16 vref_val[] = {
+ 746,
+ 654,
+ 671,
+ 686,
+ 701,
+ 713,
+ 725,
+ 736
+};
+
+static u32 mv_ddr4_config_phy_vref_tap;
+
+/* configure DDR4 SDRAM */
+int mv_ddr4_sdram_config(u32 dev_num)
+{
+ /* TODO: zq params to be frequency dependent */
+ u32 zq_init = 1023;
+ u32 zq_oper = 511;
+ u32 zq_cs = 127;
+ u32 if_id;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ int status;
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+
+ /* dtype: 0x3 for DDR4, 0x1 for DDR3 */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, SDRAM_CFG_REG,
+ (0x1 << 14) | (0x1 << 20), (0x1 << 14) | (0x1 << 20));
+ if (status != MV_OK)
+ return status;
+
+ /* cpm */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DRAM_PINS_MUX_REG,
+ 0x2, 0x3);
+ if (status != MV_OK)
+ return status;
+
+ /*
+ * set t_dllk to 1024 to the maximum of minimum for high speed bin
+ * TODO: may change for future speed bins
+ */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DRAM_DLL_TIMING_REG,
+ 0x400, 0xfff);
+ if (status != MV_OK)
+ return status;
+
+ /* set zq_init */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DRAM_ZQ_INIT_TIMIMG_REG,
+ zq_init, 0xfff);
+ if (status != MV_OK)
+ return status;
+
+ /* set zq_oper */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DRAM_ZQ_TIMING_REG,
+ zq_oper, 0x7ff);
+ if (status != MV_OK)
+ return status;
+
+ /* set zq_cs */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DRAM_ZQ_TIMING_REG,
+ zq_cs << 16, 0x3ff0000);
+ if (status != MV_OK)
+ return status;
+
+ /*
+ * set registered dimm to unbuffered dimm
+ * TODO: support registered dimm
+ */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, SDRAM_CFG_REG,
+ 0x0, 0x1 << 17);
+ if (status != MV_OK)
+ return status;
+ }
+
+ a39x_z1_config(dev_num);
+
+ return MV_OK;
+}
+
+u16 mv_ddr4_rtt_nom_to_odt(u16 rtt_nom)
+{
+ u8 odt;
+
+ if (rtt_nom == 0)
+ odt = 0xff;
+ else if (rtt_nom == (1 << 8))
+ odt = 60; /* 240 / 4 */
+ else if (rtt_nom == (2 << 8))
+ odt = 120; /* 240 / 2 */
+ else if (rtt_nom == (3 << 8))
+ odt = 40; /* 240 / 6 */
+ else if (rtt_nom == (4 << 8))
+ odt = 240; /* 240 / 1 */
+ else if (rtt_nom == (5 << 8))
+ odt = 48; /* 240 / 5 */
+ else if (rtt_nom == (6 << 8))
+ odt = 80; /* 240 / 3 */
+ else if (rtt_nom == (7 << 8))
+ odt = 34; /* 240 / 7 */
+ else
+ odt = 1;
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("mv_ddr4_rtt_nom_to_odt: rtt_nom = %d, odt = %d\n", rtt_nom, odt));
+
+ return odt;
+}
+
+u16 mv_ddr4_rtt_wr_to_odt(u16 rtt_wr)
+{
+ u8 odt;
+
+ if (rtt_wr == 0)
+ odt = 0xff;
+ else if (rtt_wr == (1 << 9))
+ odt = 120; /* 240 / 2 */
+ else if (rtt_wr == (2 << 9))
+ odt = 240; /* 240 / 1 */
+ else
+ odt = 1;
+
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("mv_ddr4_rtt_wr_to_odt rtt_wr = %d, odt = %d\n", rtt_wr, odt));
+
+ return odt;
+}
+
+static u32 mv_ddr4_rx_odt_get(void)
+{
+ u16 odt = odt_intercept[(int)g_zpodt_data / 8] - (g_zpodt_data * odt_slope[(int)g_zpodt_data / 8]) / 100;
+ u16 rtt;
+
+ if (g_odt_config & 0xf) {
+ rtt = mv_ddr4_rtt_nom_to_odt(g_rtt_nom);
+ odt = (odt * rtt) / (odt + rtt);
+ }
+
+ return odt;
+}
+
+static u8 mv_ddr4_vcommon_to_vref(u16 vcommon)
+{
+ u8 vref_tap;
+
+ if ((vcommon > 600) && (vcommon <= 662)) {
+ vref_tap = 1;
+ } else if ((vcommon > 662) && (vcommon <= 679)) {
+ vref_tap = 2;
+ } else if ((vcommon > 679) && (vcommon <= 693)) {
+ vref_tap = 3;
+ } else if ((vcommon > 693) && (vcommon <= 707)) {
+ vref_tap = 4;
+ } else if ((vcommon > 707) && (vcommon <= 719)) {
+ vref_tap = 5;
+ } else if ((vcommon > 719) && (vcommon <= 725)) {
+ vref_tap = 6;
+ } else if ((vcommon > 725) && (vcommon <= 731)) {
+ vref_tap = 7;
+ } else if ((vcommon > 731) && (vcommon <= 800)) {
+ vref_tap = 0;
+ } else if (vcommon > 800) {
+ vref_tap = 0;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_vcommon_to_vref: warning: vcommon value too high: %d\n", vcommon));
+ } else if (vcommon < 600) {
+ vref_tap = 1;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_vcommon_to_vref: warning: vcommon value too low: %d\n", vcommon));
+ } else {
+ vref_tap = 1;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_vcommon_to_vref: warning: vcommon out of range: %d\n", vcommon));
+ }
+
+ return vref_tap;
+}
+
+/* configure phy */
+int mv_ddr4_phy_config(u32 dev_num)
+{
+ u8 cs, i, pod_val;
+ u32 upper_pcal, left_pcal, upper_ncal;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ /* design GL params to be set outside */
+ u32 ron = 34; /* dic - rzq / 6 or rzq / 7 */
+ u32 rodt = mv_ddr4_rx_odt_get(); /* effective odt per DGL */
+ u32 vcommon = (1000 * (ron + rodt / 2)) / (ron + rodt);
+ u32 vref_idx;
+ u8 rc_tap;
+ u8 subphy_max = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+ int status;
+
+ mv_ddr4_config_phy_vref_tap = mv_ddr4_vcommon_to_vref(vcommon);
+
+ /* change calculation for 1GHz frequency */
+ if (tm->interface_params[0].memory_freq == MV_DDR_FREQ_1000)
+ mv_ddr4_config_phy_vref_tap += 2;
+
+ vref_idx = (mv_ddr4_config_phy_vref_tap < 8) ? mv_ddr4_config_phy_vref_tap : 0;
+ rc_tap = (430 * (vref_val[vref_idx] - vcommon)) / 1000 + 33;
+ /* 0x1 for pod mode */
+ pod_val = (vref_calibration_wa == 1) ? 0x0 : 0x1;
+ upper_pcal = pod_val;
+ left_pcal = pod_val;
+ upper_ncal = 0;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, TEST_ADLL_PHY_REG, pod_val);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, GP_RSVD0_REG,
+ (upper_pcal << 12) | (left_pcal << 6) | (upper_ncal << 5), 0x1060);
+ if (status != MV_OK)
+ return status;
+
+ /*
+ * phy register 0xbf, bit 0 - configure to pod mode (0x1)
+ * phy register 0xa8, bits [6:4] - configure to clamp (0x0)
+ * subphys (broadcast) register 0xa8, bits [2:0] - configure to int ref m (0x4),
+ * TODO: need to write it to control subphys too
+ * vref tap - configure to SSTL calibration only (4)
+ * enhanced vref value - set to no clamp (0)
+ */
+ for (i = 0; i < subphy_max; i++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, i);
+ ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, 0, i, DDR_PHY_DATA, PAD_CFG_PHY_REG,
+ (0 << 4) | 4, ((0x7 << 4) | 0x7));
+ }
+
+ for (i = 0; i < 3; i++)
+ ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, 0, i, DDR_PHY_CONTROL, PAD_CFG_PHY_REG,
+ (0 << 4) | 4 , ((0x7 << 4) | 0x7));
+
+ /* phy register 0xa4, bits [13:7] - configure to 0x7c zpri /znri */
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, PAD_ZRI_CAL_PHY_REG,
+ ((0x7f & g_zpri_data) << 7) | (0x7f & g_znri_data));
+ if (status != MV_OK)
+ return status;
+
+ /*
+ * phy register 0xa6, bits [5:0] - configure to znodt (0x0)
+ * phy register 0xa6 bits [11:6] - configure to zpodt (60Ohm, 0x1d)
+ */
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, PAD_ODT_CAL_PHY_REG, g_zpodt_data << 6);
+ if (status != MV_OK)
+ return status;
+
+ /* update for all active cs */
+ for (cs = 0; cs < MAX_CS_NUM; cs++) {
+ /*
+ * writes to present cs only
+ * phy register 0xdb, bits [5:0] - configure to rcvr cal for 50% duty cycle,
+ * broadcast to all bits cs0 (0x26)
+ */
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, VREF_BCAST_PHY_REG(cs), rc_tap);
+ if (status != MV_OK)
+ return status;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * configure sstl for manual calibration and pod for automatic one
+ * assumes subphy configured to pod ealier
+ */
+int mv_ddr4_calibration_adjust(u32 dev_num, u8 vref_en, u8 pod_only)
+{
+ u8 i, if_id = 0;
+ u32 read_data[MAX_INTERFACE_NUM];
+ u32 ncal = 0, pcal = 0;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ int status = MV_OK;
+ u8 subphy_max = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+ u8 vref_tap = mv_ddr4_config_phy_vref_tap;
+ u32 vref_idx = (vref_tap < 8) ? vref_tap : 0;
+
+ if (vref_calibration_wa == 0)
+ return mv_ddr4_calibration_validate(dev_num);
+
+ if (vref_en == 1) {
+ /* enhanced vref value set to no clamp (0) */
+ for (i = 0; i < subphy_max; i++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, i);
+ ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, 0, i, DDR_PHY_DATA,
+ PAD_CFG_PHY_REG, (0 << 4) | vref_idx, ((0x7 << 4) | 0x7));
+ }
+
+ for (i = 0; i < 3; i++)
+ ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, 0, i, DDR_PHY_CONTROL,
+ PAD_CFG_PHY_REG, (0 << 4) | vref_idx, ((0x7 << 4) | 0x7));
+ }
+
+ /* pad calibration control - enable */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG,
+ (calibration_update_control << 3) | 0x1, (0x3 << 3) | 0x1);
+ if (status != MV_OK)
+ return status;
+
+ /* calibration update external */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ MAIN_PADS_CAL_MACH_CTRL_REG, 0x2 << 3, 0x3 << 3);
+ if (status != MV_OK)
+ return status;
+
+ /* poll init calibration done */
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x80000000, 0x80000000,
+ MAIN_PADS_CAL_MACH_CTRL_REG, MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: calibration polling failed (0)\n"));
+
+ /* poll calibration propogated to io */
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x3ffffff, 0x3ffffff, 0x1674,
+ MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: calibration polling failed (1)\n"));
+
+ mdelay(10); /* TODO: check it */
+
+ /* disable dynamic */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, MAIN_PADS_CAL_MACH_CTRL_REG, 0, 0x1);
+ if (status != MV_OK)
+ return status;
+
+ /* poll initial calibration done*/
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x80000000, 0x80000000,
+ MAIN_PADS_CAL_MACH_CTRL_REG, MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: calibration polling failed (2)\n"));
+
+ /* poll calibration propogated to io */
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x3ffffff, 0x3ffffff, 0x1674,
+ MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: calibration polling failed (3)\n"));
+
+ mdelay(10); /* TODO: check why polling insufficient */
+
+ /* read calibration value and set it manually */
+ status = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1dc8, read_data, MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+
+ ncal = (read_data[if_id] & (0x3f << 10)) >> 10;
+ pcal = (read_data[if_id] & (0x3f << 4)) >> 4;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("mv_ddr4_calibration_adjust: sstl pcal = 0x%x, ncal = 0x%x\n",
+ pcal, ncal));
+ if ((ncal >= 56) || (ncal <= 6) || (pcal >= 59) || (pcal <= 7)) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: error: sstl pcal = 0x%x, ncal = 0x%x out of range\n",
+ pcal, ncal));
+ status = MV_FAIL;
+ }
+
+ if (pod_only == 0) {
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1dc8, 0x1 << 3, 0x1 << 3);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1dc8,
+ (ncal << 22) | (pcal << 16), (0x3f << 22) | (0x3f << 16));
+ if (status != MV_OK)
+ return status;
+
+ /* configure to pod mode (0x1) */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ GP_RSVD0_REG,
+ (0x1 << 12) | (0x1 << 6) | (0x1 << 5), 0x1060);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, TEST_ADLL_PHY_REG, 0x1);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_CONTROL, TEST_ADLL_PHY_REG, 0x1);
+ if (status != MV_OK)
+ return status;
+
+ /* pad calibration control - enable */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG,
+ 0x1, 0x1);
+ if (status != MV_OK)
+ return status;
+
+ /* poll initial calibration done*/
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x80000000, 0x80000000,
+ MAIN_PADS_CAL_MACH_CTRL_REG, MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: calibration polling failed (4)\n"));
+ }
+
+ /* calibration update internal */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, MAIN_PADS_CAL_MACH_CTRL_REG,
+ calibration_update_control << 3, 0x3 << 3);
+ if (status != MV_OK)
+ return status;
+
+ /* vertical */
+ status = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x14c8, read_data, MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+ ncal = (read_data[if_id] & (0x3f << 10)) >> 10;
+ pcal = (read_data[if_id] & (0x3f << 4)) >> 4;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("mv_ddr4_calibration_adjust: pod-v pcal = 0x%x, ncal = 0x%x\n",
+ pcal, ncal));
+ if ((ncal >= 56) || (ncal <= 6) || (pcal >= 59) || (pcal <= 7)) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: error: pod-v pcal = 0x%x, ncal = 0x%x out of range\n",
+ pcal, ncal));
+ status = MV_FAIL;
+ }
+
+ /* horizontal */
+ status = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x17c8, read_data, MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+ ncal = (read_data[if_id] & (0x3f << 10)) >> 10;
+ pcal = (read_data[if_id] & (0x3F << 4)) >> 4;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("mv_ddr4_calibration_adjust: pod-h pcal = 0x%x, ncal = 0x%x\n",
+ pcal, ncal));
+ if ((ncal >= 56) || (ncal <= 6) || (pcal >= 59) || (pcal <= 7)) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("mv_ddr4_calibration_adjust: error: pod-h pcal = 0x%x, ncal = 0x%x out of range\n",
+ pcal, ncal));
+ status = MV_FAIL;
+ }
+ /* pad calibration control - disable */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG,
+ (calibration_update_control << 3) | 0x0, (0x3 << 3) | 0x1);
+ if (status != MV_OK)
+ return status;
+
+ return status;
+}
+
+static int a39x_z1_config(u32 dev_num)
+{
+ u32 if_id;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ int status;
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /*
+ * xbar split bypass - dlb is off,
+ * when enabled, set to 0x1
+ */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1424, 0x0 << 3, 0x1 << 3);
+ if (status != MV_OK)
+ return status;
+
+ /* auto power save option */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1474, 0x0, 0xffffffff);
+ if (status != MV_OK)
+ return status;
+ }
+
+ return MV_OK;
+}
+
+int mv_ddr4_training_main_flow(u32 dev_num)
+{
+ int status = MV_OK;
+ u16 pbs_tap_factor[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS] = {0};
+
+ if (mask_tune_func & RECEIVER_CALIBRATION_MASK_BIT) {
+ training_stage = RECEIVER_CALIBRATION;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("RECEIVER_CALIBRATION_MASK_BIT #%d\n", effective_cs));
+ status = mv_ddr4_receiver_calibration(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (status != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_receiver_calibrate failure\n"));
+ if (debug_mode == 0)
+ return status;
+ }
+ }
+
+ if (mask_tune_func & WL_PHASE_CORRECTION_MASK_BIT) {
+ training_stage = WL_PHASE_CORRECTION;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("WL_PHASE_CORRECTION_MASK_BIT #%d\n", effective_cs));
+ status = mv_ddr4_dynamic_wl_supp(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (status != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_dynamic_wl_supp failure\n"));
+ if (debug_mode == 0)
+ return status;
+ }
+ }
+
+ if (mask_tune_func & DQ_VREF_CALIBRATION_MASK_BIT) {
+ training_stage = DQ_VREF_CALIBRATION;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("DQ_VREF_CALIBRATION_MASK_BIT #%d\n", effective_cs));
+ status = mv_ddr4_dq_vref_calibration(dev_num, pbs_tap_factor);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (status != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_dq_vref_calibrate failure\n"));
+ if (debug_mode == 0)
+ return status;
+ }
+ }
+
+ if (mask_tune_func & DM_TUNING_MASK_BIT) {
+ training_stage = DM_TUNING;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("DM_TUNING_MASK_BIT #%d\n", effective_cs));
+ status = mv_ddr4_dm_tuning(effective_cs, pbs_tap_factor);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (status != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_dm_tuning failure\n"));
+ if (debug_mode == 0)
+ return status;
+ }
+ }
+
+ if (mask_tune_func & DQ_MAPPING_MASK_BIT) {
+ training_stage = DQ_MAPPING;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("DQ_MAPPING_MASK_BIT\n"));
+ status = mv_ddr4_dq_pins_mapping(dev_num);
+ if (is_reg_dump != 0)
+ ddr3_tip_reg_dump(dev_num);
+ if (status != MV_OK) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("mv_ddr4_dq_pins_mapping failure\n"));
+ if (debug_mode == 0)
+ return status;
+ }
+ }
+
+ return status;
+}
+#endif /* CONFIG_DDR4 */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training.h b/drivers/ddr/marvell/a38x/mv_ddr4_training.h
new file mode 100644
index 0000000..fa2e9a0
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_training.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR4_TRAINING_H
+#define _MV_DDR4_TRAINING_H
+
+#include "ddr3_training_ip.h"
+
+/* configure DDR4 SDRAM */
+int mv_ddr4_sdram_config(u32 dev_num);
+
+/* configure phy */
+int mv_ddr4_phy_config(u32 dev_num);
+
+/*
+ * configure sstl for manual calibration and pod for automatic one
+ * assumes subphy configured to pod ealier
+ */
+int mv_ddr4_calibration_adjust(u32 dev_num, u8 vref_en, u8 pod_only);
+
+/*
+ * validates calibration values
+ * soc dependent; TODO: check it
+ */
+int mv_ddr4_calibration_validate(u32 dev_num);
+
+u16 mv_ddr4_rtt_nom_to_odt(u16 rtt_nom);
+u16 mv_ddr4_rtt_wr_to_odt(u16 rtt_wr);
+
+#endif /* _MV_DDR4_TRAINING_H */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.c b/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.c
new file mode 100644
index 0000000..31b6209
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.c
@@ -0,0 +1,2336 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#if defined(CONFIG_DDR4)
+
+/* DESCRIPTION: DDR4 Receiver and DQVref Calibration */
+
+#include "ddr3_init.h"
+#include "mv_ddr4_training_calibration.h"
+#include "mv_ddr4_training.h"
+#include "mv_ddr4_mpr_pda_if.h"
+#include "mv_ddr_training_db.h"
+#include "mv_ddr_regs.h"
+
+#define RX_DIR 0
+#define TX_DIR 1
+#define MAX_DIR_TYPES 2
+
+#define RECEIVER_DC_STEP_SIZE 3
+#define RECEIVER_DC_MIN_RANGE 0
+#define RECEIVER_DC_MAX_RANGE 63
+#define RECEIVER_DC_MAX_COUNT (((RECEIVER_DC_MAX_RANGE - RECEIVER_DC_MIN_RANGE) / RECEIVER_DC_STEP_SIZE) + 1)
+
+#define PBS_VAL_FACTOR 1000
+#define MV_DDR_VW_TX_NOISE_FILTER 8 /* adlls */
+
+u8 dq_vref_vec[MAX_BUS_NUM]; /* stability support */
+u8 rx_eye_hi_lvl[MAX_BUS_NUM]; /* rx adjust support */
+u8 rx_eye_lo_lvl[MAX_BUS_NUM]; /* rx adjust support */
+
+static u8 pbs_max = 31;
+static u8 vdq_tv; /* vref value for dq vref calibration */
+static u8 duty_cycle; /* duty cycle value for receiver calibration */
+static u8 rx_vw_pos[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+static u8 patterns_byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+static const char *str_dir[MAX_DIR_TYPES] = {"read", "write"};
+
+static u8 center_low_element_get(u8 dir, u8 pbs_element, u16 lambda, u8 pbs_max_val)
+{
+ u8 result;
+
+ if (dir == RX_DIR)
+ result = pbs_element * lambda / PBS_VAL_FACTOR;
+ else
+ result = (pbs_max_val - pbs_element) * lambda / PBS_VAL_FACTOR;
+
+ return result;
+}
+
+static u8 center_high_element_get(u8 dir, u8 pbs_element, u16 lambda, u8 pbs_max_val)
+{
+ u8 result;
+
+ if (dir == RX_DIR)
+ result = (pbs_max_val - pbs_element) * lambda / PBS_VAL_FACTOR;
+ else
+ result = pbs_element * lambda / PBS_VAL_FACTOR;
+
+ return result;
+}
+
+static int mv_ddr4_centralization(u8 dev_num, u16 (*lambda)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 (*copt)[MAX_BUS_NUM],
+ u8 (*pbs_result)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 (*vw_size)[MAX_BUS_NUM],
+ u8 mode, u16 param0, u8 param1);
+static int mv_ddr4_dqs_reposition(u8 dir, u16 *lambda, u8 *pbs_result, char delta, u8 *copt, u8 *dqs_pbs);
+static int mv_ddr4_copt_get(u8 dir, u16 *lambda, u8 *vw_l, u8 *vw_h, u8 *pbs_result, u8 *copt);
+static int mv_ddr4_center_of_mass_calc(u8 dev_num, u8 if_id, u8 subphy_num, u8 mode, u8 *vw_l, u8 *vw_h, u8 *vw_v,
+ u8 vw_num, u8 *v_opt, u8 *t_opt);
+static int mv_ddr4_tap_tuning(u8 dev_num, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 mode);
+
+/* dq vref calibration flow */
+int mv_ddr4_dq_vref_calibration(u8 dev_num, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS])
+{
+ u32 if_id, subphy_num;
+ u32 vref_idx, dq_idx, pad_num = 0;
+ u8 dq_vref_start_win[MAX_INTERFACE_NUM][MAX_BUS_NUM][MV_DDR4_VREF_MAX_COUNT];
+ u8 dq_vref_end_win[MAX_INTERFACE_NUM][MAX_BUS_NUM][MV_DDR4_VREF_MAX_COUNT];
+ u8 valid_win_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 c_opt_per_bus[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 valid_vref_cnt[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 valid_vref_ptr[MAX_INTERFACE_NUM][MAX_BUS_NUM][MV_DDR4_VREF_MAX_COUNT];
+ u8 center_adll[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 center_vref[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 pbs_res_per_bus[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ u16 vref_avg, vref_subphy_num;
+ int vref_tap_idx;
+ int vref_range_min;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum mv_ddr4_vref_subphy_cal_state all_subphys_state = MV_DDR4_VREF_SUBPHY_CAL_ABOVE;
+ int tap_tune_passed = 0;
+ enum mv_ddr4_vref_tap_state vref_tap_set_state = MV_DDR4_VREF_TAP_START;
+ enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
+ u8 subphy_max = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+ enum mv_ddr4_vref_subphy_cal_state vref_state_per_subphy[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ int status;
+ static u8 vref_byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM][MV_DDR4_VREF_MAX_RANGE];
+
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO, ("Starting ddr4 dq vref calibration training stage\n"));
+
+ vdq_tv = 0;
+ duty_cycle = 0;
+
+ /* reset valid vref counter per if and subphy */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ for (subphy_num = 0; subphy_num < MAX_BUS_NUM; subphy_num++) {
+ valid_vref_cnt[if_id][subphy_num] = 0;
+ vref_state_per_subphy[if_id][subphy_num] = MV_DDR4_VREF_SUBPHY_CAL_ABOVE;
+ }
+ }
+
+ if (mv_ddr4_tap_tuning(dev_num, pbs_tap_factor, TX_DIR) == MV_OK)
+ tap_tune_passed = 1;
+
+ /* place dram to vref training mode */
+ mv_ddr4_vref_training_mode_ctrl(dev_num, 0, ACCESS_TYPE_MULTICAST, 1);
+
+ /* main loop for 2d scan (low_to_high voltage scan) */
+ vref_tap_idx = MV_DDR4_VREF_MAX_RANGE;
+ vref_range_min = MV_DDR4_VREF_MIN_RANGE;
+
+ if (vref_range_min < MV_DDR4_VREF_STEP_SIZE)
+ vref_range_min = MV_DDR4_VREF_STEP_SIZE;
+
+ /* clean vref status array */
+ memset(vref_byte_status, BYTE_NOT_DEFINED, sizeof(vref_byte_status));
+
+ for (vref_tap_idx = MV_DDR4_VREF_MAX_RANGE; (vref_tap_idx >= vref_range_min) &&
+ (all_subphys_state != MV_DDR4_VREF_SUBPHY_CAL_UNDER);
+ vref_tap_idx -= MV_DDR4_VREF_STEP_SIZE) {
+ /* set new vref training value in dram */
+ mv_ddr4_vref_tap_set(dev_num, 0, ACCESS_TYPE_MULTICAST, vref_tap_idx, vref_tap_set_state);
+
+ if (tap_tune_passed == 0) {
+ if (mv_ddr4_tap_tuning(dev_num, pbs_tap_factor, TX_DIR) == MV_OK)
+ tap_tune_passed = 1;
+ else
+ continue;
+ }
+
+ if (mv_ddr4_centralization(dev_num, pbs_tap_factor, c_opt_per_bus, pbs_res_per_bus,
+ valid_win_size, TX_DIR, vref_tap_idx, 0) != MV_OK) {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_ERROR,
+ ("error: %s: ddr4 centralization failed (dq vref tap index %d)!!!\n",
+ __func__, vref_tap_idx));
+ continue;
+ }
+
+ /* go over all results and find out the vref start and end window */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ if (valid_win_size[if_id][subphy_num] > MV_DDR_VW_TX_NOISE_FILTER) {
+ if (vref_state_per_subphy[if_id][subphy_num] == MV_DDR4_VREF_SUBPHY_CAL_UNDER)
+ DEBUG_CALIBRATION(DEBUG_LEVEL_ERROR,
+ ("warning: %s: subphy %d vref tap %d voltage noise\n",
+ __func__, subphy_num, vref_tap_idx));
+ /* window is valid; keep current vref_tap_idx value and increment counter */
+ vref_idx = valid_vref_cnt[if_id][subphy_num];
+ valid_vref_ptr[if_id][subphy_num][vref_idx] = vref_tap_idx;
+ valid_vref_cnt[if_id][subphy_num]++;
+
+ /* set 0 for possible negative values */
+ vref_byte_status[if_id][subphy_num][vref_idx] |=
+ patterns_byte_status[if_id][subphy_num];
+ dq_vref_start_win[if_id][subphy_num][vref_idx] =
+ c_opt_per_bus[if_id][subphy_num] + 1 -
+ valid_win_size[if_id][subphy_num] / 2;
+ dq_vref_start_win[if_id][subphy_num][vref_idx] =
+ (valid_win_size[if_id][subphy_num] % 2 == 0) ?
+ dq_vref_start_win[if_id][subphy_num][vref_idx] :
+ dq_vref_start_win[if_id][subphy_num][vref_idx] - 1;
+ dq_vref_end_win[if_id][subphy_num][vref_idx] =
+ c_opt_per_bus[if_id][subphy_num] +
+ valid_win_size[if_id][subphy_num] / 2;
+ vref_state_per_subphy[if_id][subphy_num] = MV_DDR4_VREF_SUBPHY_CAL_INSIDE;
+ } else if (vref_state_per_subphy[if_id][subphy_num] == MV_DDR4_VREF_SUBPHY_CAL_INSIDE) {
+ vref_state_per_subphy[if_id][subphy_num] = MV_DDR4_VREF_SUBPHY_CAL_UNDER;
+ }
+ } /* subphy */
+ } /* if */
+
+ /* check all subphys are in under state */
+ all_subphys_state = MV_DDR4_VREF_SUBPHY_CAL_UNDER;
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ if (vref_state_per_subphy[if_id][subphy_num] != MV_DDR4_VREF_SUBPHY_CAL_UNDER)
+ all_subphys_state = MV_DDR4_VREF_SUBPHY_CAL_INSIDE;
+ }
+ }
+ }
+
+ if (tap_tune_passed == 0) {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("%s: tap tune not passed on any dq_vref value\n", __func__));
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* report fail for all active interfaces; multi-interface support - tbd */
+ flow_result[if_id] = TEST_FAILED;
+ }
+
+ return MV_FAIL;
+ }
+
+ /* close vref range */
+ mv_ddr4_vref_tap_set(dev_num, 0, ACCESS_TYPE_MULTICAST, vref_tap_idx, MV_DDR4_VREF_TAP_END);
+
+ /*
+ * find out the results with the mixed and low states and move the low state 64 adlls in case
+ * the center of the ui is smaller than 31
+ */
+ for (vref_idx = 0; vref_idx < MV_DDR4_VREF_MAX_RANGE; vref_idx++) {
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ if (((vref_byte_status[if_id][subphy_num][vref_idx]) &
+ (BYTE_HOMOGENEOUS_LOW | BYTE_SPLIT_OUT_MIX)) ==
+ (BYTE_HOMOGENEOUS_LOW | BYTE_SPLIT_OUT_MIX)) {
+ if ((dq_vref_start_win[if_id][subphy_num][vref_idx] +
+ dq_vref_end_win[if_id][subphy_num][vref_idx]) / 2 <= 31) {
+ dq_vref_start_win[if_id][subphy_num][vref_idx] += 64;
+ dq_vref_end_win[if_id][subphy_num][vref_idx] += 64;
+ DEBUG_CALIBRATION
+ (DEBUG_LEVEL_TRACE,
+ ("%s vref_idx %d if %d subphy %d added 64 adlls to window\n",
+ __func__, valid_vref_ptr[if_id][subphy_num][vref_idx],
+ if_id, subphy_num));
+ }
+ }
+ }
+ }
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("calculating center of mass for subphy %d, valid window size %d\n",
+ subphy_num, valid_win_size[if_id][subphy_num]));
+ if (valid_vref_cnt[if_id][subphy_num] > 0) {
+ /* calculate center of mass sampling point (t, v) for each subphy */
+ status = mv_ddr4_center_of_mass_calc(dev_num, if_id, subphy_num, TX_DIR,
+ dq_vref_start_win[if_id][subphy_num],
+ dq_vref_end_win[if_id][subphy_num],
+ valid_vref_ptr[if_id][subphy_num],
+ valid_vref_cnt[if_id][subphy_num],
+ ¢er_vref[if_id][subphy_num],
+ ¢er_adll[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("center of mass results: vref %d, adll %d\n",
+ center_vref[if_id][subphy_num], center_adll[if_id][subphy_num]));
+ } else {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_ERROR,
+ ("%s subphy %d no vref results to calculate the center of mass\n",
+ __func__, subphy_num));
+ status = MV_ERROR;
+ return status;
+ }
+ }
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ vref_avg = 0;
+ vref_subphy_num = 0;
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ vref_avg += center_vref[if_id][subphy_num];
+ dq_vref_vec[subphy_num] = center_vref[if_id][subphy_num];
+ vref_subphy_num++;
+ }
+
+ mv_ddr4_vref_tap_set(dev_num, if_id, ACCESS_TYPE_UNICAST,
+ vref_avg / vref_subphy_num, MV_DDR4_VREF_TAP_START);
+ mv_ddr4_vref_tap_set(dev_num, if_id, ACCESS_TYPE_UNICAST,
+ vref_avg / vref_subphy_num, MV_DDR4_VREF_TAP_END);
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO, ("final vref average %d\n", vref_avg / vref_subphy_num));
+ /* run centralization again with optimal vref to update global structures */
+ mv_ddr4_centralization(dev_num, pbs_tap_factor, c_opt_per_bus, pbs_res_per_bus, valid_win_size,
+ TX_DIR, vref_avg / vref_subphy_num, duty_cycle);
+ }
+
+ /* return dram from vref DRAM from vref training mode */
+ mv_ddr4_vref_training_mode_ctrl(dev_num, 0, ACCESS_TYPE_MULTICAST, 0);
+
+ /* dqs tx reposition calculation */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ pad_num = dq_map_table[dq_idx +
+ subphy_num * BUS_WIDTH_IN_BITS +
+ if_id * BUS_WIDTH_IN_BITS * subphy_max];
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ 0x10 + pad_num + effective_cs * 0x10,
+ pbs_res_per_bus[if_id][subphy_num][dq_idx]);
+ if (status != MV_OK)
+ return status;
+ }
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ CTX_PHY_REG(effective_cs),
+ center_adll[if_id][subphy_num] % 64);
+ if (status != MV_OK)
+ return status;
+ }
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* report pass for all active interfaces; multi-interface support - tbd */
+ flow_result[if_id] = TEST_SUCCESS;
+ }
+
+ return MV_OK;
+}
+
+/* centralization flow */
+static int mv_ddr4_centralization(u8 dev_num, u16 (*lambda)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 (*copt)[MAX_BUS_NUM],
+ u8 (*pbs_result)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 (*vw_size)[MAX_BUS_NUM],
+ u8 mode, u16 param0, u8 param1)
+{
+/* FIXME: remove the dependency in 64bit */
+#define MV_DDR_NUM_OF_CENTRAL_PATTERNS (PATTERN_KILLER_DQ7 - PATTERN_KILLER_DQ0 + 1)
+ static u8 subphy_end_win[MAX_DIR_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ static u8 subphy_start_win[MAX_DIR_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ static u8 final_start_win[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ static u8 final_end_win[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
+ u32 if_id, subphy_num, pattern_id, pattern_loop_idx, bit_num;
+ u8 curr_start_win[BUS_WIDTH_IN_BITS];
+ u8 curr_end_win[BUS_WIDTH_IN_BITS];
+ static u8 start_win_db[MV_DDR_NUM_OF_CENTRAL_PATTERNS][MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ static u8 end_win_db[MV_DDR_NUM_OF_CENTRAL_PATTERNS][MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ u8 curr_win[BUS_WIDTH_IN_BITS];
+ u8 opt_win, waste_win, start_win_skew, end_win_skew;
+ u8 final_subphy_win[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS];
+ enum hws_training_result result_type = RESULT_PER_BIT;
+ enum hws_dir direction;
+ enum hws_search_dir search_dir;
+ u32 *result[HWS_SEARCH_DIR_LIMIT];
+ u32 max_win_size;
+ u8 curr_end_win_min, curr_start_win_max;
+ u32 cs_ena_reg_val[MAX_INTERFACE_NUM];
+ u8 current_byte_status;
+ int status;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u8 subphy_max = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* save current cs enable reg val */
+ status = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG,
+ cs_ena_reg_val, MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+
+ /* enable single cs */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG,
+ (0x1 << 3), (0x1 << 3));
+ if (status != MV_OK)
+ return status;
+ }
+
+ if (mode == TX_DIR) {
+ max_win_size = MAX_WINDOW_SIZE_TX;
+ direction = OPER_WRITE;
+ } else {
+ max_win_size = MAX_WINDOW_SIZE_RX;
+ direction = OPER_READ;
+ }
+
+ /* database initialization */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ patterns_byte_status[if_id][subphy_num] = BYTE_NOT_DEFINED;
+ subphy_end_win[mode][if_id][subphy_num] = (max_win_size - 1);
+ subphy_start_win[mode][if_id][subphy_num] = 0;
+ vw_size[if_id][subphy_num] = (max_win_size - 1);
+ for (bit_num = 0; bit_num < BUS_WIDTH_IN_BITS; bit_num++) {
+ final_start_win[if_id][subphy_num][bit_num] = 0;
+ final_end_win[if_id][subphy_num][bit_num] = (max_win_size - 1);
+ if (mode == TX_DIR)
+ final_end_win[if_id][subphy_num][bit_num] = (2 * max_win_size - 1);
+ }
+ if (mode == TX_DIR) {
+ subphy_end_win[mode][if_id][subphy_num] = (2 * max_win_size - 1);
+ vw_size[if_id][subphy_num] = (2 * max_win_size - 1);
+ }
+ }
+ }
+
+ /* main flow */
+ /* FIXME: hard-coded "22" below for PATTERN_KILLER_DQ7_64 enum hws_pattern */
+ for (pattern_id = PATTERN_KILLER_DQ0, pattern_loop_idx = 0;
+ pattern_id <= (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) ? 22 : PATTERN_KILLER_DQ7);
+ pattern_id++, pattern_loop_idx++) {
+ ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, result_type, HWS_CONTROL_ELEMENT_ADLL,
+ PARAM_NOT_CARE, direction, tm->if_act_mask,
+ 0x0, max_win_size - 1, max_win_size - 1, pattern_id,
+ EDGE_FPF, CS_SINGLE, PARAM_NOT_CARE, training_result);
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ /*
+ * in case the previous patterns found the current subphy as BYTE_NOT_DEFINED,
+ * continue to next subphy
+ */
+ if ((patterns_byte_status[if_id][subphy_num] == BYTE_NOT_DEFINED) &&
+ (pattern_id != PATTERN_KILLER_DQ0))
+ continue;
+ /*
+ * in case the result of the current subphy is BYTE_NOT_DEFINED mark the
+ * pattern byte status as BYTE_NOT_DEFINED
+ */
+ current_byte_status = mv_ddr_tip_sub_phy_byte_status_get(if_id, subphy_num);
+ if (current_byte_status == BYTE_NOT_DEFINED) {
+ DEBUG_DDR4_CENTRALIZATION
+ (DEBUG_LEVEL_INFO,
+ ("%s:%s: failed to lock subphy, pat %d if %d subphy %d\n",
+ __func__, str_dir[mode], pattern_id, if_id, subphy_num));
+ patterns_byte_status[if_id][subphy_num] = BYTE_NOT_DEFINED;
+ /* update the valid window size which is return value from this function */
+ vw_size[if_id][subphy_num] = 0;
+ /* continue to next subphy */
+ continue;
+ }
+
+ /* set the status of this byte */
+ patterns_byte_status[if_id][subphy_num] |= current_byte_status;
+ for (search_dir = HWS_LOW2HIGH; search_dir <= HWS_HIGH2LOW; search_dir++) {
+ status = ddr3_tip_read_training_result(dev_num, if_id, ACCESS_TYPE_UNICAST,
+ subphy_num, ALL_BITS_PER_PUP,
+ search_dir, direction, result_type,
+ TRAINING_LOAD_OPERATION_UNLOAD,
+ CS_SINGLE, &result[search_dir],
+ 1, 0, 0);
+ if (status != MV_OK)
+ return status;
+
+ DEBUG_DDR4_CENTRALIZATION
+ (DEBUG_LEVEL_INFO,
+ ("param0 %d param1 %d pat %d if %d subphy %d "
+ "regs: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ param0, param1, pattern_id, if_id, subphy_num,
+ result[search_dir][0], result[search_dir][1],
+ result[search_dir][2], result[search_dir][3],
+ result[search_dir][4], result[search_dir][5],
+ result[search_dir][6], result[search_dir][7]));
+ }
+
+ for (bit_num = 0; bit_num < BUS_WIDTH_IN_BITS; bit_num++) {
+ /* read result success */
+ DEBUG_DDR4_CENTRALIZATION(
+ DEBUG_LEVEL_INFO,
+ ("%s %s subphy locked, pat %d if %d subphy %d\n",
+ __func__, str_dir[mode], pattern_id,
+ if_id, subphy_num));
+ start_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] =
+ GET_TAP_RESULT(result[HWS_LOW2HIGH][bit_num], EDGE_1);
+ end_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] =
+ GET_TAP_RESULT(result[HWS_HIGH2LOW][bit_num], EDGE_1);
+ }
+ } /* subphy */
+ } /* interface */
+ } /* pattern */
+
+ /*
+ * check if the current patterns subphys in all interfaces has mixed and low byte states
+ * in that case add 64 adlls to the low byte
+ */
+ for (pattern_id = PATTERN_KILLER_DQ0, pattern_loop_idx = 0;
+ pattern_id <= (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) ? 22 : PATTERN_KILLER_DQ7);
+ pattern_id++, pattern_loop_idx++) {
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ if (patterns_byte_status[if_id][subphy_num] == BYTE_NOT_DEFINED)
+ continue;
+ opt_win = 2 * max_win_size; /* initialize opt_win */
+ /* in case this byte in the pattern is homogeneous low add 64 adlls to the byte */
+ if (((patterns_byte_status[if_id][subphy_num]) &
+ (BYTE_HOMOGENEOUS_LOW | BYTE_SPLIT_OUT_MIX)) ==
+ (BYTE_HOMOGENEOUS_LOW | BYTE_SPLIT_OUT_MIX)) {
+ for (bit_num = 0; bit_num < BUS_WIDTH_IN_BITS; bit_num++) {
+ if (start_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] <= 31 &&
+ end_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] <= 31) {
+ start_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] +=
+ 64;
+ end_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] += 64;
+ DEBUG_DDR4_CENTRALIZATION
+ (DEBUG_LEVEL_INFO,
+ ("%s %s pattern %d if %d subphy %d bit %d added 64 "
+ "adll\n",
+ __func__, str_dir[mode], pattern_id, if_id,
+ subphy_num, bit_num));
+ }
+ }
+ }
+
+ /* calculations for the current pattern per subphy */
+ for (bit_num = 0; bit_num < BUS_WIDTH_IN_BITS; bit_num++) {
+ curr_win[bit_num] = end_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] -
+ start_win_db[pattern_loop_idx][if_id][subphy_num][bit_num] + 1;
+ curr_start_win[bit_num] =
+ start_win_db[pattern_loop_idx][if_id][subphy_num][bit_num];
+ curr_end_win[bit_num] =
+ end_win_db[pattern_loop_idx][if_id][subphy_num][bit_num];
+ }
+
+ opt_win = GET_MIN(opt_win, ddr3_tip_get_buf_min(curr_win));
+ vw_size[if_id][subphy_num] =
+ GET_MIN(vw_size[if_id][subphy_num], ddr3_tip_get_buf_min(curr_win));
+
+ /* final subphy window length */
+ final_subphy_win[if_id][subphy_num] = ddr3_tip_get_buf_min(curr_end_win) -
+ ddr3_tip_get_buf_max(curr_start_win) + 1;
+ waste_win = opt_win - final_subphy_win[if_id][subphy_num];
+ start_win_skew = ddr3_tip_get_buf_max(curr_start_win) -
+ ddr3_tip_get_buf_min(curr_start_win);
+ end_win_skew = ddr3_tip_get_buf_max(curr_end_win) -
+ ddr3_tip_get_buf_min(curr_end_win);
+
+ /* min/max updated with pattern change */
+ curr_end_win_min = ddr3_tip_get_buf_min(curr_end_win);
+ curr_start_win_max = ddr3_tip_get_buf_max(curr_start_win);
+ subphy_end_win[mode][if_id][subphy_num] =
+ GET_MIN(subphy_end_win[mode][if_id][subphy_num], curr_end_win_min);
+ subphy_start_win[mode][if_id][subphy_num] =
+ GET_MAX(subphy_start_win[mode][if_id][subphy_num], curr_start_win_max);
+ DEBUG_DDR4_CENTRALIZATION
+ (DEBUG_LEVEL_TRACE,
+ ("%s, %s pat %d if %d subphy %d opt_win %d ",
+ __func__, str_dir[mode], pattern_id, if_id, subphy_num, opt_win));
+ DEBUG_DDR4_CENTRALIZATION
+ (DEBUG_LEVEL_TRACE,
+ ("final_subphy_win %d waste_win %d "
+ "start_win_skew %d end_win_skew %d ",
+ final_subphy_win[if_id][subphy_num],
+ waste_win, start_win_skew, end_win_skew));
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("curr_start_win_max %d curr_end_win_min %d "
+ "subphy_start_win %d subphy_end_win %d\n",
+ curr_start_win_max, curr_end_win_min,
+ subphy_start_win[mode][if_id][subphy_num],
+ subphy_end_win[mode][if_id][subphy_num]));
+
+ /* valid window */
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("valid window, pat %d if %d subphy %d\n",
+ pattern_id, if_id, subphy_num));
+ for (bit_num = 0; bit_num < BUS_WIDTH_IN_BITS; bit_num++) {
+ final_start_win[if_id][subphy_num][bit_num] =
+ GET_MAX(final_start_win[if_id][subphy_num][bit_num],
+ curr_start_win[bit_num]);
+ final_end_win[if_id][subphy_num][bit_num] =
+ GET_MIN(final_end_win[if_id][subphy_num][bit_num],
+ curr_end_win[bit_num]);
+ } /* bit */
+ } /* subphy */
+ } /* if_id */
+ } /* pattern */
+
+ /* calculate valid window for each subphy */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ if (patterns_byte_status[if_id][subphy_num] != BYTE_NOT_DEFINED) {
+ /*
+ * in case of bytes status which were found as mixed and low
+ * change the their status to be mixed only, due to the fact
+ * that we have already dealt with this bytes by adding 64 adlls
+ * to the low bytes
+ */
+ if (patterns_byte_status[if_id][subphy_num] &
+ (BYTE_HOMOGENEOUS_LOW | BYTE_SPLIT_OUT_MIX))
+ patterns_byte_status[if_id][subphy_num] = BYTE_SPLIT_OUT_MIX;
+ if (rx_vw_pos[if_id][subphy_num] == 0) /* rx_vw_pos is initialized during tap tune */
+ pbs_max = 31 - 0xa;
+ else
+ pbs_max = 31;
+
+ /* continue if locked */
+ /*if (centralization_state[if_id][subphy_num] == 0) {*/
+ status = mv_ddr4_copt_get(mode, lambda[if_id][subphy_num],
+ final_start_win[if_id][subphy_num],
+ final_end_win[if_id][subphy_num],
+ pbs_result[if_id][subphy_num],
+ &copt[if_id][subphy_num]);
+
+ /*
+ * after copt the adll is moved to smaller value due to pbs compensation
+ * so the byte status might change, here we change the byte status to be
+ * homogeneous low in case the center of the ui after copt is moved below
+ * 31 adlls
+ */
+ if(copt[if_id][subphy_num] <= 31)
+ patterns_byte_status[if_id][subphy_num] = BYTE_HOMOGENEOUS_LOW;
+
+ DEBUG_DDR4_CENTRALIZATION
+ (DEBUG_LEVEL_INFO,
+ ("%s %s if %d subphy %d copt %d\n",
+ __func__, str_dir[mode], if_id, subphy_num, copt[if_id][subphy_num]));
+
+ if (status != MV_OK) {
+ /*
+ * TODO: print out error message(s) only when all points fail
+ * as temporary solution, replaced ERROR to TRACE debug level
+ */
+ DEBUG_DDR4_CENTRALIZATION
+ (DEBUG_LEVEL_TRACE,
+ ("%s %s copt calculation failed, "
+ "no valid window for subphy %d\n",
+ __func__, str_dir[mode], subphy_num));
+ /* set the byte to 0 (fail) and clean the status (continue with algorithm) */
+ vw_size[if_id][subphy_num] = 0;
+ status = MV_OK;
+
+ if (debug_mode == 0) {
+ /*
+ * TODO: print out error message(s) only when all points fail
+ * as temporary solution, commented out debug level set to TRACE
+ */
+ /*
+ * ddr3_hws_set_log_level(DEBUG_BLOCK_CALIBRATION, DEBUG_LEVEL_TRACE);
+ */
+ /* open relevant log and run function again for debug */
+ mv_ddr4_copt_get(mode, lambda[if_id][subphy_num],
+ final_start_win[if_id][subphy_num],
+ final_end_win[if_id][subphy_num],
+ pbs_result[if_id][subphy_num],
+ &copt[if_id][subphy_num]);
+ /*
+ * ddr3_hws_set_log_level(DEBUG_BLOCK_CALIBRATION, DEBUG_LEVEL_ERROR);
+ */
+ } /* debug mode */
+ } /* status */
+ } /* byte not defined */
+ } /* subphy */
+ } /* if_id */
+
+ /* restore cs enable value*/
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM - 1; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG,
+ cs_ena_reg_val[if_id], MASK_ALL_BITS);
+ if (status != MV_OK)
+ return status;
+ }
+
+ return status;
+}
+
+/*
+ * mv_ddr4_copt_get function
+ * inputs:
+ * dir - direction; 0 is for rx, 1 for tx
+ * lambda - a pointer to adll to pbs ration multiplied by PBS_VAL_FACTOR
+ * vw_l - a pointer to valid window low limit in adll taps
+ * vw_h - a pointer to valid window high limit in adll taps
+ * outputs:
+ * pbs_result - a pointer to pbs new delay value; the function's output
+ * copt - optimal center of subphy in adll taps
+ * The function assumes initial pbs tap value is zero. Otherwise, it requires logic
+ * getting pbs value per dq and setting pbs_taps_per_dq array.
+ * It provides with a solution for a single subphy (8 bits).
+ * The calling function is responsible for any additional pbs taps for dqs
+ */
+static int mv_ddr4_copt_get(u8 dir, u16 *lambda, u8 *vw_l, u8 *vw_h, u8 *pbs_result, u8 *copt)
+{
+ u8 center_per_dq[8];
+ u8 center_zone_low[8] = {0};
+ u8 center_zone_high[8] = {0};
+ u8 ext_center_zone_low[8] = {0};
+ u8 ext_center_zone_high[8] = {0};
+ u8 pbs_taps_per_dq[8] = {0};
+ u8 vw_per_dq[8];
+ u8 vw_zone_low[8] = {0};
+ u8 vw_zone_high[8] = {0};
+ u8 margin_vw[8] = {0};
+ u8 copt_val;
+ u8 dq_idx;
+ u8 center_zone_max_low = 0;
+ u8 center_zone_min_high = 128;
+ u8 vw_zone_max_low = 0;
+ u8 vw_zone_min_high = 128;
+ u8 min_vw = 63; /* minimum valid window between all bits */
+ u8 center_low_el;
+ u8 center_high_el;
+
+ /* lambda calculated as D * PBS_VALUE_FACTOR / d */
+ //printf("Copt::Debug::\t");
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ center_per_dq[dq_idx] = (vw_h[dq_idx] + vw_l[dq_idx]) / 2;
+ vw_per_dq[dq_idx] = 1 + (vw_h[dq_idx] - vw_l[dq_idx]);
+ if (min_vw > vw_per_dq[dq_idx])
+ min_vw = vw_per_dq[dq_idx];
+ }
+
+ /* calculate center zone */
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ center_low_el = center_low_element_get(dir, pbs_taps_per_dq[dq_idx], lambda[dq_idx], pbs_max);
+ if (center_per_dq[dq_idx] > center_low_el)
+ center_zone_low[dq_idx] = center_per_dq[dq_idx] - center_low_el;
+ center_high_el = center_high_element_get(dir, pbs_taps_per_dq[dq_idx], lambda[dq_idx], pbs_max);
+ center_zone_high[dq_idx] = center_per_dq[dq_idx] + center_high_el;
+ if (center_zone_max_low < center_zone_low[dq_idx])
+ center_zone_max_low = center_zone_low[dq_idx];
+ if (center_zone_min_high > center_zone_high[dq_idx])
+ center_zone_min_high = center_zone_high[dq_idx];
+ DEBUG_CALIBRATION(DEBUG_LEVEL_TRACE,
+ ("center: low %d, high %d, max_low %d, min_high %d\n",
+ center_zone_low[dq_idx], center_zone_high[dq_idx],
+ center_zone_max_low, center_zone_min_high));
+ }
+
+ if (center_zone_min_high >= center_zone_max_low) { /* center zone visib */
+ /* set copt_val to high zone for rx */
+ copt_val = (dir == RX_DIR) ? center_zone_max_low : center_zone_min_high;
+ *copt = copt_val;
+
+ /* calculate additional pbs taps */
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ if (dir == RX_DIR)
+ pbs_result[dq_idx] = (copt_val - center_per_dq[dq_idx]) *
+ PBS_VAL_FACTOR / lambda[dq_idx];
+ else
+ pbs_result[dq_idx] = (center_per_dq[dq_idx] - copt_val) *
+ PBS_VAL_FACTOR / lambda[dq_idx];
+ }
+ return MV_OK;
+ } else { /* not center zone visib */
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ if ((center_zone_low[dq_idx] + 1) > (vw_per_dq[dq_idx] / 2 + vw_per_dq[dq_idx] % 2)) {
+ vw_zone_low[dq_idx] = (center_zone_low[dq_idx] + 1) -
+ (vw_per_dq[dq_idx] / 2 + vw_per_dq[dq_idx] % 2);
+ } else {
+ vw_zone_low[dq_idx] = 0;
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("dq_idx %d, center zone low %d, vw_l %d, vw_l %d\n",
+ dq_idx, center_zone_low[dq_idx], vw_l[dq_idx], vw_h[dq_idx]));
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("vw_l[%d], vw_lh[%d], lambda[%d]\n",
+ vw_l[dq_idx], vw_h[dq_idx], lambda[dq_idx]));
+ }
+
+ vw_zone_high[dq_idx] = center_zone_high[dq_idx] + vw_per_dq[dq_idx] / 2;
+
+ if (vw_zone_max_low < vw_zone_low[dq_idx])
+ vw_zone_max_low = vw_zone_low[dq_idx];
+
+ if (vw_zone_min_high > vw_zone_high[dq_idx])
+ vw_zone_min_high = vw_zone_high[dq_idx];
+
+ DEBUG_CALIBRATION(DEBUG_LEVEL_TRACE,
+ ("valid_window: low %d, high %d, max_low %d, min_high %d\n",
+ vw_zone_low[dq_idx], vw_zone_high[dq_idx],
+ vw_zone_max_low, vw_zone_min_high));
+ }
+
+ /* try to extend center zone */
+ if (vw_zone_min_high >= vw_zone_max_low) { /* vw zone visib */
+ center_zone_max_low = 0;
+ center_zone_min_high = 128;
+
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ margin_vw[dq_idx] = vw_per_dq[dq_idx] - min_vw;
+
+ if (center_zone_low[dq_idx] > margin_vw[dq_idx])
+ ext_center_zone_low[dq_idx] = center_zone_low[dq_idx] - margin_vw[dq_idx];
+ else
+ ext_center_zone_low[dq_idx] = 0;
+
+ ext_center_zone_high[dq_idx] = center_zone_high[dq_idx] + margin_vw[dq_idx];
+
+ if (center_zone_max_low < ext_center_zone_low[dq_idx])
+ center_zone_max_low = ext_center_zone_low[dq_idx];
+
+ if (center_zone_min_high > ext_center_zone_high[dq_idx])
+ center_zone_min_high = ext_center_zone_high[dq_idx];
+
+ DEBUG_CALIBRATION(DEBUG_LEVEL_TRACE,
+ ("ext_center: low %d, high %d, max_low %d, min_high %d\n",
+ ext_center_zone_low[dq_idx], ext_center_zone_high[dq_idx],
+ center_zone_max_low, center_zone_min_high));
+ }
+
+ if (center_zone_min_high >= center_zone_max_low) { /* center zone visib */
+ /* get optimal center position */
+ copt_val = (dir == RX_DIR) ? center_zone_max_low : center_zone_min_high;
+ *copt = copt_val;
+
+ /* calculate additional pbs taps */
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ if (dir == 0) {
+ if (copt_val > center_per_dq[dq_idx])
+ pbs_result[dq_idx] = (copt_val - center_per_dq[dq_idx]) *
+ PBS_VAL_FACTOR / lambda[dq_idx];
+ else
+ pbs_result[dq_idx] = 0;
+ } else {
+ if (center_per_dq[dq_idx] > copt_val)
+ pbs_result[dq_idx] = (center_per_dq[dq_idx] - copt_val) *
+ PBS_VAL_FACTOR / lambda[dq_idx];
+ else
+ pbs_result[dq_idx] = 0;
+ }
+
+ if (pbs_result[dq_idx] > pbs_max)
+ pbs_result[dq_idx] = pbs_max;
+ }
+
+ return MV_OK;
+ } else { /* not center zone visib */
+ /*
+ * TODO: print out error message(s) only when all points fail
+ * as temporary solution, replaced ERROR to TRACE debug level
+ */
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("lambda: %d, %d, %d, %d, %d, %d, %d, %d\n",
+ lambda[0], lambda[1], lambda[2], lambda[3],
+ lambda[4], lambda[5], lambda[6], lambda[7]));
+
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("vw_h: %d, %d, %d, %d, %d, %d, %d, %d\n",
+ vw_h[0], vw_h[1], vw_h[2], vw_h[3],
+ vw_h[4], vw_h[5], vw_h[6], vw_h[7]));
+
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("vw_l: %d, %d, %d, %d, %d, %d, %d, %d\n",
+ vw_l[0], vw_l[1], vw_l[2], vw_l[3],
+ vw_l[4], vw_l[5], vw_l[6], vw_l[7]));
+
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("center: low %d, high %d, "
+ "max_low %d, min_high %d\n",
+ center_zone_low[dq_idx], center_zone_high[dq_idx],
+ center_zone_max_low, center_zone_min_high));
+
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("valid_window: low %d, high %d, "
+ "max_low %d, min_high %d\n",
+ vw_zone_low[dq_idx], vw_zone_high[dq_idx],
+ vw_zone_max_low, vw_zone_min_high));
+
+ DEBUG_DDR4_CENTRALIZATION(DEBUG_LEVEL_TRACE,
+ ("ext_center: low %d, high %d, "
+ "max_low %d, min_high %d\n",
+ ext_center_zone_low[dq_idx],
+ ext_center_zone_high[dq_idx],
+ center_zone_max_low, center_zone_min_high));
+ }
+
+ return MV_FAIL;
+ }
+ } else { /* not vw zone visib; failed to find a single sample point */
+ return MV_FAIL;
+ }
+ }
+
+ return MV_OK;
+}
+
+/*
+ * mv_ddr4_dqs_reposition function gets copt to align to and returns pbs value per bit
+ * parameters:
+ * dir - direction; 0 is for rx, 1 for tx
+ * lambda - a pointer to adll to pbs ration multiplied by PBS_VAL_FACTOR
+ * pbs_result - a pointer to pbs new delay value; the function's output
+ * delta - signed; possilbe values: +0xa, 0x0, -0xa; for rx can be only negative
+ * copt - optimal center of subphy in adll taps
+ * dqs_pbs - optimal pbs
+ * The function assumes initial pbs tap value is zero. Otherwise, it requires logic
+ * getting pbs value per dq and setting pbs_taps_per_dq array.
+ * It provides with a solution for a single subphy (8 bits).
+ * The calling function is responsible for any additional pbs taps for dqs
+ */
+static int mv_ddr4_dqs_reposition(u8 dir, u16 *lambda, u8 *pbs_result, char delta, u8 *copt, u8 *dqs_pbs)
+{
+ u8 dq_idx;
+ u32 pbs_max_val = 0;
+ u32 lambda_avg = 0;
+
+ /* lambda calculated as D * X / d */
+ for (dq_idx = 0; dq_idx < 8; dq_idx++) {
+ if (pbs_max_val < pbs_result[dq_idx])
+ pbs_max_val = pbs_result[dq_idx];
+ lambda_avg += lambda[dq_idx];
+ }
+
+ if (delta >= 0)
+ *dqs_pbs = (pbs_max_val + delta) / 2;
+ else /* dqs already 0xa */
+ *dqs_pbs = pbs_max_val / 2;
+
+ lambda_avg /= 8;
+
+ /* change in dqs pbs value requires change in final copt position from mass center solution */
+ if (dir == TX_DIR) {
+ /* for tx, additional pbs on dqs in opposite direction of adll */
+ *copt = *copt + ((*dqs_pbs) * lambda_avg) / PBS_VAL_FACTOR;
+ } else {
+ /* for rx, additional pbs on dqs in same direction of adll */
+ if (delta < 0)
+ *copt = *copt - ((*dqs_pbs + delta) * lambda_avg) / PBS_VAL_FACTOR;
+ else
+ *copt = *copt - (*dqs_pbs * lambda_avg) / PBS_VAL_FACTOR;
+ }
+
+ return MV_OK;
+}
+
+/*
+ * mv_ddr4_center_of_mass_calc function
+ * parameters:
+ * vw_l - a pointer to valid window low limit in adll taps
+ * vw_h - a pointer to valid window high limit in adll taps
+ * vw_v - a pointer to vref value matching vw_l/h arrays
+ * vw_num - number of valid windows (lenght vw_v vector)
+ * v_opt - optimal voltage value in vref taps
+ * t_opt - optimal adll value in adll taps
+ * This function solves 2D centroid equation (e.g., adll and vref axes)
+ * The function doesn't differentiate between byte and bit eyes
+ */
+static int mv_ddr4_center_of_mass_calc(u8 dev_num, u8 if_id, u8 subphy_num, u8 mode, u8 *vw_l,
+ u8 *vw_h, u8 *vw_v, u8 vw_num, u8 *v_opt, u8 *t_opt)
+{
+ u8 idx;
+ u8 edge_t[128], edge_v[128];
+ u8 min_edge_t = 127, min_edge_v = 127;
+ int polygon_area = 0;
+ int t_opt_temp = 0, v_opt_temp = 0;
+ int vw_avg = 0, v_avg = 0;
+ int s0 = 0, s1 = 0, s2 = 0, slope = 1, r_sq = 0;
+ u32 d_min = 10000, reg_val = 0;
+ int status;
+
+ /*
+ * reorder all polygon points counterclockwise
+ * get min value of each axis to shift to smaller calc value
+ */
+ for (idx = 0; idx < vw_num; idx++) {
+ edge_t[idx] = vw_l[idx];
+ edge_v[idx] = vw_v[idx];
+ if (min_edge_v > vw_v[idx])
+ min_edge_v = vw_v[idx];
+ if (min_edge_t > vw_l[idx])
+ min_edge_t = vw_l[idx];
+ edge_t[vw_num * 2 - 1 - idx] = vw_h[idx];
+ edge_v[vw_num * 2 - 1 - idx] = vw_v[idx];
+ vw_avg += vw_h[idx] - vw_l[idx];
+ v_avg += vw_v[idx];
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("%s: if %d, byte %d, direction %d, vw_v %d, vw_l %d, vw_h %d\n",
+ __func__, if_id, subphy_num, mode, vw_v[idx], vw_l[idx], vw_h[idx]));
+ }
+
+ vw_avg *= 1000 / vw_num;
+ v_avg /= vw_num;
+ for (idx = 0; idx < vw_num; idx++) {
+ s0 += (1000 * (vw_h[idx] - vw_l[idx]) - vw_avg) * (vw_v[idx] - v_avg);
+ s1 += (vw_v[idx] - v_avg) * (vw_v[idx] - v_avg);
+ s2 += (1000 * (vw_h[idx] - vw_l[idx]) - vw_avg) * (1000 * (vw_h[idx] - vw_l[idx]) - vw_avg);
+ }
+ r_sq = s0 * (s0 / s1);
+ r_sq /= (s2 / 1000);
+ slope = s0 / s1;
+
+ /* idx n is equal to idx 0 */
+ edge_t[vw_num * 2] = vw_l[0];
+ edge_v[vw_num * 2] = vw_v[0];
+
+ /* calculate polygon area, a (may be negative) */
+ for (idx = 0; idx < vw_num * 2; idx++)
+ polygon_area = polygon_area +
+ ((edge_t[idx] - min_edge_t)*(edge_v[idx + 1] - min_edge_v) -
+ (edge_t[idx + 1] - min_edge_t)*(edge_v[idx] - min_edge_v));
+
+ /* calculate optimal point */
+ for (idx = 0; idx < vw_num * 2; idx++) {
+ t_opt_temp = t_opt_temp +
+ (edge_t[idx] + edge_t[idx + 1] - 2 * min_edge_t) *
+ ((edge_t[idx] - min_edge_t)*(edge_v[idx + 1] - min_edge_v) -
+ (edge_t[idx + 1] - min_edge_t)*(edge_v[idx] - min_edge_v));
+ v_opt_temp = v_opt_temp +
+ (edge_v[idx] + edge_v[idx + 1] - 2 * min_edge_v) *
+ ((edge_t[idx] - min_edge_t)*(edge_v[idx + 1] - min_edge_v) -
+ (edge_t[idx + 1] - min_edge_t)*(edge_v[idx] - min_edge_v));
+ }
+
+ *t_opt = t_opt_temp / (3 * polygon_area);
+ *v_opt = v_opt_temp / (3 * polygon_area);
+
+ /* re-shift */
+ *t_opt += min_edge_t;
+ *v_opt += min_edge_v;
+
+ /* calculate d_min */
+ for (idx = 0; idx < 2 * vw_num; idx++) {
+ s0 = (*t_opt - edge_t[idx]) * (*t_opt - edge_t[idx]) +
+ (*v_opt - edge_v[idx]) * (*v_opt - edge_v[idx]);
+ d_min = (d_min > s0) ? s0 : d_min;
+ }
+ DEBUG_CALIBRATION(DEBUG_LEVEL_TRACE,
+ ("%s: r_sq %d, slope %d, area = %d, , d_min = %d\n",
+ __func__, r_sq, slope, polygon_area, d_min));
+
+ /* insert vw eye to register database for validation */
+ if (d_min < 0)
+ d_min = -d_min;
+ if (polygon_area < 0)
+ polygon_area = -polygon_area;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, subphy_num,
+ DDR_PHY_DATA, RESULT_PHY_REG + effective_cs + 4 * (1 - mode),
+ polygon_area);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST,
+ dmin_phy_reg_table[effective_cs * 5 + subphy_num][0], DDR_PHY_CONTROL,
+ dmin_phy_reg_table[effective_cs * 5 + subphy_num][1], ®_val);
+ if (status != MV_OK)
+ return status;
+
+ reg_val &= 0xff << (8 * mode); /* rx clean bits 0..8, tx bits 9..16 */
+ reg_val |= d_min / 2 << (8 * (1 - mode)); /* rX write bits 0..8, tx bits 9..16 */
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST,
+ dmin_phy_reg_table[effective_cs * 5 + subphy_num][0], DDR_PHY_CONTROL,
+ dmin_phy_reg_table[effective_cs * 5 + subphy_num][1], reg_val);
+ if (status != MV_OK)
+ return status;
+
+ if (polygon_area < 400) {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_ERROR,
+ ("%s: if %d, subphy %d: poligon area too small %d (dmin %d)\n",
+ __func__, if_id, subphy_num, polygon_area, d_min));
+ if (debug_mode == 0)
+ return MV_FAIL;
+ }
+
+ return MV_OK;
+}
+
+/* tap tuning flow */
+enum {
+ DQS_TO_DQ_LONG,
+ DQS_TO_DQ_SHORT
+};
+enum {
+ ALIGN_LEFT,
+ ALIGN_CENTER,
+ ALIGN_RIGHT
+};
+#define ONE_MHZ 1000000
+#define MAX_SKEW_DLY 200 /* in ps */
+#define NOMINAL_PBS_DLY 9 /* in ps */
+#define MIN_WL_TO_CTX_ADLL_DIFF 2 /* in taps */
+#define DQS_SHIFT_INIT_VAL 30
+#define MAX_PBS_NUM 31
+#define ADLL_TAPS_PER_PHASE 32
+#define ADLL_TAPS_PER_PERIOD (ADLL_TAPS_PER_PHASE * 2)
+#define ADLL_TX_RES_REG_MASK 0xff
+#define VW_DESKEW_BIAS 0xa
+static int mv_ddr4_tap_tuning(u8 dev, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS], u8 mode)
+{
+ enum hws_training_ip_stat training_result[MAX_INTERFACE_NUM];
+ u32 iface, subphy, bit, pattern;
+ u32 limit_div;
+ u8 curr_start_win, curr_end_win;
+ u8 upd_curr_start_win, upd_curr_end_win;
+ u8 start_win_diff, end_win_diff;
+ u32 max_win_size, a, b;
+ u32 cs_ena_reg_val[MAX_INTERFACE_NUM];
+ u32 reg_addr;
+ enum hws_search_dir search_dir;
+ enum hws_dir dir;
+ u32 *result[MAX_BUS_NUM][HWS_SEARCH_DIR_LIMIT];
+ u32 result1[MAX_BUS_NUM][HWS_SEARCH_DIR_LIMIT][BUS_WIDTH_IN_BITS];
+ u8 subphy_max = ddr3_tip_dev_attr_get(dev, MV_ATTR_OCTET_PER_INTERFACE);
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum hws_training_result result_type = RESULT_PER_BIT;
+ int status = MV_OK;
+ int i;
+ u32 reg_val;
+ u32 freq = mv_ddr_freq_get(tm->interface_params->memory_freq);
+ /* calc adll tap in ps based on frequency */
+ int adll_tap = (ONE_MHZ / freq) / ADLL_TAPS_PER_PERIOD;
+ int dq_to_dqs_delta[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; /* skew b/w dq and dqs */
+ u32 wl_adll[MAX_BUS_NUM]; /* wl solution adll value */
+ int is_dq_dqs_short[MAX_BUS_NUM] = {0}; /* tx byte's state */
+ u32 new_pbs_per_byte[MAX_BUS_NUM]; /* dq pads' pbs value correction */
+ /* threshold to decide subphy needs dqs pbs delay */
+ int dq_to_dqs_min_delta_threshold = MIN_WL_TO_CTX_ADLL_DIFF + MAX_SKEW_DLY / adll_tap;
+ /* search init condition */
+ int dq_to_dqs_min_delta = dq_to_dqs_min_delta_threshold * 2;
+ u32 pbs_tap_factor0 = PBS_VAL_FACTOR * NOMINAL_PBS_DLY / adll_tap; /* init lambda */
+ /* adapt pbs to frequency */
+ u32 new_pbs = (1810000 - (345 * freq)) / 100000;
+ int stage_num, loop;
+ int wl_tap, new_wl_tap;
+ int pbs_tap_factor_avg;
+ int dqs_shift[MAX_BUS_NUM]; /* dqs' pbs delay */
+ static u16 tmp_pbs_tap_factor[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO, ("Starting ddr4 tap tuning training stage\n"));
+
+ for (i = 0; i < MAX_BUS_NUM; i++)
+ dqs_shift[i] = DQS_SHIFT_INIT_VAL;
+
+ if (mode == TX_DIR) {
+ max_win_size = MAX_WINDOW_SIZE_TX;
+ dir = OPER_WRITE;
+ } else {
+ max_win_size = MAX_WINDOW_SIZE_RX;
+ dir = OPER_READ;
+ }
+
+ /* init all pbs registers */
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ if (mode == RX_DIR)
+ reg_addr = PBS_RX_BCAST_PHY_REG(effective_cs);
+ else
+ reg_addr = PBS_TX_BCAST_PHY_REG(effective_cs);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, reg_addr, 0);
+
+ if (mode == RX_DIR)
+ reg_addr = PBS_RX_PHY_REG(effective_cs, DQSP_PAD);
+ else
+ reg_addr = PBS_TX_PHY_REG(effective_cs, DQSP_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, reg_addr, 0);
+ if (mode == RX_DIR)
+ reg_addr = PBS_RX_PHY_REG(effective_cs, DQSN_PAD);
+ else
+ reg_addr = PBS_TX_PHY_REG(effective_cs, DQSN_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, DDR_PHY_DATA, reg_addr, 0);
+ }
+
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ /* save current cs enable reg val */
+ ddr3_tip_if_read(dev, ACCESS_TYPE_UNICAST, iface, DUAL_DUNIT_CFG_REG,
+ cs_ena_reg_val, MASK_ALL_BITS);
+
+ /* enable single cs */
+ ddr3_tip_if_write(dev, ACCESS_TYPE_UNICAST, iface, DUAL_DUNIT_CFG_REG,
+ (SINGLE_CS_ENA << SINGLE_CS_PIN_OFFS),
+ (SINGLE_CS_PIN_MASK << SINGLE_CS_PIN_OFFS));
+ }
+
+ /* FIXME: fix this hard-coded parameters due to compilation issue with patterns definitions */
+ pattern = MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) ? 73 : 23;
+ stage_num = (mode == RX_DIR) ? 1 : 2;
+ /* find window; run training */
+ for (loop = 0; loop < stage_num; loop++) {
+ ddr3_tip_ip_training_wrapper(dev, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, result_type, HWS_CONTROL_ELEMENT_ADLL, PARAM_NOT_CARE,
+ dir, tm->if_act_mask, 0x0, max_win_size - 1, max_win_size - 1,
+ pattern, EDGE_FPF, CS_SINGLE, PARAM_NOT_CARE, training_result);
+
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ rx_vw_pos[iface][subphy] = ALIGN_CENTER;
+ new_pbs_per_byte[subphy] = new_pbs; /* rx init */
+ if ((mode == TX_DIR) && (loop == 0)) {
+ /* read nominal wl */
+ ddr3_tip_bus_read(dev, iface, ACCESS_TYPE_UNICAST, subphy,
+ DDR_PHY_DATA, WL_PHY_REG(effective_cs),
+ ®_val);
+ wl_adll[subphy] = reg_val;
+ }
+
+ for (search_dir = HWS_LOW2HIGH; search_dir <= HWS_HIGH2LOW; search_dir++) {
+ ddr3_tip_read_training_result(dev, iface, ACCESS_TYPE_UNICAST, subphy,
+ ALL_BITS_PER_PUP, search_dir, dir,
+ result_type, TRAINING_LOAD_OPERATION_UNLOAD,
+ CS_SINGLE, &(result[subphy][search_dir]),
+ 1, 0, 0);
+
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("cs %d if %d subphy %d mode %d result: "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ effective_cs, iface, subphy, mode,
+ result[subphy][search_dir][0],
+ result[subphy][search_dir][1],
+ result[subphy][search_dir][2],
+ result[subphy][search_dir][3],
+ result[subphy][search_dir][4],
+ result[subphy][search_dir][5],
+ result[subphy][search_dir][6],
+ result[subphy][search_dir][7]));
+ }
+
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ a = result[subphy][HWS_LOW2HIGH][bit];
+ b = result[subphy][HWS_HIGH2LOW][bit];
+ result1[subphy][HWS_LOW2HIGH][bit] = a;
+ result1[subphy][HWS_HIGH2LOW][bit] = b;
+ /* measure distance between ctx and wl adlls */
+ if (mode == TX_DIR) {
+ a &= ADLL_TX_RES_REG_MASK;
+ if (a >= ADLL_TAPS_PER_PERIOD)
+ a -= ADLL_TAPS_PER_PERIOD;
+ dq_to_dqs_delta[subphy][bit] =
+ a - (wl_adll[subphy] & WR_LVL_REF_DLY_MASK);
+ if (dq_to_dqs_delta[subphy][bit] < dq_to_dqs_min_delta)
+ dq_to_dqs_min_delta = dq_to_dqs_delta[subphy][bit];
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("%s: dq_to_dqs_delta[%d][%d] %d\n",
+ __func__, subphy, bit,
+ dq_to_dqs_delta[subphy][bit]));
+ }
+ }
+
+ /* adjust wl on the first pass only */
+ if ((mode == TX_DIR) && (loop == 0)) {
+ /* dqs pbs shift if distance b/w adll is too large */
+ if (dq_to_dqs_min_delta < dq_to_dqs_min_delta_threshold) {
+ /* first calculate the WL in taps */
+ wl_tap = ((wl_adll[subphy] >> WR_LVL_REF_DLY_OFFS) &
+ WR_LVL_REF_DLY_MASK) +
+ ((wl_adll[subphy] >> WR_LVL_PH_SEL_OFFS) &
+ WR_LVL_PH_SEL_MASK) * ADLL_TAPS_PER_PHASE;
+
+ /* calc dqs pbs shift */
+ dqs_shift[subphy] =
+ dq_to_dqs_min_delta_threshold - dq_to_dqs_min_delta;
+ /* check that the WL result have enough taps to reduce */
+ if (wl_tap > 0) {
+ if (wl_tap < dqs_shift[subphy])
+ dqs_shift[subphy] = wl_tap-1;
+ else
+ dqs_shift[subphy] = dqs_shift[subphy];
+ } else {
+ dqs_shift[subphy] = 0;
+ }
+ DEBUG_TAP_TUNING_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("%s: tap tune tx: subphy %d, dqs shifted by %d adll taps, ",
+ __func__, subphy, dqs_shift[subphy]));
+ dqs_shift[subphy] =
+ (dqs_shift[subphy] * PBS_VAL_FACTOR) / pbs_tap_factor0;
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("%d pbs taps\n", dqs_shift[subphy]));
+ /* check high limit */
+ if (dqs_shift[subphy] > MAX_PBS_NUM)
+ dqs_shift[subphy] = MAX_PBS_NUM;
+ reg_addr = PBS_TX_PHY_REG(effective_cs, DQSP_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ reg_addr, dqs_shift[subphy]);
+ reg_addr = PBS_TX_PHY_REG(effective_cs, DQSN_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ reg_addr, dqs_shift[subphy]);
+
+ is_dq_dqs_short[subphy] = DQS_TO_DQ_SHORT;
+
+ new_wl_tap = wl_tap -
+ (dqs_shift[subphy] * pbs_tap_factor0) / PBS_VAL_FACTOR;
+ reg_val = (new_wl_tap & WR_LVL_REF_DLY_MASK) |
+ ((new_wl_tap &
+ ((WR_LVL_PH_SEL_MASK << WR_LVL_PH_SEL_OFFS) >> 1))
+ << 1) |
+ (wl_adll[subphy] &
+ ((CTRL_CENTER_DLY_MASK << CTRL_CENTER_DLY_OFFS) |
+ (CTRL_CENTER_DLY_INV_MASK << CTRL_CENTER_DLY_INV_OFFS)));
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), reg_val);
+ DEBUG_TAP_TUNING_ENGINE
+ (DEBUG_LEVEL_INFO,
+ ("%s: subphy %d, dq_to_dqs_min_delta %d, dqs_shift %d, old wl %d, temp wl %d 0x%08x\n",
+ __func__, subphy, dq_to_dqs_min_delta,
+ dqs_shift[subphy], wl_tap, new_wl_tap,
+ reg_val));
+ }
+ }
+ dq_to_dqs_min_delta = dq_to_dqs_min_delta_threshold * 2;
+ }
+ }
+ }
+
+ /* deskew dq */
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ if (mode == RX_DIR)
+ reg_addr = PBS_RX_BCAST_PHY_REG(effective_cs);
+ else
+ reg_addr = PBS_TX_BCAST_PHY_REG(effective_cs);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR_PHY_DATA, reg_addr, new_pbs_per_byte[0]);
+ }
+
+ /* run training search and get results */
+ ddr3_tip_ip_training_wrapper(dev, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, result_type, HWS_CONTROL_ELEMENT_ADLL, PARAM_NOT_CARE,
+ dir, tm->if_act_mask, 0x0, max_win_size - 1, max_win_size - 1,
+ pattern, EDGE_FPF, CS_SINGLE, PARAM_NOT_CARE, training_result);
+
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ /* read training ip results from db */
+ for (search_dir = HWS_LOW2HIGH; search_dir <= HWS_HIGH2LOW; search_dir++) {
+ ddr3_tip_read_training_result(dev, iface, ACCESS_TYPE_UNICAST,
+ subphy, ALL_BITS_PER_PUP, search_dir,
+ dir, result_type,
+ TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
+ &(result[subphy][search_dir]),
+ 1, 0, 0);
+
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("cs %d if %d subphy %d mode %d result: "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ effective_cs, iface, subphy, mode,
+ result[subphy][search_dir][0],
+ result[subphy][search_dir][1],
+ result[subphy][search_dir][2],
+ result[subphy][search_dir][3],
+ result[subphy][search_dir][4],
+ result[subphy][search_dir][5],
+ result[subphy][search_dir][6],
+ result[subphy][search_dir][7]));
+ }
+
+ /* calc dq skew impact on vw position */
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ start_win_diff = 0;
+ end_win_diff = 0;
+ limit_div = 0;
+ if ((GET_LOCK_RESULT(result1[subphy][HWS_LOW2HIGH][bit]) == 1) &&
+ (GET_LOCK_RESULT(result1[subphy][HWS_HIGH2LOW][bit]) == 1) &&
+ (GET_LOCK_RESULT(result[subphy][HWS_LOW2HIGH][bit]) == 1) &&
+ (GET_LOCK_RESULT(result[subphy][HWS_HIGH2LOW][bit]) == 1)) {
+ curr_start_win = GET_TAP_RESULT(result1[subphy][HWS_LOW2HIGH][bit],
+ EDGE_1);
+ curr_end_win = GET_TAP_RESULT(result1[subphy][HWS_HIGH2LOW][bit],
+ EDGE_1);
+ upd_curr_start_win = GET_TAP_RESULT(result[subphy][HWS_LOW2HIGH][bit],
+ EDGE_1);
+ upd_curr_end_win = GET_TAP_RESULT(result[subphy][HWS_HIGH2LOW][bit],
+ EDGE_1);
+
+ /* update tx start skew; set rx vw position */
+ if ((upd_curr_start_win != 0) && (curr_start_win != 0)) {
+ if (upd_curr_start_win > curr_start_win) {
+ start_win_diff = upd_curr_start_win - curr_start_win;
+ if (mode == TX_DIR)
+ start_win_diff =
+ curr_start_win + 64 - upd_curr_start_win;
+ } else {
+ start_win_diff = curr_start_win - upd_curr_start_win;
+ }
+ limit_div++;
+ } else {
+ rx_vw_pos[iface][subphy] = ALIGN_LEFT;
+ }
+
+ /* update tx end skew; set rx vw position */
+ if (((upd_curr_end_win != max_win_size) && (curr_end_win != max_win_size)) ||
+ (mode == TX_DIR)) {
+ if (upd_curr_end_win > curr_end_win) {
+ end_win_diff = upd_curr_end_win - curr_end_win;
+ if (mode == TX_DIR)
+ end_win_diff =
+ curr_end_win + 64 - upd_curr_end_win;
+ } else {
+ end_win_diff = curr_end_win - upd_curr_end_win;
+ }
+ limit_div++;
+ } else {
+ rx_vw_pos[iface][subphy] = ALIGN_RIGHT;
+ }
+
+ /*
+ * don't care about start in tx mode
+ * TODO: temporary solution for instability in the start adll search
+ */
+ if (mode == TX_DIR) {
+ start_win_diff = end_win_diff;
+ limit_div = 2;
+ }
+
+ /*
+ * workaround for false tx measurements in tap tune stage
+ * tx pbs factor will use rx pbs factor results instead
+ */
+ if ((limit_div != 0) && (mode == RX_DIR)) {
+ pbs_tap_factor[iface][subphy][bit] =
+ PBS_VAL_FACTOR * (start_win_diff + end_win_diff) /
+ (new_pbs_per_byte[subphy] * limit_div);
+ tmp_pbs_tap_factor[iface][subphy][bit] =
+ pbs_tap_factor[iface][subphy][bit];
+ } else {
+ pbs_tap_factor[iface][subphy][bit] =
+ tmp_pbs_tap_factor[iface][subphy][bit];
+ }
+
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("cs %d if %d subphy %d bit %d sw1 %d sw2 %d "
+ "ew1 %d ew2 %d sum delta %d, align %d\n",
+ effective_cs, iface, subphy, bit,
+ curr_start_win, upd_curr_start_win,
+ curr_end_win, upd_curr_end_win,
+ pbs_tap_factor[iface][subphy][bit],
+ rx_vw_pos[iface][subphy]));
+ } else {
+ status = MV_FAIL;
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("tap tuning fail %s cs %d if %d subphy %d bit %d\n",
+ (mode == RX_DIR) ? "RX" : "TX", effective_cs, iface,
+ subphy, bit));
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("cs %d if %d subphy %d mode %d result: "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ effective_cs, iface, subphy, mode,
+ result[subphy][HWS_LOW2HIGH][0],
+ result[subphy][HWS_LOW2HIGH][1],
+ result[subphy][HWS_LOW2HIGH][2],
+ result[subphy][HWS_LOW2HIGH][3],
+ result[subphy][HWS_LOW2HIGH][4],
+ result[subphy][HWS_LOW2HIGH][5],
+ result[subphy][HWS_LOW2HIGH][6],
+ result[subphy][HWS_LOW2HIGH][7]));
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("cs %d if %d subphy %d mode %d result: "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ effective_cs, iface, subphy, mode,
+ result[subphy][HWS_HIGH2LOW][0],
+ result[subphy][HWS_HIGH2LOW][1],
+ result[subphy][HWS_HIGH2LOW][2],
+ result[subphy][HWS_HIGH2LOW][3],
+ result[subphy][HWS_HIGH2LOW][4],
+ result[subphy][HWS_HIGH2LOW][5],
+ result[subphy][HWS_HIGH2LOW][6],
+ result[subphy][HWS_HIGH2LOW][7]));
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("cs %d if %d subphy %d mode %d result: "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ effective_cs, iface, subphy, mode,
+ result1[subphy][HWS_LOW2HIGH][0],
+ result1[subphy][HWS_LOW2HIGH][1],
+ result1[subphy][HWS_LOW2HIGH][2],
+ result1[subphy][HWS_LOW2HIGH][3],
+ result1[subphy][HWS_LOW2HIGH][4],
+ result1[subphy][HWS_LOW2HIGH][5],
+ result1[subphy][HWS_LOW2HIGH][6],
+ result1[subphy][HWS_LOW2HIGH][7]));
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("cs %d if %d subphy %d mode %d result: "
+ "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ effective_cs, iface, subphy, mode,
+ result1[subphy][HWS_HIGH2LOW][0],
+ result1[subphy][HWS_HIGH2LOW][1],
+ result1[subphy][HWS_HIGH2LOW][2],
+ result1[subphy][HWS_HIGH2LOW][3],
+ result1[subphy][HWS_HIGH2LOW][4],
+ result1[subphy][HWS_HIGH2LOW][5],
+ result1[subphy][HWS_HIGH2LOW][6],
+ result1[subphy][HWS_HIGH2LOW][7]));
+ }
+ }
+ }
+ }
+
+ /* restore cs enable value */
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ ddr3_tip_if_write(dev, ACCESS_TYPE_UNICAST, iface, DUAL_DUNIT_CFG_REG,
+ cs_ena_reg_val[iface], MASK_ALL_BITS);
+ }
+
+ /* restore pbs (set to 0) */
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ if (mode == RX_DIR)
+ reg_addr = PBS_RX_BCAST_PHY_REG(effective_cs);
+ else
+ reg_addr = PBS_TX_BCAST_PHY_REG(effective_cs);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA, reg_addr, 0);
+ }
+ }
+
+ /* set deskew bias for rx valid window */
+ if (mode == RX_DIR) {
+ /*
+ * pattern special for rx
+ * check for rx_vw_pos stat
+ * - add n pbs taps to every dq to align to left (pbs_max set to (31 - n))
+ * - add pbs taps to dqs to align to right
+ */
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ if (rx_vw_pos[iface][subphy] == ALIGN_LEFT) {
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, 0,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ PBS_RX_BCAST_PHY_REG(effective_cs),
+ VW_DESKEW_BIAS);
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("%s: if %d, subphy %d aligned to left\n",
+ __func__, iface, subphy));
+ } else if (rx_vw_pos[iface][subphy] == ALIGN_RIGHT) {
+ reg_addr = PBS_RX_PHY_REG(effective_cs, DQSP_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, 0,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ reg_addr, VW_DESKEW_BIAS);
+ reg_addr = PBS_RX_PHY_REG(effective_cs, DQSN_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, 0,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ reg_addr, VW_DESKEW_BIAS);
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("%s: if %d , subphy %d aligned to right\n",
+ __func__, iface, subphy));
+ }
+ } /* subphy */
+ } /* if */
+ } else { /* tx mode */
+ /* update wl solution */
+ if (status == MV_OK) {
+ for (iface = 0; iface < MAX_INTERFACE_NUM; iface++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, iface);
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ if (is_dq_dqs_short[subphy]) {
+ wl_tap = ((wl_adll[subphy] >> WR_LVL_REF_DLY_OFFS) &
+ WR_LVL_REF_DLY_MASK) +
+ ((wl_adll[subphy] >> WR_LVL_PH_SEL_OFFS) &
+ WR_LVL_PH_SEL_MASK) * ADLL_TAPS_PER_PHASE;
+ pbs_tap_factor_avg = (pbs_tap_factor[iface][subphy][0] +
+ pbs_tap_factor[iface][subphy][1] +
+ pbs_tap_factor[iface][subphy][2] +
+ pbs_tap_factor[iface][subphy][3] +
+ pbs_tap_factor[iface][subphy][4] +
+ pbs_tap_factor[iface][subphy][5] +
+ pbs_tap_factor[iface][subphy][6] +
+ pbs_tap_factor[iface][subphy][7]) / 8;
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("%s: pbs_tap_factor_avg %d\n",
+ __func__, pbs_tap_factor_avg));
+ new_wl_tap = wl_tap -
+ (dqs_shift[subphy] * pbs_tap_factor_avg) /
+ PBS_VAL_FACTOR;
+ /*
+ * check wraparound due to change in the pbs_tap_factor_avg
+ * vs the first guess
+ */
+ if (new_wl_tap <= 0)
+ new_wl_tap = 0;
+
+ reg_val = (new_wl_tap & WR_LVL_REF_DLY_MASK) |
+ ((new_wl_tap &
+ ((WR_LVL_PH_SEL_MASK << WR_LVL_PH_SEL_OFFS) >> 1))
+ << 1) |
+ (wl_adll[subphy] &
+ ((CTRL_CENTER_DLY_MASK << CTRL_CENTER_DLY_OFFS) |
+ (CTRL_CENTER_DLY_INV_MASK << CTRL_CENTER_DLY_INV_OFFS)));
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), reg_val);
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("%s: tap tune tx algorithm final wl:\n",
+ __func__));
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("%s: subphy %d, dqs pbs %d, old wl %d, final wl %d 0x%08x -> 0x%08x\n",
+ __func__, subphy, pbs_tap_factor_avg,
+ wl_tap, new_wl_tap, wl_adll[subphy],
+ reg_val));
+ }
+ }
+ }
+ } else {
+ /* return to nominal wl */
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA, WL_PHY_REG(effective_cs),
+ wl_adll[subphy]);
+ DEBUG_TAP_TUNING_ENGINE(DEBUG_LEVEL_INFO,
+ ("%s: tap tune failed; return to nominal wl\n",
+ __func__));
+ reg_addr = PBS_TX_PHY_REG(effective_cs, DQSP_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA, reg_addr, 0);
+ reg_addr = PBS_TX_PHY_REG(effective_cs, DQSN_PAD);
+ ddr3_tip_bus_write(dev, ACCESS_TYPE_UNICAST, iface, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA, reg_addr, 0);
+ }
+ }
+ }
+
+ return status;
+}
+
+/* receiver duty cycle flow */
+#define DDR_PHY_JIRA_ENABLE
+int mv_ddr4_receiver_calibration(u8 dev_num)
+{
+ u32 if_id, subphy_num;
+ u32 vref_idx, dq_idx, pad_num = 0;
+ u8 dq_vref_start_win[MAX_INTERFACE_NUM][MAX_BUS_NUM][RECEIVER_DC_MAX_COUNT];
+ u8 dq_vref_end_win[MAX_INTERFACE_NUM][MAX_BUS_NUM][RECEIVER_DC_MAX_COUNT];
+ u8 c_vref[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 valid_win_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 c_opt_per_bus[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 valid_vref_cnt[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 valid_vref_ptr[MAX_INTERFACE_NUM][MAX_BUS_NUM][RECEIVER_DC_MAX_COUNT];
+ u8 center_adll[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 center_vref[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 pbs_res_per_bus[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ u16 lambda_per_dq[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
+ u8 dqs_pbs = 0, const_pbs;
+ int tap_tune_passed = 0;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
+ u8 subphy_max = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+#ifdef DDR_PHY_JIRA_ENABLE
+ u32 dqs_pbs_jira56[MAX_INTERFACE_NUM][MAX_BUS_NUM];
+ u8 delta = 0;
+#endif
+ unsigned int max_cs = mv_ddr_cs_num_get();
+ u32 ctr_x[4], pbs_temp[4];
+ u16 cs_index = 0, pbs_rx_avg, lambda_avg;
+ int status;
+
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO, ("Starting ddr4 dc calibration training stage\n"));
+
+ vdq_tv = 0;
+ duty_cycle = 0;
+
+ /* reset valid vref counter per if and subphy */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++)
+ for (subphy_num = 0; subphy_num < MAX_BUS_NUM; subphy_num++)
+ valid_vref_cnt[if_id][subphy_num] = 0;
+
+ /* calculate pbs-adll tap tuning */
+ /* reset special pattern configuration to re-run this stage */
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR_PHY_DATA, 0x5f + effective_cs * 0x10, 0x0);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR_PHY_DATA, 0x54 + effective_cs * 0x10, 0x0);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ DDR_PHY_DATA, 0x55 + effective_cs * 0x10, 0x0);
+ if (status != MV_OK)
+ return status;
+
+#ifdef DDR_PHY_JIRA_ENABLE
+ if (effective_cs != 0) {
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ status = ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_num,
+ DDR_PHY_DATA, 0x54 + 0 * 0x10,
+ &dqs_pbs_jira56[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA, 0x54 + 0 * 0x10, 0x0);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA, 0x55 + 0 * 0x10, 0x0);
+ if (status != MV_OK)
+ return status;
+ }
+ }
+ }
+#endif
+
+ if (mv_ddr4_tap_tuning(dev_num, lambda_per_dq, RX_DIR) == MV_OK)
+ tap_tune_passed = 1;
+
+ /* main loop for 2d scan (low_to_high voltage scan) */
+ for (duty_cycle = RECEIVER_DC_MIN_RANGE;
+ duty_cycle <= RECEIVER_DC_MAX_RANGE;
+ duty_cycle += RECEIVER_DC_STEP_SIZE) {
+ /* set new receiver dc training value in dram */
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA,
+ VREF_BCAST_PHY_REG(effective_cs), duty_cycle);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA,
+ VREF_PHY_REG(effective_cs, DQSP_PAD), duty_cycle);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA,
+ VREF_PHY_REG(effective_cs, DQSN_PAD), duty_cycle);
+ if (status != MV_OK)
+ return status;
+
+ if (tap_tune_passed == 0) {
+ if (mv_ddr4_tap_tuning(dev_num, lambda_per_dq, RX_DIR) == MV_OK) {
+ tap_tune_passed = 1;
+ } else {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_ERROR,
+ ("rc, tap tune failed inside calibration\n"));
+ continue;
+ }
+ }
+
+ if (mv_ddr4_centralization(dev_num, lambda_per_dq, c_opt_per_bus, pbs_res_per_bus,
+ valid_win_size, RX_DIR, vdq_tv, duty_cycle) != MV_OK) {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_ERROR,
+ ("error: ddr4 centralization failed (duty_cycle %d)!!!\n", duty_cycle));
+ if (debug_mode == 0)
+ break;
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ if (valid_win_size[if_id][subphy_num] > 8) {
+ /* window is valid; keep current duty_cycle value and increment counter */
+ vref_idx = valid_vref_cnt[if_id][subphy_num];
+ valid_vref_ptr[if_id][subphy_num][vref_idx] = duty_cycle;
+ valid_vref_cnt[if_id][subphy_num]++;
+ c_vref[if_id][subphy_num] = c_opt_per_bus[if_id][subphy_num];
+ /* set 0 for possible negative values */
+ dq_vref_start_win[if_id][subphy_num][vref_idx] =
+ c_vref[if_id][subphy_num] + 1 - valid_win_size[if_id][subphy_num] / 2;
+ dq_vref_start_win[if_id][subphy_num][vref_idx] =
+ (valid_win_size[if_id][subphy_num] % 2 == 0) ?
+ dq_vref_start_win[if_id][subphy_num][vref_idx] :
+ dq_vref_start_win[if_id][subphy_num][vref_idx] - 1;
+ dq_vref_end_win[if_id][subphy_num][vref_idx] =
+ c_vref[if_id][subphy_num] + valid_win_size[if_id][subphy_num] / 2;
+ }
+ } /* subphy */
+ } /* if */
+ } /* duty_cycle */
+
+ if (tap_tune_passed == 0) {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("%s: tap tune not passed on any duty_cycle value\n", __func__));
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* report fail for all active interfaces; multi-interface support - tbd */
+ flow_result[if_id] = TEST_FAILED;
+ }
+
+ return MV_FAIL;
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("calculating center of mass for subphy %d, valid window size %d\n",
+ subphy_num, valid_win_size[if_id][subphy_num]));
+ if (valid_vref_cnt[if_id][subphy_num] > 0) {
+ rx_eye_hi_lvl[subphy_num] =
+ valid_vref_ptr[if_id][subphy_num][valid_vref_cnt[if_id][subphy_num] - 1];
+ rx_eye_lo_lvl[subphy_num] = valid_vref_ptr[if_id][subphy_num][0];
+ /* calculate center of mass sampling point (t, v) for each subphy */
+ status = mv_ddr4_center_of_mass_calc(dev_num, if_id, subphy_num, RX_DIR,
+ dq_vref_start_win[if_id][subphy_num],
+ dq_vref_end_win[if_id][subphy_num],
+ valid_vref_ptr[if_id][subphy_num],
+ valid_vref_cnt[if_id][subphy_num],
+ ¢er_vref[if_id][subphy_num],
+ ¢er_adll[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("center of mass results: vref %d, adll %d\n",
+ center_vref[if_id][subphy_num], center_adll[if_id][subphy_num]));
+ } else {
+ DEBUG_CALIBRATION(DEBUG_LEVEL_ERROR,
+ ("%s: no valid window found for cs %d, subphy %d\n",
+ __func__, effective_cs, subphy_num));
+ return MV_FAIL;
+ }
+ }
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_UNICAST, subphy_num, DDR_PHY_DATA,
+ VREF_BCAST_PHY_REG(effective_cs),
+ center_vref[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_UNICAST, subphy_num, DDR_PHY_DATA,
+ VREF_PHY_REG(effective_cs, DQSP_PAD),
+ center_vref[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
+ ACCESS_TYPE_UNICAST, subphy_num, DDR_PHY_DATA,
+ VREF_PHY_REG(effective_cs, DQSN_PAD),
+ center_vref[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO, ("final dc %d\n", center_vref[if_id][subphy_num]));
+ }
+
+ /* run centralization again with optimal vref to update global structures */
+ mv_ddr4_centralization(dev_num, lambda_per_dq, c_opt_per_bus, pbs_res_per_bus, valid_win_size,
+ RX_DIR, 0, center_vref[if_id][0]);
+
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+
+ const_pbs = 0xa;
+ mv_ddr4_dqs_reposition(RX_DIR, lambda_per_dq[if_id][subphy_num],
+ pbs_res_per_bus[if_id][subphy_num], 0x0,
+ ¢er_adll[if_id][subphy_num], &dqs_pbs);
+
+ /* dq pbs update */
+ for (dq_idx = 0; dq_idx < 8 ; dq_idx++) {
+ pad_num = dq_map_table[dq_idx +
+ subphy_num * BUS_WIDTH_IN_BITS +
+ if_id * BUS_WIDTH_IN_BITS * subphy_max];
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ 0x50 + pad_num + effective_cs * 0x10,
+ const_pbs + pbs_res_per_bus[if_id][subphy_num][dq_idx]);
+ if (status != MV_OK)
+ return status;
+ }
+
+ /* dqs pbs update */
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, subphy_num,
+ DDR_PHY_DATA, 0x54 + effective_cs * 0x10, dqs_pbs);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, subphy_num,
+ DDR_PHY_DATA, 0x55 + effective_cs * 0x10, dqs_pbs);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ CRX_PHY_REG(effective_cs),
+ center_adll[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+#ifdef DDR_PHY_JIRA_ENABLE
+ if (effective_cs != 0) {
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA, 0x54 + 0 * 0x10,
+ dqs_pbs_jira56[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA, 0x55 + 0 * 0x10,
+ dqs_pbs_jira56[if_id][subphy_num]);
+ if (status != MV_OK)
+ return status;
+ }
+#endif
+ }
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ /* report pass for all active interfaces; multi-interface support - tbd */
+ flow_result[if_id] = TEST_SUCCESS;
+ }
+
+#ifdef DDR_PHY_JIRA_ENABLE
+ if (effective_cs == (max_cs - 1)) {
+ /* adjust dqs to be as cs0 */
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = 0; subphy_num < subphy_max; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ pbs_rx_avg = 0;
+ /* find average of all pbs of dqs and read ctr_x */
+ for (cs_index = 0; cs_index < max_cs; cs_index++) {
+ status = ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ 0x54 + cs_index * 0x10,
+ &pbs_temp[cs_index]);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ 0x3 + cs_index * 0x4,
+ &ctr_x[cs_index]);
+ if (status != MV_OK)
+ return status;
+
+ pbs_rx_avg = pbs_rx_avg + pbs_temp[cs_index];
+ }
+
+ pbs_rx_avg = pbs_rx_avg / max_cs;
+
+ /* update pbs and ctr_x */
+ lambda_avg = (lambda_per_dq[if_id][subphy_num][0] +
+ lambda_per_dq[if_id][subphy_num][1] +
+ lambda_per_dq[if_id][subphy_num][2] +
+ lambda_per_dq[if_id][subphy_num][3] +
+ lambda_per_dq[if_id][subphy_num][4] +
+ lambda_per_dq[if_id][subphy_num][5] +
+ lambda_per_dq[if_id][subphy_num][6] +
+ lambda_per_dq[if_id][subphy_num][7]) / 8;
+
+ for (cs_index = 0; cs_index < max_cs; cs_index++) {
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST,
+ 0, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ 0x54 + cs_index * 0x10, pbs_rx_avg);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST,
+ 0, ACCESS_TYPE_UNICAST,
+ subphy_num, DDR_PHY_DATA,
+ 0x55 + cs_index * 0x10, pbs_rx_avg);
+ if (status != MV_OK)
+ return status;
+
+ /* update */
+ if (pbs_rx_avg >= pbs_temp[cs_index]) {
+ delta = ((pbs_rx_avg - pbs_temp[cs_index]) * lambda_avg) /
+ PBS_VAL_FACTOR;
+ if (ctr_x[cs_index] >= delta) {
+ ctr_x[cs_index] = ctr_x[cs_index] - delta;
+ } else {
+ ctr_x[cs_index] = 0;
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("jira ddrphy56 extend fix(-) required %d\n",
+ delta));
+ }
+ } else {
+ delta = ((pbs_temp[cs_index] - pbs_rx_avg) * lambda_avg) /
+ PBS_VAL_FACTOR;
+ if ((ctr_x[cs_index] + delta) > 32) {
+ ctr_x[cs_index] = 32;
+ DEBUG_CALIBRATION(DEBUG_LEVEL_INFO,
+ ("jira ddrphy56 extend fix(+) required %d\n",
+ delta));
+ } else {
+ ctr_x[cs_index] = (ctr_x[cs_index] + delta);
+ }
+ }
+ status = ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, subphy_num, DDR_PHY_DATA,
+ CRX_PHY_REG(effective_cs),
+ ctr_x[cs_index]);
+ if (status != MV_OK)
+ return status;
+ }
+ }
+ }
+ }
+#endif
+
+ return MV_OK;
+}
+
+#define MAX_LOOPS 2 /* maximum number of loops to get to solution */
+#define LEAST_SIGNIFICANT_BYTE_MASK 0xff
+#define VW_SUBPHY_LIMIT_MIN 0
+#define VW_SUBPHY_LIMIT_MAX 127
+#define MAX_PBS_NUM 31 /* TODO: added by another patch */
+enum{
+ LOCKED,
+ UNLOCKED
+};
+enum {
+ PASS,
+ FAIL
+};
+
+int mv_ddr4_dm_tuning(u32 cs, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS])
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ enum hws_training_ip_stat training_result;
+ enum hws_training_result result_type = RESULT_PER_BIT;
+ enum hws_search_dir search_dir;
+ enum hws_dir dir = OPER_WRITE;
+ int vw_sphy_hi_diff = 0;
+ int vw_sphy_lo_diff = 0;
+ int x, y;
+ int status;
+ unsigned int a, b, c;
+ u32 ctx_vector[MAX_BUS_NUM];
+ u32 subphy, bit, pattern;
+ u32 *result[MAX_BUS_NUM][HWS_SEARCH_DIR_LIMIT];
+ u32 max_win_size = MAX_WINDOW_SIZE_TX;
+ u32 dm_lambda[MAX_BUS_NUM] = {0};
+ u32 loop;
+ u32 adll_tap;
+ u32 dm_pbs, max_pbs;
+ u32 dq_pbs[BUS_WIDTH_IN_BITS];
+ u32 new_dq_pbs[BUS_WIDTH_IN_BITS];
+ u32 dq, pad;
+ u32 dq_pbs_diff;
+ u32 byte_center, dm_center;
+ u32 idx, reg_val;
+ u32 dm_pad = mv_ddr_dm_pad_get();
+ u8 subphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ u8 dm_vw_vector[MAX_BUS_NUM * ADLL_TAPS_PER_PERIOD];
+ u8 vw_sphy_lo_lmt[MAX_BUS_NUM];
+ u8 vw_sphy_hi_lmt[MAX_BUS_NUM];
+ u8 dm_status[MAX_BUS_NUM];
+
+ /* init */
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ dm_status[subphy] = UNLOCKED;
+ for (bit = 0 ; bit < BUS_WIDTH_IN_BITS; bit++)
+ dm_lambda[subphy] += pbs_tap_factor[0][subphy][bit];
+ dm_lambda[subphy] /= BUS_WIDTH_IN_BITS;
+ }
+
+ /* get algorithm's adll result */
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ ddr3_tip_bus_read(0, 0, ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ CTX_PHY_REG(cs), ®_val);
+ ctx_vector[subphy] = reg_val;
+ }
+
+ for (loop = 0; loop < MAX_LOOPS; loop++) {
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ vw_sphy_lo_lmt[subphy] = VW_SUBPHY_LIMIT_MIN;
+ vw_sphy_hi_lmt[subphy] = VW_SUBPHY_LIMIT_MAX;
+ for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) {
+ idx = subphy * ADLL_TAPS_PER_PERIOD + adll_tap;
+ dm_vw_vector[idx] = PASS;
+ }
+ }
+
+ /* get valid window of dm signal */
+ mv_ddr_dm_vw_get(PATTERN_ZERO, cs, dm_vw_vector);
+ mv_ddr_dm_vw_get(PATTERN_ONE, cs, dm_vw_vector);
+
+ /* get vw for dm disable */
+ pattern = MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) ? 73 : 23;
+ ddr3_tip_ip_training_wrapper(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
+ PARAM_NOT_CARE, result_type, HWS_CONTROL_ELEMENT_ADLL, PARAM_NOT_CARE,
+ dir, tm->if_act_mask, 0x0, max_win_size - 1, max_win_size - 1, pattern,
+ EDGE_FPF, CS_SINGLE, PARAM_NOT_CARE, &training_result);
+
+ /* find skew of dm signal vs. dq data bits using its valid window */
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ CTX_PHY_REG(cs), ctx_vector[subphy]);
+
+ for (search_dir = HWS_LOW2HIGH; search_dir <= HWS_HIGH2LOW; search_dir++) {
+ ddr3_tip_read_training_result(0, 0, ACCESS_TYPE_UNICAST, subphy,
+ ALL_BITS_PER_PUP, search_dir, dir, result_type,
+ TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
+ &(result[subphy][search_dir]),
+ 1, 0, 0);
+ DEBUG_DM_TUNING(DEBUG_LEVEL_INFO,
+ ("dm cs %d if %d subphy %d result: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ cs, 0, subphy,
+ result[subphy][search_dir][0],
+ result[subphy][search_dir][1],
+ result[subphy][search_dir][2],
+ result[subphy][search_dir][3],
+ result[subphy][search_dir][4],
+ result[subphy][search_dir][5],
+ result[subphy][search_dir][6],
+ result[subphy][search_dir][7]));
+ }
+
+ if (dm_status[subphy] == LOCKED)
+ continue;
+
+ for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
+ result[subphy][HWS_LOW2HIGH][bit] &= LEAST_SIGNIFICANT_BYTE_MASK;
+ result[subphy][HWS_HIGH2LOW][bit] &= LEAST_SIGNIFICANT_BYTE_MASK;
+
+ if (result[subphy][HWS_LOW2HIGH][bit] > vw_sphy_lo_lmt[subphy])
+ vw_sphy_lo_lmt[subphy] = result[subphy][HWS_LOW2HIGH][bit];
+
+ if (result[subphy][HWS_HIGH2LOW][bit] < vw_sphy_hi_lmt[subphy])
+ vw_sphy_hi_lmt[subphy] = result[subphy][HWS_HIGH2LOW][bit];
+ }
+
+ DEBUG_DM_TUNING(DEBUG_LEVEL_INFO,
+ ("loop %d, dm subphy %d, vw %d, %d\n", loop, subphy,
+ vw_sphy_lo_lmt[subphy], vw_sphy_hi_lmt[subphy]));
+
+ idx = subphy * ADLL_TAPS_PER_PERIOD;
+ status = mv_ddr_dm_to_dq_diff_get(vw_sphy_hi_lmt[subphy], vw_sphy_lo_lmt[subphy],
+ &dm_vw_vector[idx], &vw_sphy_hi_diff, &vw_sphy_lo_diff);
+ if (status != MV_OK)
+ return MV_FAIL;
+ DEBUG_DM_TUNING(DEBUG_LEVEL_INFO,
+ ("vw_sphy_lo_diff %d, vw_sphy_hi_diff %d\n",
+ vw_sphy_lo_diff, vw_sphy_hi_diff));
+
+ /* dm is the strongest signal */
+ if ((vw_sphy_hi_diff >= 0) &&
+ (vw_sphy_lo_diff >= 0)) {
+ dm_status[subphy] = LOCKED;
+ } else if ((vw_sphy_hi_diff >= 0) &&
+ (vw_sphy_lo_diff < 0) &&
+ (loop == 0)) { /* update dm only */
+ ddr3_tip_bus_read(0, 0, ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, dm_pad), &dm_pbs);
+ x = -vw_sphy_lo_diff; /* get positive x */
+ a = (unsigned int)x * PBS_VAL_FACTOR;
+ b = dm_lambda[subphy];
+ if (round_div(a, b, &c) != MV_OK)
+ return MV_FAIL;
+ dm_pbs += (u32)c;
+ dm_pbs = (dm_pbs > MAX_PBS_NUM) ? MAX_PBS_NUM : dm_pbs;
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, dm_pad), dm_pbs);
+ } else if ((vw_sphy_hi_diff < 0) &&
+ (vw_sphy_lo_diff >= 0) &&
+ (loop == 0)) { /* update dq and c_opt */
+ max_pbs = 0;
+ for (dq = 0; dq < BUS_WIDTH_IN_BITS; dq++) {
+ idx = dq + subphy * BUS_WIDTH_IN_BITS;
+ pad = dq_map_table[idx];
+ ddr3_tip_bus_read(0, 0, ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, pad), ®_val);
+ dq_pbs[dq] = reg_val;
+ x = -vw_sphy_hi_diff; /* get positive x */
+ a = (unsigned int)x * PBS_VAL_FACTOR;
+ b = pbs_tap_factor[0][subphy][dq];
+ if (round_div(a, b, &c) != MV_OK)
+ return MV_FAIL;
+ new_dq_pbs[dq] = dq_pbs[dq] + (u32)c;
+ if (max_pbs < new_dq_pbs[dq])
+ max_pbs = new_dq_pbs[dq];
+ }
+
+ dq_pbs_diff = (max_pbs > MAX_PBS_NUM) ? (max_pbs - MAX_PBS_NUM) : 0;
+ for (dq = 0; dq < BUS_WIDTH_IN_BITS; dq++) {
+ idx = dq + subphy * BUS_WIDTH_IN_BITS;
+ reg_val = new_dq_pbs[dq] - dq_pbs_diff;
+ if (reg_val < 0) {
+ DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR,
+ ("unexpected negative value found\n"));
+ return MV_FAIL;
+ }
+ pad = dq_map_table[idx];
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0,
+ ACCESS_TYPE_UNICAST, subphy,
+ DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, pad),
+ reg_val);
+ }
+
+ a = dm_lambda[subphy];
+ b = dq_pbs_diff * PBS_VAL_FACTOR;
+ if (b > 0) {
+ if (round_div(a, b, &c) != MV_OK)
+ return MV_FAIL;
+ dq_pbs_diff = (u32)c;
+ }
+
+ x = (int)ctx_vector[subphy];
+ if (x < 0) {
+ DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR,
+ ("unexpected negative value found\n"));
+ return MV_FAIL;
+ }
+ y = (int)dq_pbs_diff;
+ if (y < 0) {
+ DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR,
+ ("unexpected negative value found\n"));
+ return MV_FAIL;
+ }
+ x += (y + vw_sphy_hi_diff) / 2;
+ x %= ADLL_TAPS_PER_PERIOD;
+ ctx_vector[subphy] = (u32)x;
+ } else if (((vw_sphy_hi_diff < 0) && (vw_sphy_lo_diff < 0)) ||
+ (loop == 1)) { /* dm is the weakest signal */
+ /* update dq and c_opt */
+ dm_status[subphy] = LOCKED;
+ byte_center = (vw_sphy_lo_lmt[subphy] + vw_sphy_hi_lmt[subphy]) / 2;
+ x = (int)byte_center;
+ if (x < 0) {
+ DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR,
+ ("unexpected negative value found\n"));
+ return MV_FAIL;
+ }
+ x += (vw_sphy_hi_diff - vw_sphy_lo_diff) / 2;
+ if (x < 0) {
+ DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR,
+ ("unexpected negative value found\n"));
+ return MV_FAIL;
+ }
+ dm_center = (u32)x;
+
+ if (byte_center > dm_center) {
+ max_pbs = 0;
+ for (dq = 0; dq < BUS_WIDTH_IN_BITS; dq++) {
+ pad = dq_map_table[dq + subphy * BUS_WIDTH_IN_BITS];
+ ddr3_tip_bus_read(0, 0, ACCESS_TYPE_UNICAST,
+ subphy, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, pad),
+ ®_val);
+ dq_pbs[dq] = reg_val;
+ a = (byte_center - dm_center) * PBS_VAL_FACTOR;
+ b = pbs_tap_factor[0][subphy][dq];
+ if (round_div(a, b, &c) != MV_OK)
+ return MV_FAIL;
+ new_dq_pbs[dq] = dq_pbs[dq] + (u32)c;
+ if (max_pbs < new_dq_pbs[dq])
+ max_pbs = new_dq_pbs[dq];
+ }
+
+ dq_pbs_diff = (max_pbs > MAX_PBS_NUM) ? (max_pbs - MAX_PBS_NUM) : 0;
+ for (int dq = 0; dq < BUS_WIDTH_IN_BITS; dq++) {
+ idx = dq + subphy * BUS_WIDTH_IN_BITS;
+ pad = dq_map_table[idx];
+ reg_val = new_dq_pbs[dq] - dq_pbs_diff;
+ if (reg_val < 0) {
+ DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR,
+ ("unexpected negative value found\n"));
+ return MV_FAIL;
+ }
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, pad),
+ reg_val);
+ }
+ ctx_vector[subphy] = dm_center % ADLL_TAPS_PER_PERIOD;
+ } else {
+ ddr3_tip_bus_read(0, 0, ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, dm_pad), &dm_pbs);
+ a = (dm_center - byte_center) * PBS_VAL_FACTOR;
+ b = dm_lambda[subphy];
+ if (round_div(a, b, &c) != MV_OK)
+ return MV_FAIL;
+ dm_pbs += (u32)c;
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0,
+ ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ PBS_TX_PHY_REG(cs, dm_pad), dm_pbs);
+ }
+ } else {
+ /* below is the check whether dm signal per subphy converged or not */
+ }
+ }
+ }
+
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, subphy, DDR_PHY_DATA,
+ CTX_PHY_REG(cs), ctx_vector[subphy]);
+ }
+
+ for (subphy = 0; subphy < subphy_max; subphy++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy);
+ if (dm_status[subphy] != LOCKED) {
+ DEBUG_DM_TUNING(DEBUG_LEVEL_ERROR,
+ ("no convergence for dm signal[%u] found\n", subphy));
+ return MV_FAIL;
+ }
+ }
+
+ return MV_OK;
+}
+void refresh(void)
+{
+ u32 data_read[MAX_INTERFACE_NUM];
+ ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, data_read, MASK_ALL_BITS);
+
+ /* Refresh Command for CS0*/
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, (0 << 26), (3 << 26));
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, SDRAM_OP_REG, 0xe02, 0xf1f);
+ if (ddr3_tip_if_polling(0, ACCESS_TYPE_UNICAST, 0, 0, 0x1f, SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("DDR3 poll failed"));
+
+ /* Refresh Command for CS1*/
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, (1 << 26), (3 << 26));
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, SDRAM_OP_REG, 0xd02, 0xf1f);
+ if (ddr3_tip_if_polling(0, ACCESS_TYPE_UNICAST, 0, 0, 0x1f, SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("DDR3 poll failed"));
+
+ /* Restore Register*/
+ ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, data_read[0] , MASK_ALL_BITS);
+}
+#endif /* CONFIG_DDR4 */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.h b/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.h
new file mode 100644
index 0000000..da4a866
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_training_calibration.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR4_TRAINING_CALIBRATION_H
+#define _MV_DDR4_TRAINING_CALIBRATION_H
+
+/* vref subphy calibration state */
+enum mv_ddr4_vref_subphy_cal_state {
+ MV_DDR4_VREF_SUBPHY_CAL_ABOVE,
+ MV_DDR4_VREF_SUBPHY_CAL_UNDER,
+ MV_DDR4_VREF_SUBPHY_CAL_INSIDE,
+ MV_DDR4_VREF_SUBPHY_CAL_END
+};
+
+/* calibrate DDR4 dq vref (tx) */
+int mv_ddr4_dq_vref_calibration(u8 dev_num, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]);
+
+/* calibrate receiver (receiver duty cycle) */
+int mv_ddr4_receiver_calibration(u8 dev_num);
+
+/* tune dm signal */
+int mv_ddr4_dm_tuning(u32 cs, u16 (*pbs_tap_factor)[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]);
+
+#endif /* _MV_DDR4_TRAINING_CALIBRATION_H */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training_db.c b/drivers/ddr/marvell/a38x/mv_ddr4_training_db.c
new file mode 100644
index 0000000..1baa63a
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_training_db.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#if defined(CONFIG_DDR4)
+
+/* DDR4 Training Database */
+
+#include "ddr_ml_wrapper.h"
+
+#include "mv_ddr_topology.h"
+#include "mv_ddr_training_db.h"
+#include "ddr_topology_def.h"
+
+/* list of allowed frequencies listed in order of enum mv_ddr_freq */
+static unsigned int freq_val[MV_DDR_FREQ_LAST] = {
+ 130, /* MV_DDR_FREQ_LOW_FREQ */
+ 650, /* MV_DDR_FREQ_650 */
+ 666, /* MV_DDR_FREQ_667 */
+ 800, /* MV_DDR_FREQ_800 */
+ 933, /* MV_DDR_FREQ_933 */
+ 1066, /* MV_DDR_FREQ_1066 */
+ 900, /* MV_DDR_FREQ_900 */
+ 1000, /* MV_DDR_FREQ_1000 */
+ 1050, /* MV_DDR_FREQ_1050 */
+ 1200, /* MV_DDR_FREQ_1200 */
+ 1333, /* MV_DDR_FREQ_1333 */
+ 1466, /* MV_DDR_FREQ_1466 */
+ 1600 /* MV_DDR_FREQ_1600 */
+};
+
+unsigned int *mv_ddr_freq_tbl_get(void)
+{
+ return &freq_val[0];
+}
+
+u32 mv_ddr_freq_get(enum mv_ddr_freq freq)
+{
+ return freq_val[freq];
+}
+
+/* non-dbi mode - table for cl values per frequency for each speed bin index */
+static struct mv_ddr_cl_val_per_freq cl_table[] = {
+/* 130 650 667 800 933 1067 900 1000 1050 1200 1333 1466 1600 FREQ(MHz)*/
+/* 7.69 1.53 1.5 1.25 1.07 0.937 1.11 1 0.95 0.83 0.75 0.68 0.625 TCK(ns)*/
+ {{10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600J */
+ {{10, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600K */
+ {{10, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600L */
+ {{10, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866L */
+ {{10, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866M */
+ {{10, 12, 12, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866N */
+ {{10, 10, 10, 12, 14, 14, 14, 14, 14, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2133N */
+ {{10, 9, 9, 12, 14, 15, 14, 15, 15, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2133P */
+ {{10, 10, 10, 12, 14, 16, 14, 16, 16, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2133R */
+ {{10, 10, 10, 12, 14, 16, 14, 16, 16, 18, 0, 0, 0} },/* SPEED_BIN_DDR_2400P */
+ {{10, 9, 9, 11, 13, 15, 13, 15, 15, 18, 0, 0, 0} },/* SPEED_BIN_DDR_2400R */
+ {{10, 9, 9, 11, 13, 15, 13, 15, 15, 17, 0, 0, 0} },/* SPEED_BIN_DDR_2400T */
+ {{10, 10, 10, 12, 14, 16, 14, 16, 16, 18, 0, 0, 0} },/* SPEED_BIN_DDR_2400U */
+ {{10, 10, 10, 11, 13, 15, 13, 15, 15, 16, 17, 0, 0} },/* SPEED_BIN_DDR_2666T */
+ {{10, 9, 10, 11, 13, 15, 13, 15, 15, 17, 18, 0, 0} },/* SPEED_BIN_DDR_2666U */
+ {{10, 9, 10, 12, 14, 16, 14, 16, 16, 18, 19, 0, 0} },/* SPEED_BIN_DDR_2666V */
+ {{10, 10, 10, 12, 14, 16, 14, 16, 16, 18, 20, 0, 0} },/* SPEED_BIN_DDR_2666W */
+ {{10, 10, 9, 11, 13, 15, 13, 15, 15, 16, 18, 19, 0} },/* SPEED_BIN_DDR_2933V */
+ {{10, 9, 10, 11, 13, 15, 13, 15, 15, 17, 19, 20, 0} },/* SPEED_BIN_DDR_2933W */
+ {{10, 9, 10, 12, 14, 16, 14, 16, 16, 18, 20, 21, 0} },/* SPEED_BIN_DDR_2933Y */
+ {{10, 10, 10, 12, 14, 16, 14, 16, 16, 18, 20, 22, 0} },/* SPEED_BIN_DDR_2933AA*/
+ {{10, 10, 9, 11, 13, 15, 13, 15, 15, 16, 18, 20, 20} },/* SPEED_BIN_DDR_3200W */
+ {{10, 9, 0, 11, 13, 15, 13, 15, 15, 17, 19, 22, 22} },/* SPEED_BIN_DDR_3200AA*/
+ {{10, 9, 10, 12, 14, 16, 14, 16, 16, 18, 20, 24, 24} } /* SPEED_BIN_DDR_3200AC*/
+
+};
+
+u32 mv_ddr_cl_val_get(u32 index, u32 freq)
+{
+ return cl_table[index].cl_val[freq];
+}
+
+/* dbi mode - table for cl values per frequency for each speed bin index */
+struct mv_ddr_cl_val_per_freq cas_latency_table_dbi[] = {
+/* 130 650 667 800 933 1067 900 1000 1050 1200 1333 1466 1600 FREQ(MHz)*/
+/* 7.69 1.53 1.5 1.25 1.07 0.937 1.11 1 0.95 0.83 0.75 0.68 0.625 TCK(ns)*/
+ {{0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600J */
+ {{0, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600K */
+ {{0, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600L */
+ {{0, 14, 14, 14, 0, 0, 14, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866L */
+ {{0, 14, 14, 15, 0, 0, 15, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866M */
+ {{0, 14, 14, 16, 0, 0, 16, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866N */
+ {{0, 12, 12, 14, 16, 17, 14, 17, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2133N */
+ {{0, 11, 11, 14, 16, 18, 14, 18, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2133P */
+ {{0, 12, 12, 14, 16, 19, 14, 19, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2133R */
+ {{0, 12, 12, 14, 16, 19, 14, 19, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2400P */
+ {{0, 11, 11, 13, 15, 18, 13, 18, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2400R */
+ {{0, 11, 11, 13, 15, 18, 13, 18, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2400T */
+ {{0, 12, 12, 14, 16, 19, 14, 19, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_2400U */
+ {{10, 10, 11, 13, 15, 18, 13, 18, 18, 19, 20, 0, 0} },/* SPEED_BIN_DDR_2666T */
+ {{10, 9, 11, 13, 15, 18, 13, 18, 18, 20, 21, 0, 0} },/* SPEED_BIN_DDR_2666U */
+ {{10, 9, 12, 14, 16, 19, 14, 19, 19, 21, 22, 0, 0} },/* SPEED_BIN_DDR_2666V */
+ {{10, 10, 12, 14, 16, 19, 14, 19, 19, 21, 23, 0, 0} },/* SPEED_BIN_DDR_2666W */
+ {{10, 10, 11, 13, 15, 18, 15, 18, 18, 19, 21, 23, 0} },/* SPEED_BIN_DDR_2933V */
+ {{10, 9, 12, 13, 15, 18, 15, 18, 18, 20, 22, 24, 0} },/* SPEED_BIN_DDR_2933W */
+ {{10, 9, 12, 14, 16, 19, 16, 19, 19, 21, 23, 26, 0} },/* SPEED_BIN_DDR_2933Y */
+ {{10, 10, 12, 14, 16, 19, 16, 19, 19, 21, 23, 26, 0} },/* SPEED_BIN_DDR_2933AA*/
+ {{10, 10, 11, 13, 15, 18, 15, 18, 18, 19, 21, 24, 24} },/* SPEED_BIN_DDR_3200W */
+ {{10, 9, 0, 13, 15, 18, 15, 18, 18, 20, 22, 26, 26} },/* SPEED_BIN_DDR_3200AA*/
+ {{10, 9, 12, 14, 16, 19, 16, 19, 19, 21, 23, 28, 28} } /* SPEED_BIN_DDR_3200AC*/
+};
+
+/* table for cwl values per speed bin index */
+static struct mv_ddr_cl_val_per_freq cwl_table[] = {
+/* 130 650 667 800 933 1067 900 1000 1050 1200 1333 1466 1600 FREQ(MHz)*/
+/* 7.69 1.53 1.5 1.25 1.07 0.937 1.11 1 0.95 0.83 0.75 0.68 0.625 TCK(ns)*/
+ {{9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600J */
+ {{9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600K */
+ {{9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1600L */
+ {{9, 9, 9, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866L */
+ {{9, 9, 9, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866M */
+ {{9, 9, 9, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0} },/* SPEED_BIN_DDR_1866N */
+ {{9, 9, 9, 9, 10, 11, 10, 11, 10, 11, 0, 0, 0} },/* SPEED_BIN_DDR_2133N */
+ {{9, 9, 9, 9, 10, 11, 10, 11, 10, 11, 0, 0, 0} },/* SPEED_BIN_DDR_2133P */
+ {{9, 9, 9, 10, 10, 11, 10, 11, 10, 11, 0, 0, 0} },/* SPEED_BIN_DDR_2133R */
+ {{9, 9, 9, 9, 10, 11, 10, 11, 10, 12, 0, 0, 0} },/* SPEED_BIN_DDR_2400P */
+ {{9, 9, 9, 9, 10, 11, 10, 11, 10, 12, 0, 0, 0} },/* SPEED_BIN_DDR_2400R */
+ {{9, 9, 9, 9, 10, 11, 10, 11, 10, 12, 0, 0, 0} },/* SPEED_BIN_DDR_2400T */
+ {{9, 9, 9, 9, 10, 11, 10, 11, 10, 12, 0, 0, 0} },/* SPEED_BIN_DDR_2400U */
+ {{10, 10, 9, 9, 10, 11, 10, 11, 11, 12, 14, 0, 0} },/* SPEED_BIN_DDR_2666T */
+ {{10, 9, 9, 9, 10, 11, 10, 11, 11, 12, 14, 0, 0} },/* SPEED_BIN_DDR_2666U */
+ {{10, 9, 9, 9, 10, 11, 10, 11, 11, 12, 14, 0, 0} },/* SPEED_BIN_DDR_2666V */
+ {{10, 10, 9, 9, 10, 11, 10, 11, 11, 12, 14, 0, 0} },/* SPEED_BIN_DDR_2666W */
+ {{10, 10, 9, 9, 10, 11, 10, 11, 11, 12, 14, 16, 0} },/* SPEED_BIN_DDR_2933V */
+ {{10, 9, 9, 9, 10, 11, 10, 11, 11, 12, 14, 16, 0} },/* SPEED_BIN_DDR_2933W */
+ {{10, 9, 9, 9, 10, 11, 10, 11, 11, 12, 14, 16, 0} },/* SPEED_BIN_DDR_2933Y */
+ {{10, 10, 9, 9, 10, 11, 10, 11, 11, 12, 14, 16, 0} },/* SPEED_BIN_DDR_2933AA*/
+ {{10, 10, 9, 9, 10, 11, 10, 11, 11, 12, 14, 16, 16} },/* SPEED_BIN_DDR_3200W */
+ {{10, 9, 9, 9, 10, 11, 10, 11, 11, 12, 14, 16, 16} },/* SPEED_BIN_DDR_3200AA*/
+ {{10, 9, 9, 9, 10, 11, 10, 11, 11, 12, 14, 16, 16} } /* SPEED_BIN_DDR_3200AC*/
+};
+
+u32 mv_ddr_cwl_val_get(u32 index, u32 freq)
+{
+ return cwl_table[index].cl_val[freq];
+}
+
+/*
+ * rfc values, ns
+ * note: values per JEDEC speed bin 1866; TODO: check it
+ */
+static unsigned int rfc_table[] = {
+ 0, /* placholder */
+ 0, /* placholder */
+ 160, /* 2G */
+ 260, /* 4G */
+ 350, /* 8G */
+ 0, /* TODO: placeholder for 16-Mbit die capacity */
+ 0, /* TODO: placeholder for 32-Mbit die capacity*/
+ 0, /* TODO: placeholder for 12-Mbit die capacity */
+ 0 /* TODO: placeholder for 24-Mbit die capacity */
+};
+
+u32 mv_ddr_rfc_get(u32 mem)
+{
+ return rfc_table[mem];
+}
+
+u16 rtt_table[] = {
+ 0xffff,
+ 60,
+ 120,
+ 40,
+ 240,
+ 48,
+ 80,
+ 34
+};
+
+u8 twr_mask_table[] = {
+ 0xa,
+ 0xa,
+ 0xa,
+ 0xa,
+ 0xa,
+ 0xa,
+ 0xa,
+ 0xa,
+ 0xa,
+ 0xa,
+ 0x0, /* 10 */
+ 0xa,
+ 0x1, /* 12 */
+ 0xa,
+ 0x2, /* 14 */
+ 0xa,
+ 0x3, /* 16 */
+ 0xa,
+ 0x4, /* 18 */
+ 0xa,
+ 0x5, /* 20 */
+ 0xa,
+ 0xa, /* 22 */
+ 0xa,
+ 0x6 /* 24 */
+};
+
+u8 cl_mask_table[] = {
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1, /* 10 */
+ 0x2,
+ 0x3, /* 12 */
+ 0x4,
+ 0x5, /* 14 */
+ 0x6,
+ 0x7, /* 16 */
+ 0xd,
+ 0x8, /* 18 */
+ 0x0,
+ 0x9, /* 20 */
+ 0x0,
+ 0xa, /* 22 */
+ 0x0,
+ 0xb /* 24 */
+};
+
+u8 cwl_mask_table[] = {
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1, /* 10 */
+ 0x2,
+ 0x3, /* 12 */
+ 0x0,
+ 0x4, /* 14 */
+ 0x0,
+ 0x5, /* 16 */
+ 0x0,
+ 0x6 /* 18 */
+};
+
+u32 speed_bin_table_t_rcd_t_rp[] = {
+ 12500,
+ 13750,
+ 15000,
+ 12850,
+ 13920,
+ 15000,
+ 13130,
+ 14060,
+ 15000,
+ 12500,
+ 13320,
+ 14160,
+ 15000,
+ 12750,
+ 13500,
+ 14250,
+ 15000,
+ 12960,
+ 13640,
+ 14320,
+ 15000,
+ 12500,
+ 13750,
+ 15000
+};
+
+u32 speed_bin_table_t_rc[] = {
+ 47500,
+ 48750,
+ 50000,
+ 46850,
+ 47920,
+ 49000,
+ 46130,
+ 47060,
+ 48000,
+ 44500,
+ 45320,
+ 46160,
+ 47000,
+ 44750,
+ 45500,
+ 46250,
+ 47000,
+ 44960,
+ 45640,
+ 46320,
+ 47000,
+ 44500,
+ 45750,
+ 47000
+};
+
+static struct mv_ddr_page_element page_tbl[] = {
+ /* 8-bit, 16-bit page size */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 512M */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 1G */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 2G */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 4G */
+ {MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 8G */
+ {0, 0}, /* TODO: placeholder for 16-Mbit die capacity */
+ {0, 0}, /* TODO: placeholder for 32-Mbit die capacity */
+ {0, 0}, /* TODO: placeholder for 12-Mbit die capacity */
+ {0, 0} /* TODO: placeholder for 24-Mbit die capacity */
+};
+
+u32 mv_ddr_page_size_get(enum mv_ddr_dev_width bus_width, enum mv_ddr_die_capacity mem_size)
+{
+ if (bus_width == MV_DDR_DEV_WIDTH_8BIT)
+ return page_tbl[mem_size].page_size_8bit;
+ else
+ return page_tbl[mem_size].page_size_16bit;
+}
+
+/* DLL locking time, tDLLK */
+#define MV_DDR_TDLLK_DDR4_1600 597
+#define MV_DDR_TDLLK_DDR4_1866 597
+#define MV_DDR_TDLLK_DDR4_2133 768
+#define MV_DDR_TDLLK_DDR4_2400 768
+#define MV_DDR_TDLLK_DDR4_2666 854
+#define MV_DDR_TDLLK_DDR4_2933 940
+#define MV_DDR_TDLLK_DDR4_3200 1024
+static int mv_ddr_tdllk_get(unsigned int freq, unsigned int *tdllk)
+{
+ if (freq >= 1600)
+ *tdllk = MV_DDR_TDLLK_DDR4_3200;
+ else if (freq >= 1466)
+ *tdllk = MV_DDR_TDLLK_DDR4_2933;
+ else if (freq >= 1333)
+ *tdllk = MV_DDR_TDLLK_DDR4_2666;
+ else if (freq >= 1200)
+ *tdllk = MV_DDR_TDLLK_DDR4_2400;
+ else if (freq >= 1066)
+ *tdllk = MV_DDR_TDLLK_DDR4_2133;
+ else if (freq >= 933)
+ *tdllk = MV_DDR_TDLLK_DDR4_1866;
+ else if (freq >= 800)
+ *tdllk = MV_DDR_TDLLK_DDR4_1600;
+ else {
+ printf("error: %s: unsupported data rate found\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* return speed bin value for selected index and element */
+unsigned int mv_ddr_speed_bin_timing_get(enum mv_ddr_speed_bin index, enum mv_ddr_speed_bin_timing element)
+{
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ unsigned int freq;
+ u32 result = 0;
+
+ /* get frequency in MHz */
+ freq = mv_ddr_freq_get(tm->interface_params[0].memory_freq);
+
+ switch (element) {
+ case SPEED_BIN_TRCD:
+ case SPEED_BIN_TRP:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TRCD_MIN];
+ else
+ result = speed_bin_table_t_rcd_t_rp[index];
+ break;
+ case SPEED_BIN_TRAS:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TRAS_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 35000;
+ else if (index <= SPEED_BIN_DDR_1866N)
+ result = 34000;
+ else if (index <= SPEED_BIN_DDR_2133R)
+ result = 33000;
+ else
+ result = 32000;
+ }
+ break;
+ case SPEED_BIN_TRC:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TRC_MIN];
+ else
+ result = speed_bin_table_t_rc[index];
+ break;
+ case SPEED_BIN_TRRD0_5K:
+ case SPEED_BIN_TRRD1K:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TRRD_S_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 5000;
+ else if (index <= SPEED_BIN_DDR_1866N)
+ result = 4200;
+ else if (index <= SPEED_BIN_DDR_2133R)
+ result = 3700;
+ else if (index <= SPEED_BIN_DDR_2400U)
+ result = 3500;
+ else if (index <= SPEED_BIN_DDR_2666W)
+ result = 3000;
+ else if (index <= SPEED_BIN_DDR_2933AA)
+ result = 2700;
+ else
+ result = 2500;
+ }
+ break;
+ case SPEED_BIN_TRRD2K:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TRRD_S_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 6000;
+ else
+ result = 5300;
+ }
+
+ break;
+ case SPEED_BIN_TRRDL0_5K:
+ case SPEED_BIN_TRRDL1K:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TRRD_L_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 6000;
+ else if (index <= SPEED_BIN_DDR_2133R)
+ result = 5300;
+ else
+ result = 4900;
+ }
+ break;
+ case SPEED_BIN_TRRDL2K:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TRRD_L_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 7500;
+ else
+ result = 6400;
+ }
+ break;
+ case SPEED_BIN_TPD:
+ result = 5000;
+ break;
+ case SPEED_BIN_TFAW0_5K:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TFAW_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 20000;
+ else if (index <= SPEED_BIN_DDR_1866N)
+ result = 17000;
+ else if (index <= SPEED_BIN_DDR_2133R)
+ result = 15000;
+ else if (index <= SPEED_BIN_DDR_2400U)
+ result = 13000;
+ else if (index <= SPEED_BIN_DDR_2666W)
+ result = 12000;
+ else if (index <= SPEED_BIN_DDR_2933AA)
+ result = 10875;
+ else
+ result = 10000;
+ }
+ break;
+ case SPEED_BIN_TFAW1K:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TFAW_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 25000;
+ else if (index <= SPEED_BIN_DDR_1866N)
+ result = 23000;
+ else
+ result = 21000;
+ }
+ break;
+ case SPEED_BIN_TFAW2K:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TFAW_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 35000;
+ else
+ result = 30000;
+ }
+ break;
+ case SPEED_BIN_TWTR:
+ result = 2500;
+ /* FIXME: wa: set twtr_s to a default value, if it's unset on spd */
+ if (tm->cfg_src == MV_DDR_CFG_SPD && tm->timing_data[MV_DDR_TWTR_S_MIN])
+ result = tm->timing_data[MV_DDR_TWTR_S_MIN];
+ break;
+ case SPEED_BIN_TWTRL:
+ case SPEED_BIN_TRTP:
+ result = 7500;
+ /* FIXME: wa: set twtr_l to a default value, if it's unset on spd */
+ if (tm->cfg_src == MV_DDR_CFG_SPD && tm->timing_data[MV_DDR_TWTR_L_MIN])
+ result = tm->timing_data[MV_DDR_TWTR_L_MIN];
+ break;
+ case SPEED_BIN_TWR:
+ case SPEED_BIN_TMOD:
+ result = 15000;
+ /* FIXME: wa: set twr to a default value, if it's unset on spd */
+ if (tm->cfg_src == MV_DDR_CFG_SPD && tm->timing_data[MV_DDR_TWR_MIN])
+ result = tm->timing_data[MV_DDR_TWR_MIN];
+ break;
+ case SPEED_BIN_TXPDLL:
+ result = 24000;
+ break;
+ case SPEED_BIN_TXSDLL:
+ if (mv_ddr_tdllk_get(freq, &result))
+ result = 0;
+ break;
+ case SPEED_BIN_TCCDL:
+ if (tm->cfg_src == MV_DDR_CFG_SPD)
+ result = tm->timing_data[MV_DDR_TCCD_L_MIN];
+ else {
+ if (index <= SPEED_BIN_DDR_1600L)
+ result = 6250;
+ else if (index <= SPEED_BIN_DDR_2133R)
+ result = 5355;
+ else
+ result = 5000;
+ }
+ break;
+ default:
+ printf("error: %s: invalid element [%d] found\n", __func__, (int)element);
+ break;
+ }
+
+ return result;
+}
+#endif /* CONFIG_DDR4 */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training_leveling.c b/drivers/ddr/marvell/a38x/mv_ddr4_training_leveling.c
new file mode 100644
index 0000000..6d5b942
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_training_leveling.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#if defined(CONFIG_DDR4)
+
+#include "ddr3_init.h"
+#include "mv_ddr_regs.h"
+
+static int mv_ddr4_dynamic_pb_wl_supp(u32 dev_num, enum mv_wl_supp_mode ecc_mode);
+
+/* compare test for ddr4 write leveling supplementary */
+#define MV_DDR4_COMP_TEST_NO_RESULT 0
+#define MV_DDR4_COMP_TEST_RESULT_0 1
+#define MV_DDR4_XSB_COMP_PATTERNS_NUM 8
+
+static u8 mv_ddr4_xsb_comp_test(u32 dev_num, u32 subphy_num, u32 if_id,
+ enum mv_wl_supp_mode ecc_mode)
+{
+ u32 wl_invert;
+ u8 pb_key, bit, bit_max, word;
+ struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u32 subphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE);
+ uint64_t read_pattern_64[MV_DDR4_XSB_COMP_PATTERNS_NUM] = {0};
+ /*
+ * FIXME: the pattern below is used for writing to the memory
+ * by the cpu. it was changed to be written through the odpg.
+ * for a workaround
+ * uint64_t pattern_test_table_64[MV_DDR4_XSB_COMP_PATTERNS_NUM] = {
+ * 0xffffffffffffffff,
+ * 0xffffffffffffffff,
+ * 0x0000000000000000,
+ * 0x0000000000000000,
+ * 0x0000000000000000,
+ * 0x0000000000000000,
+ * 0xffffffffffffffff,
+ * 0xffffffffffffffff};
+ */
+ u32 read_pattern[MV_DDR4_XSB_COMP_PATTERNS_NUM];
+ /*u32 pattern_test_table[MV_DDR4_XSB_COMP_PATTERNS_NUM] = {
+ 0xffffffff,
+ 0xffffffff,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0xffffffff,
+ 0xffffffff}; TODO: use pattern_table_get_word */
+ int i, status;
+ uint64_t data64;
+ uintptr_t addr64;
+ int ecc_running = 0;
+ u32 ecc_read_subphy_num = 0; /* FIXME: change ecc read subphy num to be configurable */
+ u8 bit_counter = 0;
+ int edge = 0;
+ /* write and read data */
+ if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) {
+ status = ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG,
+ effective_cs << ODPG_DATA_CS_OFFS,
+ ODPG_DATA_CS_MASK << ODPG_DATA_CS_OFFS);
+ if (status != MV_OK)
+ return status;
+
+ addr64 = (uintptr_t)pattern_table[PATTERN_TEST].start_addr;
+ /*
+ * FIXME: changed the load pattern to memory through the odpg
+ * this change is needed to be validate
+ * this change is done due to un calibrated dm at this stage
+ * the below code is the code for loading the pattern directly
+ * to the memory
+ *
+ * for (i = 0; i < MV_DDR4_XSB_COMP_PATTERNS_NUM; i++) {
+ * data64 = pattern_test_table_64[i];
+ * writeq(addr64, data64);
+ * addr64 += sizeof(uint64_t);
+ *}
+ * FIXME: the below code loads the pattern to the memory through the odpg
+ * it loads it twice to due supplementary failure, need to check it
+ */
+ int j;
+ for (j = 0; j < 2; j++)
+ ddr3_tip_load_pattern_to_mem(dev_num, PATTERN_TEST);
+
+ } else if (MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(tm->bus_act_mask, subphy_max)) {
+ status = ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG,
+ effective_cs << ODPG_DATA_CS_OFFS,
+ ODPG_DATA_CS_MASK << ODPG_DATA_CS_OFFS);
+ if (status != MV_OK)
+ return status;
+
+ /*
+ * FIXME: changed the load pattern to memory through the odpg
+ * this change is needed to be validate
+ * this change is done due to un calibrated dm at this stage
+ * the below code is the code for loading the pattern directly
+ * to the memory
+ */
+ int j;
+ for (j = 0; j < 2; j++)
+ ddr3_tip_load_pattern_to_mem(dev_num, PATTERN_TEST);
+ } else {
+ /*
+ * FIXME: changed the load pattern to memory through the odpg
+ * this change is needed to be validate
+ * this change is done due to un calibrated dm at this stage
+ * the below code is the code for loading the pattern directly
+ * to the memory
+ */
+ int j;
+ for (j = 0; j < 2; j++)
+ ddr3_tip_load_pattern_to_mem(dev_num, PATTERN_TEST);
+ }
+
+ if ((ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4) ||
+ (ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3 ||
+ ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8)) {
+ /* disable ecc write mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x0, 0x100);
+ if (status != MV_OK)
+ return status;
+
+ /* enable read data ecc mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x3, 0x3);
+ if (status != MV_OK)
+ return status;
+
+ /* unset training start bit */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_REG, 0x80000000, 0x80000000);
+ if (status != MV_OK)
+ return status;
+
+ ecc_running = 1;
+ ecc_read_subphy_num = ECC_READ_BUS_0;
+ }
+
+ if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) {
+ status = ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG,
+ effective_cs << ODPG_DATA_CS_OFFS,
+ ODPG_DATA_CS_MASK << ODPG_DATA_CS_OFFS);
+ if (status != MV_OK)
+ return status;
+ /*
+ * in case of reading the pattern read it from the address x 8
+ * the odpg multiply by 8 the addres to read from
+ */
+ addr64 = ((uintptr_t)pattern_table[PATTERN_TEST].start_addr) << 3;
+ for (i = 0; i < MV_DDR4_XSB_COMP_PATTERNS_NUM; i++) {
+ data64 = readq(addr64);
+ addr64 += sizeof(uint64_t);
+ read_pattern_64[i] = data64;
+ }
+
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("xsb comp: if %d bus id %d\n", 0, subphy_num));
+ for (edge = 0; edge < 8; edge++)
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("0x%16llx\n", (unsigned long long)read_pattern_64[edge]));
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("\n"));
+ } else if (MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(tm->bus_act_mask, subphy_max)) {
+ status = ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG,
+ effective_cs << ODPG_DATA_CS_OFFS,
+ ODPG_DATA_CS_MASK << ODPG_DATA_CS_OFFS);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_ext_read(dev_num, if_id, pattern_table[PATTERN_TEST].start_addr << 3,
+ 1, read_pattern);
+ if (status != MV_OK)
+ return status;
+
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("xsb comp: if %d bus id %d\n", 0, subphy_num));
+ for (edge = 0; edge < 8; edge++)
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("0x%16x\n", read_pattern[edge]));
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("\n"));
+ } else {
+ status = ddr3_tip_ext_read(dev_num, if_id, ((pattern_table[PATTERN_TEST].start_addr << 3) +
+ ((SDRAM_CS_SIZE + 1) * effective_cs)), 1, read_pattern);
+ if (status != MV_OK)
+ return status;
+
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("xsb comp: if %d bus id %d\n", 0, subphy_num));
+ for (edge = 0; edge < 8; edge++)
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("0x%16x\n", read_pattern[edge]));
+ DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("\n"));
+ }
+
+ /* read centralization result to decide on half phase by inverse bit */
+ status = ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_num, DDR_PHY_DATA,
+ CTX_PHY_REG(0), &wl_invert);
+ if (status != MV_OK)
+ return status;
+
+ if ((wl_invert & 0x20) != 0)
+ wl_invert = 1;
+ else
+ wl_invert = 0;
+
+ /* for ecc, read from the "read" subphy (usualy subphy 0) */
+ if (ecc_running)
+ subphy_num = ecc_read_subphy_num;
+
+ /* per bit loop*/
+ bit_max = subphy_num * BUS_WIDTH_IN_BITS + BUS_WIDTH_IN_BITS;
+ for (bit = subphy_num * BUS_WIDTH_IN_BITS; bit < bit_max; bit++) {
+ /* get per bit pattern key (value of the same bit in the pattern) */
+ pb_key = 0;
+ for (word = 0; word < MV_DDR4_XSB_COMP_PATTERNS_NUM; word++) {
+ if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) {
+ if ((read_pattern_64[word] & ((uint64_t)1 << bit)) != 0)
+ pb_key |= (1 << word);
+ } else {
+ if ((read_pattern[word] & (1 << bit)) != 0)
+ pb_key |= (1 << word);
+ }
+ }
+
+ /* find the key value and make decision */
+ switch (pb_key) {
+ /* case(s) for 0 */
+ case 0b11000011: /* nominal */
+ case 0b10000011: /* sample at start of UI sample at the dqvref TH */
+ case 0b10000111: /* sample at start of UI sample at the dqvref TH */
+ case 0b11000001: /* sample at start of UI sample at the dqvref TH */
+ case 0b11100001: /* sample at start of UI sample at the dqvref TH */
+ case 0b11100011: /* sample at start of UI sample at the dqvref TH */
+ case 0b11000111: /* sample at start of UI sample at the dqvref TH */
+ bit_counter++;
+ break;
+ } /* end of switch */
+ } /* end of per bit loop */
+
+ /* check all bits in the current subphy has met the switch condition above */
+ if (bit_counter == BUS_WIDTH_IN_BITS)
+ return MV_DDR4_COMP_TEST_RESULT_0;
+ else {
+ DEBUG_LEVELING(
+ DEBUG_LEVEL_INFO,
+ ("different supplementary results (%d -> %d)\n",
+ MV_DDR4_COMP_TEST_NO_RESULT, MV_DDR4_COMP_TEST_RESULT_0));
+ return MV_DDR4_COMP_TEST_NO_RESULT;
+ }
+}
+
+int mv_ddr4_dynamic_wl_supp(u32 dev_num)
+{
+ int status = MV_OK;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+
+ if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) ||
+ DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask) ||
+ DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask)) {
+ if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask))
+ status = mv_ddr4_dynamic_pb_wl_supp(dev_num, WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4);
+ else if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
+ status = mv_ddr4_dynamic_pb_wl_supp(dev_num, WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3);
+ else /* WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8 */
+ status = mv_ddr4_dynamic_pb_wl_supp(dev_num, WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8);
+ if (status != MV_OK)
+ return status;
+ status = mv_ddr4_dynamic_pb_wl_supp(dev_num, WRITE_LEVELING_SUPP_ECC_MODE_DATA_PUPS);
+ } else { /* regular supplementary for data subphys in non-ecc mode */
+ status = mv_ddr4_dynamic_pb_wl_supp(dev_num, WRITE_LEVELING_SUPP_REG_MODE);
+ }
+
+ return status;
+}
+
+/* dynamic per bit write leveling supplementary */
+static int mv_ddr4_dynamic_pb_wl_supp(u32 dev_num, enum mv_wl_supp_mode ecc_mode)
+{
+ u32 if_id;
+ u32 subphy_start, subphy_end;
+ u32 subphy_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
+ u8 compare_result = 0;
+ u32 orig_phase;
+ u32 rd_data, wr_data = 0;
+ u32 flag, step;
+ struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+ u32 ecc_phy_access_id;
+ int status;
+
+ if (ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4 ||
+ ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3 ||
+ ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8) {
+ /* enable ecc write mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x100, 0x100);
+ if (status != MV_OK)
+ return status;
+
+ /* disable read data ecc mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x0, 0x3);
+ if (status != MV_OK)
+ return status;
+
+ /* unset training start bit */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_REG, 0x0, 0x80000000);
+ if (status != MV_OK)
+ return status;
+
+ if (ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3)
+ ecc_phy_access_id = ECC_PHY_ACCESS_3;
+ else if (ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4)
+ ecc_phy_access_id = ECC_PHY_ACCESS_4;
+ else /* ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8 */
+ ecc_phy_access_id = ECC_PHY_ACCESS_8;
+
+ subphy_start = ecc_phy_access_id;
+ subphy_end = subphy_start + 1;
+ } else if (ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_DATA_PUPS) {
+ /* disable ecc write mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x0, 0x100);
+ if (status != MV_OK)
+ return status;
+
+ /* disable ecc mode*/
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, 0, 0x40000);
+ if (status != MV_OK)
+ return status;
+
+ subphy_start = 0;
+ if (MV_DDR_IS_HALF_BUS_DRAM_MODE(tm->bus_act_mask, subphy_num))
+ subphy_end = (subphy_num - 1) / 2;
+ else
+ subphy_end = subphy_num - 1;
+ } else { /* ecc_mode == WRITE_LEVELING_SUPP_REG_MODE */
+ subphy_start = 0;
+ /* remove ecc subphy prior to algorithm's start */
+ subphy_end = subphy_num - 1; /* TODO: check it */
+ }
+
+ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
+ VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
+ for (subphy_num = subphy_start; subphy_num < subphy_end; subphy_num++) {
+ VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_num);
+ flag = 1;
+ step = 0;
+ status = ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_num, DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), &rd_data);
+ if (status != MV_OK)
+ return status;
+ orig_phase = (rd_data >> 6) & 0x7;
+ while (flag != 0) {
+ /* get decision for subphy */
+ compare_result = mv_ddr4_xsb_comp_test(dev_num, subphy_num, if_id, ecc_mode);
+ if (compare_result == MV_DDR4_COMP_TEST_RESULT_0) {
+ flag = 0;
+ } else { /* shift phase to -1 */
+ step++;
+ if (step == 1) { /* set phase (0x0[6-8]) to -2 */
+ if (orig_phase > 1)
+ wr_data = (rd_data & ~0x1c0) | ((orig_phase - 2) << 6);
+ else if (orig_phase == 1)
+ wr_data = (rd_data & ~0x1df);
+ if (orig_phase >= 1)
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, subphy_num,
+ DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), wr_data);
+ } else if (step == 2) { /* shift phase to +1 */
+ if (orig_phase <= 5) {
+ wr_data = (rd_data & ~0x1c0) | ((orig_phase + 2) << 6);
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, subphy_num,
+ DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), wr_data);
+ }
+ } else if (step == 3) {
+ if (orig_phase <= 3) {
+ wr_data = (rd_data & ~0x1c0) | ((orig_phase + 4) << 6);
+ ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ ACCESS_TYPE_UNICAST, subphy_num,
+ DDR_PHY_DATA,
+ WL_PHY_REG(effective_cs), wr_data);
+ }
+ } else { /* error */
+ flag = 0;
+ compare_result = MV_DDR4_COMP_TEST_NO_RESULT;
+ training_result[training_stage][if_id] = TEST_FAILED;
+ }
+ }
+ }
+ }
+ if ((training_result[training_stage][if_id] == NO_TEST_DONE) ||
+ (training_result[training_stage][if_id] == TEST_SUCCESS))
+ training_result[training_stage][if_id] = TEST_SUCCESS;
+ }
+
+ if (ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_DATA_PUPS) {
+ /* enable ecc write mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x100, 0x100);
+ if (status != MV_OK)
+ return status;
+
+ /* enable ecc mode*/
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ SDRAM_CFG_REG, 0x40000, 0x40000);
+ if (status != MV_OK)
+ return status;
+ } else if (ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4 ||
+ ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3 ||
+ ecc_mode == WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8) {
+ /* enable ecc write mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x100, 0x100);
+ if (status != MV_OK)
+ return status;
+
+ /* disable read data ecc mux */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_2_REG, 0x0, 0x3);
+ if (status != MV_OK)
+ return status;
+
+ /* unset training start bit */
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_REG, 0x0, 0x80000000);
+ if (status != MV_OK)
+ return status;
+
+ status = ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
+ TRAINING_SW_1_REG, 0x1 << 16, 0x1 << 16);
+ if (status != MV_OK)
+ return status;
+ } else {
+ /* do nothing for WRITE_LEVELING_SUPP_REG_MODE */;
+ }
+ if (training_result[training_stage][0] == TEST_SUCCESS)
+ return MV_OK;
+ else
+ return MV_FAIL;
+}
+#endif /* CONFIG_DDR4 */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr4_training_leveling.h b/drivers/ddr/marvell/a38x/mv_ddr4_training_leveling.h
new file mode 100644
index 0000000..4067cac
--- /dev/null
+++ b/drivers/ddr/marvell/a38x/mv_ddr4_training_leveling.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Marvell International Ltd. and its affiliates
+ */
+
+#ifndef _MV_DDR4_TRAINING_LEVELING_H
+#define _MV_DDR4_TRAINING_LEVELING_H
+
+int mv_ddr4_dynamic_wl_supp(u32 dev_num);
+
+#endif /* _MV_DDR4_TRAINING_LEVELING_H */
diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/drivers/ddr/marvell/a38x/mv_ddr_plat.c
index 7c7bce7..6e7949a 100644
--- a/drivers/ddr/marvell/a38x/mv_ddr_plat.c
+++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c
@@ -38,6 +38,24 @@
#define TSEN_STATUS_TEMP_OUT_OFFSET 0
#define TSEN_STATUS_TEMP_OUT_MASK (0x3ff << TSEN_STATUS_TEMP_OUT_OFFSET)
+#if defined(CONFIG_DDR4)
+static struct dlb_config ddr3_dlb_config_table[] = {
+ {DLB_CTRL_REG, 0x2000005f},
+ {DLB_BUS_OPT_WT_REG, 0x00880000},
+ {DLB_AGING_REG, 0x3f7f007f},
+ {DLB_EVICTION_CTRL_REG, 0x0000129f},
+ {DLB_EVICTION_TIMERS_REG, 0x00ff0000},
+ {DLB_WTS_DIFF_CS_REG, 0x04030803},
+ {DLB_WTS_DIFF_BG_REG, 0x00000A02},
+ {DLB_WTS_SAME_BG_REG, 0x08000901},
+ {DLB_WTS_CMDS_REG, 0x00020005},
+ {DLB_WTS_ATTR_PRIO_REG, 0x00060f10},
+ {DLB_QUEUE_MAP_REG, 0x00000543},
+ {DLB_SPLIT_REG, 0x0000000f},
+ {DLB_USER_CMD_REG, 0x00000000},
+ {0x0, 0x0}
+};
+#else /* !CONFIG_DDR4 */
static struct dlb_config ddr3_dlb_config_table[] = {
{DLB_CTRL_REG, 0x2000005c},
{DLB_BUS_OPT_WT_REG, 0x00880000},
@@ -54,6 +72,7 @@
{DLB_USER_CMD_REG, 0x00000000},
{0x0, 0x0}
};
+#endif /* CONFIG_DDR4 */
static struct dlb_config *sys_env_dlb_config_ptr_get(void)
{
@@ -62,12 +81,18 @@
static u8 a38x_bw_per_freq[MV_DDR_FREQ_LAST] = {
0x3, /* MV_DDR_FREQ_100 */
+#if !defined(CONFIG_DDR4)
0x4, /* MV_DDR_FREQ_400 */
0x4, /* MV_DDR_FREQ_533 */
+#endif /* CONFIG_DDR4 */
0x5, /* MV_DDR_FREQ_667 */
0x5, /* MV_DDR_FREQ_800 */
0x5, /* MV_DDR_FREQ_933 */
0x5, /* MV_DDR_FREQ_1066 */
+#if defined(CONFIG_DDR4)
+ 0x5, /*MV_DDR_FREQ_900*/
+ 0x5, /*MV_DDR_FREQ_1000*/
+#else /* CONFIG_DDR4 */
0x3, /* MV_DDR_FREQ_311 */
0x3, /* MV_DDR_FREQ_333 */
0x4, /* MV_DDR_FREQ_467 */
@@ -77,16 +102,23 @@
0x5, /* MV_DDR_FREQ_900 */
0x3, /* MV_DDR_FREQ_360 */
0x5 /* MV_DDR_FREQ_1000 */
+#endif /* CONFIG_DDR4 */
};
static u8 a38x_rate_per_freq[MV_DDR_FREQ_LAST] = {
0x1, /* MV_DDR_FREQ_100 */
+#if !defined(CONFIG_DDR4)
0x2, /* MV_DDR_FREQ_400 */
0x2, /* MV_DDR_FREQ_533 */
+#endif /* CONFIG_DDR4 */
0x2, /* MV_DDR_FREQ_667 */
0x2, /* MV_DDR_FREQ_800 */
0x3, /* MV_DDR_FREQ_933 */
0x3, /* MV_DDR_FREQ_1066 */
+#ifdef CONFIG_DDR4
+ 0x2, /*MV_DDR_FREQ_900*/
+ 0x2, /*MV_DDR_FREQ_1000*/
+#else /* CONFIG_DDR4 */
0x1, /* MV_DDR_FREQ_311 */
0x1, /* MV_DDR_FREQ_333 */
0x2, /* MV_DDR_FREQ_467 */
@@ -96,6 +128,7 @@
0x2, /* MV_DDR_FREQ_900 */
0x1, /* MV_DDR_FREQ_360 */
0x2 /* MV_DDR_FREQ_1000 */
+#endif /* CONFIG_DDR4 */
};
static u16 a38x_vco_freq_per_sar_ref_clk_25_mhz[] = {
@@ -166,6 +199,54 @@
1800 /* 30 - 0x1E */
};
+#if defined(CONFIG_DDR4)
+u16 odt_slope[] = {
+ 21443,
+ 1452,
+ 482,
+ 240,
+ 141,
+ 90,
+ 67,
+ 52
+};
+
+u16 odt_intercept[] = {
+ 1517,
+ 328,
+ 186,
+ 131,
+ 100,
+ 80,
+ 69,
+ 61
+};
+
+/* Map of scratch PHY registers used to store stability value */
+u32 dmin_phy_reg_table[MAX_BUS_NUM * MAX_CS_NUM][2] = {
+ /* subphy, addr */
+ {0, 0xc0}, /* cs 0, subphy 0 */
+ {0, 0xc1}, /* cs 0, subphy 1 */
+ {0, 0xc2}, /* cs 0, subphy 2 */
+ {0, 0xc3}, /* cs 0, subphy 3 */
+ {0, 0xc4}, /* cs 0, subphy 4 */
+ {1, 0xc0}, /* cs 1, subphy 0 */
+ {1, 0xc1}, /* cs 1, subphy 1 */
+ {1, 0xc2}, /* cs 1, subphy 2 */
+ {1, 0xc3}, /* cs 1, subphy 3 */
+ {1, 0xc4}, /* cs 1, subphy 4 */
+ {2, 0xc0}, /* cs 2, subphy 0 */
+ {2, 0xc1}, /* cs 2, subphy 1 */
+ {2, 0xc2}, /* cs 2, subphy 2 */
+ {2, 0xc3}, /* cs 2, subphy 3 */
+ {2, 0xc4}, /* cs 2, subphy 4 */
+ {0, 0xc5}, /* cs 3, subphy 0 */
+ {1, 0xc5}, /* cs 3, subphy 1 */
+ {2, 0xc5}, /* cs 3, subphy 2 */
+ {0, 0xc6}, /* cs 3, subphy 3 */
+ {1, 0xc6} /* cs 3, subphy 4 */
+};
+#endif /* CONFIG_DDR4 */
static u32 dq_bit_map_2_phy_pin[] = {
1, 0, 2, 6, 9, 8, 3, 7, /* 0 */
@@ -397,6 +478,7 @@
if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) ==
DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) {
switch (reg) {
+#if !defined(CONFIG_DDR4)
case 0x1:
DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
("Warning: Unsupported freq mode for 333Mhz configured(%d)\n",
@@ -424,6 +506,7 @@
case 0x6:
*freq = MV_DDR_FREQ_600;
break;
+#endif /* CONFIG_DDR4 */
case 0x11:
case 0x14:
DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
@@ -448,21 +531,32 @@
case 0x12:
*freq = MV_DDR_FREQ_900;
break;
+#if defined(CONFIG_DDR4)
+ case 0x13:
+ *freq = MV_DDR_FREQ_1000;
+ DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
+ ("Warning: Unsupported freq mode for 1000Mhz configured(%d)\n",
+ reg));
+ break;
+#else /* CONFIG_DDR4 */
case 0x13:
*freq = MV_DDR_FREQ_933;
break;
+#endif /* CONFIG_DDR4 */
default:
*freq = 0;
return MV_NOT_SUPPORTED;
}
} else { /* REFCLK 40MHz case */
switch (reg) {
+#if !defined(CONFIG_DDR4)
case 0x3:
*freq = MV_DDR_FREQ_400;
break;
case 0x5:
*freq = MV_DDR_FREQ_533;
break;
+#endif /* CONFIG_DDR4 */
case 0xb:
*freq = MV_DDR_FREQ_800;
break;
@@ -478,6 +572,7 @@
return MV_OK;
}
+#if !defined(CONFIG_DDR4)
static int ddr3_tip_a38x_get_medium_freq(int dev_num, enum mv_ddr_freq *freq)
{
u32 reg, ref_clk_satr;
@@ -554,6 +649,7 @@
return MV_OK;
}
+#endif /* CONFIG_DDR4 */
static int ddr3_tip_a38x_get_device_info(u8 dev_num, struct ddr3_device_info *info_ptr)
{
@@ -667,7 +763,9 @@
dfs_low_freq = DFS_LOW_FREQ_VALUE;
calibration_update_control = 1;
+#if !defined(CONFIG_DDR4)
ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq);
+#endif /* CONFIG_DDR4 */
return MV_OK;
}
@@ -675,6 +773,29 @@
static int mv_ddr_training_mask_set(void)
{
struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
+#if defined(CONFIG_DDR4)
+ mask_tune_func = (SET_LOW_FREQ_MASK_BIT |
+ LOAD_PATTERN_MASK_BIT |
+ SET_TARGET_FREQ_MASK_BIT |
+ WRITE_LEVELING_TF_MASK_BIT |
+ READ_LEVELING_TF_MASK_BIT |
+ RECEIVER_CALIBRATION_MASK_BIT |
+ WL_PHASE_CORRECTION_MASK_BIT |
+ DQ_VREF_CALIBRATION_MASK_BIT);
+ /* Temporarily disable the DQ_MAPPING stage */
+ /* DQ_MAPPING_MASK_BIT */
+ rl_mid_freq_wa = 0;
+
+ /* In case A382, Vref calibration workaround isn't required */
+ if (((reg_read(DEV_ID_REG) & 0xFFFF0000) >> 16) == 0x6811) {
+ printf("vref_calibration_wa is disabled\n");
+ vref_calibration_wa = 0;
+ }
+
+ if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 1)
+ mask_tune_func &= ~WL_PHASE_CORRECTION_MASK_BIT;
+
+#else /* CONFIG_DDR4 */
enum mv_ddr_freq ddr_freq = tm->interface_params[0].memory_freq;
mask_tune_func = (SET_LOW_FREQ_MASK_BIT |
@@ -711,6 +832,7 @@
mask_tune_func &= ~PBS_TX_MASK_BIT;
mask_tune_func &= ~PBS_RX_MASK_BIT;
}
+#endif /* CONFIG_DDR4 */
return MV_OK;
}
@@ -767,6 +889,7 @@
/* Set KNL values */
switch (frequency) {
+#ifndef CONFIG_DDR4 /* CONFIG_DDR3 */
case MV_DDR_FREQ_467:
async_val = 0x806f012;
break;
@@ -776,15 +899,18 @@
case MV_DDR_FREQ_600:
async_val = 0x805f00a;
break;
+#endif
case MV_DDR_FREQ_667:
async_val = 0x809f012;
break;
case MV_DDR_FREQ_800:
async_val = 0x807f00a;
break;
+#ifndef CONFIG_DDR4 /* CONFIG_DDR3 */
case MV_DDR_FREQ_850:
async_val = 0x80cb012;
break;
+#endif
case MV_DDR_FREQ_900:
async_val = 0x80d7012;
break;
@@ -1293,6 +1419,12 @@
i++;
}
+#if defined(CONFIG_DDR4)
+ reg = reg_read(DUNIT_CTRL_HIGH_REG);
+ reg &= ~(CPU_INTERJECTION_ENA_MASK << CPU_INTERJECTION_ENA_OFFS);
+ reg |= CPU_INTERJECTION_ENA_SPLIT_DIS << CPU_INTERJECTION_ENA_OFFS;
+ reg_write(DUNIT_CTRL_HIGH_REG, reg);
+#endif /* CONFIG_DDR4 */
/* Enable DLB */
reg = reg_read(DLB_CTRL_REG);
@@ -1432,10 +1564,122 @@
ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
DDR_PHY_DATA, 0x90, 0x6002));
+#if defined(CONFIG_DDR4)
+ mv_ddr4_phy_config(dev_num);
+#endif /* CONFIG_DDR4 */
return MV_OK;
}
+#if defined(CONFIG_DDR4)
+/* function: ddr4TipCalibrationValidate
+ * this function validates the calibration values
+ * the function is per soc due to the different processes the calibration values are different
+ */
+int mv_ddr4_calibration_validate(u32 dev_num)
+{
+ int status = MV_OK;
+ u8 if_id = 0;
+ u32 read_data[MAX_INTERFACE_NUM];
+ u32 cal_n = 0, cal_p = 0;
+
+ /*
+ * Pad calibration control enable: during training set the calibration to be internal
+ * at the end of the training it should be fixed to external to be configured by the mc6
+ * FIXME: set the calibration to external in the end of the training
+ */
+
+ /* pad calibration control enable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG,
+ DYN_PADS_CAL_ENABLE_ENA << DYN_PADS_CAL_ENABLE_OFFS |
+ CAL_UPDATE_CTRL_INT << CAL_UPDATE_CTRL_OFFS,
+ DYN_PADS_CAL_ENABLE_MASK << DYN_PADS_CAL_ENABLE_OFFS |
+ CAL_UPDATE_CTRL_MASK << CAL_UPDATE_CTRL_OFFS));
+
+ /* Polling initial calibration is done*/
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ CAL_MACH_RDY << CAL_MACH_STATUS_OFFS,
+ CAL_MACH_STATUS_MASK << CAL_MACH_STATUS_OFFS,
+ MAIN_PADS_CAL_MACH_CTRL_REG, MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("ddr4TipCalibrationAdjust: DDR4 calibration poll failed(0)\n"));
+
+ /* Polling that calibration propagate to io */
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x3FFFFFF, 0x3FFFFFF, PHY_LOCK_STATUS_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("ddr4TipCalibrationAdjust: DDR4 calibration poll failed(1)\n"));
+
+ /* TODO - debug why polling not enough*/
+ mdelay(10);
+
+ /* pad calibration control disable */
+ CHECK_STATUS(ddr3_tip_if_write
+ (0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG,
+ DYN_PADS_CAL_ENABLE_DIS << DYN_PADS_CAL_ENABLE_OFFS |
+ CAL_UPDATE_CTRL_INT << CAL_UPDATE_CTRL_OFFS,
+ DYN_PADS_CAL_ENABLE_MASK << DYN_PADS_CAL_ENABLE_OFFS |
+ CAL_UPDATE_CTRL_MASK << CAL_UPDATE_CTRL_OFFS));
+
+ /* Polling initial calibration is done */
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id,
+ CAL_MACH_RDY << CAL_MACH_STATUS_OFFS,
+ CAL_MACH_STATUS_MASK << CAL_MACH_STATUS_OFFS,
+ MAIN_PADS_CAL_MACH_CTRL_REG, MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("ddr4TipCalibrationAdjust: DDR4 calibration poll failed(0)\n"));
+
+ /* Polling that calibration propagate to io */
+ if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x3FFFFFF, 0x3FFFFFF, PHY_LOCK_STATUS_REG,
+ MAX_POLLING_ITERATIONS) != MV_OK)
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("ddr4TipCalibrationAdjust: DDR4 calibration poll failed(1)\n"));
+
+ /* TODO - debug why polling not enough */
+ mdelay(10);
+
+ /* Read Cal value and set to manual val */
+ CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1DC8, read_data, MASK_ALL_BITS));
+ cal_n = (read_data[if_id] & ((0x3F) << 10)) >> 10;
+ cal_p = (read_data[if_id] & ((0x3F) << 4)) >> 4;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("ddr4TipCalibrationValidate::DDR4 SSTL calib val - Pcal = 0x%x , Ncal = 0x%x\n",
+ cal_p, cal_n));
+ if ((cal_n >= 56) || (cal_n <= 6) || (cal_p >= 59) || (cal_p <= 7)) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("%s: Error:DDR4 SSTL calib val - Pcal = 0x%x, Ncal = 0x%x are out of range\n",
+ __func__, cal_p, cal_n));
+ status = MV_FAIL;
+ }
+
+ /* 14C8 - Vertical */
+ CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x14C8, read_data, MASK_ALL_BITS));
+ cal_n = (read_data[if_id] & ((0x3F) << 10)) >> 10;
+ cal_p = (read_data[if_id] & ((0x3F) << 4)) >> 4;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("ddr4TipCalibrationValidate::DDR4 POD-V calib val - Pcal = 0x%x , Ncal = 0x%x\n",
+ cal_p, cal_n));
+ if ((cal_n >= 56) || (cal_n <= 6) || (cal_p >= 59) || (cal_p <= 7)) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("%s: Error:DDR4 POD-V calib val - Pcal = 0x%x , Ncal= 0x%x are out of range\n",
+ __func__, cal_p, cal_n));
+ status = MV_FAIL;
+ }
+
+ /* 17C8 - Horizontal */
+ CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x17C8, read_data, MASK_ALL_BITS));
+ cal_n = (read_data[if_id] & ((0x3F) << 10)) >> 10;
+ cal_p = (read_data[if_id] & ((0x3F) << 4)) >> 4;
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
+ ("ddr4TipCalibrationValidate::DDR4 POD-H calib val - Pcal = 0x%x , Ncal = 0x%x\n",
+ cal_p, cal_n));
+ if ((cal_n >= 56) || (cal_n <= 6) || (cal_p >= 59) || (cal_p <= 7)) {
+ DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
+ ("%s: Error:DDR4 POD-H calib val - Pcal = 0x%x, Ncal = 0x%x are out of range\n",
+ __func__, cal_p, cal_n));
+ status = MV_FAIL;
+ }
+
+ return status;
+}
+#endif /* CONFIG_DDR4 */
int mv_ddr_manual_cal_do(void)
{
diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.h b/drivers/ddr/marvell/a38x/mv_ddr_plat.h
index 4499884..01894f6 100644
--- a/drivers/ddr/marvell/a38x/mv_ddr_plat.h
+++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.h
@@ -39,8 +39,19 @@
#define TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS 0x10000
#define TUNE_TRAINING_PARAMS_RTT_NOM 0x44
+#if defined(CONFIG_DDR4)
+#define TUNE_TRAINING_PARAMS_P_ODT_DATA_DDR4 0x1A
+#define TUNE_TRAINING_PARAMS_DIC_DDR4 0x0
+#define TUNE_TRAINING_PARAMS_ODT_CONFIG_DDR4 0 /* 0x330012 */
+#define TUNE_TRAINING_PARAMS_RTT_NOM_DDR4 0 /* 0x400, RZQ/3 = 0x600 */
+#define TUNE_TRAINING_PARAMS_RTT_WR_1CS 0x200 /*RZQ/1 = 0x400*/
+#define TUNE_TRAINING_PARAMS_RTT_WR_2CS 0x200 /*RZQ/1 = 0x400*/
+#define TUNE_TRAINING_PARAMS_RTT_PARK_1CS 0
+#define TUNE_TRAINING_PARAMS_RTT_PARK_2CS 0
+#else /* CONFIG_DDR4 */
#define TUNE_TRAINING_PARAMS_RTT_WR_1CS 0x0 /*off*/
#define TUNE_TRAINING_PARAMS_RTT_WR_2CS 0x0 /*off*/
+#endif /* CONFIG_DDR4 */
#define MARVELL_BOARD MARVELL_BOARD_ID_BASE
diff --git a/drivers/ddr/marvell/a38x/mv_ddr_regs.h b/drivers/ddr/marvell/a38x/mv_ddr_regs.h
index cf2a6c9..a19000d 100644
--- a/drivers/ddr/marvell/a38x/mv_ddr_regs.h
+++ b/drivers/ddr/marvell/a38x/mv_ddr_regs.h
@@ -373,6 +373,65 @@
#define MRS2_CMD 0x8
#define MRS3_CMD 0x9
+#if defined(CONFIG_DDR4)
+/* DDR4 MRS */
+#define MRS4_CMD 0x10
+#define MRS5_CMD 0x11
+#define MRS6_CMD 0x12
+
+/* DDR4 Registers */
+#define DDR4_MR0_REG 0x1900
+#define DDR4_MR1_REG 0x1904
+#define DDR4_MR2_REG 0x1908
+#define DDR4_MR3_REG 0x190c
+#define DDR4_MPR_PS_OFFS 0
+#define DDR4_MPR_PS_MASK 0x3
+enum mv_ddr_mpr_ps { /* DDR4 MPR Page Selection */
+ DDR4_MPR_PAGE0,
+ DDR4_MPR_PAGE1,
+ DDR4_MPR_PAGE2,
+ DDR4_MPR_PAGE3
+};
+#define DDR4_MPR_OP_OFFS 2
+#define DDR4_MPR_OP_MASK 0x1
+enum mv_ddr_mpr_op { /* DDR4 MPR Operation */
+ DDR4_MPR_OP_DIS, /* normal operation */
+ DDR4_MPR_OP_ENA /* dataflow from mpr */
+};
+#define DDR4_MPR_RF_OFFS 11
+#define DDR4_MPR_RF_MASK 0x3
+enum mv_ddr_mpr_rd_frmt { /* DDR4 MPR Read Format */
+ DDR4_MPR_RF_SERIAL,
+ DDR4_MPR_RF_PARALLEL,
+ DDR4_MPR_RF_STAGGERED,
+ DDR4_MPR_RF_RSVD_TEMP
+
+};
+
+#define DDR4_MR4_REG 0x1910
+#define DDR4_RPT_OFFS 10
+#define DDR4_RPT_MASK 0x1
+enum { /* read preamble training mode */
+ DDR4_RPT_DIS,
+ DDR4_RPT_ENA
+};
+
+#define DDR4_MR5_REG 0x1914
+#define DDR4_MR6_REG 0x1918
+#define DDR4_MPR_WR_REG 0x19d0
+#define DDR4_MPR_LOC_OFFS 8
+#define DDR4_MPR_LOC_MASK 0x3
+/*
+ * MPR Location for MPR write and read accesses
+ * MPR Location 0..3 within the selected page (page selection in MR3 [1:0] bits)
+ */
+enum {
+ DDR4_MPR_LOC0,
+ DDR4_MPR_LOC1,
+ DDR4_MPR_LOC2,
+ DDR4_MPR_LOC3
+};
+#endif /* CONFIG_DDR4 */
#define DRAM_PINS_MUX_REG 0x19d4
#define CTRL_PINS_MUX_OFFS 0
diff --git a/drivers/ddr/marvell/a38x/mv_ddr_topology.h b/drivers/ddr/marvell/a38x/mv_ddr_topology.h
index 1cb69ad..715c146 100644
--- a/drivers/ddr/marvell/a38x/mv_ddr_topology.h
+++ b/drivers/ddr/marvell/a38x/mv_ddr_topology.h
@@ -8,6 +8,77 @@
#define MAX_CS_NUM 4
+#if defined(CONFIG_DDR4)
+enum mv_ddr_speed_bin {
+ SPEED_BIN_DDR_1600J,
+ SPEED_BIN_DDR_1600K,
+ SPEED_BIN_DDR_1600L,
+ SPEED_BIN_DDR_1866L,
+ SPEED_BIN_DDR_1866M,
+ SPEED_BIN_DDR_1866N,
+ SPEED_BIN_DDR_2133N,
+ SPEED_BIN_DDR_2133P,
+ SPEED_BIN_DDR_2133R,
+ SPEED_BIN_DDR_2400P,
+ SPEED_BIN_DDR_2400R,
+ SPEED_BIN_DDR_2400T,
+ SPEED_BIN_DDR_2400U,
+ SPEED_BIN_DDR_2666T,
+ SPEED_BIN_DDR_2666U,
+ SPEED_BIN_DDR_2666V,
+ SPEED_BIN_DDR_2666W,
+ SPEED_BIN_DDR_2933V,
+ SPEED_BIN_DDR_2933W,
+ SPEED_BIN_DDR_2933Y,
+ SPEED_BIN_DDR_2933AA,
+ SPEED_BIN_DDR_3200W,
+ SPEED_BIN_DDR_3200AA,
+ SPEED_BIN_DDR_3200AC
+};
+
+enum mv_ddr_freq {
+ MV_DDR_FREQ_LOW_FREQ,
+ MV_DDR_FREQ_650,
+ MV_DDR_FREQ_667,
+ MV_DDR_FREQ_800,
+ MV_DDR_FREQ_933,
+ MV_DDR_FREQ_1066,
+ MV_DDR_FREQ_900,
+ MV_DDR_FREQ_1000,
+ MV_DDR_FREQ_1050,
+ MV_DDR_FREQ_1200,
+ MV_DDR_FREQ_1333,
+ MV_DDR_FREQ_1466,
+ MV_DDR_FREQ_1600,
+ MV_DDR_FREQ_LAST,
+ MV_DDR_FREQ_SAR
+};
+
+enum mv_ddr_speed_bin_timing {
+ SPEED_BIN_TRCD,
+ SPEED_BIN_TRP,
+ SPEED_BIN_TRAS,
+ SPEED_BIN_TRC,
+ SPEED_BIN_TRRD0_5K,
+ SPEED_BIN_TRRD1K,
+ SPEED_BIN_TRRD2K,
+ SPEED_BIN_TRRDL0_5K,
+ SPEED_BIN_TRRDL1K,
+ SPEED_BIN_TRRDL2K,
+ SPEED_BIN_TPD,
+ SPEED_BIN_TFAW0_5K,
+ SPEED_BIN_TFAW1K,
+ SPEED_BIN_TFAW2K,
+ SPEED_BIN_TWTR,
+ SPEED_BIN_TWTRL,
+ SPEED_BIN_TRTP,
+ SPEED_BIN_TWR,
+ SPEED_BIN_TMOD,
+ SPEED_BIN_TXPDLL,
+ SPEED_BIN_TXSDLL,
+ SPEED_BIN_TCCDL
+};
+#else /* CONFIG_DDR3 */
enum mv_ddr_speed_bin {
SPEED_BIN_DDR_800D,
SPEED_BIN_DDR_800E,
@@ -74,6 +145,7 @@
SPEED_BIN_TXPDLL,
SPEED_BIN_TXSDLL
};
+#endif /* CONFIG_DDR4 */
/* ddr bus masks */
#define BUS_MASK_32BIT 0xf
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig
index b97c67b..eefa347 100644
--- a/drivers/fastboot/Kconfig
+++ b/drivers/fastboot/Kconfig
@@ -80,12 +80,13 @@
this to enable the "fastboot flash" command.
config FASTBOOT_UUU_SUPPORT
- bool "Enable FASTBOOT i.MX UUU special command"
+ bool "Enable UUU support"
help
- The fastboot protocol includes "UCmd" and "ACmd" command.
- Be aware that you provide full access to any U-Boot command,
- including working with memory and may open a huge backdoor,
- when enabling this option.
+ This extends the fastboot protocol with the "UCmd" and "ACmd"
+ commands, which are used by NXP's "universal update utility" (UUU).
+ These commands allow running any shell command. Do not enable this
+ feature if you are using verified boot, as it will allow an attacker
+ to bypass any restrictions you have in place.
choice
prompt "Flash provider for FASTBOOT"
@@ -218,6 +219,14 @@
Add support for the "oem bootbus" command from a client. This set
the mmc boot configuration for the selecting eMMC device.
+config FASTBOOT_OEM_RUN
+ bool "Enable the 'oem run' command"
+ help
+ This extends the fastboot protocol with an "oem run" command. This
+ command allows running arbitrary U-Boot shell commands. Do not enable
+ this feature if you are using verified boot, as it will allow an
+ attacker to bypass any restrictions you have in place.
+
endif # FASTBOOT
endmenu
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c
index bdfdf26..67a9479 100644
--- a/drivers/fastboot/fb_command.c
+++ b/drivers/fastboot/fb_command.c
@@ -31,27 +31,16 @@
static void okay(char *, char *);
static void getvar(char *, char *);
static void download(char *, char *);
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
static void flash(char *, char *);
static void erase(char *, char *);
-#endif
static void reboot_bootloader(char *, char *);
static void reboot_fastbootd(char *, char *);
static void reboot_recovery(char *, char *);
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
static void oem_format(char *, char *);
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
static void oem_partconf(char *, char *);
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
static void oem_bootbus(char *, char *);
-#endif
-
-#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
static void run_ucmd(char *, char *);
static void run_acmd(char *, char *);
-#endif
static const struct {
const char *command;
@@ -65,16 +54,14 @@
.command = "download",
.dispatch = download
},
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
[FASTBOOT_COMMAND_FLASH] = {
.command = "flash",
- .dispatch = flash
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (flash), (NULL))
},
[FASTBOOT_COMMAND_ERASE] = {
.command = "erase",
- .dispatch = erase
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_FLASH, (erase), (NULL))
},
-#endif
[FASTBOOT_COMMAND_BOOT] = {
.command = "boot",
.dispatch = okay
@@ -103,34 +90,30 @@
.command = "set_active",
.dispatch = okay
},
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
[FASTBOOT_COMMAND_OEM_FORMAT] = {
.command = "oem format",
- .dispatch = oem_format,
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT, (oem_format), (NULL))
},
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
[FASTBOOT_COMMAND_OEM_PARTCONF] = {
.command = "oem partconf",
- .dispatch = oem_partconf,
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF, (oem_partconf), (NULL))
},
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
[FASTBOOT_COMMAND_OEM_BOOTBUS] = {
.command = "oem bootbus",
- .dispatch = oem_bootbus,
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS, (oem_bootbus), (NULL))
},
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+ [FASTBOOT_COMMAND_OEM_RUN] = {
+ .command = "oem run",
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_RUN, (run_ucmd), (NULL))
+ },
[FASTBOOT_COMMAND_UCMD] = {
.command = "UCmd",
- .dispatch = run_ucmd,
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), (NULL))
},
[FASTBOOT_COMMAND_ACMD] = {
.command = "ACmd",
- .dispatch = run_acmd,
+ .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_acmd), (NULL))
},
-#endif
};
/**
@@ -156,7 +139,9 @@
response);
return i;
} else {
- break;
+ pr_err("command %s not supported.\n", cmd_string);
+ fastboot_fail("Unsupported command", response);
+ return -1;
}
}
}
@@ -299,7 +284,6 @@
fastboot_bytes_received = 0;
}
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
/**
* flash() - write the downloaded image to the indicated partition.
*
@@ -309,16 +293,15 @@
* Writes the previously downloaded image to the partition indicated by
* cmd_parameter. Writes to response.
*/
-static void flash(char *cmd_parameter, char *response)
+static void __maybe_unused flash(char *cmd_parameter, char *response)
{
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
- fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr, image_size,
- response);
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
- fastboot_nand_flash_write(cmd_parameter, fastboot_buf_addr, image_size,
- response);
-#endif
+ if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC))
+ fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr,
+ image_size, response);
+
+ if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND))
+ fastboot_nand_flash_write(cmd_parameter, fastboot_buf_addr,
+ image_size, response);
}
/**
@@ -330,25 +313,22 @@
* Erases the partition indicated by cmd_parameter (clear to 0x00s). Writes
* to response.
*/
-static void erase(char *cmd_parameter, char *response)
+static void __maybe_unused erase(char *cmd_parameter, char *response)
{
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
- fastboot_mmc_erase(cmd_parameter, response);
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
- fastboot_nand_erase(cmd_parameter, response);
-#endif
-}
-#endif
+ if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC))
+ fastboot_mmc_erase(cmd_parameter, response);
-#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+ if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND))
+ fastboot_nand_erase(cmd_parameter, response);
+}
+
/**
* run_ucmd() - Execute the UCmd command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
-static void run_ucmd(char *cmd_parameter, char *response)
+static void __maybe_unused run_ucmd(char *cmd_parameter, char *response)
{
if (!cmd_parameter) {
pr_err("missing slot suffix\n");
@@ -375,7 +355,7 @@
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
-static void run_acmd(char *cmd_parameter, char *response)
+static void __maybe_unused run_acmd(char *cmd_parameter, char *response)
{
if (!cmd_parameter) {
pr_err("missing slot suffix\n");
@@ -392,7 +372,6 @@
strcpy(g_a_cmd_buff, cmd_parameter);
fastboot_okay(NULL, response);
}
-#endif
/**
* reboot_bootloader() - Sets reboot bootloader flag.
@@ -436,40 +415,40 @@
fastboot_okay(NULL, response);
}
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
/**
* oem_format() - Execute the OEM format command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
-static void oem_format(char *cmd_parameter, char *response)
+static void __maybe_unused oem_format(char *cmd_parameter, char *response)
{
char cmdbuf[32];
+ const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
+ CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
if (!env_get("partitions")) {
fastboot_fail("partitions not set", response);
} else {
- sprintf(cmdbuf, "gpt write mmc %x $partitions",
- CONFIG_FASTBOOT_FLASH_MMC_DEV);
+ sprintf(cmdbuf, "gpt write mmc %x $partitions", mmc_dev);
if (run_command(cmdbuf, 0))
fastboot_fail("", response);
else
fastboot_okay(NULL, response);
}
}
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
/**
* oem_partconf() - Execute the OEM partconf command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
-static void oem_partconf(char *cmd_parameter, char *response)
+static void __maybe_unused oem_partconf(char *cmd_parameter, char *response)
{
char cmdbuf[32];
+ const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
+ CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
if (!cmd_parameter) {
fastboot_fail("Expected command parameter", response);
@@ -477,26 +456,25 @@
}
/* execute 'mmc partconfg' command with cmd_parameter arguments*/
- snprintf(cmdbuf, sizeof(cmdbuf), "mmc partconf %x %s 0",
- CONFIG_FASTBOOT_FLASH_MMC_DEV, cmd_parameter);
+ snprintf(cmdbuf, sizeof(cmdbuf), "mmc partconf %x %s 0", mmc_dev, cmd_parameter);
printf("Execute: %s\n", cmdbuf);
if (run_command(cmdbuf, 0))
fastboot_fail("Cannot set oem partconf", response);
else
fastboot_okay(NULL, response);
}
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
/**
* oem_bootbus() - Execute the OEM bootbus command
*
* @cmd_parameter: Pointer to command parameter
* @response: Pointer to fastboot response buffer
*/
-static void oem_bootbus(char *cmd_parameter, char *response)
+static void __maybe_unused oem_bootbus(char *cmd_parameter, char *response)
{
char cmdbuf[32];
+ const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
+ CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
if (!cmd_parameter) {
fastboot_fail("Expected command parameter", response);
@@ -504,12 +482,10 @@
}
/* execute 'mmc bootbus' command with cmd_parameter arguments*/
- snprintf(cmdbuf, sizeof(cmdbuf), "mmc bootbus %x %s",
- CONFIG_FASTBOOT_FLASH_MMC_DEV, cmd_parameter);
+ snprintf(cmdbuf, sizeof(cmdbuf), "mmc bootbus %x %s", mmc_dev, cmd_parameter);
printf("Execute: %s\n", cmdbuf);
if (run_command(cmdbuf, 0))
fastboot_fail("Cannot set oem bootbus", response);
else
fastboot_okay(NULL, response);
}
-#endif
diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c
index ef399d0..7563650 100644
--- a/drivers/fastboot/fb_common.c
+++ b/drivers/fastboot/fb_common.c
@@ -91,20 +91,21 @@
*/
int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason)
{
-#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
static const char * const boot_cmds[] = {
[FASTBOOT_REBOOT_REASON_BOOTLOADER] = "bootonce-bootloader",
[FASTBOOT_REBOOT_REASON_FASTBOOTD] = "boot-fastboot",
[FASTBOOT_REBOOT_REASON_RECOVERY] = "boot-recovery"
};
+ const int mmc_dev = config_opt_enabled(CONFIG_FASTBOOT_FLASH_MMC,
+ CONFIG_FASTBOOT_FLASH_MMC_DEV, -1);
+
+ if (!CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC))
+ return -EINVAL;
if (reason >= FASTBOOT_REBOOT_REASONS_COUNT)
return -EINVAL;
- return bcb_write_reboot_reason(CONFIG_FASTBOOT_FLASH_MMC_DEV, "misc", boot_cmds[reason]);
-#else
- return -EINVAL;
-#endif
+ return bcb_write_reboot_reason(mmc_dev, "misc", boot_cmds[reason]);
}
/**
diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c
index 018989d..2fbd285 100644
--- a/drivers/fastboot/fb_getvar.c
+++ b/drivers/fastboot/fb_getvar.c
@@ -21,15 +21,9 @@
static void getvar_product(char *var_parameter, char *response);
static void getvar_platform(char *var_parameter, char *response);
static void getvar_current_slot(char *var_parameter, char *response);
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
static void getvar_has_slot(char *var_parameter, char *response);
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
static void getvar_partition_type(char *part_name, char *response);
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
static void getvar_partition_size(char *part_name, char *response);
-#endif
static void getvar_is_userspace(char *var_parameter, char *response);
static const struct {
@@ -84,7 +78,6 @@
}
};
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
/**
* Get partition number and size for any storage type.
*
@@ -102,28 +95,26 @@
size_t *size)
{
int r;
-# if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
struct blk_desc *dev_desc;
- struct disk_partition part_info;
-
- r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
- response);
- if (r >= 0 && size)
- *size = part_info.size * part_info.blksz;
-# elif CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
+ struct disk_partition disk_part;
struct part_info *part_info;
- r = fastboot_nand_get_part_info(part_name, &part_info, response);
- if (r >= 0 && size)
- *size = part_info->size;
-# else
- fastboot_fail("this storage is not supported in bootloader", response);
- r = -ENODEV;
-# endif
+ if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)) {
+ r = fastboot_mmc_get_part_info(part_name, &dev_desc, &disk_part,
+ response);
+ if (r >= 0 && size)
+ *size = disk_part.size * disk_part.blksz;
+ } else if (CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)) {
+ r = fastboot_nand_get_part_info(part_name, &part_info, response);
+ if (r >= 0 && size)
+ *size = part_info->size;
+ } else {
+ fastboot_fail("this storage is not supported in bootloader", response);
+ r = -ENODEV;
+ }
return r;
}
-#endif
static void getvar_version(char *var_parameter, char *response)
{
@@ -181,8 +172,7 @@
fastboot_okay("a", response);
}
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
-static void getvar_has_slot(char *part_name, char *response)
+static void __maybe_unused getvar_has_slot(char *part_name, char *response)
{
char part_name_wslot[PART_NAME_LEN];
size_t len;
@@ -213,10 +203,8 @@
fail:
fastboot_fail("invalid partition name", response);
}
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
-static void getvar_partition_type(char *part_name, char *response)
+static void __maybe_unused getvar_partition_type(char *part_name, char *response)
{
int r;
struct blk_desc *dev_desc;
@@ -232,10 +220,8 @@
fastboot_okay(fs_get_type_name(), response);
}
}
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
-static void getvar_partition_size(char *part_name, char *response)
+static void __maybe_unused getvar_partition_size(char *part_name, char *response)
{
int r;
size_t size;
@@ -244,7 +230,6 @@
if (r >= 0)
fastboot_response("OKAY", response, "0x%016zx", size);
}
-#endif
static void getvar_is_userspace(char *var_parameter, char *response)
{
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 727e090..bd7379a 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -1935,7 +1935,7 @@
info = handle_to_ti_sci_info(handle);
- xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMIAGE,
+ xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMAGE,
TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
(u32 *)&req, sizeof(req), sizeof(*resp));
if (IS_ERR(xfer)) {
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index e4a087c..101210e 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -49,7 +49,7 @@
#define TISCI_MSG_PROC_HANDOVER 0xc005
#define TISCI_MSG_SET_PROC_BOOT_CONFIG 0xc100
#define TISCI_MSG_SET_PROC_BOOT_CTRL 0xc101
-#define TISCI_MSG_PROC_AUTH_BOOT_IMIAGE 0xc120
+#define TISCI_MSG_PROC_AUTH_BOOT_IMAGE 0xc120
#define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400
#define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index 11b742e..4113de2 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -153,4 +153,9 @@
This is a driver model based FPGA driver for sandbox.
Currently it is a stub only, as there are no usable uclass methods yet.
+config MAX_FPGA_DEVICES
+ int "Maximum number of FPGA devices"
+ depends on FPGA
+ default 5
+
endmenu
diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c
index 4db5c0a..7f6b6bc 100644
--- a/drivers/fpga/fpga.c
+++ b/drivers/fpga/fpga.c
@@ -13,11 +13,6 @@
#include <lattice.h>
#include <dm/device_compat.h>
-/* Local definitions */
-#ifndef CONFIG_MAX_FPGA_DEVICES
-#define CONFIG_MAX_FPGA_DEVICES 5
-#endif
-
/* Local static data */
static int next_desc = FPGA_INVALID_DEVICE;
static fpga_desc desc_table[CONFIG_MAX_FPGA_DEVICES];
diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c
index 3b785e6..96b1950 100644
--- a/drivers/fpga/socfpga_arria10.c
+++ b/drivers/fpga/socfpga_arria10.c
@@ -777,42 +777,20 @@
{
struct fpga_loadfs_info fpga_loadfs;
struct udevice *dev;
- int status, ret, size;
+ int status, ret;
u32 buffer = (uintptr_t)buf;
size_t buffer_sizebytes = bsize;
size_t buffer_sizebytes_ori = bsize;
size_t total_sizeof_image = 0;
ofnode node;
- const fdt32_t *phandle_p;
- u32 phandle;
node = get_fpga_mgr_ofnode(ofnode_null());
-
- if (ofnode_valid(node)) {
- phandle_p = ofnode_get_property(node, "firmware-loader", &size);
- if (!phandle_p) {
- node = ofnode_path("/chosen");
- if (!ofnode_valid(node)) {
- debug("FPGA: /chosen node was not found.\n");
- return -ENOENT;
- }
-
- phandle_p = ofnode_get_property(node, "firmware-loader",
- &size);
- if (!phandle_p) {
- debug("FPGA: firmware-loader property was not");
- debug(" found.\n");
- return -ENOENT;
- }
- }
- } else {
+ if (!ofnode_valid(node)) {
debug("FPGA: FPGA manager node was not found.\n");
return -ENOENT;
}
- phandle = fdt32_to_cpu(*phandle_p);
- ret = uclass_get_device_by_phandle_id(UCLASS_FS_FIRMWARE_LOADER,
- phandle, &dev);
+ ret = get_fs_loader(&dev);
if (ret)
return ret;
diff --git a/drivers/fpga/virtex2.c b/drivers/fpga/virtex2.c
index fc99a5f..3ded27f 100644
--- a/drivers/fpga/virtex2.c
+++ b/drivers/fpga/virtex2.c
@@ -34,8 +34,8 @@
/*
* Check for errors during configuration by default
*/
-#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
-#define CONFIG_SYS_FPGA_CHECK_ERROR
+#ifndef CFG_SYS_FPGA_CHECK_ERROR
+#define CFG_SYS_FPGA_CHECK_ERROR
#endif
/*
@@ -323,7 +323,7 @@
break;
}
-#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
+#ifdef CFG_SYS_FPGA_CHECK_ERROR
if ((*fn->init)(cookie)) {
printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
__func__, __LINE__);
@@ -458,7 +458,7 @@
break;
}
-#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
+#ifdef CFG_SYS_FPGA_CHECK_ERROR
if ((*fn->init)(cookie)) {
printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
__func__, __LINE__);
diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c
index 53dd780..a2e3b30 100644
--- a/drivers/fpga/zynqpl.c
+++ b/drivers/fpga/zynqpl.c
@@ -40,8 +40,8 @@
#define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
#endif
-#ifndef CONFIG_SYS_FPGA_PROG_TIME
-#define CONFIG_SYS_FPGA_PROG_TIME (CONFIG_SYS_HZ * 4) /* 4 s */
+#ifndef CFG_SYS_FPGA_PROG_TIME
+#define CFG_SYS_FPGA_PROG_TIME (CONFIG_SYS_HZ * 4) /* 4 s */
#endif
#define DUMMY_WORD 0xffffffff
@@ -181,7 +181,7 @@
return FPGA_FAIL;
}
- if (get_timer(ts) > CONFIG_SYS_FPGA_PROG_TIME) {
+ if (get_timer(ts) > CFG_SYS_FPGA_PROG_TIME) {
printf("%s: Timeout wait for DMA to complete\n",
__func__);
return FPGA_FAIL;
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 3a6ef3b..dbebf3a 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -311,34 +311,11 @@
return 0;
}
-int gpio_hog_probe_all(void)
-{
- struct udevice *dev;
- int ret;
- int retval = 0;
-
- for (uclass_first_device(UCLASS_NOP, &dev);
- dev;
- uclass_find_next_device(&dev)) {
- if (dev->driver == DM_DRIVER_GET(gpio_hog)) {
- ret = device_probe(dev);
- if (ret) {
- printf("Failed to probe device %s err: %d\n",
- dev->name, ret);
- retval = ret;
- }
- }
- }
-
- return retval;
-}
-
int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc)
{
struct udevice *dev;
*desc = NULL;
- gpio_hog_probe_all();
if (!uclass_get_device_by_name(UCLASS_NOP, name, &dev)) {
struct gpio_hog_priv *priv = dev_get_priv(dev);
@@ -1505,9 +1482,17 @@
&child);
if (ret)
return ret;
+
+ /*
+ * Make sure gpio-hogs are probed after bind
+ * since hogs can be essential to the hardware
+ * system.
+ */
+ dev_or_flags(child, DM_FLAG_PROBE_AFTER_BIND);
}
}
}
+
return 0;
}
diff --git a/drivers/gpio/mpc83xx_gpio.c b/drivers/gpio/mpc83xx_gpio.c
index 276a3b3..bf693c8 100644
--- a/drivers/gpio/mpc83xx_gpio.c
+++ b/drivers/gpio/mpc83xx_gpio.c
@@ -9,23 +9,23 @@
#include <asm/gpio.h>
#include <asm/io.h>
-#ifndef CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION
-#define CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION 0
+#ifndef CFG_MPC83XX_GPIO_0_INIT_DIRECTION
+#define CFG_MPC83XX_GPIO_0_INIT_DIRECTION 0
#endif
-#ifndef CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION
-#define CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION 0
+#ifndef CFG_MPC83XX_GPIO_1_INIT_DIRECTION
+#define CFG_MPC83XX_GPIO_1_INIT_DIRECTION 0
#endif
-#ifndef CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN
-#define CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN 0
+#ifndef CFG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN
+#define CFG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN 0
#endif
-#ifndef CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN
-#define CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN 0
+#ifndef CFG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN
+#define CFG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN 0
#endif
-#ifndef CONFIG_MPC83XX_GPIO_0_INIT_VALUE
-#define CONFIG_MPC83XX_GPIO_0_INIT_VALUE 0
+#ifndef CFG_MPC83XX_GPIO_0_INIT_VALUE
+#define CFG_MPC83XX_GPIO_0_INIT_VALUE 0
#endif
-#ifndef CONFIG_MPC83XX_GPIO_1_INIT_VALUE
-#define CONFIG_MPC83XX_GPIO_1_INIT_VALUE 0
+#ifndef CFG_MPC83XX_GPIO_1_INIT_VALUE
+#define CFG_MPC83XX_GPIO_1_INIT_VALUE 0
#endif
static unsigned int gpio_output_value[MPC83XX_GPIO_CTRLRS];
@@ -152,18 +152,18 @@
immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
#if MPC83XX_GPIO_CTRLRS >= 1
- out_be32(&im->gpio[0].dir, CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION);
- out_be32(&im->gpio[0].odr, CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN);
- out_be32(&im->gpio[0].dat, CONFIG_MPC83XX_GPIO_0_INIT_VALUE);
+ out_be32(&im->gpio[0].dir, CFG_MPC83XX_GPIO_0_INIT_DIRECTION);
+ out_be32(&im->gpio[0].odr, CFG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN);
+ out_be32(&im->gpio[0].dat, CFG_MPC83XX_GPIO_0_INIT_VALUE);
out_be32(&im->gpio[0].ier, 0xFFFFFFFF); /* Clear all events */
out_be32(&im->gpio[0].imr, 0);
out_be32(&im->gpio[0].icr, 0);
#endif
#if MPC83XX_GPIO_CTRLRS >= 2
- out_be32(&im->gpio[1].dir, CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION);
- out_be32(&im->gpio[1].odr, CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN);
- out_be32(&im->gpio[1].dat, CONFIG_MPC83XX_GPIO_1_INIT_VALUE);
+ out_be32(&im->gpio[1].dir, CFG_MPC83XX_GPIO_1_INIT_DIRECTION);
+ out_be32(&im->gpio[1].odr, CFG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN);
+ out_be32(&im->gpio[1].dat, CFG_MPC83XX_GPIO_1_INIT_VALUE);
out_be32(&im->gpio[1].ier, 0xFFFFFFFF); /* Clear all events */
out_be32(&im->gpio[1].imr, 0);
out_be32(&im->gpio[1].icr, 0);
@@ -174,10 +174,10 @@
void mpc83xx_gpio_init_r(void)
{
#if MPC83XX_GPIO_CTRLRS >= 1
- gpio_output_value[0] = CONFIG_MPC83XX_GPIO_0_INIT_VALUE;
+ gpio_output_value[0] = CFG_MPC83XX_GPIO_0_INIT_VALUE;
#endif
#if MPC83XX_GPIO_CTRLRS >= 2
- gpio_output_value[1] = CONFIG_MPC83XX_GPIO_1_INIT_VALUE;
+ gpio_output_value[1] = CFG_MPC83XX_GPIO_1_INIT_VALUE;
#endif
}
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index 187db92..d312f35 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -23,16 +23,16 @@
* released the bus. If not defined in the board header file, then use a
* generic value.
*/
-#ifndef CONFIG_I2C_MBB_TIMEOUT
-#define CONFIG_I2C_MBB_TIMEOUT 100000
+#ifndef CFG_I2C_MBB_TIMEOUT
+#define CFG_I2C_MBB_TIMEOUT 100000
#endif
/* The maximum number of microseconds we will wait for a read or write
* operation to complete. If not defined in the board header file, then use a
* generic value.
*/
-#ifndef CONFIG_I2C_TIMEOUT
-#define CONFIG_I2C_TIMEOUT 100000
+#ifndef CFG_I2C_TIMEOUT
+#define CFG_I2C_TIMEOUT 100000
#endif
#define I2C_READ_BIT 1
@@ -41,20 +41,22 @@
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_M68K
-#define CONFIG_SYS_IMMR CFG_SYS_MBAR
+#define CFG_FSL_I2C_BASE_ADDR CFG_SYS_MBAR
+#else
+#define CFG_FSL_I2C_BASE_ADDR CONFIG_SYS_IMMR
#endif
#if !CONFIG_IS_ENABLED(DM_I2C)
static const struct fsl_i2c_base *i2c_base[4] = {
- (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C_OFFSET),
+ (struct fsl_i2c_base *)(CFG_FSL_I2C_BASE_ADDR + CONFIG_SYS_FSL_I2C_OFFSET),
#ifdef CONFIG_SYS_FSL_I2C2_OFFSET
- (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C2_OFFSET),
+ (struct fsl_i2c_base *)(CFG_FSL_I2C_BASE_ADDR + CONFIG_SYS_FSL_I2C2_OFFSET),
#endif
#ifdef CONFIG_SYS_FSL_I2C3_OFFSET
- (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C3_OFFSET),
+ (struct fsl_i2c_base *)(CFG_FSL_I2C_BASE_ADDR + CONFIG_SYS_FSL_I2C3_OFFSET),
#endif
#ifdef CONFIG_SYS_FSL_I2C4_OFFSET
- (struct fsl_i2c_base *)(CONFIG_SYS_IMMR + CONFIG_SYS_FSL_I2C4_OFFSET)
+ (struct fsl_i2c_base *)(CFG_FSL_I2C_BASE_ADDR + CONFIG_SYS_FSL_I2C4_OFFSET)
#endif
};
#endif
@@ -219,7 +221,7 @@
static int fsl_i2c_fixup(const struct fsl_i2c_base *base)
{
- const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT);
+ const unsigned long long timeout = usec2ticks(CFG_I2C_MBB_TIMEOUT);
unsigned long long timeval = 0;
int ret = -1;
uint flags = 0;
@@ -268,7 +270,7 @@
static void __i2c_init(const struct fsl_i2c_base *base, int speed, int
slaveadd, int i2c_clk, int busnum)
{
- const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT);
+ const unsigned long long timeout = usec2ticks(CFG_I2C_MBB_TIMEOUT);
unsigned long long timeval;
writeb(0, &base->cr); /* stop I2C controller */
@@ -294,7 +296,7 @@
static int i2c_wait4bus(const struct fsl_i2c_base *base)
{
unsigned long long timeval = get_ticks();
- const unsigned long long timeout = usec2ticks(CONFIG_I2C_MBB_TIMEOUT);
+ const unsigned long long timeout = usec2ticks(CFG_I2C_MBB_TIMEOUT);
while (readb(&base->sr) & I2C_SR_MBB) {
if ((get_ticks() - timeval) > timeout)
@@ -308,7 +310,7 @@
{
u32 csr;
unsigned long long timeval = get_ticks();
- const unsigned long long timeout = usec2ticks(CONFIG_I2C_TIMEOUT);
+ const unsigned long long timeout = usec2ticks(CFG_I2C_TIMEOUT);
do {
csr = readb(&base->sr);
diff --git a/drivers/i2c/lpc32xx_i2c.c b/drivers/i2c/lpc32xx_i2c.c
index 774129a..496f4fe 100644
--- a/drivers/i2c/lpc32xx_i2c.c
+++ b/drivers/i2c/lpc32xx_i2c.c
@@ -20,12 +20,12 @@
* Provide default speed and slave if target did not
*/
-#if !defined(CONFIG_SYS_I2C_LPC32XX_SPEED)
-#define CONFIG_SYS_I2C_LPC32XX_SPEED 350000
+#if !defined(CFG_SYS_I2C_LPC32XX_SPEED)
+#define CFG_SYS_I2C_LPC32XX_SPEED 350000
#endif
-#if !defined(CONFIG_SYS_I2C_LPC32XX_SLAVE)
-#define CONFIG_SYS_I2C_LPC32XX_SLAVE 0
+#if !defined(CFG_SYS_I2C_LPC32XX_SLAVE)
+#define CFG_SYS_I2C_LPC32XX_SLAVE 0
#endif
/* TX register fields */
@@ -260,15 +260,15 @@
U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_0, lpc32xx_i2c_init, lpc32xx_i2c_probe_chip,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
- CONFIG_SYS_I2C_LPC32XX_SPEED,
- CONFIG_SYS_I2C_LPC32XX_SLAVE,
+ CFG_SYS_I2C_LPC32XX_SPEED,
+ CFG_SYS_I2C_LPC32XX_SLAVE,
0)
U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_1, lpc32xx_i2c_init, lpc32xx_i2c_probe_chip,
lpc32xx_i2c_read, lpc32xx_i2c_write,
lpc32xx_i2c_set_bus_speed,
- CONFIG_SYS_I2C_LPC32XX_SPEED,
- CONFIG_SYS_I2C_LPC32XX_SLAVE,
+ CFG_SYS_I2C_LPC32XX_SPEED,
+ CFG_SYS_I2C_LPC32XX_SLAVE,
1)
U_BOOT_I2C_ADAP_COMPLETE(lpc32xx_2, lpc32xx_i2c_init, NULL,
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 2822749..93bbc69 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -205,9 +205,9 @@
case 1:
return (struct mvtwsi_registers *)CFG_I2C_MVTWSI_BASE1;
#endif
-#ifdef CONFIG_I2C_MVTWSI_BASE2
+#ifdef CFG_I2C_MVTWSI_BASE2
case 2:
- return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE2;
+ return (struct mvtwsi_registers *)CFG_I2C_MVTWSI_BASE2;
#endif
#ifdef CONFIG_I2C_MVTWSI_BASE3
case 3:
@@ -750,7 +750,7 @@
CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 1)
#endif
-#ifdef CONFIG_I2C_MVTWSI_BASE2
+#ifdef CFG_I2C_MVTWSI_BASE2
U_BOOT_I2C_ADAP_COMPLETE(twsi2, twsi_i2c_init, twsi_i2c_probe,
twsi_i2c_read, twsi_i2c_write,
twsi_i2c_set_bus_speed,
diff --git a/drivers/i2c/octeon_i2c.c b/drivers/i2c/octeon_i2c.c
index e54ef18..f2dea56 100644
--- a/drivers/i2c/octeon_i2c.c
+++ b/drivers/i2c/octeon_i2c.c
@@ -146,7 +146,7 @@
TWSI_STAT_IDLE = 0xf8
};
-#define CONFIG_SYS_I2C_OCTEON_SLAVE_ADDR 0x77
+#define CFG_SYS_I2C_OCTEON_SLAVE_ADDR 0x77
enum {
PROBE_PCI = 0, /* PCI based probing */
@@ -800,7 +800,7 @@
twsi->base += twsi->data->reg_offs;
i2c_slave_addr = dev_read_u32_default(dev, "i2c-sda-hold-time-ns",
- CONFIG_SYS_I2C_OCTEON_SLAVE_ADDR);
+ CFG_SYS_I2C_OCTEON_SLAVE_ADDR);
ret = clk_get_by_index(dev, 0, &twsi->clk);
if (ret < 0)
diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c
index c72839e..ed8ba47 100644
--- a/drivers/i2c/soft_i2c.c
+++ b/drivers/i2c/soft_i2c.c
@@ -88,13 +88,6 @@
# define I2C_SOFT_DECLARATIONS
#endif
-#if !defined(CONFIG_SYS_I2C_SOFT_SPEED)
-#define CONFIG_SYS_I2C_SOFT_SPEED CONFIG_SYS_I2C_SPEED
-#endif
-#if !defined(CONFIG_SYS_I2C_SOFT_SLAVE)
-#define CONFIG_SYS_I2C_SOFT_SLAVE CONFIG_SYS_I2C_SLAVE
-#endif
-
/*-----------------------------------------------------------------------
* Definitions
*/
diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c
index 5b4d036..ccf5c7a 100644
--- a/drivers/misc/fs_loader.c
+++ b/drivers/misc/fs_loader.c
@@ -15,6 +15,8 @@
#include <fs_loader.h>
#include <log.h>
#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/root.h>
#include <linux/string.h>
#include <mapmem.h>
#include <malloc.h>
@@ -297,6 +299,31 @@
.priv_auto = sizeof(struct firmware),
};
+static struct device_plat default_plat = { 0 };
+
+int get_fs_loader(struct udevice **dev)
+{
+ int ret;
+ ofnode node = ofnode_get_chosen_node("firmware-loader");
+
+ if (ofnode_valid(node))
+ return uclass_get_device_by_ofnode(UCLASS_FS_FIRMWARE_LOADER,
+ node, dev);
+
+ /* Try the first device if none was chosen */
+ ret = uclass_first_device_err(UCLASS_FS_FIRMWARE_LOADER, dev);
+ if (ret != -ENODEV)
+ return ret;
+
+ /* Just create a new device */
+ ret = device_bind(dm_root(), DM_DRIVER_GET(fs_loader), "default-loader",
+ &default_plat, ofnode_null(), dev);
+ if (ret)
+ return ret;
+
+ return device_probe(*dev);
+}
+
UCLASS_DRIVER(fs_loader) = {
.id = UCLASS_FS_FIRMWARE_LOADER,
.name = "fs-loader",
diff --git a/drivers/misc/gpio_led.c b/drivers/misc/gpio_led.c
index b913069..30679f8 100644
--- a/drivers/misc/gpio_led.c
+++ b/drivers/misc/gpio_led.c
@@ -9,11 +9,11 @@
#include <status_led.h>
#include <asm/gpio.h>
-#ifndef CONFIG_GPIO_LED_INVERTED_TABLE
-#define CONFIG_GPIO_LED_INVERTED_TABLE {}
+#ifndef CFG_GPIO_LED_INVERTED_TABLE
+#define CFG_GPIO_LED_INVERTED_TABLE {}
#endif
-static led_id_t gpio_led_inv[] = CONFIG_GPIO_LED_INVERTED_TABLE;
+static led_id_t gpio_led_inv[] = CFG_GPIO_LED_INVERTED_TABLE;
static int gpio_led_gpio_value(led_id_t mask, int state)
{
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 759a6b7..01d9b02 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -421,7 +421,7 @@
mmc->cfg = cfg;
mmc->priv = dev;
- ret = bootdev_setup_for_dev(dev, "mmc_bootdev");
+ ret = bootdev_setup_sibling_blk(bdev, "mmc_bootdev");
if (ret)
return log_msg_ret("bootdev", ret);
diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c
index b4f41fb..b57b8a6 100644
--- a/drivers/mmc/mmc_bootdev.c
+++ b/drivers/mmc/mmc_bootdev.c
@@ -11,41 +11,16 @@
#include <dm.h>
#include <mmc.h>
-static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
- struct bootflow *bflow)
-{
- struct udevice *mmc_dev = dev_get_parent(dev);
- struct udevice *blk;
- int ret;
-
- ret = mmc_get_blk(mmc_dev, &blk);
- /*
- * If there is no media, indicate that no more partitions should be
- * checked
- */
- if (ret == -EOPNOTSUPP)
- ret = -ESHUTDOWN;
- if (ret)
- return log_msg_ret("blk", ret);
- assert(blk);
- ret = bootdev_find_in_blk(dev, blk, iter, bflow);
- if (ret)
- return log_msg_ret("find", ret);
-
- return 0;
-}
-
static int mmc_bootdev_bind(struct udevice *dev)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
- ucp->prio = BOOTDEVP_0_INTERNAL_FAST;
+ ucp->prio = BOOTDEVP_2_INTERNAL_FAST;
return 0;
}
struct bootdev_ops mmc_bootdev_ops = {
- .get_bootflow = mmc_get_bootflow,
};
static const struct udevice_id mmc_bootdev_ids[] = {
@@ -60,3 +35,9 @@
.bind = mmc_bootdev_bind,
.of_match = mmc_bootdev_ids,
};
+
+BOOTDEV_HUNTER(mmc_bootdev_hunter) = {
+ .prio = BOOTDEVP_2_INTERNAL_FAST,
+ .uclass = UCLASS_MMC,
+ .drv = DM_DRIVER_REF(mmc_bootdev),
+};
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index ba79a55..0ba7940 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -183,7 +183,7 @@
priv->csize = 0;
priv->size = (priv->csize + 1) * SIZE_MULTIPLE; /* 1 MiB */
- priv->buf = malloc(priv->size);
+ priv->buf = calloc(1, priv->size);
if (!priv->buf) {
log_err("%s: Not enough memory (%x bytes)\n",
dev->name, priv->size);
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 1bb7b6d..23bc7da 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -5,6 +5,12 @@
* Aaron <leafy.myeh@allwinnertech.com>
*
* MMC driver for allwinner sunxi platform.
+ *
+ * This driver is used by the (ARM) SPL with the legacy MMC interface, and
+ * by U-Boot proper using the full DM interface. The actual hardware access
+ * code is common, and comes first in this file.
+ * The legacy MMC interface implementation comes next, followed by the
+ * proper DM_MMC implementation at the end.
*/
#include <common.h>
@@ -40,69 +46,6 @@
struct mmc_config cfg;
};
-#if !CONFIG_IS_ENABLED(DM_MMC)
-/* support 4 mmc hosts */
-struct sunxi_mmc_priv mmc_host[4];
-
-static int sunxi_mmc_getcd_gpio(int sdc_no)
-{
- switch (sdc_no) {
- case 0: return sunxi_name_to_gpio(CONFIG_MMC0_CD_PIN);
- case 1: return sunxi_name_to_gpio(CONFIG_MMC1_CD_PIN);
- case 2: return sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN);
- case 3: return sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN);
- }
- return -EINVAL;
-}
-
-static int mmc_resource_init(int sdc_no)
-{
- struct sunxi_mmc_priv *priv = &mmc_host[sdc_no];
- struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- int cd_pin, ret = 0;
-
- debug("init mmc %d resource\n", sdc_no);
-
- switch (sdc_no) {
- case 0:
- priv->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE;
- priv->mclkreg = &ccm->sd0_clk_cfg;
- break;
- case 1:
- priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
- priv->mclkreg = &ccm->sd1_clk_cfg;
- break;
-#ifdef SUNXI_MMC2_BASE
- case 2:
- priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
- priv->mclkreg = &ccm->sd2_clk_cfg;
- break;
-#endif
-#ifdef SUNXI_MMC3_BASE
- case 3:
- priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
- priv->mclkreg = &ccm->sd3_clk_cfg;
- break;
-#endif
- default:
- printf("Wrong mmc number %d\n", sdc_no);
- return -1;
- }
- priv->mmc_no = sdc_no;
-
- cd_pin = sunxi_mmc_getcd_gpio(sdc_no);
- if (cd_pin >= 0) {
- ret = gpio_request(cd_pin, "mmc_cd");
- if (!ret) {
- sunxi_gpio_set_pull(cd_pin, SUNXI_GPIO_PULL_UP);
- ret = gpio_direction_input(cd_pin);
- }
- }
-
- return ret;
-}
-#endif
-
/*
* All A64 and later MMC controllers feature auto-calibration. This would
* normally be detected via the compatible string, but we need something
@@ -290,19 +233,6 @@
return 0;
}
-#if !CONFIG_IS_ENABLED(DM_MMC)
-static int sunxi_mmc_core_init(struct mmc *mmc)
-{
- struct sunxi_mmc_priv *priv = mmc->priv;
-
- /* Reset controller */
- writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
- udelay(1000);
-
- return 0;
-}
-#endif
-
static int mmc_trans_data_by_cpu(struct sunxi_mmc_priv *priv, struct mmc *mmc,
struct mmc_data *data)
{
@@ -507,7 +437,60 @@
return error;
}
+/* non-DM code here is used by the (ARM) SPL only */
+
#if !CONFIG_IS_ENABLED(DM_MMC)
+/* support 4 mmc hosts */
+struct sunxi_mmc_priv mmc_host[4];
+
+static int mmc_resource_init(int sdc_no)
+{
+ struct sunxi_mmc_priv *priv = &mmc_host[sdc_no];
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ debug("init mmc %d resource\n", sdc_no);
+
+ switch (sdc_no) {
+ case 0:
+ priv->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE;
+ priv->mclkreg = &ccm->sd0_clk_cfg;
+ break;
+ case 1:
+ priv->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
+ priv->mclkreg = &ccm->sd1_clk_cfg;
+ break;
+#ifdef SUNXI_MMC2_BASE
+ case 2:
+ priv->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
+ priv->mclkreg = &ccm->sd2_clk_cfg;
+ break;
+#endif
+#ifdef SUNXI_MMC3_BASE
+ case 3:
+ priv->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
+ priv->mclkreg = &ccm->sd3_clk_cfg;
+ break;
+#endif
+ default:
+ printf("Wrong mmc number %d\n", sdc_no);
+ return -1;
+ }
+ priv->mmc_no = sdc_no;
+
+ return 0;
+}
+
+static int sunxi_mmc_core_init(struct mmc *mmc)
+{
+ struct sunxi_mmc_priv *priv = mmc->priv;
+
+ /* Reset controller */
+ writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
+ udelay(1000);
+
+ return 0;
+}
+
static int sunxi_mmc_set_ios_legacy(struct mmc *mmc)
{
struct sunxi_mmc_priv *priv = mmc->priv;
@@ -523,23 +506,11 @@
return sunxi_mmc_send_cmd_common(priv, mmc, cmd, data);
}
-static int sunxi_mmc_getcd_legacy(struct mmc *mmc)
-{
- struct sunxi_mmc_priv *priv = mmc->priv;
- int cd_pin;
-
- cd_pin = sunxi_mmc_getcd_gpio(priv->mmc_no);
- if (cd_pin < 0)
- return 1;
-
- return !gpio_get_value(cd_pin);
-}
-
+/* .getcd is not needed by the SPL */
static const struct mmc_ops sunxi_mmc_ops = {
.send_cmd = sunxi_mmc_send_cmd_legacy,
.set_ios = sunxi_mmc_set_ios_legacy,
.init = sunxi_mmc_core_init,
- .getcd = sunxi_mmc_getcd_legacy,
};
struct mmc *sunxi_mmc_init(int sdc_no)
@@ -595,7 +566,8 @@
return mmc_create(cfg, priv);
}
-#else
+
+#else /* CONFIG_DM_MMC code below, as used by U-Boot proper */
static int sunxi_mmc_set_ios(struct udevice *dev)
{
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index 18abd75..1d7c1fd 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -20,10 +20,6 @@
#include <linux/errno.h>
#include <fsl_ifc.h>
-#ifndef CONFIG_SYS_FSL_IFC_BANK_COUNT
-#define CONFIG_SYS_FSL_IFC_BANK_COUNT 4
-#endif
-
#define MAX_BANKS CONFIG_SYS_FSL_IFC_BANK_COUNT
#define ERR_BYTE 0xFF /* Value returned for read bytes
when read failed */
diff --git a/drivers/mtd/nand/raw/kmeter1_nand.c b/drivers/mtd/nand/raw/kmeter1_nand.c
index 84564b2..dfe73d6 100644
--- a/drivers/mtd/nand/raw/kmeter1_nand.c
+++ b/drivers/mtd/nand/raw/kmeter1_nand.c
@@ -10,13 +10,13 @@
#include <linux/delay.h>
#include <linux/mtd/rawnand.h>
-#define CONFIG_NAND_MODE_REG (void *)(CFG_SYS_NAND_BASE + 0x20000)
-#define CONFIG_NAND_DATA_REG (void *)(CFG_SYS_NAND_BASE + 0x30000)
+#define CFG_NAND_MODE_REG (void *)(CFG_SYS_NAND_BASE + 0x20000)
+#define CFG_NAND_DATA_REG (void *)(CFG_SYS_NAND_BASE + 0x30000)
-#define read_mode() in_8(CONFIG_NAND_MODE_REG)
-#define write_mode(val) out_8(CONFIG_NAND_MODE_REG, val)
-#define read_data() in_8(CONFIG_NAND_DATA_REG)
-#define write_data(val) out_8(CONFIG_NAND_DATA_REG, val)
+#define read_mode() in_8(CFG_NAND_MODE_REG)
+#define write_mode(val) out_8(CFG_NAND_MODE_REG, val)
+#define read_data() in_8(CFG_NAND_DATA_REG)
+#define write_data(val) out_8(CFG_NAND_DATA_REG, val)
#define KPN_RDY2 (1 << 7)
#define KPN_RDY1 (1 << 6)
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 7b858a3..a9617c6 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -80,6 +80,14 @@
if SPI_FLASH
+config BOOTDEV_SPI_FLASH
+ bool "SPI Flash bootdev support"
+ help
+ Enable a boot device for SPI flash. This allows reading a script
+ from SPI flash so that it can be used to boot an Operating System.
+
+ If unsure, say N
+
config SPI_FLASH_SFDP_SUPPORT
bool "SFDP table parsing support for SPI NOR flashes"
depends on !SPI_FLASH_BAR
diff --git a/drivers/mtd/spi/Makefile b/drivers/mtd/spi/Makefile
index 99cc418..4093953 100644
--- a/drivers/mtd/spi/Makefile
+++ b/drivers/mtd/spi/Makefile
@@ -21,3 +21,4 @@
obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
obj-$(CONFIG_$(SPL_TPL_)SPI_FLASH_MTD) += sf_mtd.o
obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
+obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_SPI_FLASH) += sf_bootdev.o
diff --git a/drivers/mtd/spi/fsl_espi_spl.c b/drivers/mtd/spi/fsl_espi_spl.c
index dfc35d6..cdbdbd6 100644
--- a/drivers/mtd/spi/fsl_espi_spl.c
+++ b/drivers/mtd/spi/fsl_espi_spl.c
@@ -11,7 +11,7 @@
#define ESPI_BOOT_IMAGE_SIZE 0x48
#define ESPI_BOOT_IMAGE_ADDR 0x50
-#define CONFIG_CFG_DATA_SECTOR 0
+#define CFG_CFG_DATA_SECTOR 0
void fsl_spi_spl_load_image(uint32_t offs, unsigned int size, void *vdst)
{
@@ -62,7 +62,7 @@
}
memset(buf, 0, flash->page_size);
- spi_flash_read(flash, CONFIG_CFG_DATA_SECTOR,
+ spi_flash_read(flash, CFG_CFG_DATA_SECTOR,
flash->page_size, (void *)buf);
offset = *(u32 *)(buf + ESPI_BOOT_IMAGE_ADDR);
/* Skip spl code */
diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c
index e6e650e..df1f753 100644
--- a/drivers/mtd/spi/sf-uclass.c
+++ b/drivers/mtd/spi/sf-uclass.c
@@ -6,6 +6,7 @@
#define LOG_CATEGORY UCLASS_SPI_FLASH
#include <common.h>
+#include <bootdev.h>
#include <dm.h>
#include <log.h>
#include <malloc.h>
@@ -13,6 +14,7 @@
#include <spi_flash.h>
#include <asm/global_data.h>
#include <dm/device-internal.h>
+#include <test/test.h>
#include "sf_internal.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -86,6 +88,14 @@
static int spi_flash_post_bind(struct udevice *dev)
{
+ int ret;
+
+ if (CONFIG_IS_ENABLED(BOOTDEV_SPI_FLASH) && test_sf_bootdev_enabled()) {
+ ret = bootdev_setup_for_dev(dev, "sf_bootdev");
+ if (ret)
+ return log_msg_ret("bd", ret);
+ }
+
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
struct dm_spi_flash_ops *ops = sf_get_ops(dev);
static int reloc_done;
@@ -101,6 +111,7 @@
reloc_done++;
}
#endif
+
return 0;
}
diff --git a/drivers/mtd/spi/sf_bootdev.c b/drivers/mtd/spi/sf_bootdev.c
new file mode 100644
index 0000000..d6b47b1
--- /dev/null
+++ b/drivers/mtd/spi/sf_bootdev.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Read a bootflow from SPI flash
+ *
+ * Copyright 2022 Google LLC
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <dm.h>
+#include <env.h>
+#include <malloc.h>
+#include <spi_flash.h>
+
+static int sf_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
+ struct bootflow *bflow)
+{
+ struct udevice *sf = dev_get_parent(dev);
+ uint size;
+ char *buf;
+ int ret;
+
+ /* We only support the whole device, not partitions */
+ if (iter->part)
+ return log_msg_ret("max", -ESHUTDOWN);
+
+ size = env_get_hex("script_size_f", 0);
+ if (!size)
+ return log_msg_ret("sz", -EINVAL);
+
+ buf = malloc(size + 1);
+ if (!buf)
+ return log_msg_ret("buf", -ENOMEM);
+
+ ret = spi_flash_read_dm(sf, env_get_hex("script_offset_f", 0),
+ size, buf);
+ if (ret)
+ return log_msg_ret("cmd", -EINVAL);
+ bflow->state = BOOTFLOWST_MEDIA;
+
+ ret = bootmeth_set_bootflow(bflow->method, bflow, buf, size);
+ if (ret) {
+ free(buf);
+ return log_msg_ret("method", ret);
+ }
+
+ return 0;
+}
+
+static int sf_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_4_SCAN_FAST;
+
+ return 0;
+}
+
+struct bootdev_ops sf_bootdev_ops = {
+ .get_bootflow = sf_get_bootflow,
+};
+
+static const struct udevice_id sf_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-sf" },
+ { }
+};
+
+U_BOOT_DRIVER(sf_bootdev) = {
+ .name = "sf_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &sf_bootdev_ops,
+ .bind = sf_bootdev_bind,
+ .of_match = sf_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(sf_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_SPI_FLASH,
+ .drv = DM_DRIVER_REF(sf_bootdev),
+};
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 1ea8363..2c3116e 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -3195,7 +3195,11 @@
}
#ifdef CONFIG_SPI_FLASH_SPANSION
-static int s25hx_t_mdp_ready(struct spi_nor *nor)
+
+/* Use ID byte 4 to distinguish S25FS256T and S25Hx-T */
+#define S25FS256T_ID4 (0x08)
+
+static int s25_mdp_ready(struct spi_nor *nor)
{
u32 addr;
int ret;
@@ -3209,7 +3213,7 @@
return 1;
}
-static int s25hx_t_quad_enable(struct spi_nor *nor)
+static int s25_quad_enable(struct spi_nor *nor)
{
u32 addr;
int ret;
@@ -3223,51 +3227,67 @@
return 0;
}
-static int s25hx_t_erase_non_uniform(struct spi_nor *nor, loff_t addr)
+static int s25_erase_non_uniform(struct spi_nor *nor, loff_t addr)
{
/* Support 32 x 4KB sectors at bottom */
return spansion_erase_non_uniform(nor, addr, SPINOR_OP_BE_4K_4B, 0,
SZ_128K);
}
-static int s25hx_t_setup(struct spi_nor *nor, const struct flash_info *info,
- const struct spi_nor_flash_parameter *params)
+static int s25_setup(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_flash_parameter *params)
{
int ret;
- u8 cfr3v;
+ u8 cr;
#ifdef CONFIG_SPI_FLASH_BAR
return -ENOTSUPP; /* Bank Address Register is not supported */
#endif
/*
+ * S25FS256T has multiple sector architecture options, with selection of
+ * count and location of 128KB and 64KB sectors. This driver supports
+ * uniform 128KB only due to complexity of non-uniform layout.
+ */
+ if (nor->info->id[4] == S25FS256T_ID4) {
+ ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_ARCFN, 8, &cr);
+ if (ret)
+ return ret;
+
+ if (cr) /* Option 0 (ARCFN[7:0] == 0x00) is uniform */
+ return -EOPNOTSUPP;
+
+ return spi_nor_default_setup(nor, info, params);
+ }
+
+ /*
* Read CFR3V to check if uniform sector is selected. If not, assign an
* erase hook that supports non-uniform erase.
*/
- ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V, 0, &cfr3v);
+ ret = spansion_read_any_reg(nor, SPINOR_REG_ADDR_CFR3V, 0, &cr);
if (ret)
return ret;
- if (!(cfr3v & CFR3V_UNHYSA))
- nor->erase = s25hx_t_erase_non_uniform;
+ if (!(cr & CFR3V_UNHYSA))
+ nor->erase = s25_erase_non_uniform;
/*
* For the multi-die package parts, the ready() hook is needed to check
* all dies' status via read any register.
*/
if (nor->mtd.size > SZ_128M)
- nor->ready = s25hx_t_mdp_ready;
+ nor->ready = s25_mdp_ready;
return spi_nor_default_setup(nor, info, params);
}
-static void s25hx_t_default_init(struct spi_nor *nor)
+static void s25_default_init(struct spi_nor *nor)
{
- nor->setup = s25hx_t_setup;
+ nor->setup = s25_setup;
}
-static int s25hx_t_post_bfpt_fixup(struct spi_nor *nor,
- const struct sfdp_parameter_header *header,
- const struct sfdp_bfpt *bfpt,
- struct spi_nor_flash_parameter *params)
+static int s25_post_bfpt_fixup(struct spi_nor *nor,
+ const struct sfdp_parameter_header *header,
+ const struct sfdp_bfpt *bfpt,
+ struct spi_nor_flash_parameter *params)
{
int ret;
u32 addr;
@@ -3296,6 +3316,10 @@
nor->addr_mode_nbytes = 4;
}
+ /* The default address mode in S25FS256T is 4. */
+ if (nor->info->id[4] == S25FS256T_ID4)
+ nor->addr_mode_nbytes = 4;
+
/*
* The page_size is set to 512B from BFPT, but it actually depends on
* the configuration register. Look up the CFR3V and determine the
@@ -3318,21 +3342,26 @@
return 0;
}
-static void s25hx_t_post_sfdp_fixup(struct spi_nor *nor,
- struct spi_nor_flash_parameter *params)
+static void s25_post_sfdp_fixup(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
{
- /* READ_FAST_4B (0Ch) requires mode cycles*/
- params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8;
- /* PP_1_1_4 is not supported */
- params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4;
- /* Use volatile register to enable quad */
- params->quad_enable = s25hx_t_quad_enable;
+ if (nor->info->id[4] == S25FS256T_ID4) {
+ /* PP_1_1_4 is supported */
+ params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
+ } else {
+ /* READ_FAST_4B (0Ch) requires mode cycles*/
+ params->reads[SNOR_CMD_READ_FAST].num_mode_clocks = 8;
+ /* PP_1_1_4 is not supported */
+ params->hwcaps.mask &= ~SNOR_HWCAPS_PP_1_1_4;
+ /* Use volatile register to enable quad */
+ params->quad_enable = s25_quad_enable;
+ }
}
-static struct spi_nor_fixups s25hx_t_fixups = {
- .default_init = s25hx_t_default_init,
- .post_bfpt = s25hx_t_post_bfpt_fixup,
- .post_sfdp = s25hx_t_post_sfdp_fixup,
+static struct spi_nor_fixups s25_fixups = {
+ .default_init = s25_default_init,
+ .post_bfpt = s25_post_bfpt_fixup,
+ .post_sfdp = s25_post_sfdp_fixup,
};
static int s25fl256l_setup(struct spi_nor *nor, const struct flash_info *info,
@@ -3373,7 +3402,7 @@
if (ret)
return ret;
- buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
+ buf = SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24;
op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR2V, 1),
SPI_MEM_OP_NO_DUMMY,
@@ -3396,7 +3425,7 @@
if (ret)
return ret;
- buf = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
+ buf = SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN;
op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_CYPRESS_CFR5V, 1),
SPI_MEM_OP_NO_DUMMY,
@@ -3444,7 +3473,7 @@
if (ret)
return ret;
- if (!(buf & SPINOR_REG_CYPRESS_CFR3V_UNISECT))
+ if (!(buf & SPINOR_REG_CYPRESS_CFR3_UNISECT))
nor->erase = s28hx_t_erase_non_uniform;
return spi_nor_default_setup(nor, info, params);
@@ -3511,7 +3540,7 @@
if (ret)
return ret;
- if (buf & SPINOR_REG_CYPRESS_CFR3V_PGSZ)
+ if (buf & SPINOR_REG_CYPRESS_CFR3_PGSZ)
params->page_size = 512;
else
params->page_size = 256;
@@ -3850,7 +3879,7 @@
switch (nor->info->id[1]) {
case 0x2a: /* S25HL (QSPI, 3.3V) */
case 0x2b: /* S25HS (QSPI, 1.8V) */
- nor->fixups = &s25hx_t_fixups;
+ nor->fixups = &s25_fixups;
break;
#ifdef CONFIG_SPI_FLASH_S28HX_T
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index f97e10d..3f8b796 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -362,6 +362,8 @@
USE_CLSR) },
{ INFO6("s25hs02gt", 0x342b1c, 0x0f0090, 256 * 1024, 1024,
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+ { INFO6("s25fs256t", 0x342b19, 0x0f0890, 128 * 1024, 256,
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
#ifdef CONFIG_SPI_FLASH_S28HX_T
{ INFO("s28hl512t", 0x345a1a, 0, 256 * 1024, 256, SPI_NOR_OCTAL_DTR_READ) },
{ INFO("s28hl01gt", 0x345a1b, 0, 256 * 1024, 512, SPI_NOR_OCTAL_DTR_READ) },
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index e2bd326..3ac0b19 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -86,13 +86,7 @@
#endif
#else
#ifdef CONFIG_MTD_UBI_FASTMAP
-#if !defined(CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT)
-#define CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT 0
-#endif
static bool fm_autoconvert = CONFIG_MTD_UBI_FASTMAP_AUTOCONVERT;
-#if !defined(CONFIG_MTD_UBI_FM_DEBUG)
-#define CONFIG_MTD_UBI_FM_DEBUG 0
-#endif
static bool fm_debug = CONFIG_MTD_UBI_FM_DEBUG;
#endif
#endif
diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c
index a16c998..da1f3f4 100644
--- a/drivers/net/ag7xxx.c
+++ b/drivers/net/ag7xxx.c
@@ -143,11 +143,11 @@
#define AG7XXX_ETH_CFG_MII_GE0 BIT(1)
#define AG7XXX_ETH_CFG_RGMII_GE0 BIT(0)
-#define CONFIG_TX_DESCR_NUM 8
-#define CONFIG_RX_DESCR_NUM 8
-#define CONFIG_ETH_BUFSIZE 2048
-#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
-#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
+#define CFG_TX_DESCR_NUM 8
+#define CFG_RX_DESCR_NUM 8
+#define CFG_ETH_BUFSIZE 2048
+#define TX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_TX_DESCR_NUM)
+#define RX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_RX_DESCR_NUM)
/* DMA descriptor. */
struct ag7xxx_dma_desc {
@@ -162,8 +162,8 @@
};
struct ar7xxx_eth_priv {
- struct ag7xxx_dma_desc tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
- struct ag7xxx_dma_desc rx_mac_descrtable[CONFIG_RX_DESCR_NUM];
+ struct ag7xxx_dma_desc tx_mac_descrtable[CFG_TX_DESCR_NUM];
+ struct ag7xxx_dma_desc rx_mac_descrtable[CFG_RX_DESCR_NUM];
char txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
char rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
@@ -408,11 +408,11 @@
u32 start, end;
int i;
- for (i = 0; i < CONFIG_TX_DESCR_NUM; i++) {
+ for (i = 0; i < CFG_TX_DESCR_NUM; i++) {
curr = &priv->tx_mac_descrtable[i];
- next = &priv->tx_mac_descrtable[(i + 1) % CONFIG_TX_DESCR_NUM];
+ next = &priv->tx_mac_descrtable[(i + 1) % CFG_TX_DESCR_NUM];
- curr->data_addr = virt_to_phys(&priv->txbuffs[i * CONFIG_ETH_BUFSIZE]);
+ curr->data_addr = virt_to_phys(&priv->txbuffs[i * CFG_ETH_BUFSIZE]);
curr->config = AG7XXX_DMADESC_IS_EMPTY;
curr->next_desc = virt_to_phys(next);
}
@@ -432,11 +432,11 @@
u32 start, end;
int i;
- for (i = 0; i < CONFIG_RX_DESCR_NUM; i++) {
+ for (i = 0; i < CFG_RX_DESCR_NUM; i++) {
curr = &priv->rx_mac_descrtable[i];
- next = &priv->rx_mac_descrtable[(i + 1) % CONFIG_RX_DESCR_NUM];
+ next = &priv->rx_mac_descrtable[(i + 1) % CFG_RX_DESCR_NUM];
- curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CONFIG_ETH_BUFSIZE]);
+ curr->data_addr = virt_to_phys(&priv->rxbuffs[i * CFG_ETH_BUFSIZE]);
curr->config = AG7XXX_DMADESC_IS_EMPTY;
curr->next_desc = virt_to_phys(next);
}
@@ -492,7 +492,7 @@
priv->regs + AG7XXX_ETH_DMA_TX_CTRL);
/* Switch to next TX descriptor. */
- priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CONFIG_TX_DESCR_NUM;
+ priv->tx_currdescnum = (priv->tx_currdescnum + 1) % CFG_TX_DESCR_NUM;
return 0;
}
@@ -543,7 +543,7 @@
flush_dcache_range(start, end);
/* Switch to next RX descriptor. */
- priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CONFIG_RX_DESCR_NUM;
+ priv->rx_currdescnum = (priv->rx_currdescnum + 1) % CFG_RX_DESCR_NUM;
return 0;
}
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index ddaf7ed..e09ca33 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -38,7 +38,7 @@
struct eth_mac_regs *mac_p = priv->mac_regs_p;
ulong start;
u16 miiaddr;
- int timeout = CONFIG_MDIO_TIMEOUT;
+ int timeout = CFG_MDIO_TIMEOUT;
miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
((reg << MIIREGSHIFT) & MII_REGMSK);
@@ -62,7 +62,7 @@
struct eth_mac_regs *mac_p = priv->mac_regs_p;
ulong start;
u16 miiaddr;
- int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT;
+ int ret = -ETIMEDOUT, timeout = CFG_MDIO_TIMEOUT;
writel(val, &mac_p->miidata);
miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
@@ -229,9 +229,9 @@
struct dmamacdescr *desc_p;
u32 idx;
- for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
+ for (idx = 0; idx < CFG_TX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
- desc_p->dmamac_addr = (ulong)&txbuffs[idx * CONFIG_ETH_BUFSIZE];
+ desc_p->dmamac_addr = (ulong)&txbuffs[idx * CFG_ETH_BUFSIZE];
desc_p->dmamac_next = (ulong)&desc_table_p[idx + 1];
#if defined(CONFIG_DW_ALTDESCRIPTOR)
@@ -277,9 +277,9 @@
* GMAC data will be corrupted. */
flush_dcache_range((ulong)rxbuffs, (ulong)rxbuffs + RX_TOTAL_BUFSIZE);
- for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
+ for (idx = 0; idx < CFG_RX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
- desc_p->dmamac_addr = (ulong)&rxbuffs[idx * CONFIG_ETH_BUFSIZE];
+ desc_p->dmamac_addr = (ulong)&rxbuffs[idx * CFG_ETH_BUFSIZE];
desc_p->dmamac_next = (ulong)&desc_table_p[idx + 1];
desc_p->dmamac_cntl =
@@ -377,7 +377,7 @@
start = get_timer(0);
while (readl(&dma_p->busmode) & DMAMAC_SRST) {
- if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) {
+ if (get_timer(start) >= CFG_MACRESET_TIMEOUT) {
printf("DMA reset timeout\n");
return -ETIMEDOUT;
}
@@ -495,7 +495,7 @@
flush_dcache_range(desc_start, desc_end);
/* Test the wrap-around condition. */
- if (++desc_num >= CONFIG_TX_DESCR_NUM)
+ if (++desc_num >= CFG_TX_DESCR_NUM)
desc_num = 0;
priv->tx_currdescnum = desc_num;
@@ -555,7 +555,7 @@
flush_dcache_range(desc_start, desc_end);
/* Test the wrap-around condition. */
- if (++desc_num >= CONFIG_RX_DESCR_NUM)
+ if (++desc_num >= CFG_RX_DESCR_NUM)
desc_num = 0;
priv->rx_currdescnum = desc_num;
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index 138c3c1..9da4e90 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -14,14 +14,14 @@
#include <asm-generic/gpio.h>
#endif
-#define CONFIG_TX_DESCR_NUM 16
-#define CONFIG_RX_DESCR_NUM 16
-#define CONFIG_ETH_BUFSIZE 2048
-#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
-#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
+#define CFG_TX_DESCR_NUM 16
+#define CFG_RX_DESCR_NUM 16
+#define CFG_ETH_BUFSIZE 2048
+#define TX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_TX_DESCR_NUM)
+#define RX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_RX_DESCR_NUM)
-#define CONFIG_MACRESET_TIMEOUT (3 * CONFIG_SYS_HZ)
-#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
+#define CFG_MACRESET_TIMEOUT (3 * CONFIG_SYS_HZ)
+#define CFG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
struct eth_mac_regs {
u32 conf; /* 0x00 */
@@ -221,8 +221,8 @@
#endif
struct dw_eth_dev {
- struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM];
- struct dmamacdescr rx_mac_descrtable[CONFIG_RX_DESCR_NUM];
+ struct dmamacdescr tx_mac_descrtable[CFG_TX_DESCR_NUM];
+ struct dmamacdescr rx_mac_descrtable[CFG_RX_DESCR_NUM];
char txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
char rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index a042450..38d96ab 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -168,14 +168,12 @@
unsigned char params[0];
};
-#define CONFIG_SYS_CMD_EL 0x8000
-#define CONFIG_SYS_CMD_SUSPEND 0x4000
-#define CONFIG_SYS_CMD_INT 0x2000
-#define CONFIG_SYS_CMD_IAS 0x0001 /* individual address setup */
-#define CONFIG_SYS_CMD_CONFIGURE 0x0002 /* configure */
+#define CFG_SYS_CMD_SUSPEND 0x4000
+#define CFG_SYS_CMD_IAS 0x0001 /* individual address setup */
+#define CFG_SYS_CMD_CONFIGURE 0x0002 /* configure */
-#define CONFIG_SYS_STATUS_C 0x8000
-#define CONFIG_SYS_STATUS_OK 0x2000
+#define CFG_SYS_STATUS_C 0x8000
+#define CFG_SYS_STATUS_OK 0x2000
/* Misc. */
#define NUM_RX_DESC PKTBUFSRX
@@ -413,7 +411,7 @@
invalidate_dcache_range((unsigned long)desc,
(unsigned long)desc + sizeof(*desc));
rstat = le16_to_cpu(desc->status);
- if (rstat & CONFIG_SYS_STATUS_C)
+ if (rstat & CFG_SYS_STATUS_C)
break;
if (i++ >= TOUT_LOOP) {
@@ -426,7 +424,7 @@
(unsigned long)desc + sizeof(*desc));
rstat = le16_to_cpu(desc->status);
- if (!(rstat & CONFIG_SYS_STATUS_OK)) {
+ if (!(rstat & CFG_SYS_STATUS_OK)) {
printf("TX error status = 0x%08X\n", rstat);
return -EIO;
}
@@ -579,8 +577,8 @@
priv->tx_next = ((priv->tx_next + 1) % NUM_TX_DESC);
cfg_cmd = &tx_ring[tx_cur];
- cfg_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND |
- CONFIG_SYS_CMD_CONFIGURE);
+ cfg_cmd->command = cpu_to_le16(CFG_SYS_CMD_SUSPEND |
+ CFG_SYS_CMD_CONFIGURE);
cfg_cmd->status = 0;
cfg_cmd->link = cpu_to_le32(phys_to_bus(priv->devno,
(u32)&tx_ring[priv->tx_next]));
@@ -591,7 +589,7 @@
ret = eepro100_txcmd_send(priv, cfg_cmd);
if (ret) {
if (ret == -ETIMEDOUT)
- printf("Error---CONFIG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n");
+ printf("Error---CFG_SYS_CMD_CONFIGURE: Can not reset ethernet controller.\n");
goto done;
}
@@ -600,8 +598,8 @@
priv->tx_next = ((priv->tx_next + 1) % NUM_TX_DESC);
ias_cmd = &tx_ring[tx_cur];
- ias_cmd->command = cpu_to_le16(CONFIG_SYS_CMD_SUSPEND |
- CONFIG_SYS_CMD_IAS);
+ ias_cmd->command = cpu_to_le16(CFG_SYS_CMD_SUSPEND |
+ CFG_SYS_CMD_IAS);
ias_cmd->status = 0;
ias_cmd->link = cpu_to_le32(phys_to_bus(priv->devno,
(u32)&tx_ring[priv->tx_next]));
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index ab52cc1..006d270 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -59,7 +59,7 @@
* sending and after receiving.
*/
#ifdef CONFIG_MX28
-#define CONFIG_FEC_MXC_SWAP_PACKET
+#define CFG_FEC_MXC_SWAP_PACKET
#endif
#define RXDESC_PER_CACHELINE (ARCH_DMA_MINALIGN/sizeof(struct fec_bd))
@@ -76,7 +76,7 @@
#undef DEBUG
-#ifdef CONFIG_FEC_MXC_SWAP_PACKET
+#ifdef CFG_FEC_MXC_SWAP_PACKET
static void swap_packet(uint32_t *packet, int length)
{
int i;
@@ -685,7 +685,7 @@
* transmission, the second will be empty and only used to stop the DMA
* engine. We also flush the packet to RAM here to avoid cache trouble.
*/
-#ifdef CONFIG_FEC_MXC_SWAP_PACKET
+#ifdef CFG_FEC_MXC_SWAP_PACKET
swap_packet((uint32_t *)packet, length);
#endif
@@ -875,7 +875,7 @@
invalidate_dcache_range(addr, end);
/* Fill the buffer and pass it to upper layers */
-#ifdef CONFIG_FEC_MXC_SWAP_PACKET
+#ifdef CFG_FEC_MXC_SWAP_PACKET
swap_packet((uint32_t *)addr, frame_length);
#endif
diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c
index 055dd61..7dfa821 100644
--- a/drivers/net/fm/fm.c
+++ b/drivers/net/fm/fm.c
@@ -5,9 +5,11 @@
*/
#include <common.h>
#include <env.h>
+#include <fs_loader.h>
#include <image.h>
#include <malloc.h>
#include <asm/io.h>
+#include <dm/device_compat.h>
#include <linux/errno.h>
#include <u-boot/crc.h>
#include <dm.h>
@@ -353,7 +355,7 @@
/* Init common part of FM, index is fm num# like fm as above */
#ifdef CONFIG_TFABOOT
-int fm_init_common(int index, struct ccsr_fman *reg)
+int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name)
{
int rc;
void *addr = NULL;
@@ -361,7 +363,7 @@
if (src == BOOT_SOURCE_IFC_NOR) {
addr = (void *)(CONFIG_SYS_FMAN_FW_ADDR +
- CONFIG_SYS_FSL_IFC_BASE);
+ CFG_SYS_FSL_IFC_BASE);
#ifdef CONFIG_CMD_NAND
} else if (src == BOOT_SOURCE_IFC_NAND) {
size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
@@ -448,10 +450,32 @@
return fm_init_bmi(index, ®->fm_bmi_common);
}
#else
-int fm_init_common(int index, struct ccsr_fman *reg)
+int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name)
{
int rc;
-#if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR)
+#if defined(CONFIG_SYS_QE_FMAN_FW_IN_FS)
+ struct udevice *fs_loader;
+ void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
+
+ if (!addr)
+ return -ENOMEM;
+
+ rc = get_fs_loader(&fs_loader);
+ if (rc) {
+ debug("could not get fs loader: %d\n", rc);
+ return rc;
+ }
+
+ if (!firmware_name)
+ firmware_name = "fman.itb";
+
+ rc = request_firmware_into_buf(fs_loader, firmware_name, addr,
+ CONFIG_SYS_QE_FMAN_FW_LENGTH, 0);
+ if (rc < 0) {
+ debug("could not request %s: %d\n", firmware_name, rc);
+ return rc;
+ }
+#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR)
void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR;
#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND)
size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
@@ -561,6 +585,8 @@
static int fman_probe(struct udevice *dev)
{
+ const char *firmware_name = NULL;
+ int ret;
struct fman_priv *priv = dev_get_priv(dev);
priv->reg = (struct ccsr_fman *)(uintptr_t)dev_read_addr(dev);
@@ -570,7 +596,13 @@
return -EINVAL;
}
- return fm_init_common(priv->fman_id, priv->reg);
+ ret = dev_read_string_index(dev, "firmware-name", 0, &firmware_name);
+ if (ret && ret != -EINVAL) {
+ dev_dbg(dev, "Could not read firmware-name\n");
+ return ret;
+ }
+
+ return fm_init_common(priv->fman_id, priv->reg, firmware_name);
}
static int fman_remove(struct udevice *dev)
diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h
index ba858cc..a2d5b03 100644
--- a/drivers/net/fm/fm.h
+++ b/drivers/net/fm/fm.h
@@ -106,7 +106,7 @@
void *fm_muram_alloc(int fm_idx, size_t size, ulong align);
void *fm_muram_base(int fm_idx);
-int fm_init_common(int index, struct ccsr_fman *reg);
+int fm_init_common(int index, struct ccsr_fman *reg, const char *firmware_name);
int fm_eth_initialize(struct ccsr_fman *reg, struct fm_eth_info *info);
phy_interface_t fman_port_enet_if(enum fm_port port);
void fman_disable_port(enum fm_port port);
diff --git a/drivers/net/mcfmii.c b/drivers/net/mcfmii.c
index 48dd558..eae2065 100644
--- a/drivers/net/mcfmii.c
+++ b/drivers/net/mcfmii.c
@@ -32,11 +32,11 @@
#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \
(REG & 0x1f) << 18) | (VAL & 0xffff))
-#ifndef CONFIG_SYS_UNSPEC_PHYID
-# define CONFIG_SYS_UNSPEC_PHYID 0
+#ifndef CFG_SYS_UNSPEC_PHYID
+# define CFG_SYS_UNSPEC_PHYID 0
#endif
-#ifndef CONFIG_SYS_UNSPEC_STRID
-# define CONFIG_SYS_UNSPEC_STRID 0
+#ifndef CFG_SYS_UNSPEC_STRID
+# define CFG_SYS_UNSPEC_STRID 0
#endif
typedef struct phy_info_struct {
@@ -58,8 +58,8 @@
{0x20005C90, "N83848"}, /* National 83848 */
{0x20005CA2, "N83849"}, /* National 83849 */
{0x01814400, "QS6612"}, /* QS6612 */
-#if defined(CONFIG_SYS_UNSPEC_PHYID) && defined(CONFIG_SYS_UNSPEC_STRID)
- {CONFIG_SYS_UNSPEC_PHYID, CONFIG_SYS_UNSPEC_STRID},
+#if defined(CFG_SYS_UNSPEC_PHYID) && defined(CFG_SYS_UNSPEC_STRID)
+ {CFG_SYS_UNSPEC_PHYID, CFG_SYS_UNSPEC_STRID},
#endif
{0, 0}
};
diff --git a/drivers/net/mt7628-eth.c b/drivers/net/mt7628-eth.c
index 50d066a..0a9bdb3 100644
--- a/drivers/net/mt7628-eth.c
+++ b/drivers/net/mt7628-eth.c
@@ -127,9 +127,9 @@
#define MTK_QDMA_PAGE_SIZE 2048
-#define CONFIG_MDIO_TIMEOUT 100
-#define CONFIG_DMA_STOP_TIMEOUT 100
-#define CONFIG_TX_DMA_TIMEOUT 100
+#define CFG_MDIO_TIMEOUT 100
+#define CFG_DMA_STOP_TIMEOUT 100
+#define CFG_TX_DMA_TIMEOUT 100
struct mt7628_eth_dev {
void __iomem *base; /* frame engine base address */
@@ -162,7 +162,7 @@
int ret;
ret = wait_for_bit_le32(base + MT7628_SWITCH_PCR1, mask, mask_set,
- CONFIG_MDIO_TIMEOUT, false);
+ CFG_MDIO_TIMEOUT, false);
if (ret) {
printf("MDIO operation timeout!\n");
return -ETIMEDOUT;
@@ -352,7 +352,7 @@
/* Wait for DMA to stop */
ret = wait_for_bit_le32(base + PDMA_GLO_CFG,
RX_DMA_BUSY | TX_DMA_BUSY, false,
- CONFIG_DMA_STOP_TIMEOUT, false);
+ CFG_DMA_STOP_TIMEOUT, false);
if (ret)
printf("DMA stop timeout error!\n");
}
@@ -399,7 +399,7 @@
/* Check if buffer is ready for next TX DMA */
ret = wait_for_bit_le32(&priv->tx_ring[idx].txd2, TX_DMA_DONE, true,
- CONFIG_TX_DMA_TIMEOUT, false);
+ CFG_TX_DMA_TIMEOUT, false);
if (ret) {
printf("TX: DMA still busy on buffer %d\n", idx);
return ret;
diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c
index 8c9afdf..1bad50d 100644
--- a/drivers/net/mvpp2.c
+++ b/drivers/net/mvpp2.c
@@ -66,8 +66,6 @@
#define NET_SKB_PAD max(32, MVPP2_CPU_D_CACHE_LINE_SIZE)
-#define CONFIG_NR_CPUS 1
-
/* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */
#define WRAP (2 + ETH_HLEN + 4 + 32)
#define MTU 1500
@@ -589,7 +587,7 @@
/* Default number of RXQs in use */
#define MVPP2_DEFAULT_RXQ 1
-#define CONFIG_MV_ETH_RXQ 8 /* increment by 8 */
+#define CFG_MV_ETH_RXQ 8 /* increment by 8 */
/* Max number of Rx descriptors */
#define MVPP2_MAX_RXD 16
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 1e52917..151bc55 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -11,11 +11,11 @@
#include <stdio_dev.h>
#include <net.h>
-#ifndef CONFIG_NETCONSOLE_BUFFER_SIZE
-#define CONFIG_NETCONSOLE_BUFFER_SIZE 512
+#ifndef CFG_NETCONSOLE_BUFFER_SIZE
+#define CFG_NETCONSOLE_BUFFER_SIZE 512
#endif
-static char input_buffer[CONFIG_NETCONSOLE_BUFFER_SIZE];
+static char input_buffer[CFG_NETCONSOLE_BUFFER_SIZE];
static int input_size; /* char count in input buffer */
static int input_offset; /* offset to valid chars in input buffer */
static int input_recursion;
diff --git a/drivers/net/npcm750_eth.c b/drivers/net/npcm750_eth.c
index bd29a10..2028f4a 100644
--- a/drivers/net/npcm750_eth.c
+++ b/drivers/net/npcm750_eth.c
@@ -18,15 +18,15 @@
#include <linux/iopoll.h>
#define MAC_ADDR_SIZE 6
-#define CONFIG_TX_DESCR_NUM 32
-#define CONFIG_RX_DESCR_NUM 32
+#define CFG_TX_DESCR_NUM 32
+#define CFG_RX_DESCR_NUM 32
#define TX_TOTAL_BUFSIZE \
- ((CONFIG_TX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN)
+ ((CFG_TX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN)
#define RX_TOTAL_BUFSIZE \
- ((CONFIG_RX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN)
+ ((CFG_RX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN)
-#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
+#define CFG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
struct npcm750_rxbd {
unsigned int sl;
@@ -101,8 +101,8 @@
};
struct npcm750_eth_dev {
- struct npcm750_txbd tdesc[CONFIG_TX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN);
- struct npcm750_rxbd rdesc[CONFIG_RX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN);
+ struct npcm750_txbd tdesc[CFG_TX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN);
+ struct npcm750_rxbd rdesc[CFG_RX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN);
u8 txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
u8 rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
struct emc_regs *emc_regs_p;
@@ -279,7 +279,7 @@
struct npcm750_eth_dev *priv = (struct npcm750_eth_dev *)bus->priv;
struct emc_regs *reg = priv->emc_regs_p;
u32 start, val;
- int timeout = CONFIG_MDIO_TIMEOUT;
+ int timeout = CFG_MDIO_TIMEOUT;
val = (addr << 0x08) | regs | PHYBUSY | (MIIDA_MDCCR_60 << 20);
writel(val, ®->miida);
@@ -301,7 +301,7 @@
struct npcm750_eth_dev *priv = (struct npcm750_eth_dev *)bus->priv;
struct emc_regs *reg = priv->emc_regs_p;
ulong start;
- int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT;
+ int ret = -ETIMEDOUT, timeout = CFG_MDIO_TIMEOUT;
writel(val, ®->miid);
writel((addr << 0x08) | regs | PHYBUSY | PHYWR | (MIIDA_MDCCR_60 << 20), ®->miida);
@@ -354,19 +354,19 @@
writel((u32)desc_table_p, ®->txdlsa);
priv->curr_txd = desc_table_p;
- for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) {
+ for (idx = 0; idx < CFG_TX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
desc_p->buffer = (u32)&txbuffs[idx * PKTSIZE_ALIGN];
desc_p->sl = 0;
desc_p->mode = 0;
desc_p->mode = TX_OWEN_CPU | PADDINGMODE | CRCMODE | MACTXINTEN;
- if (idx < (CONFIG_TX_DESCR_NUM - 1))
+ if (idx < (CFG_TX_DESCR_NUM - 1))
desc_p->next = (u32)&desc_table_p[idx + 1];
else
desc_p->next = (u32)&priv->tdesc[0];
}
flush_dcache_range((ulong)&desc_table_p[0],
- (ulong)&desc_table_p[CONFIG_TX_DESCR_NUM]);
+ (ulong)&desc_table_p[CFG_TX_DESCR_NUM]);
}
static void npcm750_rx_descs_init(struct npcm750_eth_dev *priv)
@@ -378,22 +378,22 @@
u32 idx;
flush_dcache_range((ulong)priv->rxbuffs[0],
- (ulong)priv->rxbuffs[CONFIG_RX_DESCR_NUM]);
+ (ulong)priv->rxbuffs[CFG_RX_DESCR_NUM]);
writel((u32)desc_table_p, ®->rxdlsa);
priv->curr_rxd = desc_table_p;
- for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) {
+ for (idx = 0; idx < CFG_RX_DESCR_NUM; idx++) {
desc_p = &desc_table_p[idx];
desc_p->sl = RX_OWEN_DMA;
desc_p->buffer = (u32)&rxbuffs[idx * PKTSIZE_ALIGN];
- if (idx < (CONFIG_RX_DESCR_NUM - 1))
+ if (idx < (CFG_RX_DESCR_NUM - 1))
desc_p->next = (u32)&desc_table_p[idx + 1];
else
desc_p->next = (u32)&priv->rdesc[0];
}
flush_dcache_range((ulong)&desc_table_p[0],
- (ulong)&desc_table_p[CONFIG_RX_DESCR_NUM]);
+ (ulong)&desc_table_p[CFG_RX_DESCR_NUM]);
}
static void npcm750_set_fifo_threshold(struct npcm750_eth_dev *priv)
diff --git a/drivers/net/octeon/octeon_eth.c b/drivers/net/octeon/octeon_eth.c
index fbb1afc..659ba51 100644
--- a/drivers/net/octeon/octeon_eth.c
+++ b/drivers/net/octeon/octeon_eth.c
@@ -58,7 +58,7 @@
#include <mach/cvmx-mdio.h>
/** Maximum receive packet size (hardware default is 1536) */
-#define CONFIG_OCTEON_NETWORK_MRU 1536
+#define CFG_OCTEON_NETWORK_MRU 1536
#define OCTEON_BOOTLOADER_NAMED_BLOCK_TMP_PREFIX "__tmp"
@@ -199,7 +199,7 @@
*/
static void cvm_oct_configure_common_hw(void)
{
- int mru = env_get_ulong("octeon_mru", 0, CONFIG_OCTEON_NETWORK_MRU);
+ int mru = env_get_ulong("octeon_mru", 0, CFG_OCTEON_NETWORK_MRU);
int packet_pool_size = CVMX_FPA_PACKET_POOL_SIZE;
if (mru > packet_pool_size)
@@ -224,7 +224,7 @@
cvmx_helper_initialize_packet_io_local();
/* The MRU defaults to 1536 bytes by the hardware. Setting
- * CONFIG_OCTEON_NETWORK_MRU allows this to be overridden.
+ * CFG_OCTEON_NETWORK_MRU allows this to be overridden.
*/
if (octeon_has_feature(OCTEON_FEATURE_PKI)) {
struct cvmx_pki_global_config gbl_cfg;
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 580ac8e..5eaff05 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -62,6 +62,10 @@
config MV88E61XX_FIXED_PORTS
hex "Bitmask of PHYless serdes Ports"
+ default 0x0
+ help
+ These are ports without PHYs that may be wired directly to other
+ serdes interfaces
endif # MV88E61XX_SWITCH
diff --git a/drivers/net/phy/mv88e61xx.c b/drivers/net/phy/mv88e61xx.c
index 7eff37b..7ab6016 100644
--- a/drivers/net/phy/mv88e61xx.c
+++ b/drivers/net/phy/mv88e61xx.c
@@ -167,14 +167,6 @@
#error Define CONFIG_MV88E61XX_CPU_PORT to the port the CPU is attached to
#endif
-/*
- * These are ports without PHYs that may be wired directly
- * to other serdes interfaces
- */
-#ifndef CONFIG_MV88E61XX_FIXED_PORTS
-#define CONFIG_MV88E61XX_FIXED_PORTS 0
-#endif
-
/* ID register values for different switch models */
#define PORT_SWITCH_ID_6020 0x0200
#define PORT_SWITCH_ID_6070 0x0700
diff --git a/drivers/net/qe/dm_qe_uec.c b/drivers/net/qe/dm_qe_uec.c
index 8fec1c2..6d1509d 100644
--- a/drivers/net/qe/dm_qe_uec.c
+++ b/drivers/net/qe/dm_qe_uec.c
@@ -20,8 +20,8 @@
#define QE_UEC_DRIVER_NAME "ucc_geth"
/* Default UTBIPAR SMI address */
-#ifndef CONFIG_UTBIPAR_INIT_TBIPA
-#define CONFIG_UTBIPAR_INIT_TBIPA 0x1F
+#ifndef CFG_UTBIPAR_INIT_TBIPA
+#define CFG_UTBIPAR_INIT_TBIPA 0x1F
#endif
static int uec_mac_enable(struct uec_priv *uec, comm_dir_e mode)
@@ -840,10 +840,10 @@
utbipar = in_be32(&uec_regs->utbipar);
utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK;
- /* Initialize UTBIPAR address to CONFIG_UTBIPAR_INIT_TBIPA for ALL UEC.
+ /* Initialize UTBIPAR address to CFG_UTBIPAR_INIT_TBIPA for ALL UEC.
* This frees up the remaining SMI addresses for use.
*/
- utbipar |= CONFIG_UTBIPAR_INIT_TBIPA << UTBIPAR_PHY_ADDRESS_SHIFT;
+ utbipar |= CFG_UTBIPAR_INIT_TBIPA << UTBIPAR_PHY_ADDRESS_SHIFT;
out_be32(&uec_regs->utbipar, utbipar);
/* Allocate Tx BDs */
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 9cca8fa..e800a32 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -43,19 +43,19 @@
#define MDIO_CMD_MII_CLK_CSR_DIV_128 0x3
#define MDIO_CMD_MII_CLK_CSR_SHIFT 20
-#define CONFIG_TX_DESCR_NUM 32
-#define CONFIG_RX_DESCR_NUM 32
-#define CONFIG_ETH_BUFSIZE 2048 /* Note must be dma aligned */
+#define CFG_TX_DESCR_NUM 32
+#define CFG_RX_DESCR_NUM 32
+#define CFG_ETH_BUFSIZE 2048 /* Note must be dma aligned */
/*
* The datasheet says that each descriptor can transfers up to 4096 bytes
* But later, the register documentation reduces that value to 2048,
* using 2048 cause strange behaviours and even BSP driver use 2047
*/
-#define CONFIG_ETH_RXSIZE 2044 /* Note must fit in ETH_BUFSIZE */
+#define CFG_ETH_RXSIZE 2044 /* Note must fit in ETH_BUFSIZE */
-#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM)
-#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM)
+#define TX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_TX_DESCR_NUM)
+#define RX_TOTAL_BUFSIZE (CFG_ETH_BUFSIZE * CFG_RX_DESCR_NUM)
#define H3_EPHY_DEFAULT_VALUE 0x58000
#define H3_EPHY_DEFAULT_MASK GENMASK(31, 15)
@@ -75,7 +75,7 @@
#define SC_ERXDC_MASK GENMASK(9, 5)
#define SC_ERXDC_OFFSET 5
-#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
+#define CFG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ)
#define AHB_GATE_OFFSET_EPHY 0
@@ -143,8 +143,8 @@
} __aligned(ARCH_DMA_MINALIGN);
struct emac_eth_dev {
- struct emac_dma_desc rx_chain[CONFIG_TX_DESCR_NUM];
- struct emac_dma_desc tx_chain[CONFIG_RX_DESCR_NUM];
+ struct emac_dma_desc rx_chain[CFG_TX_DESCR_NUM];
+ struct emac_dma_desc tx_chain[CFG_RX_DESCR_NUM];
char rxbuffer[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
char txbuffer[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN);
@@ -209,7 +209,7 @@
ret = wait_for_bit_le32(priv->mac_reg + EMAC_MII_CMD,
MDIO_CMD_MII_BUSY, false,
- CONFIG_MDIO_TIMEOUT, true);
+ CFG_MDIO_TIMEOUT, true);
if (ret < 0)
return ret;
@@ -244,7 +244,7 @@
return wait_for_bit_le32(priv->mac_reg + EMAC_MII_CMD,
MDIO_CMD_MII_BUSY, false,
- CONFIG_MDIO_TIMEOUT, true);
+ CFG_MDIO_TIMEOUT, true);
}
static int sun8i_eth_write_hwaddr(struct udevice *dev)
@@ -412,11 +412,11 @@
invalidate_dcache_range((uintptr_t)rxbuffs,
(uintptr_t)rxbuffs + sizeof(priv->rxbuffer));
- for (i = 0; i < CONFIG_RX_DESCR_NUM; i++) {
+ for (i = 0; i < CFG_RX_DESCR_NUM; i++) {
desc_p = &desc_table_p[i];
- desc_p->buf_addr = (uintptr_t)&rxbuffs[i * CONFIG_ETH_BUFSIZE];
+ desc_p->buf_addr = (uintptr_t)&rxbuffs[i * CFG_ETH_BUFSIZE];
desc_p->next = (uintptr_t)&desc_table_p[i + 1];
- desc_p->ctl_size = CONFIG_ETH_RXSIZE;
+ desc_p->ctl_size = CFG_ETH_RXSIZE;
desc_p->status = EMAC_DESC_OWN_DMA;
}
@@ -438,9 +438,9 @@
struct emac_dma_desc *desc_p;
int i;
- for (i = 0; i < CONFIG_TX_DESCR_NUM; i++) {
+ for (i = 0; i < CFG_TX_DESCR_NUM; i++) {
desc_p = &desc_table_p[i];
- desc_p->buf_addr = (uintptr_t)&txbuffs[i * CONFIG_ETH_BUFSIZE];
+ desc_p->buf_addr = (uintptr_t)&txbuffs[i * CFG_ETH_BUFSIZE];
desc_p->next = (uintptr_t)&desc_table_p[i + 1];
desc_p->ctl_size = 0;
desc_p->status = 0;
@@ -541,7 +541,7 @@
return 0;
}
- if (length > CONFIG_ETH_RXSIZE) {
+ if (length > CFG_ETH_RXSIZE) {
debug("RX: Too large packet (%d bytes)\n", length);
return 0;
}
@@ -575,7 +575,7 @@
cache_clean_descriptor(desc_p);
/* Move to next Descriptor and wrap around */
- if (++desc_num >= CONFIG_TX_DESCR_NUM)
+ if (++desc_num >= CFG_TX_DESCR_NUM)
desc_num = 0;
priv->tx_currdescnum = desc_num;
@@ -701,7 +701,7 @@
cache_clean_descriptor(desc_p);
/* Move to next desc and wrap-around condition. */
- if (++desc_num >= CONFIG_RX_DESCR_NUM)
+ if (++desc_num >= CFG_RX_DESCR_NUM)
desc_num = 0;
priv->rx_currdescnum = desc_num;
diff --git a/drivers/net/ti/davinci_emac.c b/drivers/net/ti/davinci_emac.c
index 2dfadbd..29d2fc9 100644
--- a/drivers/net/ti/davinci_emac.c
+++ b/drivers/net/ti/davinci_emac.c
@@ -65,8 +65,8 @@
#define emac_gigabit_enable(phy_addr) /* no gigabit to enable */
#endif
-#if !defined(CONFIG_SYS_EMAC_TI_CLKDIV)
-#define CONFIG_SYS_EMAC_TI_CLKDIV ((EMAC_MDIO_BUS_FREQ / \
+#if !defined(CFG_SYS_EMAC_TI_CLKDIV)
+#define CFG_SYS_EMAC_TI_CLKDIV ((EMAC_MDIO_BUS_FREQ / \
EMAC_MDIO_CLOCK_FREQ) - 1)
#endif
@@ -98,17 +98,17 @@
static unsigned char emac_rx_buffers[EMAC_MAX_RX_BUFFERS * EMAC_RXBUF_SIZE]
__aligned(ARCH_DMA_MINALIGN);
-#ifndef CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT
-#define CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT 3
+#ifndef CFG_SYS_DAVINCI_EMAC_PHY_COUNT
+#define CFG_SYS_DAVINCI_EMAC_PHY_COUNT 3
#endif
/* PHY address for a discovered PHY (0xff - not found) */
-static u_int8_t active_phy_addr[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
+static u_int8_t active_phy_addr[CFG_SYS_DAVINCI_EMAC_PHY_COUNT];
/* number of PHY found active */
static u_int8_t num_phy;
-phy_t phy[CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT];
+phy_t phy[CFG_SYS_DAVINCI_EMAC_PHY_COUNT];
static int davinci_emac_write_hwaddr(struct udevice *dev)
{
@@ -152,7 +152,7 @@
{
u_int32_t clkdiv;
- clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
+ clkdiv = CFG_SYS_EMAC_TI_CLKDIV;
writel((clkdiv & 0xff) |
MDIO_CONTROL_ENABLE |
@@ -176,7 +176,7 @@
int j;
unsigned int count = 0;
- for (i = 0; i < CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT; i++)
+ for (i = 0; i < CFG_SYS_DAVINCI_EMAC_PHY_COUNT; i++)
active_phy_addr[i] = 0xff;
udelay(1000);
@@ -190,7 +190,7 @@
for (i = 0, j = 0; i < 32; i++)
if (phy_act_state & (1 << i)) {
count++;
- if (count <= CONFIG_SYS_DAVINCI_EMAC_PHY_COUNT) {
+ if (count <= CFG_SYS_DAVINCI_EMAC_PHY_COUNT) {
active_phy_addr[j++] = i;
} else {
printf("%s: to many PHYs detected.\n",
@@ -501,7 +501,7 @@
writel(1, &adap_emac->RXUNICASTSET);
/* Init MDIO & get link state */
- clkdiv = CONFIG_SYS_EMAC_TI_CLKDIV;
+ clkdiv = CFG_SYS_EMAC_TI_CLKDIV;
writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT,
&adap_mdio->CONTROL);
diff --git a/drivers/nvme/nvme-uclass.c b/drivers/nvme/nvme-uclass.c
index 239a92a..f3af6a2 100644
--- a/drivers/nvme/nvme-uclass.c
+++ b/drivers/nvme/nvme-uclass.c
@@ -7,9 +7,63 @@
#define LOG_CATEGORY UCLASS_NVME
#include <common.h>
+#include <bootdev.h>
#include <dm.h>
+#include <init.h>
+#include <log.h>
+#include <nvme.h>
+
+static int nvme_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_4_SCAN_FAST;
+
+ return 0;
+}
+
+static int nvme_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ /* init PCI first since this is often used to provide NVMe */
+ if (IS_ENABLED(CONFIG_PCI)) {
+ ret = pci_init();
+ if (ret)
+ log_warning("Failed to init PCI (%dE)\n", ret);
+ }
+
+ ret = nvme_scan_namespace();
+ if (ret)
+ return log_msg_ret("scan", ret);
+
+ return 0;
+}
UCLASS_DRIVER(nvme) = {
.name = "nvme",
.id = UCLASS_NVME,
};
+
+struct bootdev_ops nvme_bootdev_ops = {
+};
+
+static const struct udevice_id nvme_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-nvme" },
+ { }
+};
+
+U_BOOT_DRIVER(nvme_bootdev) = {
+ .name = "nvme_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &nvme_bootdev_ops,
+ .bind = nvme_bootdev_bind,
+ .of_match = nvme_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(nvme_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_NVME,
+ .hunt = nvme_bootdev_hunt,
+ .drv = DM_DRIVER_REF(nvme_bootdev),
+};
diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c
index 6d0d3f3..74e7a5b 100644
--- a/drivers/nvme/nvme.c
+++ b/drivers/nvme/nvme.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <blk.h>
+#include <bootdev.h>
#include <cpu_func.h>
#include <dm.h>
#include <errno.h>
@@ -893,6 +894,10 @@
if (ret)
goto free_id;
+ ret = bootdev_setup_sibling_blk(ns_udev, "nvme_bootdev");
+ if (ret)
+ return log_msg_ret("bootdev", ret);
+
ret = blk_probe_or_unbind(ns_udev);
if (ret)
goto free_id;
diff --git a/drivers/phy/phy-ti-am654.c b/drivers/phy/phy-ti-am654.c
index 82010e7..27a3122 100644
--- a/drivers/phy/phy-ti-am654.c
+++ b/drivers/phy/phy-ti-am654.c
@@ -28,8 +28,8 @@
#define CMU_MASTER_CDN_O BIT(24)
#define COMLANE_R138 0xb38
-#define CONFIG_VERSION_REG_MASK GENMASK(23, 16)
-#define CONFIG_VERSION_REG_SHIFT 16
+#define CFG_VERSION_REG_MASK GENMASK(23, 16)
+#define CFG_VERSION_REG_SHIFT 16
#define VERSION 0x70
#define COMLANE_R190 0xb90
@@ -286,8 +286,8 @@
u32 mask;
u32 val;
- mask = CONFIG_VERSION_REG_MASK;
- val = VERSION << CONFIG_VERSION_REG_SHIFT;
+ mask = CFG_VERSION_REG_MASK;
+ val = VERSION << CFG_VERSION_REG_SHIFT;
regmap_update_bits(phy->regmap, COMLANE_R138, mask, val);
val = CMU_MASTER_CDN_O;
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
index 31678f5..1ad8bfb 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -47,6 +47,10 @@
#define WD0RST BIT(29)
#define WD1RST BIT(24)
#define WD2RST BIT(23)
+#define SWRST1 BIT(28)
+#define SWRST2 BIT(27)
+#define SWRST3 BIT(26)
+#define SW4RST BIT(25)
#define GPIOX_MODULE_RESET 16
#define CA9C_RESET BIT(0)
@@ -1374,6 +1378,14 @@
regmap_read(priv->rst_regmap, NPCM7XX_RST_WD1RCR, &tmp);
else if (value & WD2RST)
regmap_read(priv->rst_regmap, NPCM7XX_RST_WD2RCR, &tmp);
+ else if (value & SWRST1)
+ regmap_read(priv->rst_regmap, NPCM7XX_RST_SWRSTC1, &tmp);
+ else if (value & SWRST2)
+ regmap_read(priv->rst_regmap, NPCM7XX_RST_SWRSTC2, &tmp);
+ else if (value & SWRST3)
+ regmap_read(priv->rst_regmap, NPCM7XX_RST_SWRSTC3, &tmp);
+ else if (value & SW4RST)
+ regmap_read(priv->rst_regmap, NPCM7XX_RST_SWRSTC4, &tmp);
else
return false;
@@ -1392,11 +1404,19 @@
regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_WD1RCR, BIT(num), 0);
regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_WD2RCR, BIT(num), 0);
regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_CORSTC, BIT(num), 0);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC1, BIT(num), 0);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC2, BIT(num), 0);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC3, BIT(num), 0);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC4, BIT(num), 0);
} else {
regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_WD0RCR, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_WD1RCR, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_WD2RCR, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_CORSTC, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC1, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC2, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC3, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
+ regmap_update_bits(priv->rst_regmap, NPCM7XX_RST_SWRSTC4, BIT(num) | CA9C_RESET, BIT(num) | CA9C_RESET);
}
return 0;
diff --git a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
index c6ffa89..0ec47e9 100644
--- a/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
+++ b/drivers/pinctrl/nuvoton/pinctrl-npcm8xx.c
@@ -20,7 +20,7 @@
#define SWRSTC1 0x44
#define SWRSTC2 0x48
#define SWRSTC3 0x4c
-#define SWRSTC4 0x50
+#define TIPRSTC 0x50
#define CORSTC 0x5c
#define FLOCKR1 0x74
#define INTCR4 0xc0
@@ -772,6 +772,10 @@
regmap_update_bits(priv->rst_regmap, WD1RCR, BIT(offset), 0);
regmap_update_bits(priv->rst_regmap, WD2RCR, BIT(offset), 0);
regmap_update_bits(priv->rst_regmap, CORSTC, BIT(offset), 0);
+ regmap_update_bits(priv->rst_regmap, SWRSTC1, BIT(offset), 0);
+ regmap_update_bits(priv->rst_regmap, SWRSTC2, BIT(offset), 0);
+ regmap_update_bits(priv->rst_regmap, SWRSTC3, BIT(offset), 0);
+ regmap_update_bits(priv->rst_regmap, TIPRSTC, BIT(offset), 0);
} else {
regmap_update_bits(priv->rst_regmap, WD0RCR, BIT(offset),
BIT(offset));
@@ -781,6 +785,14 @@
BIT(offset));
regmap_update_bits(priv->rst_regmap, CORSTC, BIT(offset),
BIT(offset));
+ regmap_update_bits(priv->rst_regmap, SWRSTC1, BIT(offset),
+ BIT(offset));
+ regmap_update_bits(priv->rst_regmap, SWRSTC2, BIT(offset),
+ BIT(offset));
+ regmap_update_bits(priv->rst_regmap, SWRSTC3, BIT(offset),
+ BIT(offset));
+ regmap_update_bits(priv->rst_regmap, TIPRSTC, BIT(offset),
+ BIT(offset));
}
return 0;
@@ -804,6 +816,14 @@
regmap_read(priv->rst_regmap, WD1RCR, &val);
else if (status & WD2RST)
regmap_read(priv->rst_regmap, WD2RCR, &val);
+ else if (status & SW1RST)
+ regmap_read(priv->rst_regmap, SWRSTC1, &val);
+ else if (status & SW2RST)
+ regmap_read(priv->rst_regmap, SWRSTC2, &val);
+ else if (status & SW3RST)
+ regmap_read(priv->rst_regmap, SWRSTC3, &val);
+ else if (status & TIPRST)
+ regmap_read(priv->rst_regmap, TIPRSTC, &val);
else
return false;
diff --git a/drivers/pinctrl/nxp/pinctrl-imx.h b/drivers/pinctrl/nxp/pinctrl-imx.h
index 947975e..fa4c084 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx.h
+++ b/drivers/pinctrl/nxp/pinctrl-imx.h
@@ -45,7 +45,7 @@
#define SHARE_MUX_CONF_REG 0x1
#define ZERO_OFFSET_VALID 0x2
-#define CONFIG_IBE_OBE 0x4
+#define CFG_IBE_OBE 0x4
#define IMX8_USE_SCU 0x8
#define IOMUXC_CONFIG_SION (0x1 << 4)
diff --git a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
index da0f6c9..6da9ff7 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx7ulp.c
@@ -12,11 +12,11 @@
#include "pinctrl-imx.h"
static struct imx_pinctrl_soc_info imx7ulp_pinctrl_soc_info0 = {
- .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE,
+ .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CFG_IBE_OBE,
};
static struct imx_pinctrl_soc_info imx7ulp_pinctrl_soc_info1 = {
- .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE,
+ .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CFG_IBE_OBE,
};
static int imx7ulp_pinctrl_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/nxp/pinctrl-imx8ulp.c b/drivers/pinctrl/nxp/pinctrl-imx8ulp.c
index 3f15f1d..4e8fa08 100644
--- a/drivers/pinctrl/nxp/pinctrl-imx8ulp.c
+++ b/drivers/pinctrl/nxp/pinctrl-imx8ulp.c
@@ -11,11 +11,11 @@
#include "pinctrl-imx.h"
static struct imx_pinctrl_soc_info imx8ulp_pinctrl_soc_info0 = {
- .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE,
+ .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CFG_IBE_OBE,
};
static struct imx_pinctrl_soc_info imx8ulp_pinctrl_soc_info1 = {
- .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CONFIG_IBE_OBE,
+ .flags = ZERO_OFFSET_VALID | SHARE_MUX_CONF_REG | CFG_IBE_OBE,
};
static int imx8ulp_pinctrl_probe(struct udevice *dev)
diff --git a/drivers/pinctrl/nxp/pinctrl-mxs.c b/drivers/pinctrl/nxp/pinctrl-mxs.c
index 9a54b8b..eb90e28 100644
--- a/drivers/pinctrl/nxp/pinctrl-mxs.c
+++ b/drivers/pinctrl/nxp/pinctrl-mxs.c
@@ -94,9 +94,9 @@
config = mxs_dt_node_to_map(conf);
- ma = CONFIG_TO_MA(config);
- vol = CONFIG_TO_VOL(config);
- pull = CONFIG_TO_PULL(config);
+ ma = CFG_TO_MA(config);
+ vol = CFG_TO_VOL(config);
+ pull = CFG_TO_PULL(config);
for (i = 0; i < npins; i++) {
int pinid, bank, pin, shift;
diff --git a/drivers/pinctrl/nxp/pinctrl-mxs.h b/drivers/pinctrl/nxp/pinctrl-mxs.h
index a398e43..20d6dea 100644
--- a/drivers/pinctrl/nxp/pinctrl-mxs.h
+++ b/drivers/pinctrl/nxp/pinctrl-mxs.h
@@ -43,9 +43,9 @@
#define VOL_SHIFT 3
#define MA_PRESENT (1 << 2)
#define MA_SHIFT 0
-#define CONFIG_TO_PULL(c) ((c) >> PULL_SHIFT & 0x1)
-#define CONFIG_TO_VOL(c) ((c) >> VOL_SHIFT & 0x1)
-#define CONFIG_TO_MA(c) ((c) >> MA_SHIFT & 0x3)
+#define CFG_TO_PULL(c) ((c) >> PULL_SHIFT & 0x1)
+#define CFG_TO_VOL(c) ((c) >> VOL_SHIFT & 0x1)
+#define CFG_TO_MA(c) ((c) >> MA_SHIFT & 0x3)
struct mxs_regs {
u16 muxsel;
diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c
index ce2d5dd..a1b85ca 100644
--- a/drivers/pinctrl/pinctrl-uclass.c
+++ b/drivers/pinctrl/pinctrl-uclass.c
@@ -403,13 +403,6 @@
{
const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
- /*
- * Make sure that the pinctrl driver gets probed after binding
- * as some pinctrl drivers also register the GPIO driver during
- * probe, and if they are not probed GPIO-s are not registered.
- */
- dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND);
-
if (!ops) {
dev_dbg(dev, "ops is not set. Do not bind.\n");
return -EINVAL;
diff --git a/drivers/pinctrl/pinctrl-zynqmp.c b/drivers/pinctrl/pinctrl-zynqmp.c
index 7c5a02d..ee6529b 100644
--- a/drivers/pinctrl/pinctrl-zynqmp.c
+++ b/drivers/pinctrl/pinctrl-zynqmp.c
@@ -73,7 +73,7 @@
/**
* enum zynqmp_pin_config_param - possible pin configuration parameters
- * @PIN_CONFIG_IOSTANDARD: if the pin can select an IO standard,
+ * @PIN_CFG_IOSTANDARD: if the pin can select an IO standard,
* the argument to this parameter (on a
* custom format) tells the driver which
* alternative IO standard to use
@@ -81,7 +81,7 @@
* to select schmitt or cmos input for MIO pins
*/
enum zynqmp_pin_config_param {
- PIN_CONFIG_IOSTANDARD = PIN_CONFIG_END + 1,
+ PIN_CFG_IOSTANDARD = PIN_CONFIG_END + 1,
PIN_CONFIG_SCHMITTCMOS,
};
@@ -452,7 +452,7 @@
param = PM_PINCTRL_CONFIG_DRIVE_STRENGTH;
ret = zynqmp_pm_pinctrl_set_config(pin, param, value);
break;
- case PIN_CONFIG_IOSTANDARD:
+ case PIN_CFG_IOSTANDARD:
param = PM_PINCTRL_CONFIG_VOLTAGE_STATUS;
ret = zynqmp_pm_pinctrl_get_config(pin, param, &value);
if (arg != value)
@@ -608,7 +608,7 @@
{ "slew-rate", PIN_CONFIG_SLEW_RATE, 0 },
{ "skew-delay", PIN_CONFIG_SKEW_DELAY, 0 },
/* zynqmp specific */
- {"io-standard", PIN_CONFIG_IOSTANDARD, IO_STANDARD_LVCMOS18},
+ {"io-standard", PIN_CFG_IOSTANDARD, IO_STANDARD_LVCMOS18},
{"schmitt-cmos", PIN_CONFIG_SCHMITTCMOS, PM_PINCTRL_INPUT_TYPE_SCHMITT},
};
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
index 7d03f81..9884355 100644
--- a/drivers/pinctrl/rockchip/Makefile
+++ b/drivers/pinctrl/rockchip/Makefile
@@ -15,3 +15,4 @@
obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
+obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o
diff --git a/drivers/pinctrl/rockchip/pinctrl-px30.c b/drivers/pinctrl/rockchip/pinctrl-px30.c
index 9de29c0..2c35491 100644
--- a/drivers/pinctrl/rockchip/pinctrl-px30.c
+++ b/drivers/pinctrl/rockchip/pinctrl-px30.c
@@ -80,7 +80,7 @@
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, route_reg, route_val;
+ u32 data;
regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
? priv->regmap_pmu : priv->regmap_base;
@@ -90,15 +90,6 @@
reg = bank->iomux[iomux_num].offset;
reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
- if (bank->route_mask & BIT(pin)) {
- if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
- &route_val)) {
- ret = regmap_write(regmap, route_reg, route_val);
- if (ret)
- return ret;
- }
- }
-
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3128.c b/drivers/pinctrl/rockchip/pinctrl-rk3128.c
index e6dc1af..355c45e 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3128.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3128.c
@@ -106,7 +106,7 @@
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, route_reg, route_val;
+ u32 data;
regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
? priv->regmap_pmu : priv->regmap_base;
@@ -119,15 +119,6 @@
if (bank->recalced_mask & BIT(pin))
rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
- if (bank->route_mask & BIT(pin)) {
- if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
- &route_val)) {
- ret = regmap_write(regmap, route_reg, route_val);
- if (ret)
- return ret;
- }
- }
-
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk322x.c b/drivers/pinctrl/rockchip/pinctrl-rk322x.c
index 7c58f40..351406d 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk322x.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk322x.c
@@ -150,7 +150,7 @@
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, route_reg, route_val;
+ u32 data;
regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
? priv->regmap_pmu : priv->regmap_base;
@@ -160,15 +160,6 @@
reg = bank->iomux[iomux_num].offset;
reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
- if (bank->route_mask & BIT(pin)) {
- if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
- &route_val)) {
- ret = regmap_write(regmap, route_reg, route_val);
- if (ret)
- return ret;
- }
- }
-
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3288.c b/drivers/pinctrl/rockchip/pinctrl-rk3288.c
index 5894f47..a976b7a 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3288.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3288.c
@@ -37,7 +37,7 @@
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, route_reg, route_val;
+ u32 data;
regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
? priv->regmap_pmu : priv->regmap_base;
@@ -47,15 +47,6 @@
reg = bank->iomux[iomux_num].offset;
reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
- if (bank->route_mask & BIT(pin)) {
- if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
- &route_val)) {
- ret = regmap_write(regmap, route_reg, route_val);
- if (ret)
- return ret;
- }
- }
-
/* bank0 is special, there are no higher 16 bit writing bits. */
if (bank->bank_num == 0) {
regmap_read(regmap, reg, &data);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3308.c b/drivers/pinctrl/rockchip/pinctrl-rk3308.c
index 83186f4..f9ac634 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3308.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3308.c
@@ -258,7 +258,7 @@
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, route_reg, route_val;
+ u32 data;
regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
? priv->regmap_pmu : priv->regmap_base;
@@ -271,15 +271,6 @@
if (bank->recalced_mask & BIT(pin))
rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
- if (bank->route_mask & BIT(pin)) {
- if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
- &route_val)) {
- ret = regmap_write(regmap, route_reg, route_val);
- if (ret)
- return ret;
- }
- }
-
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3328.c b/drivers/pinctrl/rockchip/pinctrl-rk3328.c
index 1c3c598..65a7500 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3328.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3328.c
@@ -130,7 +130,7 @@
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, route_reg, route_val;
+ u32 data;
regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
? priv->regmap_pmu : priv->regmap_base;
@@ -143,15 +143,6 @@
if (bank->recalced_mask & BIT(pin))
rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
- if (bank->route_mask & BIT(pin)) {
- if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
- &route_val)) {
- ret = regmap_write(regmap, route_reg, route_val);
- if (ret)
- return ret;
- }
- }
-
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3399.c b/drivers/pinctrl/rockchip/pinctrl-rk3399.c
index caa9220..ae78557 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rk3399.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rk3399.c
@@ -59,7 +59,7 @@
struct regmap *regmap;
int reg, ret, mask, mux_type;
u8 bit;
- u32 data, route_reg, route_val;
+ u32 data;
regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
? priv->regmap_pmu : priv->regmap_base;
@@ -69,15 +69,6 @@
reg = bank->iomux[iomux_num].offset;
reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
- if (bank->route_mask & BIT(pin)) {
- if (rockchip_get_mux_route(bank, pin, mux, &route_reg,
- &route_val)) {
- ret = regmap_write(regmap, route_reg, route_val);
- if (ret)
- return ret;
- }
- }
-
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
index 630513b..d9d61fd 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c
@@ -62,8 +62,9 @@
*bit = data->bit;
}
-bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
- int mux, u32 *reg, u32 *value)
+static enum rockchip_pin_route_type
+rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
+ int mux, u32 *reg, u32 *value)
{
struct rockchip_pinctrl_priv *priv = bank->priv;
struct rockchip_pin_ctrl *ctrl = priv->ctrl;
@@ -78,12 +79,12 @@
}
if (i >= ctrl->niomux_routes)
- return false;
+ return ROUTE_TYPE_INVALID;
*reg = data->route_offset;
*value = data->route_val;
- return true;
+ return data->route_type;
}
int rockchip_get_mux_data(int mux_type, int pin, u8 *bit, int *mask)
@@ -214,8 +215,40 @@
return -ENOTSUPP;
ret = ctrl->set_mux(bank, pin, mux);
+ if (ret)
+ return ret;
- return ret;
+ if (bank->route_mask & BIT(pin)) {
+ struct regmap *regmap;
+ u32 route_reg = 0, route_val = 0;
+
+ ret = rockchip_get_mux_route(bank, pin, mux,
+ &route_reg, &route_val);
+ switch (ret) {
+ case ROUTE_TYPE_DEFAULT:
+ if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+ regmap = priv->regmap_pmu;
+ else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
+ regmap = (pin % 8 < 4) ? priv->regmap_pmu : priv->regmap_base;
+ else
+ regmap = priv->regmap_base;
+
+ regmap_write(regmap, route_reg, route_val);
+ break;
+ case ROUTE_TYPE_TOPGRF:
+ regmap_write(priv->regmap_base, route_reg, route_val);
+ break;
+ case ROUTE_TYPE_PMUGRF:
+ regmap_write(priv->regmap_pmu, route_reg, route_val);
+ break;
+ case ROUTE_TYPE_INVALID:
+ fallthrough;
+ default:
+ break;
+ }
+ }
+
+ return 0;
}
static int rockchip_perpin_drv_list[DRV_TYPE_MAX][8] = {
@@ -545,7 +578,7 @@
inc = (iom->type & (IOMUX_WIDTH_4BIT |
IOMUX_WIDTH_3BIT |
IOMUX_8WIDTH_2BIT)) ? 8 : 4;
- if (iom->type & IOMUX_SOURCE_PMU)
+ if ((iom->type & IOMUX_SOURCE_PMU) || (iom->type & IOMUX_L_SOURCE_PMU))
pmu_offs += inc;
else
grf_offs += inc;
diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
index d969c20..8dfaba5 100644
--- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h
+++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h
@@ -9,6 +9,9 @@
#include <linux/bitops.h>
#include <linux/types.h>
+#define RK_GENMASK_VAL(h, l, v) \
+ (GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l))))
+
/**
* Encode variants of iomux registers into a type variable
*/
@@ -18,6 +21,7 @@
#define IOMUX_UNROUTED BIT(3)
#define IOMUX_WIDTH_3BIT BIT(4)
#define IOMUX_8WIDTH_2BIT BIT(5)
+#define IOMUX_L_SOURCE_PMU BIT(6)
/**
* Defined some common pins constants
@@ -63,6 +67,22 @@
};
/**
+ * Rockchip pinctrl route type
+ *
+ * DEFAULT : Same regmap as pin iomux
+ * TOPGRF : Mux route setting in topgrf
+ * PMUGRF : Mux route setting in pmugrf
+ * INVALID : Nnot need to set mux route
+ */
+enum rockchip_pin_route_type {
+ ROUTE_TYPE_DEFAULT = 0,
+ ROUTE_TYPE_TOPGRF = 1,
+ ROUTE_TYPE_PMUGRF = 2,
+
+ ROUTE_TYPE_INVALID = -1,
+};
+
+/**
* @drv_type: drive strength variant using rockchip_perpin_drv_type
* @offset: if initialized to -1 it will be autocalculated, by specifying
* an initial offset value the relevant source offset can be reset
@@ -126,6 +146,21 @@
}, \
}
+#define PIN_BANK_IOMUX_FLAGS_OFFSET(id, pins, label, iom0, iom1, iom2, \
+ iom3, offset0, offset1, offset2, \
+ offset3) \
+ { \
+ .bank_num = id, \
+ .nr_pins = pins, \
+ .name = label, \
+ .iomux = { \
+ { .type = iom0, .offset = offset0 }, \
+ { .type = iom1, .offset = offset1 }, \
+ { .type = iom2, .offset = offset2 }, \
+ { .type = iom3, .offset = offset3 }, \
+ }, \
+ }
+
#define PIN_BANK_DRV_FLAGS(id, pins, label, type0, type1, type2, type3) \
{ \
.bank_num = id, \
@@ -220,6 +255,25 @@
.pull_type[3] = pull3, \
}
+#define PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, FLAG) \
+ { \
+ .bank_num = ID, \
+ .pin = PIN, \
+ .func = FUNC, \
+ .route_offset = REG, \
+ .route_val = VAL, \
+ .route_type = FLAG, \
+ }
+
+#define MR_DEFAULT(ID, PIN, FUNC, REG, VAL) \
+ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_DEFAULT)
+
+#define MR_TOPGRF(ID, PIN, FUNC, REG, VAL) \
+ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_TOPGRF)
+
+#define MR_PMUGRF(ID, PIN, FUNC, REG, VAL) \
+ PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF)
+
/**
* struct rockchip_mux_recalced_data: recalculate a pin iomux data.
* @num: bank number.
@@ -241,6 +295,7 @@
* @bank_num: bank number.
* @pin: index at register or used to calc index.
* @func: the min pin.
+ * @route_type: the register type.
* @route_offset: the max pin.
* @route_val: the register offset.
*/
@@ -248,6 +303,7 @@
u8 bank_num;
u8 pin;
u8 func;
+ enum rockchip_pin_route_type route_type : 8;
u32 route_offset;
u32 route_val;
};
@@ -289,8 +345,6 @@
int rockchip_pinctrl_probe(struct udevice *dev);
void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
int *reg, u8 *bit, int *mask);
-bool rockchip_get_mux_route(struct rockchip_pin_bank *bank, int pin,
- int mux, u32 *reg, u32 *value);
int rockchip_get_mux_data(int mux_type, int pin, u8 *bit, int *mask);
int rockchip_translate_drive_value(int type, int strength);
int rockchip_translate_pull_value(int type, int pull);
diff --git a/drivers/pinctrl/rockchip/pinctrl-rv1126.c b/drivers/pinctrl/rockchip/pinctrl-rv1126.c
new file mode 100644
index 0000000..eefb8b1
--- /dev/null
+++ b/drivers/pinctrl/rockchip/pinctrl-rv1126.c
@@ -0,0 +1,416 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <dm/pinctrl.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <linux/bitops.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+#include "pinctrl-rockchip.h"
+
+static struct rockchip_mux_recalced_data rv1126_mux_recalced_data[] = {
+ {
+ .num = 0,
+ .pin = 20,
+ .reg = 0x10000,
+ .bit = 0,
+ .mask = 0xf
+ },
+ {
+ .num = 0,
+ .pin = 21,
+ .reg = 0x10000,
+ .bit = 4,
+ .mask = 0xf
+ },
+ {
+ .num = 0,
+ .pin = 22,
+ .reg = 0x10000,
+ .bit = 8,
+ .mask = 0xf
+ },
+ {
+ .num = 0,
+ .pin = 23,
+ .reg = 0x10000,
+ .bit = 12,
+ .mask = 0xf
+ },
+};
+
+static struct rockchip_mux_route_data rv1126_mux_route_data[] = {
+ MR_TOPGRF(RK_GPIO3, RK_PD2, 1, 0x10260, RK_GENMASK_VAL(0, 0, 0)), /* I2S0_MCLK_M0 */
+ MR_TOPGRF(RK_GPIO3, RK_PB0, 3, 0x10260, RK_GENMASK_VAL(0, 0, 1)), /* I2S0_MCLK_M1 */
+
+ MR_TOPGRF(RK_GPIO0, RK_PD4, 4, 0x10260, RK_GENMASK_VAL(3, 2, 0)), /* I2S1_MCLK_M0 */
+ MR_TOPGRF(RK_GPIO1, RK_PD5, 2, 0x10260, RK_GENMASK_VAL(3, 2, 1)), /* I2S1_MCLK_M1 */
+ MR_TOPGRF(RK_GPIO2, RK_PC7, 6, 0x10260, RK_GENMASK_VAL(3, 2, 2)), /* I2S1_MCLK_M2 */
+
+ MR_TOPGRF(RK_GPIO1, RK_PD0, 1, 0x10260, RK_GENMASK_VAL(4, 4, 0)), /* I2S2_MCLK_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PB3, 2, 0x10260, RK_GENMASK_VAL(4, 4, 1)), /* I2S2_MCLK_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PD4, 2, 0x10260, RK_GENMASK_VAL(12, 12, 0)), /* PDM_CLK0_M0 */
+ MR_TOPGRF(RK_GPIO3, RK_PC0, 3, 0x10260, RK_GENMASK_VAL(12, 12, 1)), /* PDM_CLK0_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PC6, 1, 0x10264, RK_GENMASK_VAL(0, 0, 0)), /* CIF_CLKOUT_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PD1, 3, 0x10264, RK_GENMASK_VAL(0, 0, 1)), /* CIF_CLKOUT_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA4, 5, 0x10264, RK_GENMASK_VAL(5, 4, 0)), /* I2C3_SCL_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PD4, 7, 0x10264, RK_GENMASK_VAL(5, 4, 1)), /* I2C3_SCL_M1 */
+ MR_TOPGRF(RK_GPIO1, RK_PD6, 3, 0x10264, RK_GENMASK_VAL(5, 4, 2)), /* I2C3_SCL_M2 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA0, 7, 0x10264, RK_GENMASK_VAL(6, 6, 0)), /* I2C4_SCL_M0 */
+ MR_TOPGRF(RK_GPIO4, RK_PA0, 4, 0x10264, RK_GENMASK_VAL(6, 6, 1)), /* I2C4_SCL_M1 */
+
+ MR_TOPGRF(RK_GPIO2, RK_PA5, 7, 0x10264, RK_GENMASK_VAL(9, 8, 0)), /* I2C5_SCL_M0 */
+ MR_TOPGRF(RK_GPIO3, RK_PB0, 5, 0x10264, RK_GENMASK_VAL(9, 8, 1)), /* I2C5_SCL_M1 */
+ MR_TOPGRF(RK_GPIO1, RK_PD0, 4, 0x10264, RK_GENMASK_VAL(9, 8, 2)), /* I2C5_SCL_M2 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PC0, 5, 0x10264, RK_GENMASK_VAL(11, 10, 0)), /* SPI1_CLK_M0 */
+ MR_TOPGRF(RK_GPIO1, RK_PC6, 3, 0x10264, RK_GENMASK_VAL(11, 10, 1)), /* SPI1_CLK_M1 */
+ MR_TOPGRF(RK_GPIO2, RK_PD5, 6, 0x10264, RK_GENMASK_VAL(11, 10, 2)), /* SPI1_CLK_M2 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PC0, 2, 0x10264, RK_GENMASK_VAL(12, 12, 0)), /* RGMII_CLK_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PB7, 2, 0x10264, RK_GENMASK_VAL(12, 12, 1)), /* RGMII_CLK_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA1, 3, 0x10264, RK_GENMASK_VAL(13, 13, 0)), /* CAN_TXD_M0 */
+ MR_TOPGRF(RK_GPIO3, RK_PA7, 5, 0x10264, RK_GENMASK_VAL(13, 13, 1)), /* CAN_TXD_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA4, 6, 0x10268, RK_GENMASK_VAL(0, 0, 0)), /* PWM8_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PD7, 5, 0x10268, RK_GENMASK_VAL(0, 0, 1)), /* PWM8_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA5, 6, 0x10268, RK_GENMASK_VAL(2, 2, 0)), /* PWM9_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PD6, 5, 0x10268, RK_GENMASK_VAL(2, 2, 1)), /* PWM9_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA6, 6, 0x10268, RK_GENMASK_VAL(4, 4, 0)), /* PWM10_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PD5, 5, 0x10268, RK_GENMASK_VAL(4, 4, 1)), /* PWM10_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA7, 6, 0x10268, RK_GENMASK_VAL(6, 6, 0)), /* PWM11_IR_M0 */
+ MR_TOPGRF(RK_GPIO3, RK_PA1, 5, 0x10268, RK_GENMASK_VAL(6, 6, 1)), /* PWM11_IR_M1 */
+
+ MR_TOPGRF(RK_GPIO1, RK_PA5, 3, 0x10268, RK_GENMASK_VAL(8, 8, 0)), /* UART2_TX_M0 */
+ MR_TOPGRF(RK_GPIO3, RK_PA2, 1, 0x10268, RK_GENMASK_VAL(8, 8, 1)), /* UART2_TX_M1 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PC6, 3, 0x10268, RK_GENMASK_VAL(11, 10, 0)), /* UART3_TX_M0 */
+ MR_TOPGRF(RK_GPIO1, RK_PA7, 2, 0x10268, RK_GENMASK_VAL(11, 10, 1)), /* UART3_TX_M1 */
+ MR_TOPGRF(RK_GPIO3, RK_PA0, 4, 0x10268, RK_GENMASK_VAL(11, 10, 2)), /* UART3_TX_M2 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA4, 4, 0x10268, RK_GENMASK_VAL(13, 12, 0)), /* UART4_TX_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PA6, 4, 0x10268, RK_GENMASK_VAL(13, 12, 1)), /* UART4_TX_M1 */
+ MR_TOPGRF(RK_GPIO1, RK_PD5, 3, 0x10268, RK_GENMASK_VAL(13, 12, 2)), /* UART4_TX_M2 */
+
+ MR_TOPGRF(RK_GPIO3, RK_PA6, 4, 0x10268, RK_GENMASK_VAL(15, 14, 0)), /* UART5_TX_M0 */
+ MR_TOPGRF(RK_GPIO2, RK_PB0, 4, 0x10268, RK_GENMASK_VAL(15, 14, 1)), /* UART5_TX_M1 */
+ MR_TOPGRF(RK_GPIO2, RK_PA0, 3, 0x10268, RK_GENMASK_VAL(15, 14, 2)), /* UART5_TX_M2 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PB6, 3, 0x0114, RK_GENMASK_VAL(0, 0, 0)), /* PWM0_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PB3, 5, 0x0114, RK_GENMASK_VAL(0, 0, 1)), /* PWM0_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PB7, 3, 0x0114, RK_GENMASK_VAL(2, 2, 0)), /* PWM1_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PB2, 5, 0x0114, RK_GENMASK_VAL(2, 2, 1)), /* PWM1_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PC0, 3, 0x0114, RK_GENMASK_VAL(4, 4, 0)), /* PWM2_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PB1, 5, 0x0114, RK_GENMASK_VAL(4, 4, 1)), /* PWM2_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PC1, 3, 0x0114, RK_GENMASK_VAL(6, 6, 0)), /* PWM3_IR_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PB0, 5, 0x0114, RK_GENMASK_VAL(6, 6, 1)), /* PWM3_IR_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PC2, 3, 0x0114, RK_GENMASK_VAL(8, 8, 0)), /* PWM4_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PA7, 5, 0x0114, RK_GENMASK_VAL(8, 8, 1)), /* PWM4_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PC3, 3, 0x0114, RK_GENMASK_VAL(10, 10, 0)), /* PWM5_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PA6, 5, 0x0114, RK_GENMASK_VAL(10, 10, 1)), /* PWM5_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PB2, 3, 0x0114, RK_GENMASK_VAL(12, 12, 0)), /* PWM6_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PD4, 5, 0x0114, RK_GENMASK_VAL(12, 12, 1)), /* PWM6_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PB1, 3, 0x0114, RK_GENMASK_VAL(14, 14, 0)), /* PWM7_IR_M0 */
+ MR_PMUGRF(RK_GPIO3, RK_PA0, 5, 0x0114, RK_GENMASK_VAL(14, 14, 1)), /* PWM7_IR_M1 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PB0, 1, 0x0118, RK_GENMASK_VAL(1, 0, 0)), /* SPI0_CLK_M0 */
+ MR_PMUGRF(RK_GPIO2, RK_PA1, 1, 0x0118, RK_GENMASK_VAL(1, 0, 1)), /* SPI0_CLK_M1 */
+ MR_PMUGRF(RK_GPIO2, RK_PB2, 6, 0x0118, RK_GENMASK_VAL(1, 0, 2)), /* SPI0_CLK_M2 */
+
+ MR_PMUGRF(RK_GPIO0, RK_PB6, 2, 0x0118, RK_GENMASK_VAL(2, 2, 0)), /* UART1_TX_M0 */
+ MR_PMUGRF(RK_GPIO1, RK_PD0, 5, 0x0118, RK_GENMASK_VAL(2, 2, 1)), /* UART1_TX_M1 */
+ MR_PMUGRF(RK_GPIO0, RK_PC3, 1, 0x0118, RK_GENMASK_VAL(4, 4, 1)), /* I2C2 */
+};
+
+static int rv1126_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+ int iomux_num = (pin / 8);
+ struct regmap *regmap;
+ int reg, ret, mask, mux_type;
+ u8 bit;
+ u32 data;
+
+ debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
+
+ if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
+ regmap = priv->regmap_pmu;
+ else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
+ regmap = (pin % 8 < 4) ? priv->regmap_pmu : priv->regmap_base;
+ else
+ regmap = priv->regmap_base;
+
+ /* get basic quadrupel of mux registers and the correct reg inside */
+ mux_type = bank->iomux[iomux_num].type;
+ reg = bank->iomux[iomux_num].offset;
+ if (mux_type & IOMUX_WIDTH_4BIT) {
+ if ((pin % 8) >= 4)
+ reg += 0x4;
+ bit = (pin % 4) * 4;
+ mask = 0xf;
+ } else {
+ bit = (pin % 8) * 2;
+ mask = 0x3;
+ }
+
+ if (bank->recalced_mask & BIT(pin))
+ rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
+
+ data = (mask << (bit + 16));
+ data |= (mux & mask) << bit;
+ ret = regmap_write(regmap, reg, data);
+
+ return ret;
+}
+
+#define RV1126_PULL_PMU_OFFSET 0x40
+#define RV1126_PULL_GRF_GPIO1A0_OFFSET 0x10108
+#define RV1126_PULL_PINS_PER_REG 8
+#define RV1126_PULL_BITS_PER_PIN 2
+#define RV1126_PULL_BANK_STRIDE 16
+#define RV1126_GPIO_C4_D7(p) (p >= 20 && p <= 31) /* GPIO0_C4 ~ GPIO0_D7 */
+
+static void rv1126_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ /* The first 24 pins of the first bank are located in PMU */
+ if (bank->bank_num == 0) {
+ if (RV1126_GPIO_C4_D7(pin_num)) {
+ *regmap = priv->regmap_base;
+ *reg = RV1126_PULL_GRF_GPIO1A0_OFFSET;
+ *reg -= (((31 - pin_num) / RV1126_PULL_PINS_PER_REG + 1) * 4);
+ *bit = pin_num % RV1126_PULL_PINS_PER_REG;
+ *bit *= RV1126_PULL_BITS_PER_PIN;
+ return;
+ }
+ *regmap = priv->regmap_pmu;
+ *reg = RV1126_PULL_PMU_OFFSET;
+ } else {
+ *reg = RV1126_PULL_GRF_GPIO1A0_OFFSET;
+ *regmap = priv->regmap_base;
+ *reg += (bank->bank_num - 1) * RV1126_PULL_BANK_STRIDE;
+ }
+
+ *reg += ((pin_num / RV1126_PULL_PINS_PER_REG) * 4);
+ *bit = (pin_num % RV1126_PULL_PINS_PER_REG);
+ *bit *= RV1126_PULL_BITS_PER_PIN;
+}
+
+static int rv1126_set_pull(struct rockchip_pin_bank *bank,
+ int pin_num, int pull)
+{
+ struct regmap *regmap;
+ int reg, ret;
+ u8 bit, type;
+ u32 data;
+
+ if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
+ return -EOPNOTSUPP;
+
+ rv1126_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit);
+ type = bank->pull_type[pin_num / 8];
+ ret = rockchip_translate_pull_value(type, pull);
+ if (ret < 0) {
+ debug("unsupported pull setting %d\n", pull);
+ return ret;
+ }
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+
+ data |= (ret << bit);
+ ret = regmap_write(regmap, reg, data);
+
+ return ret;
+}
+
+#define RV1126_DRV_PMU_OFFSET 0x20
+#define RV1126_DRV_GRF_GPIO1A0_OFFSET 0x10090
+#define RV1126_DRV_BITS_PER_PIN 4
+#define RV1126_DRV_PINS_PER_REG 4
+#define RV1126_DRV_BANK_STRIDE 32
+
+static void rv1126_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+
+ /* The first 24 pins of the first bank are located in PMU */
+ if (bank->bank_num == 0) {
+ if (RV1126_GPIO_C4_D7(pin_num)) {
+ *regmap = priv->regmap_base;
+ *reg = RV1126_DRV_GRF_GPIO1A0_OFFSET;
+ *reg -= (((31 - pin_num) / RV1126_DRV_PINS_PER_REG + 1) * 4);
+ *reg -= 0x4;
+ *bit = pin_num % RV1126_DRV_PINS_PER_REG;
+ *bit *= RV1126_DRV_BITS_PER_PIN;
+ return;
+ }
+ *regmap = priv->regmap_pmu;
+ *reg = RV1126_DRV_PMU_OFFSET;
+ } else {
+ *regmap = priv->regmap_base;
+ *reg = RV1126_DRV_GRF_GPIO1A0_OFFSET;
+ *reg += (bank->bank_num - 1) * RV1126_DRV_BANK_STRIDE;
+ }
+
+ *reg += ((pin_num / RV1126_DRV_PINS_PER_REG) * 4);
+ *bit = pin_num % RV1126_DRV_PINS_PER_REG;
+ *bit *= RV1126_DRV_BITS_PER_PIN;
+}
+
+static int rv1126_set_drive(struct rockchip_pin_bank *bank,
+ int pin_num, int strength)
+{
+ struct regmap *regmap;
+ int reg;
+ u32 data;
+ u8 bit;
+
+ rv1126_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit);
+
+ /* enable the write to the equivalent lower bits */
+ data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+ data |= (strength << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+#define RV1126_SCHMITT_PMU_OFFSET 0x60
+#define RV1126_SCHMITT_GRF_GPIO1A0_OFFSET 0x10188
+#define RV1126_SCHMITT_BANK_STRIDE 16
+#define RV1126_SCHMITT_PINS_PER_GRF_REG 8
+#define RV1126_SCHMITT_PINS_PER_PMU_REG 8
+
+static int rv1126_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num,
+ struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl_priv *priv = bank->priv;
+ int pins_per_reg;
+
+ if (bank->bank_num == 0) {
+ if (RV1126_GPIO_C4_D7(pin_num)) {
+ *regmap = priv->regmap_base;
+ *reg = RV1126_SCHMITT_GRF_GPIO1A0_OFFSET;
+ *reg -= (((31 - pin_num) / RV1126_SCHMITT_PINS_PER_GRF_REG + 1) * 4);
+ *bit = pin_num % RV1126_SCHMITT_PINS_PER_GRF_REG;
+ return 0;
+ }
+ *regmap = priv->regmap_pmu;
+ *reg = RV1126_SCHMITT_PMU_OFFSET;
+ pins_per_reg = RV1126_SCHMITT_PINS_PER_PMU_REG;
+ } else {
+ *regmap = priv->regmap_base;
+ *reg = RV1126_SCHMITT_GRF_GPIO1A0_OFFSET;
+ pins_per_reg = RV1126_SCHMITT_PINS_PER_GRF_REG;
+ *reg += (bank->bank_num - 1) * RV1126_SCHMITT_BANK_STRIDE;
+ }
+ *reg += ((pin_num / pins_per_reg) * 4);
+ *bit = pin_num % pins_per_reg;
+
+ return 0;
+}
+
+static int rv1126_set_schmitt(struct rockchip_pin_bank *bank,
+ int pin_num, int enable)
+{
+ struct regmap *regmap;
+ int reg;
+ u8 bit;
+ u32 data;
+
+ rv1126_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit);
+ /* enable the write to the equivalent lower bits */
+ data = BIT(bit + 16) | (enable << bit);
+
+ return regmap_write(regmap, reg, data);
+}
+
+static struct rockchip_pin_bank rv1126_pin_banks[] = {
+ PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0",
+ IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+ IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
+ IOMUX_WIDTH_4BIT | IOMUX_L_SOURCE_PMU,
+ IOMUX_WIDTH_4BIT),
+ PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ 0x10010, 0x10018, 0x10020, 0x10028),
+ PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT),
+ PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT,
+ IOMUX_WIDTH_4BIT),
+ PIN_BANK_IOMUX_FLAGS(4, 2, "gpio4",
+ IOMUX_WIDTH_4BIT, 0, 0, 0),
+};
+
+static const struct rockchip_pin_ctrl rv1126_pin_ctrl = {
+ .pin_banks = rv1126_pin_banks,
+ .nr_banks = ARRAY_SIZE(rv1126_pin_banks),
+ .nr_pins = 130,
+ .grf_mux_offset = 0x10004, /* mux offset from GPIO0_D0 */
+ .pmu_mux_offset = 0x0,
+ .iomux_routes = rv1126_mux_route_data,
+ .niomux_routes = ARRAY_SIZE(rv1126_mux_route_data),
+ .iomux_recalced = rv1126_mux_recalced_data,
+ .niomux_recalced = ARRAY_SIZE(rv1126_mux_recalced_data),
+ .set_mux = rv1126_set_mux,
+ .set_pull = rv1126_set_pull,
+ .set_drive = rv1126_set_drive,
+ .set_schmitt = rv1126_set_schmitt,
+};
+
+static const struct udevice_id rv1126_pinctrl_ids[] = {
+ {
+ .compatible = "rockchip,rv1126-pinctrl",
+ .data = (ulong)&rv1126_pin_ctrl
+ },
+ { }
+};
+
+U_BOOT_DRIVER(pinctrl_rv1126) = {
+ .name = "rockchip_rv1126_pinctrl",
+ .id = UCLASS_PINCTRL,
+ .of_match = rv1126_pinctrl_ids,
+ .priv_auto = sizeof(struct rockchip_pinctrl_priv),
+ .ops = &rockchip_pinctrl_ops,
+#if !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .bind = dm_scan_fdt_dev,
+#endif
+ .probe = rockchip_pinctrl_probe,
+};
diff --git a/drivers/power/pmic/axp.c b/drivers/power/pmic/axp.c
index 0f2b24a..025dac2 100644
--- a/drivers/power/pmic/axp.c
+++ b/drivers/power/pmic/axp.c
@@ -45,14 +45,32 @@
.write = dm_i2c_write,
};
+static const struct pmic_child_info axp_pmic_child_info[] = {
+ { "aldo", "axp_regulator" },
+ { "bldo", "axp_regulator" },
+ { "cldo", "axp_regulator" },
+ { "dc", "axp_regulator" },
+ { "dldo", "axp_regulator" },
+ { "eldo", "axp_regulator" },
+ { "fldo", "axp_regulator" },
+ { "ldo", "axp_regulator" },
+ { "sw", "axp_regulator" },
+ { }
+};
+
static int axp_pmic_bind(struct udevice *dev)
{
+ ofnode regulators_node;
int ret;
ret = dm_scan_fdt_dev(dev);
if (ret)
return ret;
+ regulators_node = dev_read_subnode(dev, "regulators");
+ if (ofnode_valid(regulators_node))
+ pmic_bind_children(dev, regulators_node, axp_pmic_child_info);
+
if (CONFIG_IS_ENABLED(SYSRESET)) {
ret = device_bind_driver_to_node(dev, "axp_sysreset", "axp_sysreset",
dev_ofnode(dev), NULL);
@@ -64,15 +82,15 @@
}
static const struct udevice_id axp_pmic_ids[] = {
- { .compatible = "x-powers,axp152" },
- { .compatible = "x-powers,axp202" },
- { .compatible = "x-powers,axp209" },
- { .compatible = "x-powers,axp221" },
- { .compatible = "x-powers,axp223" },
- { .compatible = "x-powers,axp803" },
- { .compatible = "x-powers,axp806" },
- { .compatible = "x-powers,axp809" },
- { .compatible = "x-powers,axp813" },
+ { .compatible = "x-powers,axp152", .data = AXP152_ID },
+ { .compatible = "x-powers,axp202", .data = AXP202_ID },
+ { .compatible = "x-powers,axp209", .data = AXP209_ID },
+ { .compatible = "x-powers,axp221", .data = AXP221_ID },
+ { .compatible = "x-powers,axp223", .data = AXP223_ID },
+ { .compatible = "x-powers,axp803", .data = AXP803_ID },
+ { .compatible = "x-powers,axp806", .data = AXP806_ID },
+ { .compatible = "x-powers,axp809", .data = AXP809_ID },
+ { .compatible = "x-powers,axp813", .data = AXP813_ID },
{ }
};
diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index c02e637..c346d03 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -43,6 +43,20 @@
but does not yet support change voltages. Currently this must be
done using direct register writes to the PMIC.
+config REGULATOR_AXP
+ bool "Enable driver for X-Powers AXP PMIC regulators"
+ depends on DM_REGULATOR && PMIC_AXP
+ help
+ Enable support for the regulators (DCDCs, LDOs) in the
+ X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
+
+config SPL_REGULATOR_AXP
+ bool "Enable driver for X-Powers AXP PMIC regulators in SPL"
+ depends on SPL_DM_REGULATOR && SPL_PMIC_AXP
+ help
+ Enable support in SPL for the regulators (DCDCs, LDOs) in the
+ X-Powers AXP152, AXP2xx, and AXP8xx PMICs.
+
config DM_REGULATOR_BD71837
bool "Enable Driver Model for ROHM BD71837/BD71847 regulators"
depends on DM_REGULATOR && DM_PMIC_BD71837
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 68e4c0f..2d97e10 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o
obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o
+obj-$(CONFIG_$(SPL_)REGULATOR_AXP) += axp_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_DA9063) += da9063.o
obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
obj-$(CONFIG_DM_REGULATOR_NPCM8XX) += npcm8xx_regulator.o
diff --git a/drivers/power/regulator/axp_regulator.c b/drivers/power/regulator/axp_regulator.c
new file mode 100644
index 0000000..02f320e
--- /dev/null
+++ b/drivers/power/regulator/axp_regulator.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2023 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <axp_pmic.h>
+#include <dm.h>
+#include <errno.h>
+#include <dm/device-internal.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+#define NA 0xff
+
+struct axp_regulator_plat {
+ const char *name;
+ u8 enable_reg;
+ u8 enable_mask;
+ u8 volt_reg;
+ u8 volt_mask;
+ u16 min_mV;
+ u16 max_mV;
+ u8 step_mV;
+ u8 split;
+ const u16 *table;
+};
+
+static int axp_regulator_get_value(struct udevice *dev)
+{
+ const struct axp_regulator_plat *plat = dev_get_plat(dev);
+ int mV, sel;
+
+ if (plat->volt_reg == NA)
+ return -EINVAL;
+
+ sel = pmic_reg_read(dev->parent, plat->volt_reg);
+ if (sel < 0)
+ return sel;
+
+ sel &= plat->volt_mask;
+ sel >>= ffs(plat->volt_mask) - 1;
+
+ if (plat->table) {
+ mV = plat->table[sel];
+ } else {
+ if (sel > plat->split)
+ sel = plat->split + (sel - plat->split) * 2;
+ mV = plat->min_mV + sel * plat->step_mV;
+ }
+
+ return mV * 1000;
+}
+
+static int axp_regulator_set_value(struct udevice *dev, int uV)
+{
+ const struct axp_regulator_plat *plat = dev_get_plat(dev);
+ int mV = uV / 1000;
+ uint sel, shift;
+
+ if (plat->volt_reg == NA)
+ return -EINVAL;
+ if (mV < plat->min_mV || mV > plat->max_mV)
+ return -EINVAL;
+
+ shift = ffs(plat->volt_mask) - 1;
+
+ if (plat->table) {
+ /*
+ * The table must be monotonically increasing and
+ * have an entry for each possible field value.
+ */
+ sel = plat->volt_mask >> shift;
+ while (sel && plat->table[sel] > mV)
+ sel--;
+ } else {
+ sel = (mV - plat->min_mV) / plat->step_mV;
+ if (sel > plat->split)
+ sel = plat->split + (sel - plat->split) / 2;
+ }
+
+ return pmic_clrsetbits(dev->parent, plat->volt_reg,
+ plat->volt_mask, sel << shift);
+}
+
+static int axp_regulator_get_enable(struct udevice *dev)
+{
+ const struct axp_regulator_plat *plat = dev_get_plat(dev);
+ int reg;
+
+ reg = pmic_reg_read(dev->parent, plat->enable_reg);
+ if (reg < 0)
+ return reg;
+
+ return (reg & plat->enable_mask) == plat->enable_mask;
+}
+
+static int axp_regulator_set_enable(struct udevice *dev, bool enable)
+{
+ const struct axp_regulator_plat *plat = dev_get_plat(dev);
+
+ return pmic_clrsetbits(dev->parent, plat->enable_reg,
+ plat->enable_mask,
+ enable ? plat->enable_mask : 0);
+}
+
+static const struct dm_regulator_ops axp_regulator_ops = {
+ .get_value = axp_regulator_get_value,
+ .set_value = axp_regulator_set_value,
+ .get_enable = axp_regulator_get_enable,
+ .set_enable = axp_regulator_set_enable,
+};
+
+static const u16 axp152_dcdc1_table[] = {
+ 1700, 1800, 1900, 2000, 2100, 2400, 2500, 2600,
+ 2700, 2800, 3000, 3100, 3200, 3300, 3400, 3500,
+};
+
+static const u16 axp152_aldo12_table[] = {
+ 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900,
+ 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300,
+};
+
+static const u16 axp152_ldo0_table[] = {
+ 5000, 3300, 2800, 2500,
+};
+
+static const struct axp_regulator_plat axp152_regulators[] = {
+ { "dcdc1", 0x12, BIT(7), 0x26, 0x0f, .table = axp152_dcdc1_table },
+ { "dcdc2", 0x12, BIT(6), 0x23, 0x3f, 700, 2275, 25, NA },
+ { "dcdc3", 0x12, BIT(5), 0x27, 0x3f, 700, 3500, 50, NA },
+ { "dcdc4", 0x12, BIT(4), 0x2b, 0x7f, 700, 3500, 25, NA },
+ { "aldo1", 0x12, BIT(3), 0x28, 0xf0, .table = axp152_aldo12_table },
+ { "aldo2", 0x12, BIT(2), 0x28, 0x0f, .table = axp152_aldo12_table },
+ { "dldo1", 0x12, BIT(1), 0x29, 0x1f, 700, 3500, 100, NA },
+ { "dldo2", 0x12, BIT(0), 0x2a, 0x1f, 700, 3500, 100, NA },
+ { "ldo0", 0x15, BIT(7), 0x15, 0x30, .table = axp152_ldo0_table },
+ { }
+};
+
+static const u16 axp20x_ldo4_table[] = {
+ 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900,
+ 2000, 2500, 2700, 2800, 3000, 3100, 3200, 3300,
+};
+
+static const struct axp_regulator_plat axp20x_regulators[] = {
+ { "dcdc2", 0x12, BIT(4), 0x23, 0x3f, 700, 2275, 25, NA },
+ { "dcdc3", 0x12, BIT(1), 0x27, 0x7f, 700, 3500, 25, NA },
+ { "ldo2", 0x12, BIT(2), 0x28, 0xf0, 1800, 3300, 100, NA },
+ { "ldo3", 0x12, BIT(6), 0x29, 0x7f, 700, 2275, 25, NA },
+ { "ldo4", 0x12, BIT(3), 0x28, 0x0f, .table = axp20x_ldo4_table },
+ { }
+};
+
+static const struct axp_regulator_plat axp22x_regulators[] = {
+ {"dc5ldo", 0x10, BIT(0), 0x1c, 0x07, 700, 1400, 100, NA },
+ { "dcdc1", 0x10, BIT(1), 0x21, 0x1f, 1600, 3400, 100, NA },
+ { "dcdc2", 0x10, BIT(2), 0x22, 0x3f, 600, 1540, 20, NA },
+ { "dcdc3", 0x10, BIT(3), 0x23, 0x3f, 600, 1860, 20, NA },
+ { "dcdc4", 0x10, BIT(4), 0x24, 0x3f, 600, 1540, 20, NA },
+ { "dcdc5", 0x10, BIT(5), 0x25, 0x1f, 1000, 2550, 50, NA },
+ { "aldo1", 0x10, BIT(6), 0x28, 0x1f, 700, 3300, 100, NA },
+ { "aldo2", 0x10, BIT(7), 0x29, 0x1f, 700, 3300, 100, NA },
+ { "aldo3", 0x13, BIT(7), 0x2a, 0x1f, 700, 3300, 100, NA },
+ { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
+ { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 3300, 100, NA },
+ { "dldo3", 0x12, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
+ { "dldo4", 0x12, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
+ { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 3300, 100, NA },
+ { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 3300, 100, NA },
+ { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 3300, 100, NA },
+ { "dc1sw", 0x12, BIT(7), NA, NA, NA, NA, NA, NA },
+ { }
+};
+
+static const struct axp_regulator_plat axp803_regulators[] = {
+ { "dcdc1", 0x10, BIT(0), 0x20, 0x1f, 1600, 3400, 100, NA },
+ { "dcdc2", 0x10, BIT(1), 0x21, 0x7f, 500, 1300, 10, 70 },
+ { "dcdc3", 0x10, BIT(2), 0x22, 0x7f, 500, 1300, 10, 70 },
+ { "dcdc4", 0x10, BIT(3), 0x23, 0x7f, 500, 1300, 10, 70 },
+ { "dcdc5", 0x10, BIT(4), 0x24, 0x7f, 800, 1840, 10, 32 },
+ { "dcdc6", 0x10, BIT(5), 0x25, 0x7f, 600, 1520, 10, 50 },
+ { "aldo1", 0x13, BIT(5), 0x28, 0x1f, 700, 3300, 100, NA },
+ { "aldo2", 0x13, BIT(6), 0x29, 0x1f, 700, 3300, 100, NA },
+ { "aldo3", 0x13, BIT(7), 0x2a, 0x1f, 700, 3300, 100, NA },
+ { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
+ { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 4200, 100, 27 },
+ { "dldo3", 0x12, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
+ { "dldo4", 0x12, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
+ { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 1900, 50, NA },
+ { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 1900, 50, NA },
+ { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 1900, 50, NA },
+ { "fldo1", 0x13, BIT(2), 0x1c, 0x0f, 700, 1450, 50, NA },
+ { "fldo2", 0x13, BIT(3), 0x1d, 0x0f, 700, 1450, 50, NA },
+ { "dc1sw", 0x12, BIT(7), NA, NA, NA, NA, NA, NA },
+ { }
+};
+
+/*
+ * The "dcdcd" split changes the step size by a factor of 5, not 2;
+ * disallow values above the split to maintain accuracy.
+ */
+static const struct axp_regulator_plat axp806_regulators[] = {
+ { "dcdca", 0x10, BIT(0), 0x12, 0x7f, 600, 1520, 10, 50 },
+ { "dcdcb", 0x10, BIT(1), 0x13, 0x1f, 1000, 2550, 50, NA },
+ { "dcdcc", 0x10, BIT(2), 0x14, 0x7f, 600, 1520, 10, 50 },
+ { "dcdcd", 0x10, BIT(3), 0x15, 0x3f, 600, 1500, 20, NA },
+ { "dcdce", 0x10, BIT(4), 0x16, 0x1f, 1100, 3400, 100, NA },
+ { "aldo1", 0x10, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
+ { "aldo2", 0x10, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
+ { "aldo3", 0x10, BIT(7), 0x19, 0x1f, 700, 3300, 100, NA },
+ { "bldo1", 0x11, BIT(0), 0x20, 0x0f, 700, 1900, 100, NA },
+ { "bldo2", 0x11, BIT(1), 0x21, 0x0f, 700, 1900, 100, NA },
+ { "bldo3", 0x11, BIT(2), 0x22, 0x0f, 700, 1900, 100, NA },
+ { "bldo4", 0x11, BIT(3), 0x23, 0x0f, 700, 1900, 100, NA },
+ { "cldo1", 0x11, BIT(4), 0x24, 0x1f, 700, 3300, 100, NA },
+ { "cldo2", 0x11, BIT(5), 0x25, 0x1f, 700, 4200, 100, 27 },
+ { "cldo3", 0x11, BIT(6), 0x26, 0x1f, 700, 3300, 100, NA },
+ { "sw", 0x11, BIT(7), NA, NA, NA, NA, NA, NA },
+ { }
+};
+
+/*
+ * The "dcdc4" split changes the step size by a factor of 5, not 2;
+ * disallow values above the split to maintain accuracy.
+ */
+static const struct axp_regulator_plat axp809_regulators[] = {
+ {"dc5ldo", 0x10, BIT(0), 0x1c, 0x07, 700, 1400, 100, NA },
+ { "dcdc1", 0x10, BIT(1), 0x21, 0x1f, 1600, 3400, 100, NA },
+ { "dcdc2", 0x10, BIT(2), 0x22, 0x3f, 600, 1540, 20, NA },
+ { "dcdc3", 0x10, BIT(3), 0x23, 0x3f, 600, 1860, 20, NA },
+ { "dcdc4", 0x10, BIT(4), 0x24, 0x3f, 600, 1540, 20, NA },
+ { "dcdc5", 0x10, BIT(5), 0x25, 0x1f, 1000, 2550, 50, NA },
+ { "aldo1", 0x10, BIT(6), 0x28, 0x1f, 700, 3300, 100, NA },
+ { "aldo2", 0x10, BIT(7), 0x29, 0x1f, 700, 3300, 100, NA },
+ { "aldo3", 0x12, BIT(5), 0x2a, 0x1f, 700, 3300, 100, NA },
+ { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
+ { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 3300, 100, NA },
+ { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 3300, 100, NA },
+ { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 3300, 100, NA },
+ { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 3300, 100, NA },
+ { "sw", 0x12, BIT(6), NA, NA, NA, NA, NA, NA },
+ { "dc1sw", 0x12, BIT(7), NA, NA, NA, NA, NA, NA },
+ { }
+};
+
+static const struct axp_regulator_plat axp813_regulators[] = {
+ { "dcdc1", 0x10, BIT(0), 0x20, 0x1f, 1600, 3400, 100, NA },
+ { "dcdc2", 0x10, BIT(1), 0x21, 0x7f, 500, 1300, 10, 70 },
+ { "dcdc3", 0x10, BIT(2), 0x22, 0x7f, 500, 1300, 10, 70 },
+ { "dcdc4", 0x10, BIT(3), 0x23, 0x7f, 500, 1300, 10, 70 },
+ { "dcdc5", 0x10, BIT(4), 0x24, 0x7f, 800, 1840, 10, 32 },
+ { "dcdc6", 0x10, BIT(5), 0x25, 0x7f, 600, 1520, 10, 50 },
+ { "dcdc7", 0x10, BIT(6), 0x26, 0x7f, 600, 1520, 10, 50 },
+ { "aldo1", 0x13, BIT(5), 0x28, 0x1f, 700, 3300, 100, NA },
+ { "aldo2", 0x13, BIT(6), 0x29, 0x1f, 700, 3300, 100, NA },
+ { "aldo3", 0x13, BIT(7), 0x2a, 0x1f, 700, 3300, 100, NA },
+ { "dldo1", 0x12, BIT(3), 0x15, 0x1f, 700, 3300, 100, NA },
+ { "dldo2", 0x12, BIT(4), 0x16, 0x1f, 700, 4200, 100, 27 },
+ { "dldo3", 0x12, BIT(5), 0x17, 0x1f, 700, 3300, 100, NA },
+ { "dldo4", 0x12, BIT(6), 0x18, 0x1f, 700, 3300, 100, NA },
+ { "eldo1", 0x12, BIT(0), 0x19, 0x1f, 700, 1900, 50, NA },
+ { "eldo2", 0x12, BIT(1), 0x1a, 0x1f, 700, 1900, 50, NA },
+ { "eldo3", 0x12, BIT(2), 0x1b, 0x1f, 700, 1900, 50, NA },
+ { "fldo1", 0x13, BIT(2), 0x1c, 0x0f, 700, 1450, 50, NA },
+ { "fldo2", 0x13, BIT(3), 0x1d, 0x0f, 700, 1450, 50, NA },
+ { "fldo3", 0x13, BIT(4), NA, NA, NA, NA, NA, NA },
+ { }
+};
+
+static const struct axp_regulator_plat *const axp_regulators[] = {
+ [AXP152_ID] = axp152_regulators,
+ [AXP202_ID] = axp20x_regulators,
+ [AXP209_ID] = axp20x_regulators,
+ [AXP221_ID] = axp22x_regulators,
+ [AXP223_ID] = axp22x_regulators,
+ [AXP803_ID] = axp803_regulators,
+ [AXP806_ID] = axp806_regulators,
+ [AXP809_ID] = axp809_regulators,
+ [AXP813_ID] = axp813_regulators,
+};
+
+static int axp_regulator_bind(struct udevice *dev)
+{
+ struct dm_regulator_uclass_plat *uc_plat = dev_get_uclass_plat(dev);
+ ulong id = dev_get_driver_data(dev->parent);
+ const struct axp_regulator_plat *plat;
+
+ for (plat = axp_regulators[id]; plat && plat->name; plat++)
+ if (!strcmp(plat->name, dev->name))
+ break;
+ if (!plat || !plat->name)
+ return -ENODEV;
+
+ dev_set_plat(dev, (void *)plat);
+
+ if (plat->volt_reg == NA)
+ uc_plat->type = REGULATOR_TYPE_FIXED;
+ else if (!strncmp(plat->name, "dcdc", strlen("dcdc")))
+ uc_plat->type = REGULATOR_TYPE_BUCK;
+ else
+ uc_plat->type = REGULATOR_TYPE_LDO;
+
+ return 0;
+}
+
+U_BOOT_DRIVER(axp_regulator) = {
+ .name = "axp_regulator",
+ .id = UCLASS_REGULATOR,
+ .bind = axp_regulator_bind,
+ .ops = &axp_regulator_ops,
+};
diff --git a/drivers/qe/Kconfig b/drivers/qe/Kconfig
index c44a81f..89a75c1 100644
--- a/drivers/qe/Kconfig
+++ b/drivers/qe/Kconfig
@@ -27,6 +27,10 @@
depends on FMAN_ENET || QE
default SYS_QE_FMAN_FW_IN_ROM
+config SYS_QE_FMAN_FW_IN_FS
+ depends on FS_LOADER && FMAN_ENET
+ bool "Filesystem"
+
config SYS_QE_FMAN_FW_IN_NOR
bool "NOR flash"
diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c
index fb1f683..2825dc6 100644
--- a/drivers/qe/qe.c
+++ b/drivers/qe/qe.c
@@ -185,7 +185,7 @@
* which do not have ROM in QE.
*/
qe_upload_firmware((const void *)(CONFIG_SYS_QE_FW_ADDR +
- CONFIG_SYS_FSL_IFC_BASE));
+ CFG_SYS_FSL_IFC_BASE));
/* enable the microcode in IRAM */
out_be32(&qe_immr->iram.iready, QE_IRAM_READY);
@@ -234,7 +234,7 @@
if (src == BOOT_SOURCE_IFC_NOR)
addr = (void *)(CONFIG_SYS_QE_FW_ADDR +
- CONFIG_SYS_FSL_IFC_BASE);
+ CFG_SYS_FSL_IFC_BASE);
if (src == BOOT_SOURCE_QSPI_NOR)
addr = (void *)(CONFIG_SYS_QE_FW_ADDR +
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 5a39611..83948e2 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -3,7 +3,7 @@
# Copyright (c) 2015 Google, Inc
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
-obj-$(CONFIG_RAM) += ram-uclass.o
+obj-$(CONFIG_$(SPL_TPL_)DM) += ram-uclass.o
obj-$(CONFIG_MPC83XX_SDRAM) += mpc83xx_sdram.o
obj-$(CONFIG_SANDBOX) += sandbox_ram.o
obj-$(CONFIG_STM32MP1_DDR) += stm32mp1/
diff --git a/drivers/ram/aspeed/sdram_ast2600.c b/drivers/ram/aspeed/sdram_ast2600.c
index a2d7ca8..1876755 100644
--- a/drivers/ram/aspeed/sdram_ast2600.c
+++ b/drivers/ram/aspeed/sdram_ast2600.c
@@ -104,10 +104,10 @@
* -> WL = AL + CWL + PL = CWL
* -> RL = AL + CL + PL = CL
*/
-#define CONFIG_WL 9
-#define CONFIG_RL 12
-#define T_RDDATA_EN ((CONFIG_RL - 2) << 8)
-#define T_PHY_WRLAT (CONFIG_WL - 2)
+#define CFG_WL 9
+#define CFG_RL 12
+#define T_RDDATA_EN ((CFG_RL - 2) << 8)
+#define T_PHY_WRLAT (CFG_WL - 2)
/* MR0 */
#define MR0_CL_12 (BIT(4) | BIT(2))
@@ -974,8 +974,8 @@
/* update CL and WL */
reg = readl(®s->ac_timing[1]);
reg &= ~(SDRAM_WL_SETTING | SDRAM_CL_SETTING);
- reg |= FIELD_PREP(SDRAM_WL_SETTING, CONFIG_WL - 5) |
- FIELD_PREP(SDRAM_CL_SETTING, CONFIG_RL - 5);
+ reg |= FIELD_PREP(SDRAM_WL_SETTING, CFG_WL - 5) |
+ FIELD_PREP(SDRAM_CL_SETTING, CFG_RL - 5);
writel(reg, ®s->ac_timing[1]);
writel(DDR4_MR01_MODE, ®s->mr01_mode_setting);
diff --git a/drivers/ram/octeon/octeon_ddr.c b/drivers/ram/octeon/octeon_ddr.c
index bb21078..ff2899d 100644
--- a/drivers/ram/octeon/octeon_ddr.c
+++ b/drivers/ram/octeon/octeon_ddr.c
@@ -17,7 +17,7 @@
#include <mach/octeon_ddr.h>
-#define CONFIG_REF_HERTZ 50000000
+#define CFG_REF_HERTZ 50000000
DECLARE_GLOBAL_DATA_PTR;
@@ -152,7 +152,7 @@
static u32 octeon3_refclock(u32 alt_refclk, u32 ddr_hertz,
struct dimm_config *dimm_config)
{
- u32 ddr_ref_hertz = CONFIG_REF_HERTZ;
+ u32 ddr_ref_hertz = CFG_REF_HERTZ;
int ddr_type;
int spd_dimm_type;
@@ -2453,7 +2453,7 @@
} else {
if (ddr_ref_hertz == 100000000) {
debug("N0: DRAM init: requested 100 MHz refclk NOT SUPPORTED\n");
- ddr_ref_hertz = CONFIG_REF_HERTZ;
+ ddr_ref_hertz = CFG_REF_HERTZ;
}
}
@@ -2486,7 +2486,7 @@
if (hertz_diff > ((int)ddr_hertz * 5 / 100)) {
// nope, diff is greater than than 5%
debug("N0: DRAM init: requested 100 MHz refclk NOT FOUND\n");
- ddr_ref_hertz = CONFIG_REF_HERTZ;
+ ddr_ref_hertz = CFG_REF_HERTZ;
// clear the flag before trying again!!
set_ddr_clock_initialized(priv, 0, 0);
goto try_again;
diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig
index c29d5e8..67c63ec 100644
--- a/drivers/ram/rockchip/Kconfig
+++ b/drivers/ram/rockchip/Kconfig
@@ -11,9 +11,10 @@
help
This enable sdram common driver
+if RAM_ROCKCHIP
+
config RAM_ROCKCHIP_DEBUG
bool "Rockchip ram drivers debugging"
- depends on RAM_ROCKCHIP
default y
help
This enables debugging ram driver API's for the platforms
@@ -22,31 +23,28 @@
This is an option for developers to understand the ram drivers
initialization, configurations and etc.
-config RAM_PX30_DDR4
- bool "DDR4 support for Rockchip PX30"
- depends on RAM_ROCKCHIP && ROCKCHIP_PX30
+config RAM_ROCKCHIP_DDR4
+ bool "DDR4 support for Rockchip SoCs"
help
This enables DDR4 sdram support instead of the default DDR3 support
- on Rockchip PC30 SoCs.
+ on Rockchip SoCs.
-config RAM_PX30_LPDDR2
- bool "LPDDR2 support for Rockchip PX30"
- depends on RAM_ROCKCHIP && ROCKCHIP_PX30
+config RAM_ROCKCHIP_LPDDR2
+ bool "LPDDR2 support for Rockchip SoCs"
help
This enables LPDDR2 sdram support instead of the default DDR3 support
- on Rockchip PC30 SoCs.
+ on Rockchip SoCs.
-config RAM_PX30_LPDDR3
- bool "LPDDR3 support for Rockchip PX30"
- depends on RAM_ROCKCHIP && ROCKCHIP_PX30
+config RAM_ROCKCHIP_LPDDR3
+ bool "LPDDR3 support for Rockchip SoCs"
help
This enables LPDDR3 sdram support instead of the default DDR3 support
- on Rockchip PC30 SoCs.
+ on Rockchip SoCs.
-config RAM_RK3399_LPDDR4
- bool "LPDDR4 support for Rockchip RK3399"
- depends on RAM_ROCKCHIP && ROCKCHIP_RK3399
+config RAM_ROCKCHIP_LPDDR4
+ bool "LPDDR4 support for Rockchip SoCs"
help
This enables LPDDR4 sdram code support for the platforms based
- on Rockchip RK3399 SoC.
+ on Rockchip SoCs.
+endif # RAM_ROCKCHIP
diff --git a/drivers/ram/rockchip/Makefile b/drivers/ram/rockchip/Makefile
index 6d530c2..98839ad 100644
--- a/drivers/ram/rockchip/Makefile
+++ b/drivers/ram/rockchip/Makefile
@@ -14,4 +14,5 @@
obj-$(CONFIG_ROCKCHIP_RK3328) = sdram_rk3328.o sdram_pctl_px30.o sdram_phy_px30.o
obj-$(CONFIG_ROCKCHIP_RK3399) += sdram_rk3399.o
obj-$(CONFIG_ROCKCHIP_RK3568) += sdram_rk3568.o
+obj-$(CONFIG_ROCKCHIP_RV1126) += sdram_rv1126.o sdram_pctl_px30.o
obj-$(CONFIG_ROCKCHIP_SDRAM_COMMON) += sdram_common.o
diff --git a/drivers/ram/rockchip/dmc-rk3368.c b/drivers/ram/rockchip/dmc-rk3368.c
index 6929a7e..dd5b191 100644
--- a/drivers/ram/rockchip/dmc-rk3368.c
+++ b/drivers/ram/rockchip/dmc-rk3368.c
@@ -109,7 +109,7 @@
PCTL_STAT_MSK = 7,
INIT_MEM = 0,
CONFIG,
- CONFIG_REQ,
+ CFG_REQ,
ACCESS,
ACCESS_REQ,
LOW_POWER,
diff --git a/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-1056.inc b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-1056.inc
new file mode 100644
index 0000000..4cde215
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-1056.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x0,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0
+ },
+ {
+ {0x351b1019},
+ {0x12030903},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 1056, /* clock rate(MHz) */
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x43042001}, /* MSTR */
+ {0x00000064, 0x008000b9}, /* RFSHTMG */
+ {0x000000d0, 0x00020103}, /* INIT0 */
+ {0x000000d4, 0x00690000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x01240040}, /* INIT3 */
+ {0x000000e0, 0x00280000}, /* INIT4 */
+ {0x000000e4, 0x000c0000}, /* INIT5 */
+ {0x000000f4, 0x000f011f}, /* RANKCTL */
+ {0x00000100, 0x0f132414}, /* DRAMTMG0 */
+ {0x00000104, 0x000d0419}, /* DRAMTMG1 */
+ {0x00000108, 0x0507050b}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202008}, /* DRAMTMG3 */
+ {0x00000110, 0x07020408}, /* DRAMTMG4 */
+ {0x00000114, 0x06060404}, /* DRAMTMG5 */
+ {0x00000120, 0x00000907}, /* DRAMTMG8 */
+ {0x00000180, 0x00a9002b}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07050003}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x06000610}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008a}, /* PHYREG01 */
+ {0x00000014, 0x0000000e}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x0000000a}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-328.inc b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-328.inc
new file mode 100644
index 0000000..eef61ab
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-328.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x0,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0
+ },
+ {
+ {0x270a0509},
+ {0x08020401},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 328, /* clock rate(MHz) */
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0
+ },
+ {
+ {
+ {0x00000000, 0x43042001}, /* MSTR */
+ {0x00000064, 0x0027003a}, /* RFSHTMG */
+ {0x000000d0, 0x00020052}, /* INIT0 */
+ {0x000000d4, 0x00220000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x03100000}, /* INIT3 */
+ {0x000000e0, 0x00000000}, /* INIT4 */
+ {0x000000e4, 0x00090000}, /* INIT5 */
+ {0x000000f4, 0x000f011f}, /* RANKCTL */
+ {0x00000100, 0x07090b06}, /* DRAMTMG0 */
+ {0x00000104, 0x00050209}, /* DRAMTMG1 */
+ {0x00000108, 0x03030307}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202006}, /* DRAMTMG3 */
+ {0x00000110, 0x03020203}, /* DRAMTMG4 */
+ {0x00000114, 0x03030202}, /* DRAMTMG5 */
+ {0x00000120, 0x00000903}, /* DRAMTMG8 */
+ {0x00000180, 0x00800020}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07010001}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x06000600}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008a}, /* PHYREG01 */
+ {0x00000014, 0x00000005}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000005}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-396.inc b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-396.inc
new file mode 100644
index 0000000..39a8271
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-396.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x0,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0
+ },
+ {
+ {0x290b060a},
+ {0x0a020401},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 396, /* clock rate(MHz) */
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0
+ },
+ {
+ {
+ {0x00000000, 0x43042001}, /* MSTR */
+ {0x00000064, 0x00300046}, /* RFSHTMG */
+ {0x000000d0, 0x00020062}, /* INIT0 */
+ {0x000000d4, 0x00280000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x05200000}, /* INIT3 */
+ {0x000000e0, 0x00000000}, /* INIT4 */
+ {0x000000e4, 0x00090000}, /* INIT5 */
+ {0x000000f4, 0x000f011f}, /* RANKCTL */
+ {0x00000100, 0x070a0d07}, /* DRAMTMG0 */
+ {0x00000104, 0x0005020b}, /* DRAMTMG1 */
+ {0x00000108, 0x03030407}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202006}, /* DRAMTMG3 */
+ {0x00000110, 0x03020204}, /* DRAMTMG4 */
+ {0x00000114, 0x03030202}, /* DRAMTMG5 */
+ {0x00000120, 0x00000904}, /* DRAMTMG8 */
+ {0x00000180, 0x00800020}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07010001}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x06000604}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008a}, /* PHYREG01 */
+ {0x00000014, 0x00000006}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000005}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-528.inc b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-528.inc
new file mode 100644
index 0000000..9dbbb1a
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-528.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x0,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0
+ },
+ {
+ {0x2c0f080e},
+ {0x0d030502},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 528, /* clock rate(MHz) */
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0
+ },
+ {
+ {
+ {0x00000000, 0x43042001}, /* MSTR */
+ {0x00000064, 0x0040005d}, /* RFSHTMG */
+ {0x000000d0, 0x00020082}, /* INIT0 */
+ {0x000000d4, 0x00350000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x09400000}, /* INIT3 */
+ {0x000000e0, 0x00080000}, /* INIT4 */
+ {0x000000e4, 0x00090000}, /* INIT5 */
+ {0x000000f4, 0x000f011f}, /* RANKCTL */
+ {0x00000100, 0x090e120a}, /* DRAMTMG0 */
+ {0x00000104, 0x0007020e}, /* DRAMTMG1 */
+ {0x00000108, 0x03040407}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202006}, /* DRAMTMG3 */
+ {0x00000110, 0x04020305}, /* DRAMTMG4 */
+ {0x00000114, 0x03030302}, /* DRAMTMG5 */
+ {0x00000120, 0x00000904}, /* DRAMTMG8 */
+ {0x00000180, 0x00800020}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07020001}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x06000608}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008a}, /* PHYREG01 */
+ {0x00000014, 0x00000008}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000006}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-664.inc b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-664.inc
new file mode 100644
index 0000000..2b57132
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-664.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x0,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0
+ },
+ {
+ {0x2f120a11},
+ {0x0f020602},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 664, /* clock rate(MHz) */
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x43042001}, /* MSTR */
+ {0x00000064, 0x00500075}, /* RFSHTMG */
+ {0x000000d0, 0x000200a4}, /* INIT0 */
+ {0x000000d4, 0x00420000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x0b600040}, /* INIT3 */
+ {0x000000e0, 0x00100000}, /* INIT4 */
+ {0x000000e4, 0x00090000}, /* INIT5 */
+ {0x000000f4, 0x000f011f}, /* RANKCTL */
+ {0x00000100, 0x0a0f160c}, /* DRAMTMG0 */
+ {0x00000104, 0x00080211}, /* DRAMTMG1 */
+ {0x00000108, 0x04050508}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202006}, /* DRAMTMG3 */
+ {0x00000110, 0x05020306}, /* DRAMTMG4 */
+ {0x00000114, 0x04040302}, /* DRAMTMG5 */
+ {0x00000120, 0x00000905}, /* DRAMTMG8 */
+ {0x00000180, 0x00800020}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07030002}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0600060c}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008a}, /* PHYREG01 */
+ {0x00000014, 0x0000000a}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000007}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-784.inc b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-784.inc
new file mode 100644
index 0000000..8ad2272
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-784.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x0,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0
+ },
+ {
+ {0x30150c13},
+ {0x10030702},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 784, /* clock rate(MHz) */
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x43042001}, /* MSTR */
+ {0x00000064, 0x005f008a}, /* RFSHTMG */
+ {0x000000d0, 0x000200c1}, /* INIT0 */
+ {0x000000d4, 0x004e0000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x0d700040}, /* INIT3 */
+ {0x000000e0, 0x00180000}, /* INIT4 */
+ {0x000000e4, 0x00090000}, /* INIT5 */
+ {0x000000f4, 0x000f011f}, /* RANKCTL */
+ {0x00000100, 0x0c101a0f}, /* DRAMTMG0 */
+ {0x00000104, 0x000a0314}, /* DRAMTMG1 */
+ {0x00000108, 0x04060509}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202006}, /* DRAMTMG3 */
+ {0x00000110, 0x06020306}, /* DRAMTMG4 */
+ {0x00000114, 0x04040303}, /* DRAMTMG5 */
+ {0x00000120, 0x00000906}, /* DRAMTMG8 */
+ {0x00000180, 0x00800020}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07040002}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0600060c}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008a}, /* PHYREG01 */
+ {0x00000014, 0x0000000b}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000008}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-924.inc b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-924.inc
new file mode 100644
index 0000000..4cc36b0
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-ddr3-detect-924.inc
@@ -0,0 +1,72 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xC,
+ .bk = 0x3,
+ .bw = 0x0,
+ .dbw = 0x0,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x10,
+ .cs1_row = 0x10,
+ .cs0_high16bit_row = 0x10,
+ .cs1_high16bit_row = 0x10,
+ .ddrconfig = 0
+ },
+ {
+ {0x33180e16},
+ {0x10030803},
+ {0x00000002},
+ {0x00001111},
+ {0x0000000c},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 924, /* clock rate(MHz) */
+ .dramtype = DDR3,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x43042001}, /* MSTR */
+ {0x00000064, 0x007000a2}, /* RFSHTMG */
+ {0x000000d0, 0x000200e3}, /* INIT0 */
+ {0x000000d4, 0x005c0000}, /* INIT1 */
+ {0x000000d8, 0x00000100}, /* INIT2 */
+ {0x000000dc, 0x0f140040}, /* INIT3 */
+ {0x000000e0, 0x00200000}, /* INIT4 */
+ {0x000000e4, 0x000b0000}, /* INIT5 */
+ {0x000000f4, 0x000f011f}, /* RANKCTL */
+ {0x00000100, 0x0d111f11}, /* DRAMTMG0 */
+ {0x00000104, 0x000c0317}, /* DRAMTMG1 */
+ {0x00000108, 0x0507050a}, /* DRAMTMG2 */
+ {0x0000010c, 0x00202007}, /* DRAMTMG3 */
+ {0x00000110, 0x07020307}, /* DRAMTMG4 */
+ {0x00000114, 0x05050403}, /* DRAMTMG5 */
+ {0x00000120, 0x00000907}, /* DRAMTMG8 */
+ {0x00000180, 0x00940025}, /* ZQCTL0 */
+ {0x00000184, 0x00000000}, /* ZQCTL1 */
+ {0x00000190, 0x07050003}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x06000610}, /* ODTCFG */
+ {0x00000244, 0x00000201}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008a}, /* PHYREG01 */
+ {0x00000014, 0x0000000d}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000009}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-loader_params.inc b/drivers/ram/rockchip/sdram-rv1126-loader_params.inc
new file mode 100644
index 0000000..a4c9e7f
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-loader_params.inc
@@ -0,0 +1,197 @@
+0x12345678,
+2,/* version */
+(0 << 0) | (1 << 8) | (9 << 16) | (8 << 24),/* cpu_gen,global index */
+(0 << 0) | (9 << 8) | (17 << 16) | (9 << 24),/* d2,d3 index */
+(26 << 0) | (9 << 8) | (0 << 16) | (0 << 24),/* d4,d5 index */
+(0 << 0) | (9 << 8) | (35 << 16) | (9 << 24),/* lp2,lp3 index */
+(44 << 0) | (13 << 8) | (0 << 16) | (0 << 24),/* lp4,lp5 index */
+(0 << 0) | (0 << 8) | (57 << 16) | (8 << 24),/* skew index, dq_map index */
+(65 << 0) | (13 << 8) | (0 << 16) | (0 << 24), /*lp4x index*/
+/* global info */
+0,
+(93 << 16) | 13,/* sr_idle << 16 | pd_idle */
+0,/* channel info */
+1,/* 2t info */
+0, 0, 0, 0,/* reserved */
+
+/* ddr3 */
+(924 << DDR_FREQ_F0_SHIFT) | (328 << DDR_FREQ_F1_SHIFT),
+(528 << DDR_FREQ_F2_SHIFT) | (784 << DDR_FREQ_F3_SHIFT),
+(0 << DDR_FREQ_F4_SHIFT) | (0 << DDR_FREQ_F5_SHIFT),
+/* drv when odt on */
+(30 << PHY_DQ_DRV_SHIFT) | (41 << PHY_CA_DRV_SHIFT) |
+ (38 << PHY_CLK_DRV_SHIFT) | (34 << DRAM_DQ_DRV_SHIFT),
+/* drv when odt off */
+(30 << PHY_DQ_DRV_SHIFT) | (30 << PHY_CA_DRV_SHIFT) |
+ (38 << PHY_CLK_DRV_SHIFT) | (34 << DRAM_DQ_DRV_SHIFT),
+/* odt info */
+(120 << DRAM_ODT_SHIFT) | (141 << PHY_ODT_SHIFT) |
+ (1 << PHY_ODT_PUUP_EN_SHIFT) |
+ (0 << PHY_ODT_PUDN_EN_SHIFT),
+/* odt enable freq */
+(333 << DRAM_ODT_EN_FREQ_SHIFT) | (333 << PHY_ODT_EN_FREQ_SHIFT),
+/* slew rate when odt enable */
+(0x1f << PHY_DQ_SR_SHIFT) | (0x1f << PHY_CA_SR_SHIFT) |
+ (0x1f << PHY_CLK_SR_SHIFT),
+/* slew ratee when odt disable */
+(0x1f << PHY_DQ_SR_SHIFT) | (0x1f << PHY_CA_SR_SHIFT) |
+ (0x1f << PHY_CLK_SR_SHIFT),
+
+/* ddr4 */
+(924 << DDR_FREQ_F0_SHIFT) | (328 << DDR_FREQ_F1_SHIFT),
+(528 << DDR_FREQ_F2_SHIFT) | (784 << DDR_FREQ_F3_SHIFT),
+(0 << DDR_FREQ_F4_SHIFT) | (0 << DDR_FREQ_F5_SHIFT),
+/* drv when odt on */
+(37 << PHY_DQ_DRV_SHIFT) | (44 << PHY_CA_DRV_SHIFT) |
+ (37 << PHY_CLK_DRV_SHIFT) | (34 << DRAM_DQ_DRV_SHIFT),
+/* drv when odt off */
+(37 << PHY_DQ_DRV_SHIFT) | (44 << PHY_CA_DRV_SHIFT) |
+ (37 << PHY_CLK_DRV_SHIFT) | (34 << DRAM_DQ_DRV_SHIFT),
+/* odt info */
+(120 << DRAM_ODT_SHIFT) | (148 << PHY_ODT_SHIFT) |
+ (1 << PHY_ODT_PUUP_EN_SHIFT) | (1 << PHY_ODT_PUDN_EN_SHIFT),
+/* odt enable freq */
+(625 << DRAM_ODT_EN_FREQ_SHIFT) | (625 << PHY_ODT_EN_FREQ_SHIFT),
+/* slew rate when odt enable */
+(0xe << PHY_DQ_SR_SHIFT) | (0x3 << PHY_CA_SR_SHIFT) |
+ (0x3 << PHY_CLK_SR_SHIFT),
+/* slew ratee when odt disable */
+(0xe << PHY_DQ_SR_SHIFT) | (0x3 << PHY_CA_SR_SHIFT) |
+ (0x3 << PHY_CLK_SR_SHIFT),
+
+/* lpddr3 */
+(924 << DDR_FREQ_F0_SHIFT) | (328 << DDR_FREQ_F1_SHIFT),
+(528 << DDR_FREQ_F2_SHIFT) | (784 << DDR_FREQ_F3_SHIFT),
+(0 << DDR_FREQ_F4_SHIFT) | (0 << DDR_FREQ_F5_SHIFT),
+/* drv when odt on */
+(28 << PHY_DQ_DRV_SHIFT) | (37 << PHY_CA_DRV_SHIFT) |
+ (34 << PHY_CLK_DRV_SHIFT) | (34 << DRAM_DQ_DRV_SHIFT),
+/* drv when odt off */
+(28 << PHY_DQ_DRV_SHIFT) | (37 << PHY_CA_DRV_SHIFT) |
+ (34 << PHY_CLK_DRV_SHIFT) | (34 << DRAM_DQ_DRV_SHIFT),
+/* odt info */
+(120 << DRAM_ODT_SHIFT) | (148 << PHY_ODT_SHIFT) |
+ (1 << PHY_ODT_PUUP_EN_SHIFT) | (1 << PHY_ODT_PUDN_EN_SHIFT),
+/* odt enable freq */
+(333 << DRAM_ODT_EN_FREQ_SHIFT) | (333 << PHY_ODT_EN_FREQ_SHIFT),
+
+/* slew rate when odt enable */
+(0xe << PHY_DQ_SR_SHIFT) | (0x0 << PHY_CA_SR_SHIFT) |
+ (0x0 << PHY_CLK_SR_SHIFT),
+/* slew ratee when odt disable */
+(0xe << PHY_DQ_SR_SHIFT) | (0x0 << PHY_CA_SR_SHIFT) |
+ (0x0 << PHY_CLK_SR_SHIFT),
+
+/* lpddr4 */
+(924 << DDR_FREQ_F0_SHIFT) | (328 << DDR_FREQ_F1_SHIFT),
+(528 << DDR_FREQ_F2_SHIFT) | (784 << DDR_FREQ_F3_SHIFT),
+(0 << DDR_FREQ_F4_SHIFT) | (0 << DDR_FREQ_F5_SHIFT),
+
+/* drv when odt on */
+(38 << PHY_DQ_DRV_SHIFT) | (46 << PHY_CA_DRV_SHIFT) |
+ (38 << PHY_CLK_DRV_SHIFT) | (40 << DRAM_DQ_DRV_SHIFT),
+/* drv when odt off */
+(38 << PHY_DQ_DRV_SHIFT) | (46 << PHY_CA_DRV_SHIFT) |
+ (38 << PHY_CLK_DRV_SHIFT) | (40 << DRAM_DQ_DRV_SHIFT),
+/* odt info and PU-cal info */
+(240 << DRAM_ODT_SHIFT) | (80 << PHY_ODT_SHIFT) |
+ (0 << LP4_CA_ODT_SHIFT) |
+ (LPDDR4_VDDQ_2_5 << LP4_DRV_PU_CAL_ODTEN_SHIFT) |
+ (LPDDR4_VDDQ_2_5 << LP4_DRV_PU_CAL_ODTOFF_SHIFT) |
+ (0 << PHY_LP4_DRV_PULLDOWN_EN_ODTEN_SHIFT) |
+ (0 << PHY_LP4_DRV_PULLDOWN_EN_ODTOFF_SHIFT),
+/* odt enable freq */
+(333 << PHY_LP4_ODT_EN_FREQ_SHIFT) | (333 << LP4_DQ_ODT_EN_FREQ_SHIFT),
+/* slew rate when odt enable */
+(0xf << PHY_DQ_SR_SHIFT) | (0xf << PHY_CA_SR_SHIFT) |
+ (0xf << PHY_CLK_SR_SHIFT),
+/* slew ratee when odt disable */
+(0xf << PHY_DQ_SR_SHIFT) | (0xf << PHY_CA_SR_SHIFT) |
+ (0xf << PHY_CLK_SR_SHIFT),
+/* ca odt en freq */
+(333 << LP4_CA_ODT_EN_FREQ_SHIFT),
+/* cs drv info and ca odt info */
+(0 << PHY_LP4_CS_DRV_ODTEN_SHIFT) |
+ (0 << PHY_LP4_CS_DRV_ODTOFF_SHIFT) |
+ (0 << LP4_ODTE_CK_SHIFT) | (0 << LP4_ODTE_CS_EN_SHIFT) |
+ (0 << LP4_ODTD_CA_EN_SHIFT),
+/* vref info when odt enable */
+(200 << PHY_LP4_DQ_VREF_SHIFT) | (420 << LP4_DQ_VREF_SHIFT) |
+ (420 << LP4_CA_VREF_SHIFT),
+/* vref info when odt disable */
+(420 << PHY_LP4_DQ_VREF_SHIFT) | (420 << LP4_DQ_VREF_SHIFT) |
+ (420 << LP4_CA_VREF_SHIFT),
+/* ddr4 map << 0 | ddr3 map << 24 */
+((0x2 << 6) | (0x1 << 4) | (0x3 << 2) | (0x0 << 0)) |
+ (0 << 8) | (0 << 16) |
+ (((0x2 << 6) | (0x1 << 4) | (0x3 << 2) | (0x0 << 0)) << 24),
+/* lp3 map << 16 | lp4 map << 24 */
+/* lp4 should equal to 0xc9 */
+(((0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0)) << 16) |
+ (((0x3 << 6) | (0x0 << 4) | (0x2 << 2) | (0x1 << 0)) << 24),
+/* lp3 dq0-7 map */
+(2 << 0) | (6 << 4) | (4 << 8) | (0 << 12) | (3 << 16) | (7 << 20) |
+ ( 5 << 24) | (1 << 28),
+/* lp2 dq0-7 map */
+0,
+/* ddr4 dq map */
+/* cs0 dq0-15 */
+ ((2 << 0 | 0 << 2 | 3 << 4 | 1 << 6) << 0) |
+ ((0 << 0 | 2 << 2 | 3 << 4 | 1 << 6) << 8) |
+ ((2 << 0 | 2 << 2 | 1 << 4 | 3 << 6) << 16) |
+ ((1 << 0 | 3 << 2 | 0 << 4 | 0 << 6) << 24),
+/* cs0 dq16-31 */
+ ((2 << 0 | 0 << 2 | 2 << 4 | 0 << 6) << 0) |
+ ((1 << 0 | 3 << 2 | 3 << 4 | 1 << 6) << 8) |
+ ((0 << 0 | 0 << 2 | 1 << 4 | 3 << 6) << 16) |
+ ((1 << 0 | 3 << 2 | 2 << 4 | 2 << 6) << 24),
+/* cs1 dq0-15 */
+ ((2 << 0 | 0 << 2 | 3 << 4 | 1 << 6) << 0) |
+ ((0 << 0 | 2 << 2 | 3 << 4 | 1 << 6) << 8) |
+ ((2 << 0 | 2 << 2 | 1 << 4 | 3 << 6) << 16) |
+ ((1 << 0 | 3 << 2 | 0 << 4 | 0 << 6) << 24),
+/* cs1 dq16-31 */
+ ((2 << 0 | 0 << 2 | 2 << 4 | 0 << 6) << 0) |
+ ((1 << 0 | 3 << 2 | 3 << 4 | 1 << 6) << 8) |
+ ((0 << 0 | 0 << 2 | 1 << 4 | 3 << 6) << 16) |
+ ((1 << 0 | 3 << 2 | 2 << 4 | 2 << 6) << 24),
+
+/* lpddr4x */
+(1056 << DDR_FREQ_F0_SHIFT) | (328 << DDR_FREQ_F1_SHIFT),
+(528 << DDR_FREQ_F2_SHIFT) | (784 << DDR_FREQ_F3_SHIFT),
+(0 << DDR_FREQ_F4_SHIFT) | (0 << DDR_FREQ_F5_SHIFT),
+
+/* drv when odt on */
+(38 << PHY_DQ_DRV_SHIFT) | (38 << PHY_CA_DRV_SHIFT) |
+ (38 << PHY_CLK_DRV_SHIFT) | (40 << DRAM_DQ_DRV_SHIFT),
+/* drv when odt off */
+(38 << PHY_DQ_DRV_SHIFT) | (38 << PHY_CA_DRV_SHIFT) |
+ (38 << PHY_CLK_DRV_SHIFT) | (40 << DRAM_DQ_DRV_SHIFT),
+/* odt info and PU-cal info */
+(48 << DRAM_ODT_SHIFT) | (60 << PHY_ODT_SHIFT) |
+ (120 << LP4_CA_ODT_SHIFT) |
+ (LPDDR4X_VDDQ_0_6 << LP4_DRV_PU_CAL_ODTEN_SHIFT) |
+ (LPDDR4X_VDDQ_0_6 << LP4_DRV_PU_CAL_ODTOFF_SHIFT) |
+ (0 << PHY_LP4_DRV_PULLDOWN_EN_ODTEN_SHIFT) |
+ (0 << PHY_LP4_DRV_PULLDOWN_EN_ODTOFF_SHIFT),
+/* odt enable freq */
+(0 << PHY_LP4_ODT_EN_FREQ_SHIFT) | (0 << LP4_DQ_ODT_EN_FREQ_SHIFT),
+/* slew rate when odt enable */
+(0xf << PHY_DQ_SR_SHIFT) | (0xf << PHY_CA_SR_SHIFT) |
+ (0xf << PHY_CLK_SR_SHIFT),
+/* slew ratee when odt disable */
+(0xf << PHY_DQ_SR_SHIFT) | (0xf << PHY_CA_SR_SHIFT) |
+ (0xf << PHY_CLK_SR_SHIFT),
+/* ca odt en freq */
+(333 << LP4_CA_ODT_EN_FREQ_SHIFT),
+/* cs drv info and ca odt info */
+(0 << PHY_LP4_CS_DRV_ODTEN_SHIFT) |
+ (0 << PHY_LP4_CS_DRV_ODTOFF_SHIFT) |
+ (0 << LP4_ODTE_CK_SHIFT) | (0 << LP4_ODTE_CS_EN_SHIFT) |
+ (0 << LP4_ODTD_CA_EN_SHIFT),
+/* vref info when odt enable, phy vddq=1.1V, lp4x vddq=0.6V */
+(153 << PHY_LP4_DQ_VREF_SHIFT) | (515 << LP4_DQ_VREF_SHIFT) |
+ (629 << LP4_CA_VREF_SHIFT),
+/* vref info when odt disable */
+(153 << PHY_LP4_DQ_VREF_SHIFT) | (629 << LP4_DQ_VREF_SHIFT) |
+ (629 << LP4_CA_VREF_SHIFT),
diff --git a/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-1056.inc b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-1056.inc
new file mode 100644
index 0000000..705cbfb
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-1056.inc
@@ -0,0 +1,78 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xB,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x1,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x11,
+ .cs0_high16bit_row = 0x0,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0
+ },
+ {
+ {0x41241522},
+ {0x15050b07},
+ {0x00000602},
+ {0x00001111},
+ {0x00000054},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 1056, /* clock rate(MHz) */
+ .dramtype = LPDDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x81081020}, /* MSTR */
+ {0x00000064, 0x00400094}, /* RFSHTMG */
+ {0x000000d0, 0x00030409}, /* INIT0 */
+ {0x000000d4, 0x00690000}, /* INIT1 */
+ {0x000000d8, 0x00000206}, /* INIT2 */
+ {0x000000dc, 0x0034001b}, /* INIT3 */
+ {0x000000e0, 0x00310000}, /* INIT4 */
+ {0x000000e8, 0x00110000}, /* INIT6 */
+ {0x000000ec, 0x00000000}, /* INIT7 */
+ {0x000000f4, 0x000f033f}, /* RANKCTL */
+ {0x00000100, 0x14161217}, /* DRAMTMG0 */
+ {0x00000104, 0x00040422}, /* DRAMTMG1 */
+ {0x00000108, 0x050a0e0f}, /* DRAMTMG2 */
+ {0x0000010c, 0x00808000}, /* DRAMTMG3 */
+ {0x00000110, 0x0a04060c}, /* DRAMTMG4 */
+ {0x00000114, 0x02040808}, /* DRAMTMG5 */
+ {0x00000118, 0x01010005}, /* DRAMTMG6 */
+ {0x0000011c, 0x00000401}, /* DRAMTMG7 */
+ {0x00000120, 0x00000606}, /* DRAMTMG8 */
+ {0x00000130, 0x00020000}, /* DRAMTMG12 */
+ {0x00000134, 0x0a100002}, /* DRAMTMG13 */
+ {0x00000138, 0x00000098}, /* DRAMTMG14 */
+ {0x00000180, 0x02100010}, /* ZQCTL0 */
+ {0x00000184, 0x01b00000}, /* ZQCTL1 */
+ {0x00000190, 0x07070001}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0b050d3c}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008d}, /* PHYREG01 */
+ {0x00000014, 0x00000014}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x0000000a}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-328.inc b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-328.inc
new file mode 100644
index 0000000..3864b00
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-328.inc
@@ -0,0 +1,78 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xB,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x1,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x11,
+ .cs0_high16bit_row = 0x0,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0
+ },
+ {
+ {0x2f0d060a},
+ {0x07020804},
+ {0x00000602},
+ {0x00001111},
+ {0x00000054},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 328, /* clock rate(MHz) */
+ .dramtype = LPDDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0
+ },
+ {
+ {
+ {0x00000000, 0x81081020}, /* MSTR */
+ {0x00000064, 0x0014002e}, /* RFSHTMG */
+ {0x000000d0, 0x00020142}, /* INIT0 */
+ {0x000000d4, 0x00220000}, /* INIT1 */
+ {0x000000d8, 0x00000202}, /* INIT2 */
+ {0x000000dc, 0x00240012}, /* INIT3 */
+ {0x000000e0, 0x00310000}, /* INIT4 */
+ {0x000000e8, 0x00100000}, /* INIT6 */
+ {0x000000ec, 0x00000000}, /* INIT7 */
+ {0x000000f4, 0x000f033f}, /* RANKCTL */
+ {0x00000100, 0x0c070507}, /* DRAMTMG0 */
+ {0x00000104, 0x0003040b}, /* DRAMTMG1 */
+ {0x00000108, 0x04070c0d}, /* DRAMTMG2 */
+ {0x0000010c, 0x00505000}, /* DRAMTMG3 */
+ {0x00000110, 0x03040204}, /* DRAMTMG4 */
+ {0x00000114, 0x02030303}, /* DRAMTMG5 */
+ {0x00000118, 0x01010004}, /* DRAMTMG6 */
+ {0x0000011c, 0x00000301}, /* DRAMTMG7 */
+ {0x00000120, 0x00000303}, /* DRAMTMG8 */
+ {0x00000130, 0x00020000}, /* DRAMTMG12 */
+ {0x00000134, 0x00100002}, /* DRAMTMG13 */
+ {0x00000138, 0x00000030}, /* DRAMTMG14 */
+ {0x00000180, 0x00a40005}, /* ZQCTL0 */
+ {0x00000184, 0x00900000}, /* ZQCTL1 */
+ {0x00000190, 0x07040000}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0905092c}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008d}, /* PHYREG01 */
+ {0x00000014, 0x0000000e}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000008}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-396.inc b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-396.inc
new file mode 100644
index 0000000..9018c3a
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-396.inc
@@ -0,0 +1,78 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xB,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x1,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x11,
+ .cs0_high16bit_row = 0x0,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0
+ },
+ {
+ {0x3110080d},
+ {0x08020804},
+ {0x00000602},
+ {0x00001111},
+ {0x00000054},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 396, /* clock rate(MHz) */
+ .dramtype = LPDDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0
+ },
+ {
+ {
+ {0x00000000, 0x81081020}, /* MSTR */
+ {0x00000064, 0x00180038}, /* RFSHTMG */
+ {0x000000d0, 0x00020184}, /* INIT0 */
+ {0x000000d4, 0x00280000}, /* INIT1 */
+ {0x000000d8, 0x00000202}, /* INIT2 */
+ {0x000000dc, 0x00240012}, /* INIT3 */
+ {0x000000e0, 0x00310000}, /* INIT4 */
+ {0x000000e8, 0x00100000}, /* INIT6 */
+ {0x000000ec, 0x00000000}, /* INIT7 */
+ {0x000000f4, 0x000f033f}, /* RANKCTL */
+ {0x00000100, 0x0d080609}, /* DRAMTMG0 */
+ {0x00000104, 0x0003040d}, /* DRAMTMG1 */
+ {0x00000108, 0x04070c0d}, /* DRAMTMG2 */
+ {0x0000010c, 0x00505000}, /* DRAMTMG3 */
+ {0x00000110, 0x04040205}, /* DRAMTMG4 */
+ {0x00000114, 0x02030303}, /* DRAMTMG5 */
+ {0x00000118, 0x01010004}, /* DRAMTMG6 */
+ {0x0000011c, 0x00000301}, /* DRAMTMG7 */
+ {0x00000120, 0x00000303}, /* DRAMTMG8 */
+ {0x00000130, 0x00020000}, /* DRAMTMG12 */
+ {0x00000134, 0x00100002}, /* DRAMTMG13 */
+ {0x00000138, 0x00000039}, /* DRAMTMG14 */
+ {0x00000180, 0x00c60006}, /* ZQCTL0 */
+ {0x00000184, 0x00a00000}, /* ZQCTL1 */
+ {0x00000190, 0x07040000}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0905092c}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008d}, /* PHYREG01 */
+ {0x00000014, 0x0000000e}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000008}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-528.inc b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-528.inc
new file mode 100644
index 0000000..8c8e14c
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-528.inc
@@ -0,0 +1,78 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xB,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x1,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x11,
+ .cs0_high16bit_row = 0x0,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0
+ },
+ {
+ {0x34140b11},
+ {0x0b030804},
+ {0x00000602},
+ {0x00001111},
+ {0x00000054},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 528, /* clock rate(MHz) */
+ .dramtype = LPDDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 0
+ },
+ {
+ {
+ {0x00000000, 0x81081020}, /* MSTR */
+ {0x00000064, 0x0020004a}, /* RFSHTMG */
+ {0x000000d0, 0x00020205}, /* INIT0 */
+ {0x000000d4, 0x00350000}, /* INIT1 */
+ {0x000000d8, 0x00000203}, /* INIT2 */
+ {0x000000dc, 0x00240012}, /* INIT3 */
+ {0x000000e0, 0x00310000}, /* INIT4 */
+ {0x000000e8, 0x00100000}, /* INIT6 */
+ {0x000000ec, 0x00000000}, /* INIT7 */
+ {0x000000f4, 0x000f033f}, /* RANKCTL */
+ {0x00000100, 0x0e0b090c}, /* DRAMTMG0 */
+ {0x00000104, 0x00030412}, /* DRAMTMG1 */
+ {0x00000108, 0x04070c0d}, /* DRAMTMG2 */
+ {0x0000010c, 0x00505000}, /* DRAMTMG3 */
+ {0x00000110, 0x05040306}, /* DRAMTMG4 */
+ {0x00000114, 0x02030404}, /* DRAMTMG5 */
+ {0x00000118, 0x01010004}, /* DRAMTMG6 */
+ {0x0000011c, 0x00000301}, /* DRAMTMG7 */
+ {0x00000120, 0x00000404}, /* DRAMTMG8 */
+ {0x00000130, 0x00020000}, /* DRAMTMG12 */
+ {0x00000134, 0x00100002}, /* DRAMTMG13 */
+ {0x00000138, 0x0000004c}, /* DRAMTMG14 */
+ {0x00000180, 0x01080008}, /* ZQCTL0 */
+ {0x00000184, 0x00e00000}, /* ZQCTL1 */
+ {0x00000190, 0x07040000}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0905092c}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008d}, /* PHYREG01 */
+ {0x00000014, 0x0000000e}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000008}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-664.inc b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-664.inc
new file mode 100644
index 0000000..f601fe5
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-664.inc
@@ -0,0 +1,78 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xB,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x1,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x11,
+ .cs0_high16bit_row = 0x0,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0
+ },
+ {
+ {0x36170d15},
+ {0x0d030805},
+ {0x00000602},
+ {0x00001111},
+ {0x00000054},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 664, /* clock rate(MHz) */
+ .dramtype = LPDDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x81081020}, /* MSTR */
+ {0x00000064, 0x0028005d}, /* RFSHTMG */
+ {0x000000d0, 0x0002028a}, /* INIT0 */
+ {0x000000d4, 0x00420000}, /* INIT1 */
+ {0x000000d8, 0x00000204}, /* INIT2 */
+ {0x000000dc, 0x00240012}, /* INIT3 */
+ {0x000000e0, 0x00310000}, /* INIT4 */
+ {0x000000e8, 0x00110000}, /* INIT6 */
+ {0x000000ec, 0x00000000}, /* INIT7 */
+ {0x000000f4, 0x000f033f}, /* RANKCTL */
+ {0x00000100, 0x0f0e0b0e}, /* DRAMTMG0 */
+ {0x00000104, 0x00030415}, /* DRAMTMG1 */
+ {0x00000108, 0x04070d0d}, /* DRAMTMG2 */
+ {0x0000010c, 0x00505000}, /* DRAMTMG3 */
+ {0x00000110, 0x06040407}, /* DRAMTMG4 */
+ {0x00000114, 0x02030505}, /* DRAMTMG5 */
+ {0x00000118, 0x01010004}, /* DRAMTMG6 */
+ {0x0000011c, 0x00000301}, /* DRAMTMG7 */
+ {0x00000120, 0x00000404}, /* DRAMTMG8 */
+ {0x00000130, 0x00020000}, /* DRAMTMG12 */
+ {0x00000134, 0x00100002}, /* DRAMTMG13 */
+ {0x00000138, 0x00000060}, /* DRAMTMG14 */
+ {0x00000180, 0x014c000a}, /* ZQCTL0 */
+ {0x00000184, 0x01100000}, /* ZQCTL1 */
+ {0x00000190, 0x07040000}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0a040b28}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008d}, /* PHYREG01 */
+ {0x00000014, 0x0000000e}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000008}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-784.inc b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-784.inc
new file mode 100644
index 0000000..b8d9d5f
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-784.inc
@@ -0,0 +1,78 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xB,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x1,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x11,
+ .cs0_high16bit_row = 0x0,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0
+ },
+ {
+ {0x391b1019},
+ {0x10040805},
+ {0x00000602},
+ {0x00001111},
+ {0x00000054},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 784, /* clock rate(MHz) */
+ .dramtype = LPDDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x81081020}, /* MSTR */
+ {0x00000064, 0x002f006e}, /* RFSHTMG */
+ {0x000000d0, 0x000202ff}, /* INIT0 */
+ {0x000000d4, 0x004e0000}, /* INIT1 */
+ {0x000000d8, 0x00000204}, /* INIT2 */
+ {0x000000dc, 0x00240012}, /* INIT3 */
+ {0x000000e0, 0x00310000}, /* INIT4 */
+ {0x000000e8, 0x00110000}, /* INIT6 */
+ {0x000000ec, 0x00000000}, /* INIT7 */
+ {0x000000f4, 0x000f033f}, /* RANKCTL */
+ {0x00000100, 0x10100d11}, /* DRAMTMG0 */
+ {0x00000104, 0x00030419}, /* DRAMTMG1 */
+ {0x00000108, 0x04070c0d}, /* DRAMTMG2 */
+ {0x0000010c, 0x00606000}, /* DRAMTMG3 */
+ {0x00000110, 0x08040409}, /* DRAMTMG4 */
+ {0x00000114, 0x02030606}, /* DRAMTMG5 */
+ {0x00000118, 0x01010004}, /* DRAMTMG6 */
+ {0x0000011c, 0x00000301}, /* DRAMTMG7 */
+ {0x00000120, 0x00000505}, /* DRAMTMG8 */
+ {0x00000130, 0x00020000}, /* DRAMTMG12 */
+ {0x00000134, 0x00100002}, /* DRAMTMG13 */
+ {0x00000138, 0x00000071}, /* DRAMTMG14 */
+ {0x00000180, 0x0188000c}, /* ZQCTL0 */
+ {0x00000184, 0x01400000}, /* ZQCTL1 */
+ {0x00000190, 0x07040000}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0a040b28}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008d}, /* PHYREG01 */
+ {0x00000014, 0x0000000e}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x00000008}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-924.inc b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-924.inc
new file mode 100644
index 0000000..a2050f6
--- /dev/null
+++ b/drivers/ram/rockchip/sdram-rv1126-lpddr4-detect-924.inc
@@ -0,0 +1,78 @@
+{
+ {
+ {
+ .rank = 0x1,
+ .col = 0xB,
+ .bk = 0x3,
+ .bw = 0x1,
+ .dbw = 0x1,
+ .row_3_4 = 0x0,
+ .cs0_row = 0x11,
+ .cs1_row = 0x11,
+ .cs0_high16bit_row = 0x0,
+ .cs1_high16bit_row = 0x0,
+ .ddrconfig = 0
+ },
+ {
+ {0x3e20121d},
+ {0x12050a07},
+ {0x00000602},
+ {0x00001111},
+ {0x00000054},
+ {0x00000000},
+ 0x000000ff
+ }
+ },
+ {
+ .ddr_freq = 924, /* clock rate(MHz) */
+ .dramtype = LPDDR4,
+ .num_channels = 1,
+ .stride = 0,
+ .odt = 1
+ },
+ {
+ {
+ {0x00000000, 0x81081020}, /* MSTR */
+ {0x00000064, 0x00380082}, /* RFSHTMG */
+ {0x000000d0, 0x00020388}, /* INIT0 */
+ {0x000000d4, 0x005c0000}, /* INIT1 */
+ {0x000000d8, 0x00000205}, /* INIT2 */
+ {0x000000dc, 0x0034001b}, /* INIT3 */
+ {0x000000e0, 0x00310000}, /* INIT4 */
+ {0x000000e8, 0x00110000}, /* INIT6 */
+ {0x000000ec, 0x00000000}, /* INIT7 */
+ {0x000000f4, 0x000f033f}, /* RANKCTL */
+ {0x00000100, 0x12130f14}, /* DRAMTMG0 */
+ {0x00000104, 0x0004041e}, /* DRAMTMG1 */
+ {0x00000108, 0x050a0e0f}, /* DRAMTMG2 */
+ {0x0000010c, 0x00707000}, /* DRAMTMG3 */
+ {0x00000110, 0x0904050a}, /* DRAMTMG4 */
+ {0x00000114, 0x02040707}, /* DRAMTMG5 */
+ {0x00000118, 0x01010005}, /* DRAMTMG6 */
+ {0x0000011c, 0x00000401}, /* DRAMTMG7 */
+ {0x00000120, 0x00000606}, /* DRAMTMG8 */
+ {0x00000130, 0x00020000}, /* DRAMTMG12 */
+ {0x00000134, 0x0a100002}, /* DRAMTMG13 */
+ {0x00000138, 0x00000085}, /* DRAMTMG14 */
+ {0x00000180, 0x01ce000e}, /* ZQCTL0 */
+ {0x00000184, 0x01800000}, /* ZQCTL1 */
+ {0x00000190, 0x07070001}, /* DFITMG0 */
+ {0x00000198, 0x07000101}, /* DFILPCFG0 */
+ {0x000001a0, 0xc0400003}, /* DFIUPD0 */
+ {0x00000240, 0x0b050d3c}, /* ODTCFG */
+ {0x00000244, 0x00000101}, /* ODTMAP */
+ {0x00000250, 0x00001f00}, /* SCHED */
+ {0x00000490, 0x00000001}, /* PCTRL_0 */
+ {0xffffffff, 0xffffffff}
+ }
+ },
+ {
+ {
+ {0x00000004, 0x0000008d}, /* PHYREG01 */
+ {0x00000014, 0x00000014}, /* PHYREG05 */
+ {0x00000018, 0x00000000}, /* PHYREG06 */
+ {0x0000001c, 0x0000000a}, /* PHYREG07 */
+ {0xffffffff, 0xffffffff}
+ }
+ }
+},
diff --git a/drivers/ram/rockchip/sdram_common.c b/drivers/ram/rockchip/sdram_common.c
index ec46ba5..60fc90d 100644
--- a/drivers/ram/rockchip/sdram_common.c
+++ b/drivers/ram/rockchip/sdram_common.c
@@ -36,7 +36,7 @@
}
void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
- struct sdram_base_params *base)
+ struct sdram_base_params *base, u32 split)
{
u64 cap;
u32 bg;
@@ -83,6 +83,8 @@
cap = sdram_get_cs_cap(cap_info, 3, base->dramtype);
if (cap_info->row_3_4)
cap = cap * 3 / 4;
+ else if (split)
+ cap = cap / 2 + (split << 24) / 2;
printascii(" Size=");
printdec(cap >> 20);
@@ -123,7 +125,7 @@
}
inline void sdram_print_ddr_info(struct sdram_cap_info *cap_info,
- struct sdram_base_params *base)
+ struct sdram_base_params *base, u32 split)
{
}
diff --git a/drivers/ram/rockchip/sdram_pctl_px30.c b/drivers/ram/rockchip/sdram_pctl_px30.c
index 331d85f..e5c80fb 100644
--- a/drivers/ram/rockchip/sdram_pctl_px30.c
+++ b/drivers/ram/rockchip/sdram_pctl_px30.c
@@ -21,7 +21,7 @@
setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
continue;
- while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+ while (readl(pctl_base + DDR_PCTL2_MRSTAT) & PCTL2_MR_WR_BUSY)
continue;
}
@@ -33,7 +33,7 @@
int pctl_write_mr(void __iomem *pctl_base, u32 rank, u32 mr_num, u32 arg,
u32 dramtype)
{
- while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+ while (readl(pctl_base + DDR_PCTL2_MRSTAT) & PCTL2_MR_WR_BUSY)
continue;
if (dramtype == DDR3 || dramtype == DDR4) {
writel((mr_num << 12) | (rank << 4) | (0 << 0),
@@ -49,7 +49,7 @@
setbits_le32(pctl_base + DDR_PCTL2_MRCTRL0, 1u << 31);
while (readl(pctl_base + DDR_PCTL2_MRCTRL0) & (1u << 31))
continue;
- while (readl(pctl_base + DDR_PCTL2_MRSTAT) & MR_WR_BUSY)
+ while (readl(pctl_base + DDR_PCTL2_MRSTAT) & PCTL2_MR_WR_BUSY)
continue;
return 0;
diff --git a/drivers/ram/rockchip/sdram_px30.c b/drivers/ram/rockchip/sdram_px30.c
index 98b2593..2728d93 100644
--- a/drivers/ram/rockchip/sdram_px30.c
+++ b/drivers/ram/rockchip/sdram_px30.c
@@ -125,11 +125,11 @@
struct dram_info dram_info;
struct px30_sdram_params sdram_configs[] = {
-#if defined(CONFIG_RAM_PX30_DDR4)
+#if defined(CONFIG_RAM_ROCKCHIP_DDR4)
#include "sdram-px30-ddr4-detect-333.inc"
-#elif defined(CONFIG_RAM_PX30_LPDDR2)
+#elif defined(CONFIG_RAM_ROCKCHIP_LPDDR2)
#include "sdram-px30-lpddr2-detect-333.inc"
-#elif defined(CONFIG_RAM_PX30_LPDDR3)
+#elif defined(CONFIG_RAM_ROCKCHIP_LPDDR3)
#include "sdram-px30-lpddr3-detect-333.inc"
#else
#include "sdram-px30-ddr3-detect-333.inc"
@@ -711,7 +711,7 @@
if (ret)
goto error;
- sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base);
+ sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base, 0);
printascii("out\n");
return ret;
diff --git a/drivers/ram/rockchip/sdram_rk3328.c b/drivers/ram/rockchip/sdram_rk3328.c
index b511c6b..184c93f 100644
--- a/drivers/ram/rockchip/sdram_rk3328.c
+++ b/drivers/ram/rockchip/sdram_rk3328.c
@@ -506,7 +506,7 @@
writel(sys_reg3, &dram->grf->os_reg[3]);
}
- sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base);
+ sdram_print_ddr_info(&sdram_params->ch.cap_info, &sdram_params->base, 0);
return 0;
}
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index 136e4ed..b1fea04 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -1625,7 +1625,7 @@
rk_clrsetreg(&pmusgrf->soc_con4, 0x1f << 10, stride << 10);
}
-#if !defined(CONFIG_RAM_RK3399_LPDDR4)
+#if !defined(CONFIG_RAM_ROCKCHIP_LPDDR4)
static int data_training_first(struct dram_info *dram, u32 channel, u8 rank,
struct rk3399_sdram_params *params)
{
@@ -2558,8 +2558,7 @@
return 0;
}
-
-#endif /* CONFIG_RAM_RK3399_LPDDR4 */
+#endif /* CONFIG_RAM_ROCKCHIP_LPDDR4 */
/* CS0,n=1
* CS1,n=2
@@ -2987,7 +2986,7 @@
continue;
}
- sdram_print_ddr_info(cap_info, ¶ms->base);
+ sdram_print_ddr_info(cap_info, ¶ms->base, 0);
set_memory_map(chan, channel, params);
cap_info->ddrconfig =
calculate_ddrconfig(params, channel);
@@ -3059,7 +3058,7 @@
#endif
static const struct sdram_rk3399_ops rk3399_ops = {
-#if !defined(CONFIG_RAM_RK3399_LPDDR4)
+#if !defined(CONFIG_RAM_ROCKCHIP_LPDDR4)
.data_training_first = data_training_first,
.set_rate_index = switch_to_phy_index1,
.modify_param = modify_param,
diff --git a/drivers/ram/rockchip/sdram_rv1126.c b/drivers/ram/rockchip/sdram_rv1126.c
new file mode 100644
index 0000000..9e1376a
--- /dev/null
+++ b/drivers/ram/rockchip/sdram_rv1126.c
@@ -0,0 +1,3543 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2020 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <ram.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/arch-rockchip/cru_rv1126.h>
+#include <asm/arch-rockchip/grf_rv1126.h>
+#include <asm/arch-rockchip/sdram_common.h>
+#include <asm/arch-rockchip/sdram_rv1126.h>
+#include <linux/delay.h>
+
+/* define training flag */
+#define CA_TRAINING (0x1 << 0)
+#define READ_GATE_TRAINING (0x1 << 1)
+#define WRITE_LEVELING (0x1 << 2)
+#define WRITE_TRAINING (0x1 << 3)
+#define READ_TRAINING (0x1 << 4)
+#define FULL_TRAINING (0xff)
+
+#define SKEW_RX_SIGNAL (0)
+#define SKEW_TX_SIGNAL (1)
+#define SKEW_CA_SIGNAL (2)
+
+#define DESKEW_MDF_ABS_VAL (0)
+#define DESKEW_MDF_DIFF_VAL (1)
+
+struct dram_info {
+#if defined(CONFIG_TPL_BUILD) || \
+ (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+ void __iomem *pctl;
+ void __iomem *phy;
+ struct rv1126_cru *cru;
+ struct msch_regs *msch;
+ struct rv1126_ddrgrf *ddrgrf;
+ struct rv1126_grf *grf;
+ u32 sr_idle;
+ u32 pd_idle;
+#endif
+ struct ram_info info;
+ struct rv1126_pmugrf *pmugrf;
+};
+
+#if defined(CONFIG_TPL_BUILD) || \
+ (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+
+#define GRF_BASE_ADDR 0xfe000000
+#define PMU_GRF_BASE_ADDR 0xfe020000
+#define DDR_GRF_BASE_ADDR 0xfe030000
+#define BUS_SGRF_BASE_ADDR 0xfe0a0000
+#define SERVER_MSCH_BASE_ADDR 0xfe800000
+#define CRU_BASE_ADDR 0xff490000
+#define DDR_PHY_BASE_ADDR 0xff4a0000
+#define UPCTL2_BASE_ADDR 0xffa50000
+
+#define SGRF_SOC_CON2 0x8
+#define SGRF_SOC_CON12 0x30
+#define SGRF_SOC_CON13 0x34
+
+struct dram_info dram_info;
+
+struct rv1126_sdram_params sdram_configs[] = {
+#if defined(CONFIG_RAM_ROCKCHIP_LPDDR4)
+# include "sdram-rv1126-lpddr4-detect-328.inc"
+# include "sdram-rv1126-lpddr4-detect-396.inc"
+# include "sdram-rv1126-lpddr4-detect-528.inc"
+# include "sdram-rv1126-lpddr4-detect-664.inc"
+# include "sdram-rv1126-lpddr4-detect-784.inc"
+# include "sdram-rv1126-lpddr4-detect-924.inc"
+# include "sdram-rv1126-lpddr4-detect-1056.inc"
+#else
+# include "sdram-rv1126-ddr3-detect-328.inc"
+# include "sdram-rv1126-ddr3-detect-396.inc"
+# include "sdram-rv1126-ddr3-detect-528.inc"
+# include "sdram-rv1126-ddr3-detect-664.inc"
+# include "sdram-rv1126-ddr3-detect-784.inc"
+# include "sdram-rv1126-ddr3-detect-924.inc"
+# include "sdram-rv1126-ddr3-detect-1056.inc"
+#endif
+};
+
+u32 common_info[] = {
+#include "sdram-rv1126-loader_params.inc"
+};
+
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+static struct rw_trn_result rw_trn_result;
+#endif
+
+static struct rv1126_fsp_param fsp_param[MAX_IDX];
+
+static u8 lp3_odt_value;
+
+static s8 wrlvl_result[2][4];
+
+/* DDR configuration 0-9 */
+u16 ddr_cfg_2_rbc[] = {
+ ((0 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 3), /* 0 */
+ ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 2), /* 1 */
+ ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 3), /* 2 */
+ ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 1), /* 3 */
+ ((0 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 4), /* 4 */
+ ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 1), /* 5 */
+ ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 2), /* 6 */
+ ((0 << 8) | (2 << 5) | (1 << 4) | (1 << 3) | 3), /* 7 */
+ ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 2), /* 8 */
+ ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 2) /* 9 */
+};
+
+/* DDR configuration 10-21 */
+u8 ddr4_cfg_2_rbc[] = {
+ ((0 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 0), /* 10 */
+ ((1 << 7) | (2 << 4) | (0 << 3) | (2 << 1) | 0), /* 11 */
+ ((0 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 0), /* 12 */
+ ((1 << 7) | (3 << 4) | (0 << 3) | (1 << 1) | 0), /* 13 */
+ ((0 << 7) | (4 << 4) | (0 << 3) | (2 << 1) | 1), /* 14 */
+ ((1 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 1), /* 15 */
+ ((1 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 1), /* 16 */
+ ((0 << 7) | (2 << 4) | (1 << 3) | (2 << 1) | 0), /* 17 */
+ ((0 << 7) | (3 << 4) | (1 << 3) | (1 << 1) | 0), /* 18 */
+ ((0 << 7) | (3 << 4) | (1 << 3) | (2 << 1) | 1), /* 19 */
+ ((0 << 7) | (4 << 4) | (1 << 3) | (1 << 1) | 1), /* 20 */
+ ((1 << 7) | (4 << 4) | (0 << 3) | (0 << 1) | 0) /* 21 */
+};
+
+/* DDR configuration 22-28 */
+u16 ddr_cfg_2_rbc_p2[] = {
+ ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 0), /* 22 */
+ ((0 << 8) | (4 << 5) | (0 << 4) | (1 << 3) | 2), /* 23 */
+ ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 3), /* 24 */
+ ((0 << 8) | (3 << 5) | (1 << 4) | (0 << 3) | 3), /* 25 */
+ ((0 << 8) | (4 << 5) | (1 << 4) | (0 << 3) | 2), /* 26 */
+ ((1 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 2), /* 27 */
+ ((0 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 3) /* 28 */
+};
+
+u8 d4_rbc_2_d3_rbc[][2] = {
+ {10, 0},
+ {11, 2},
+ {12, 23},
+ {13, 1},
+ {14, 28},
+ {15, 24},
+ {16, 27},
+ {17, 7},
+ {18, 6},
+ {19, 25},
+ {20, 26},
+ {21, 3}
+};
+
+u32 addrmap[29][9] = {
+ {24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x3f3f}, /* 0 */
+ {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f0f, 0x3f3f}, /* 1 */
+ {23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+ 0x0f080808, 0x00000f0f, 0x3f3f}, /* 2 */
+ {22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000f0f, 0x3f3f}, /* 3 */
+ {24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
+ 0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
+ {6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f0f, 0x3f3f}, /* 5 */
+ {7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x3f3f}, /* 6 */
+ {8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909,
+ 0x0f090909, 0x00000f0f, 0x3f3f}, /* 7 */
+ {22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000f0f, 0x3f3f}, /* 8 */
+ {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+ 0x0f070707, 0x00000f0f, 0x3f3f}, /* 9 */
+
+ {24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x0801}, /* 10 */
+ {23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+ 0x0f080808, 0x00000f0f, 0x0801}, /* 11 */
+ {24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x0700}, /* 12 */
+ {23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f0f, 0x0700}, /* 13 */
+ {24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f01}, /* 14 */
+ {23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f0f, 0x3f01}, /* 15 */
+ {23, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000f06, 0x3f00}, /* 16 */
+ {8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909,
+ 0x0f090909, 0x00000f0f, 0x0801}, /* 17 */
+ {7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x0700}, /* 18 */
+ {7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x3f01}, /* 19 */
+
+ {6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f00}, /* 20 */
+ {23, 0x003f0909, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000f06, 0x0600}, /* 21 */
+ {21, 0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
+ 0x05050505, 0x00000f0f, 0x3f3f}, /* 22 */
+
+ {24, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f3f}, /* 23 */
+ {23, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
+ 0x07070707, 0x00000f0f, 0x3f3f}, /* 24 */
+ {7, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
+ 0x08080808, 0x00000f0f, 0x3f3f}, /* 25 */
+ {6, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f3f}, /* 26 */
+ {23, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
+ 0x06060606, 0x00000f06, 0x3f3f}, /* 27 */
+ {24, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
+ 0x07070707, 0x00000f07, 0x3f3f} /* 28 */
+};
+
+static u8 dq_sel[22][3] = {
+ {0x0, 0x17, 0x22},
+ {0x1, 0x18, 0x23},
+ {0x2, 0x19, 0x24},
+ {0x3, 0x1a, 0x25},
+ {0x4, 0x1b, 0x26},
+ {0x5, 0x1c, 0x27},
+ {0x6, 0x1d, 0x28},
+ {0x7, 0x1e, 0x29},
+ {0x8, 0x16, 0x21},
+ {0x9, 0x1f, 0x2a},
+ {0xa, 0x20, 0x2b},
+ {0x10, 0x1, 0xc},
+ {0x11, 0x2, 0xd},
+ {0x12, 0x3, 0xe},
+ {0x13, 0x4, 0xf},
+ {0x14, 0x5, 0x10},
+ {0x15, 0x6, 0x11},
+ {0x16, 0x7, 0x12},
+ {0x17, 0x8, 0x13},
+ {0x18, 0x0, 0xb},
+ {0x19, 0x9, 0x14},
+ {0x1a, 0xa, 0x15}
+};
+
+static u16 grp_addr[4] = {
+ ADD_GROUP_CS0_A,
+ ADD_GROUP_CS0_B,
+ ADD_GROUP_CS1_A,
+ ADD_GROUP_CS1_B
+};
+
+static u8 wrlvl_result_offset[2][4] = {
+ {0xa0 + 0x26, 0xa0 + 0x27, 0xd0 + 0x26, 0xd0 + 0x27},
+ {0xa0 + 0x28, 0xa0 + 0x29, 0xd0 + 0x28, 0xd0 + 0x29},
+};
+
+static u16 dqs_dq_skew_adr[16] = {
+ 0x170 + 0, /* SKEW_UPDATE_RX_CS0_DQS0 */
+ 0x170 + 0xb, /* SKEW_UPDATE_RX_CS0_DQS1 */
+ 0x1d0 + 0, /* SKEW_UPDATE_RX_CS0_DQS2 */
+ 0x1d0 + 0xb, /* SKEW_UPDATE_RX_CS0_DQS3 */
+ 0x1a0 + 0, /* SKEW_UPDATE_RX_CS1_DQS0 */
+ 0x1a0 + 0xb, /* SKEW_UPDATE_RX_CS1_DQS1 */
+ 0x200 + 0, /* SKEW_UPDATE_RX_CS1_DQS2 */
+ 0x200 + 0xb, /* SKEW_UPDATE_RX_CS1_DQS3 */
+ 0x170 + 0x16, /* SKEW_UPDATE_TX_CS0_DQS0 */
+ 0x170 + 0x21, /* SKEW_UPDATE_TX_CS0_DQS1 */
+ 0x1d0 + 0x16, /* SKEW_UPDATE_TX_CS0_DQS2 */
+ 0x1d0 + 0x21, /* SKEW_UPDATE_TX_CS0_DQS3 */
+ 0x1a0 + 0x16, /* SKEW_UPDATE_TX_CS1_DQS0 */
+ 0x1a0 + 0x21, /* SKEW_UPDATE_TX_CS1_DQS1 */
+ 0x200 + 0x16, /* SKEW_UPDATE_TX_CS1_DQS2 */
+ 0x200 + 0x21, /* SKEW_UPDATE_TX_CS1_DQS3 */
+};
+
+static void rkclk_ddr_reset(struct dram_info *dram,
+ u32 ctl_srstn, u32 ctl_psrstn,
+ u32 phy_srstn, u32 phy_psrstn)
+{
+ writel(UPCTL2_SRSTN_REQ(ctl_srstn) | UPCTL2_PSRSTN_REQ(ctl_psrstn) |
+ UPCTL2_ASRSTN_REQ(ctl_srstn),
+ BUS_SGRF_BASE_ADDR + SGRF_SOC_CON13);
+
+ writel(DDRPHY_SRSTN_REQ(phy_srstn) | DDRPHY_PSRSTN_REQ(phy_psrstn),
+ &dram->cru->softrst_con[12]);
+}
+
+static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
+{
+ unsigned int refdiv, postdiv1, postdiv2, fbdiv;
+ int delay = 1000;
+ u32 mhz = hz / MHz;
+ struct global_info *gbl_info;
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ u32 ssmod_info;
+ u32 dsmpd = 1;
+
+ gbl_info = (struct global_info *)((void *)common_info +
+ index->global_index.offset * 4);
+ ssmod_info = gbl_info->info_2t;
+ refdiv = 1;
+ if (mhz <= 100) {
+ postdiv1 = 6;
+ postdiv2 = 4;
+ } else if (mhz <= 150) {
+ postdiv1 = 4;
+ postdiv2 = 4;
+ } else if (mhz <= 200) {
+ postdiv1 = 6;
+ postdiv2 = 2;
+ } else if (mhz <= 300) {
+ postdiv1 = 4;
+ postdiv2 = 2;
+ } else if (mhz <= 400) {
+ postdiv1 = 6;
+ postdiv2 = 1;
+ } else {
+ postdiv1 = 4;
+ postdiv2 = 1;
+ }
+ fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
+
+ writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
+
+ writel(0x1f000000, &dram->cru->clksel_con[64]);
+ writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
+ /* enable ssmod */
+ if (PLL_SSMOD_SPREAD(ssmod_info)) {
+ dsmpd = 0;
+ clrsetbits_le32(&dram->cru->pll[1].con2,
+ 0xffffff << 0, 0x0 << 0);
+ writel(SSMOD_SPREAD(PLL_SSMOD_SPREAD(ssmod_info)) |
+ SSMOD_DIVVAL(PLL_SSMOD_DIV(ssmod_info)) |
+ SSMOD_DOWNSPREAD(PLL_SSMOD_DOWNSPREAD(ssmod_info)) |
+ SSMOD_RESET(0) |
+ SSMOD_DIS_SSCG(0) |
+ SSMOD_BP(0),
+ &dram->cru->pll[1].con3);
+ }
+ writel(DSMPD(dsmpd) | POSTDIV2(postdiv2) | REFDIV(refdiv),
+ &dram->cru->pll[1].con1);
+
+ while (delay > 0) {
+ udelay(1);
+ if (LOCK(readl(&dram->cru->pll[1].con1)))
+ break;
+ delay--;
+ }
+
+ writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
+}
+
+static void rkclk_configure_ddr(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ /* for inno ddr phy need freq / 2 */
+ rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ / 2);
+}
+
+static unsigned int
+ calculate_ddrconfig(struct rv1126_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 cs, bw, die_bw, col, row, bank;
+ u32 cs1_row;
+ u32 i, tmp;
+ u32 ddrconf = -1;
+ u32 row_3_4;
+
+ cs = cap_info->rank;
+ bw = cap_info->bw;
+ die_bw = cap_info->dbw;
+ col = cap_info->col;
+ row = cap_info->cs0_row;
+ cs1_row = cap_info->cs1_row;
+ bank = cap_info->bk;
+ row_3_4 = cap_info->row_3_4;
+
+ if (sdram_params->base.dramtype == DDR4) {
+ if (cs == 2 && row == cs1_row && !row_3_4) {
+ tmp = ((row - 13) << 4) | (1 << 3) | (bw << 1) |
+ die_bw;
+ for (i = 17; i < 21; i++) {
+ if (((tmp & 0xf) ==
+ (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
+ ((tmp & 0x70) <=
+ (ddr4_cfg_2_rbc[i - 10] & 0x70))) {
+ ddrconf = i;
+ goto out;
+ }
+ }
+ }
+
+ tmp = ((cs - 1) << 7) | ((row - 13) << 4) | (bw << 1) | die_bw;
+ for (i = 10; i < 21; i++) {
+ if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
+ ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) &&
+ ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) {
+ ddrconf = i;
+ goto out;
+ }
+ }
+ } else {
+ if (cs == 2 && row == cs1_row && bank == 3) {
+ for (i = 5; i < 8; i++) {
+ if (((bw + col - 10) == (ddr_cfg_2_rbc[i] &
+ 0x7)) &&
+ ((row - 13) << 5) <= (ddr_cfg_2_rbc[i] &
+ (0x7 << 5))) {
+ ddrconf = i;
+ goto out;
+ }
+ }
+ }
+
+ tmp = ((cs - 1) << 8) | ((row - 13) << 5) |
+ ((bw + col - 10) << 0);
+ if (bank == 3)
+ tmp |= (1 << 3);
+
+ for (i = 0; i < 9; i++)
+ if (((tmp & 0x1f) == (ddr_cfg_2_rbc[i] & 0x1f)) &&
+ ((tmp & (7 << 5)) <=
+ (ddr_cfg_2_rbc[i] & (7 << 5))) &&
+ ((tmp & (1 << 8)) <=
+ (ddr_cfg_2_rbc[i] & (1 << 8)))) {
+ ddrconf = i;
+ goto out;
+ }
+
+ for (i = 0; i < 7; i++)
+ if (((tmp & 0x1f) == (ddr_cfg_2_rbc_p2[i] & 0x1f)) &&
+ ((tmp & (7 << 5)) <=
+ (ddr_cfg_2_rbc_p2[i] & (7 << 5))) &&
+ ((tmp & (1 << 8)) <=
+ (ddr_cfg_2_rbc_p2[i] & (1 << 8)))) {
+ ddrconf = i + 22;
+ goto out;
+ }
+
+ if (cs == 1 && bank == 3 && row <= 17 &&
+ (col + bw) == 12)
+ ddrconf = 23;
+ }
+
+out:
+ if (ddrconf > 28)
+ printascii("calculate ddrconfig error\n");
+
+ if (sdram_params->base.dramtype == DDR4) {
+ for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
+ if (ddrconf == d4_rbc_2_d3_rbc[i][0]) {
+ if (ddrconf == 21 && row > 16)
+ printascii("warn:ddrconf21 row > 16\n");
+ else
+ ddrconf = d4_rbc_2_d3_rbc[i][1];
+ break;
+ }
+ }
+ }
+
+ return ddrconf;
+}
+
+static void sw_set_req(struct dram_info *dram)
+{
+ void __iomem *pctl_base = dram->pctl;
+
+ /* clear sw_done=0 */
+ writel(PCTL2_SW_DONE_CLEAR, pctl_base + DDR_PCTL2_SWCTL);
+}
+
+static void sw_set_ack(struct dram_info *dram)
+{
+ void __iomem *pctl_base = dram->pctl;
+
+ /* set sw_done=1 */
+ writel(PCTL2_SW_DONE, pctl_base + DDR_PCTL2_SWCTL);
+ while (1) {
+ /* wait programming done */
+ if (readl(pctl_base + DDR_PCTL2_SWSTAT) &
+ PCTL2_SW_DONE_ACK)
+ break;
+ }
+}
+
+static void set_ctl_address_map(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ void __iomem *pctl_base = dram->pctl;
+ u32 ddrconf = cap_info->ddrconfig;
+ u32 i, row;
+
+ row = cap_info->cs0_row;
+ if (sdram_params->base.dramtype == DDR4) {
+ for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
+ if (ddrconf == d4_rbc_2_d3_rbc[i][1]) {
+ ddrconf = d4_rbc_2_d3_rbc[i][0];
+ break;
+ }
+ }
+ }
+
+ if (ddrconf >= ARRAY_SIZE(addrmap)) {
+ printascii("set ctl address map fail\n");
+ return;
+ }
+
+ sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
+ &addrmap[ddrconf][0], ARRAY_SIZE(addrmap[ddrconf]) * 4);
+
+ /* unused row set to 0xf */
+ for (i = 17; i >= row; i--)
+ setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
+ ((i - 12) * 8 / 32) * 4,
+ 0xf << ((i - 12) * 8 % 32));
+
+ if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
+ setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
+ if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
+ setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
+
+ if (cap_info->rank == 1)
+ clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
+}
+
+static void phy_pll_set(struct dram_info *dram, u32 freq, u32 wait)
+{
+ void __iomem *phy_base = dram->phy;
+ u32 fbdiv, prediv, postdiv, postdiv_en;
+
+ if (wait) {
+ clrbits_le32(PHY_REG(phy_base, 0x53), PHY_PD_DISB);
+ while (!(readl(PHY_REG(phy_base, 0x90)) & PHY_PLL_LOCK))
+ continue;
+ } else {
+ freq /= MHz;
+ prediv = 1;
+ if (freq <= 200) {
+ fbdiv = 16;
+ postdiv = 2;
+ postdiv_en = 1;
+ } else if (freq <= 456) {
+ fbdiv = 8;
+ postdiv = 1;
+ postdiv_en = 1;
+ } else {
+ fbdiv = 4;
+ postdiv = 0;
+ postdiv_en = 0;
+ }
+ writel(fbdiv & 0xff, PHY_REG(phy_base, 0x50));
+ clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_PBDIV_BIT9_MASK,
+ (fbdiv >> 8) & 1);
+ clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_POSTDIV_EN_MASK,
+ postdiv_en << PHY_POSTDIV_EN_SHIFT);
+
+ clrsetbits_le32(PHY_REG(phy_base, 0x52),
+ PHY_PREDIV_MASK << PHY_PREDIV_SHIFT, prediv);
+ clrsetbits_le32(PHY_REG(phy_base, 0x53),
+ PHY_POSTDIV_MASK << PHY_POSTDIV_SHIFT,
+ postdiv << PHY_POSTDIV_SHIFT);
+ }
+}
+
+static const u16 d3_phy_drv_2_ohm[][2] = {
+ {PHY_DDR3_RON_455ohm, 455},
+ {PHY_DDR3_RON_230ohm, 230},
+ {PHY_DDR3_RON_153ohm, 153},
+ {PHY_DDR3_RON_115ohm, 115},
+ {PHY_DDR3_RON_91ohm, 91},
+ {PHY_DDR3_RON_76ohm, 76},
+ {PHY_DDR3_RON_65ohm, 65},
+ {PHY_DDR3_RON_57ohm, 57},
+ {PHY_DDR3_RON_51ohm, 51},
+ {PHY_DDR3_RON_46ohm, 46},
+ {PHY_DDR3_RON_41ohm, 41},
+ {PHY_DDR3_RON_38ohm, 38},
+ {PHY_DDR3_RON_35ohm, 35},
+ {PHY_DDR3_RON_32ohm, 32},
+ {PHY_DDR3_RON_30ohm, 30},
+ {PHY_DDR3_RON_28ohm, 28},
+ {PHY_DDR3_RON_27ohm, 27},
+ {PHY_DDR3_RON_25ohm, 25},
+ {PHY_DDR3_RON_24ohm, 24},
+ {PHY_DDR3_RON_23ohm, 23},
+ {PHY_DDR3_RON_22ohm, 22},
+ {PHY_DDR3_RON_21ohm, 21},
+ {PHY_DDR3_RON_20ohm, 20}
+};
+
+static u16 d3_phy_odt_2_ohm[][2] = {
+ {PHY_DDR3_RTT_DISABLE, 0},
+ {PHY_DDR3_RTT_561ohm, 561},
+ {PHY_DDR3_RTT_282ohm, 282},
+ {PHY_DDR3_RTT_188ohm, 188},
+ {PHY_DDR3_RTT_141ohm, 141},
+ {PHY_DDR3_RTT_113ohm, 113},
+ {PHY_DDR3_RTT_94ohm, 94},
+ {PHY_DDR3_RTT_81ohm, 81},
+ {PHY_DDR3_RTT_72ohm, 72},
+ {PHY_DDR3_RTT_64ohm, 64},
+ {PHY_DDR3_RTT_58ohm, 58},
+ {PHY_DDR3_RTT_52ohm, 52},
+ {PHY_DDR3_RTT_48ohm, 48},
+ {PHY_DDR3_RTT_44ohm, 44},
+ {PHY_DDR3_RTT_41ohm, 41},
+ {PHY_DDR3_RTT_38ohm, 38},
+ {PHY_DDR3_RTT_37ohm, 37},
+ {PHY_DDR3_RTT_34ohm, 34},
+ {PHY_DDR3_RTT_32ohm, 32},
+ {PHY_DDR3_RTT_31ohm, 31},
+ {PHY_DDR3_RTT_29ohm, 29},
+ {PHY_DDR3_RTT_28ohm, 28},
+ {PHY_DDR3_RTT_27ohm, 27},
+ {PHY_DDR3_RTT_25ohm, 25}
+};
+
+static u16 d4lp3_phy_drv_2_ohm[][2] = {
+ {PHY_DDR4_LPDDR3_RON_482ohm, 482},
+ {PHY_DDR4_LPDDR3_RON_244ohm, 244},
+ {PHY_DDR4_LPDDR3_RON_162ohm, 162},
+ {PHY_DDR4_LPDDR3_RON_122ohm, 122},
+ {PHY_DDR4_LPDDR3_RON_97ohm, 97},
+ {PHY_DDR4_LPDDR3_RON_81ohm, 81},
+ {PHY_DDR4_LPDDR3_RON_69ohm, 69},
+ {PHY_DDR4_LPDDR3_RON_61ohm, 61},
+ {PHY_DDR4_LPDDR3_RON_54ohm, 54},
+ {PHY_DDR4_LPDDR3_RON_48ohm, 48},
+ {PHY_DDR4_LPDDR3_RON_44ohm, 44},
+ {PHY_DDR4_LPDDR3_RON_40ohm, 40},
+ {PHY_DDR4_LPDDR3_RON_37ohm, 37},
+ {PHY_DDR4_LPDDR3_RON_34ohm, 34},
+ {PHY_DDR4_LPDDR3_RON_32ohm, 32},
+ {PHY_DDR4_LPDDR3_RON_30ohm, 30},
+ {PHY_DDR4_LPDDR3_RON_28ohm, 28},
+ {PHY_DDR4_LPDDR3_RON_27ohm, 27},
+ {PHY_DDR4_LPDDR3_RON_25ohm, 25},
+ {PHY_DDR4_LPDDR3_RON_24ohm, 24},
+ {PHY_DDR4_LPDDR3_RON_23ohm, 23},
+ {PHY_DDR4_LPDDR3_RON_22ohm, 22},
+ {PHY_DDR4_LPDDR3_RON_21ohm, 21}
+};
+
+static u16 d4lp3_phy_odt_2_ohm[][2] = {
+ {PHY_DDR4_LPDDR3_RTT_DISABLE, 0},
+ {PHY_DDR4_LPDDR3_RTT_586ohm, 586},
+ {PHY_DDR4_LPDDR3_RTT_294ohm, 294},
+ {PHY_DDR4_LPDDR3_RTT_196ohm, 196},
+ {PHY_DDR4_LPDDR3_RTT_148ohm, 148},
+ {PHY_DDR4_LPDDR3_RTT_118ohm, 118},
+ {PHY_DDR4_LPDDR3_RTT_99ohm, 99},
+ {PHY_DDR4_LPDDR3_RTT_85ohm, 58},
+ {PHY_DDR4_LPDDR3_RTT_76ohm, 76},
+ {PHY_DDR4_LPDDR3_RTT_67ohm, 67},
+ {PHY_DDR4_LPDDR3_RTT_60ohm, 60},
+ {PHY_DDR4_LPDDR3_RTT_55ohm, 55},
+ {PHY_DDR4_LPDDR3_RTT_50ohm, 50},
+ {PHY_DDR4_LPDDR3_RTT_46ohm, 46},
+ {PHY_DDR4_LPDDR3_RTT_43ohm, 43},
+ {PHY_DDR4_LPDDR3_RTT_40ohm, 40},
+ {PHY_DDR4_LPDDR3_RTT_38ohm, 38},
+ {PHY_DDR4_LPDDR3_RTT_36ohm, 36},
+ {PHY_DDR4_LPDDR3_RTT_34ohm, 34},
+ {PHY_DDR4_LPDDR3_RTT_32ohm, 32},
+ {PHY_DDR4_LPDDR3_RTT_31ohm, 31},
+ {PHY_DDR4_LPDDR3_RTT_29ohm, 29},
+ {PHY_DDR4_LPDDR3_RTT_28ohm, 28},
+ {PHY_DDR4_LPDDR3_RTT_27ohm, 27}
+};
+
+static u16 lp4_phy_drv_2_ohm[][2] = {
+ {PHY_LPDDR4_RON_501ohm, 501},
+ {PHY_LPDDR4_RON_253ohm, 253},
+ {PHY_LPDDR4_RON_168ohm, 168},
+ {PHY_LPDDR4_RON_126ohm, 126},
+ {PHY_LPDDR4_RON_101ohm, 101},
+ {PHY_LPDDR4_RON_84ohm, 84},
+ {PHY_LPDDR4_RON_72ohm, 72},
+ {PHY_LPDDR4_RON_63ohm, 63},
+ {PHY_LPDDR4_RON_56ohm, 56},
+ {PHY_LPDDR4_RON_50ohm, 50},
+ {PHY_LPDDR4_RON_46ohm, 46},
+ {PHY_LPDDR4_RON_42ohm, 42},
+ {PHY_LPDDR4_RON_38ohm, 38},
+ {PHY_LPDDR4_RON_36ohm, 36},
+ {PHY_LPDDR4_RON_33ohm, 33},
+ {PHY_LPDDR4_RON_31ohm, 31},
+ {PHY_LPDDR4_RON_29ohm, 29},
+ {PHY_LPDDR4_RON_28ohm, 28},
+ {PHY_LPDDR4_RON_26ohm, 26},
+ {PHY_LPDDR4_RON_25ohm, 25},
+ {PHY_LPDDR4_RON_24ohm, 24},
+ {PHY_LPDDR4_RON_23ohm, 23},
+ {PHY_LPDDR4_RON_22ohm, 22}
+};
+
+static u16 lp4_phy_odt_2_ohm[][2] = {
+ {PHY_LPDDR4_RTT_DISABLE, 0},
+ {PHY_LPDDR4_RTT_604ohm, 604},
+ {PHY_LPDDR4_RTT_303ohm, 303},
+ {PHY_LPDDR4_RTT_202ohm, 202},
+ {PHY_LPDDR4_RTT_152ohm, 152},
+ {PHY_LPDDR4_RTT_122ohm, 122},
+ {PHY_LPDDR4_RTT_101ohm, 101},
+ {PHY_LPDDR4_RTT_87ohm, 87},
+ {PHY_LPDDR4_RTT_78ohm, 78},
+ {PHY_LPDDR4_RTT_69ohm, 69},
+ {PHY_LPDDR4_RTT_62ohm, 62},
+ {PHY_LPDDR4_RTT_56ohm, 56},
+ {PHY_LPDDR4_RTT_52ohm, 52},
+ {PHY_LPDDR4_RTT_48ohm, 48},
+ {PHY_LPDDR4_RTT_44ohm, 44},
+ {PHY_LPDDR4_RTT_41ohm, 41},
+ {PHY_LPDDR4_RTT_39ohm, 39},
+ {PHY_LPDDR4_RTT_37ohm, 37},
+ {PHY_LPDDR4_RTT_35ohm, 35},
+ {PHY_LPDDR4_RTT_33ohm, 33},
+ {PHY_LPDDR4_RTT_32ohm, 32},
+ {PHY_LPDDR4_RTT_30ohm, 30},
+ {PHY_LPDDR4_RTT_29ohm, 29},
+ {PHY_LPDDR4_RTT_27ohm, 27}
+};
+
+static u32 lp4_odt_calc(u32 odt_ohm)
+{
+ u32 odt;
+
+ if (odt_ohm == 0)
+ odt = LPDDR4_DQODT_DIS;
+ else if (odt_ohm <= 40)
+ odt = LPDDR4_DQODT_40;
+ else if (odt_ohm <= 48)
+ odt = LPDDR4_DQODT_48;
+ else if (odt_ohm <= 60)
+ odt = LPDDR4_DQODT_60;
+ else if (odt_ohm <= 80)
+ odt = LPDDR4_DQODT_80;
+ else if (odt_ohm <= 120)
+ odt = LPDDR4_DQODT_120;
+ else
+ odt = LPDDR4_DQODT_240;
+
+ return odt;
+}
+
+static void *get_ddr_drv_odt_info(u32 dramtype)
+{
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ void *ddr_info = 0;
+
+ if (dramtype == DDR4)
+ ddr_info = (void *)common_info + index->ddr4_index.offset * 4;
+ else if (dramtype == DDR3)
+ ddr_info = (void *)common_info + index->ddr3_index.offset * 4;
+ else if (dramtype == LPDDR3)
+ ddr_info = (void *)common_info + index->lp3_index.offset * 4;
+ else if (dramtype == LPDDR4)
+ ddr_info = (void *)common_info + index->lp4_index.offset * 4;
+ else
+ printascii("unsupported dram type\n");
+ return ddr_info;
+}
+
+static void set_lp4_vref(struct dram_info *dram, struct lp4_info *lp4_info,
+ u32 freq_mhz, u32 dst_fsp, u32 dramtype)
+{
+ void __iomem *pctl_base = dram->pctl;
+ u32 ca_vref, dq_vref;
+
+ if (freq_mhz <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
+ ca_vref = LP4_CA_VREF(lp4_info->vref_when_odtoff);
+ else
+ ca_vref = LP4_CA_VREF(lp4_info->vref_when_odten);
+
+ if (freq_mhz <= LP4_DQ_ODT_EN_FREQ(lp4_info->dq_odten_freq))
+ dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odtoff);
+ else
+ dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odten);
+
+ if (dramtype == LPDDR4) {
+ if (ca_vref < 100)
+ ca_vref = 100;
+ if (ca_vref > 420)
+ ca_vref = 420;
+
+ if (ca_vref <= 300)
+ ca_vref = (0 << 6) | (ca_vref - 100) / 4;
+ else
+ ca_vref = (1 << 6) | (ca_vref - 220) / 4;
+
+ if (dq_vref < 100)
+ dq_vref = 100;
+ if (dq_vref > 420)
+ dq_vref = 420;
+
+ if (dq_vref <= 300)
+ dq_vref = (0 << 6) | (dq_vref - 100) / 4;
+ else
+ dq_vref = (1 << 6) | (dq_vref - 220) / 4;
+ } else {
+ ca_vref = ca_vref * 11 / 6;
+ if (ca_vref < 150)
+ ca_vref = 150;
+ if (ca_vref > 629)
+ ca_vref = 629;
+
+ if (ca_vref <= 449)
+ ca_vref = (0 << 6) | (ca_vref - 150) / 4;
+ else
+ ca_vref = (1 << 6) | (ca_vref - 329) / 4;
+
+ if (dq_vref < 150)
+ dq_vref = 150;
+ if (dq_vref > 629)
+ dq_vref = 629;
+
+ if (dq_vref <= 449)
+ dq_vref = (0 << 6) | (dq_vref - 150) / 6;
+ else
+ dq_vref = (1 << 6) | (dq_vref - 329) / 6;
+ }
+ sw_set_req(dram);
+ clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT6,
+ PCTL2_MR_MASK << PCTL2_LPDDR4_MR12_SHIFT,
+ ca_vref << PCTL2_LPDDR4_MR12_SHIFT);
+
+ clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT7,
+ PCTL2_MR_MASK << PCTL2_LPDDR4_MR14_SHIFT,
+ dq_vref << PCTL2_LPDDR4_MR14_SHIFT);
+ sw_set_ack(dram);
+}
+
+static void set_ds_odt(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params, u32 dst_fsp)
+{
+ void __iomem *phy_base = dram->phy;
+ void __iomem *pctl_base = dram->pctl;
+ u32 dramtype = sdram_params->base.dramtype;
+ struct ddr2_3_4_lp2_3_info *ddr_info;
+ struct lp4_info *lp4_info;
+ u32 i, j, tmp;
+ const u16 (*p_drv)[2];
+ const u16 (*p_odt)[2];
+ u32 drv_info, sr_info;
+ u32 phy_dq_drv_ohm, phy_clk_drv_ohm, phy_ca_drv_ohm, dram_drv_ohm;
+ u32 phy_odt_ohm, dram_odt_ohm;
+ u32 lp4_pu_cal, phy_lp4_drv_pd_en;
+ u32 phy_odt_up_en, phy_odt_dn_en;
+ u32 sr_dq, sr_clk;
+ u32 freq = sdram_params->base.ddr_freq;
+ u32 mr1_mr3, mr11, mr22, vref_out, vref_inner;
+ u32 phy_clk_drv = 0, phy_odt = 0, phy_ca_drv = 0, dram_caodt_ohm = 0;
+ u32 phy_dq_drv = 0;
+ u32 phy_odt_up = 0, phy_odt_dn = 0;
+
+ ddr_info = get_ddr_drv_odt_info(dramtype);
+ lp4_info = (void *)ddr_info;
+
+ if (!ddr_info)
+ return;
+
+ /* dram odt en freq control phy drv, dram odt and phy sr */
+ if (freq <= DRAMODT_EN_FREQ(ddr_info->odten_freq)) {
+ drv_info = ddr_info->drv_when_odtoff;
+ dram_odt_ohm = 0;
+ sr_info = ddr_info->sr_when_odtoff;
+ phy_lp4_drv_pd_en =
+ PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(lp4_info->odt_info);
+ } else {
+ drv_info = ddr_info->drv_when_odten;
+ dram_odt_ohm = ODT_INFO_DRAM_ODT(ddr_info->odt_info);
+ sr_info = ddr_info->sr_when_odten;
+ phy_lp4_drv_pd_en =
+ PHY_LP4_DRV_PULLDOWN_EN_ODTEN(lp4_info->odt_info);
+ }
+ phy_dq_drv_ohm =
+ DRV_INFO_PHY_DQ_DRV(drv_info);
+ phy_clk_drv_ohm =
+ DRV_INFO_PHY_CLK_DRV(drv_info);
+ phy_ca_drv_ohm =
+ DRV_INFO_PHY_CA_DRV(drv_info);
+
+ sr_dq = DQ_SR_INFO(sr_info);
+ sr_clk = CLK_SR_INFO(sr_info);
+
+ /* phy odt en freq control dram drv and phy odt */
+ if (freq <= PHYODT_EN_FREQ(ddr_info->odten_freq)) {
+ dram_drv_ohm = DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odtoff);
+ lp4_pu_cal = LP4_DRV_PU_CAL_ODTOFF(lp4_info->odt_info);
+ phy_odt_ohm = 0;
+ phy_odt_up_en = 0;
+ phy_odt_dn_en = 0;
+ } else {
+ dram_drv_ohm =
+ DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odten);
+ phy_odt_ohm = ODT_INFO_PHY_ODT(ddr_info->odt_info);
+ phy_odt_up_en =
+ ODT_INFO_PULLUP_EN(ddr_info->odt_info);
+ phy_odt_dn_en =
+ ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
+ lp4_pu_cal = LP4_DRV_PU_CAL_ODTEN(lp4_info->odt_info);
+ }
+
+ if (dramtype == LPDDR4) {
+ if (phy_odt_ohm) {
+ phy_odt_up_en = 0;
+ phy_odt_dn_en = 1;
+ }
+ if (freq <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
+ dram_caodt_ohm = 0;
+ else
+ dram_caodt_ohm =
+ ODT_INFO_LP4_CA_ODT(lp4_info->odt_info);
+ }
+
+ if (dramtype == DDR3) {
+ p_drv = d3_phy_drv_2_ohm;
+ p_odt = d3_phy_odt_2_ohm;
+ } else if (dramtype == LPDDR4) {
+ p_drv = lp4_phy_drv_2_ohm;
+ p_odt = lp4_phy_odt_2_ohm;
+ } else {
+ p_drv = d4lp3_phy_drv_2_ohm;
+ p_odt = d4lp3_phy_odt_2_ohm;
+ }
+
+ for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
+ if (phy_dq_drv_ohm <= *(*(p_drv + i) + 1)) {
+ phy_dq_drv = **(p_drv + i);
+ break;
+ }
+ if (i == 0)
+ break;
+ }
+ for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
+ if (phy_clk_drv_ohm <= *(*(p_drv + i) + 1)) {
+ phy_clk_drv = **(p_drv + i);
+ break;
+ }
+ if (i == 0)
+ break;
+ }
+ for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
+ if (phy_ca_drv_ohm <= *(*(p_drv + i) + 1)) {
+ phy_ca_drv = **(p_drv + i);
+ break;
+ }
+ if (i == 0)
+ break;
+ }
+ if (!phy_odt_ohm)
+ phy_odt = 0;
+ else
+ for (i = ARRAY_SIZE(d4lp3_phy_odt_2_ohm) - 1; ; i--) {
+ if (phy_odt_ohm <= *(*(p_odt + i) + 1)) {
+ phy_odt = **(p_odt + i);
+ break;
+ }
+ if (i == 0)
+ break;
+ }
+
+ if (dramtype != LPDDR4) {
+ if (!phy_odt_ohm || (phy_odt_up_en && phy_odt_dn_en))
+ vref_inner = 0x80;
+ else if (phy_odt_up_en)
+ vref_inner = (2 * dram_drv_ohm + phy_odt_ohm) * 128 /
+ (dram_drv_ohm + phy_odt_ohm);
+ else
+ vref_inner = phy_odt_ohm * 128 /
+ (phy_odt_ohm + dram_drv_ohm);
+
+ if (dramtype != DDR3 && dram_odt_ohm)
+ vref_out = (2 * phy_dq_drv_ohm + dram_odt_ohm) * 128 /
+ (phy_dq_drv_ohm + dram_odt_ohm);
+ else
+ vref_out = 0x80;
+ } else {
+ /* for lp4 and lp4x*/
+ if (phy_odt_ohm)
+ vref_inner =
+ (PHY_LP4_DQ_VREF(lp4_info->vref_when_odten) *
+ 256) / 1000;
+ else
+ vref_inner =
+ (PHY_LP4_DQ_VREF(lp4_info->vref_when_odtoff) *
+ 256) / 1000;
+
+ vref_out = 0x80;
+ }
+
+ /* default ZQCALIB bypass mode */
+ clrsetbits_le32(PHY_REG(phy_base, 0x100), 0x1f, phy_ca_drv);
+ clrsetbits_le32(PHY_REG(phy_base, 0x101), 0x1f, phy_ca_drv);
+ clrsetbits_le32(PHY_REG(phy_base, 0x102), 0x1f, phy_clk_drv);
+ clrsetbits_le32(PHY_REG(phy_base, 0x103), 0x1f, phy_clk_drv);
+ if (dramtype == LPDDR4) {
+ clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_clk_drv);
+ clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_clk_drv);
+ } else {
+ clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_ca_drv);
+ clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_ca_drv);
+ }
+ /* clk / cmd slew rate */
+ clrsetbits_le32(PHY_REG(phy_base, 0x106), 0x1f, sr_clk);
+
+ phy_lp4_drv_pd_en = (~phy_lp4_drv_pd_en) & 1;
+ if (phy_odt_up_en)
+ phy_odt_up = phy_odt;
+ if (phy_odt_dn_en)
+ phy_odt_dn = phy_odt;
+
+ for (i = 0; i < 4; i++) {
+ j = 0x110 + i * 0x10;
+ clrsetbits_le32(PHY_REG(phy_base, j + 1), 0x1f, phy_odt_up);
+ clrsetbits_le32(PHY_REG(phy_base, j), 0x1f, phy_odt_dn);
+ clrsetbits_le32(PHY_REG(phy_base, j + 2), 0x1f, phy_dq_drv);
+ clrsetbits_le32(PHY_REG(phy_base, j + 3), 0x1f, phy_dq_drv);
+ writel(vref_inner, PHY_REG(phy_base, 0x118 + i * 0x10));
+
+ clrsetbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10),
+ 1 << 3, phy_lp4_drv_pd_en << 3);
+ if (dramtype == LPDDR4)
+ clrbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10), BIT(5));
+ /* dq slew rate */
+ clrsetbits_le32(PHY_REG(phy_base, 0x117 + i * 0x10),
+ 0x1f, sr_dq);
+ }
+
+ /* reg_rx_vref_value_update */
+ setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+ clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+
+ /* RAM VREF */
+ writel(vref_out, PHY_REG(phy_base, 0x105));
+ if (dramtype == LPDDR3)
+ udelay(100);
+
+ if (dramtype == LPDDR4)
+ set_lp4_vref(dram, lp4_info, freq, dst_fsp, dramtype);
+
+ if (dramtype == DDR3 || dramtype == DDR4) {
+ mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT3);
+ mr1_mr3 = mr1_mr3 >> PCTL2_DDR34_MR1_SHIFT & PCTL2_MR_MASK;
+ } else {
+ mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT4);
+ mr1_mr3 = mr1_mr3 >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK;
+ }
+
+ if (dramtype == DDR3) {
+ mr1_mr3 &= ~(DDR3_DS_MASK | DDR3_RTT_NOM_MASK);
+ if (dram_drv_ohm == 34)
+ mr1_mr3 |= DDR3_DS_34;
+
+ if (dram_odt_ohm == 0)
+ mr1_mr3 |= DDR3_RTT_NOM_DIS;
+ else if (dram_odt_ohm <= 40)
+ mr1_mr3 |= DDR3_RTT_NOM_40;
+ else if (dram_odt_ohm <= 60)
+ mr1_mr3 |= DDR3_RTT_NOM_60;
+ else
+ mr1_mr3 |= DDR3_RTT_NOM_120;
+
+ } else if (dramtype == DDR4) {
+ mr1_mr3 &= ~(DDR4_DS_MASK | DDR4_RTT_NOM_MASK);
+ if (dram_drv_ohm == 48)
+ mr1_mr3 |= DDR4_DS_48;
+
+ if (dram_odt_ohm == 0)
+ mr1_mr3 |= DDR4_RTT_NOM_DIS;
+ else if (dram_odt_ohm <= 34)
+ mr1_mr3 |= DDR4_RTT_NOM_34;
+ else if (dram_odt_ohm <= 40)
+ mr1_mr3 |= DDR4_RTT_NOM_40;
+ else if (dram_odt_ohm <= 48)
+ mr1_mr3 |= DDR4_RTT_NOM_48;
+ else if (dram_odt_ohm <= 60)
+ mr1_mr3 |= DDR4_RTT_NOM_60;
+ else
+ mr1_mr3 |= DDR4_RTT_NOM_120;
+
+ } else if (dramtype == LPDDR3) {
+ if (dram_drv_ohm <= 34)
+ mr1_mr3 |= LPDDR3_DS_34;
+ else if (dram_drv_ohm <= 40)
+ mr1_mr3 |= LPDDR3_DS_40;
+ else if (dram_drv_ohm <= 48)
+ mr1_mr3 |= LPDDR3_DS_48;
+ else if (dram_drv_ohm <= 60)
+ mr1_mr3 |= LPDDR3_DS_60;
+ else if (dram_drv_ohm <= 80)
+ mr1_mr3 |= LPDDR3_DS_80;
+
+ if (dram_odt_ohm == 0)
+ lp3_odt_value = LPDDR3_ODT_DIS;
+ else if (dram_odt_ohm <= 60)
+ lp3_odt_value = LPDDR3_ODT_60;
+ else if (dram_odt_ohm <= 120)
+ lp3_odt_value = LPDDR3_ODT_120;
+ else
+ lp3_odt_value = LPDDR3_ODT_240;
+ } else {/* for lpddr4 and lpddr4x */
+ /* MR3 for lp4 PU-CAL and PDDS */
+ mr1_mr3 &= ~(LPDDR4_PDDS_MASK | LPDDR4_PU_CAL_MASK);
+ mr1_mr3 |= lp4_pu_cal;
+
+ tmp = lp4_odt_calc(dram_drv_ohm);
+ if (!tmp)
+ tmp = LPDDR4_PDDS_240;
+ mr1_mr3 |= (tmp << LPDDR4_PDDS_SHIFT);
+
+ /* MR11 for lp4 ca odt, dq odt set */
+ mr11 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT6);
+ mr11 = mr11 >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK;
+
+ mr11 &= ~(LPDDR4_DQODT_MASK | LPDDR4_CAODT_MASK);
+
+ tmp = lp4_odt_calc(dram_odt_ohm);
+ mr11 |= (tmp << LPDDR4_DQODT_SHIFT);
+
+ tmp = lp4_odt_calc(dram_caodt_ohm);
+ mr11 |= (tmp << LPDDR4_CAODT_SHIFT);
+ sw_set_req(dram);
+ clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT6,
+ PCTL2_MR_MASK << PCTL2_LPDDR4_MR11_SHIFT,
+ mr11 << PCTL2_LPDDR4_MR11_SHIFT);
+ sw_set_ack(dram);
+
+ /* MR22 for soc odt/odt-ck/odt-cs/odt-ca */
+ mr22 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT7);
+ mr22 = mr22 >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK;
+ mr22 &= ~LPDDR4_SOC_ODT_MASK;
+
+ tmp = lp4_odt_calc(phy_odt_ohm);
+ mr22 |= tmp;
+ mr22 = mr22 |
+ (LP4_ODTE_CK_EN(lp4_info->cs_drv_ca_odt_info) <<
+ LPDDR4_ODTE_CK_SHIFT) |
+ (LP4_ODTE_CS_EN(lp4_info->cs_drv_ca_odt_info) <<
+ LPDDR4_ODTE_CS_SHIFT) |
+ (LP4_ODTD_CA_EN(lp4_info->cs_drv_ca_odt_info) <<
+ LPDDR4_ODTD_CA_SHIFT);
+
+ sw_set_req(dram);
+ clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT7,
+ PCTL2_MR_MASK << PCTL2_LPDDR4_MR22_SHIFT,
+ mr22 << PCTL2_LPDDR4_MR22_SHIFT);
+ sw_set_ack(dram);
+ }
+
+ if (dramtype == DDR4 || dramtype == DDR3) {
+ sw_set_req(dram);
+ clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT3,
+ PCTL2_MR_MASK << PCTL2_DDR34_MR1_SHIFT,
+ mr1_mr3 << PCTL2_DDR34_MR1_SHIFT);
+ sw_set_ack(dram);
+ } else {
+ sw_set_req(dram);
+ clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT4,
+ PCTL2_MR_MASK << PCTL2_LPDDR234_MR3_SHIFT,
+ mr1_mr3 << PCTL2_LPDDR234_MR3_SHIFT);
+ sw_set_ack(dram);
+ }
+}
+
+static int sdram_cmd_dq_path_remap(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ void __iomem *phy_base = dram->phy;
+ u32 dramtype = sdram_params->base.dramtype;
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ struct dq_map_info *map_info;
+
+ map_info = (struct dq_map_info *)((void *)common_info +
+ index->dq_map_index.offset * 4);
+
+ if (dramtype <= LPDDR4)
+ writel((map_info->byte_map[dramtype / 4] >>
+ ((dramtype % 4) * 8)) & 0xff,
+ PHY_REG(phy_base, 0x4f));
+
+ return 0;
+}
+
+static void phy_cfg(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ void __iomem *phy_base = dram->phy;
+ u32 i, dq_map, tmp;
+ u32 byte1 = 0, byte0 = 0;
+
+ sdram_cmd_dq_path_remap(dram, sdram_params);
+
+ phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 0);
+ for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
+ writel(sdram_params->phy_regs.phy[i][1],
+ phy_base + sdram_params->phy_regs.phy[i][0]);
+ }
+
+ clrbits_le32(PHY_REG(phy_base, 0x62), BIT(5));
+ dq_map = readl(PHY_REG(phy_base, 0x4f));
+ for (i = 0; i < 4; i++) {
+ if (((dq_map >> (i * 2)) & 0x3) == 0)
+ byte0 = i;
+ if (((dq_map >> (i * 2)) & 0x3) == 1)
+ byte1 = i;
+ }
+
+ tmp = readl(PHY_REG(phy_base, 0xf)) & (~PHY_DQ_WIDTH_MASK);
+ if (cap_info->bw == 2)
+ tmp |= 0xf;
+ else if (cap_info->bw == 1)
+ tmp |= ((1 << byte0) | (1 << byte1));
+ else
+ tmp |= (1 << byte0);
+
+ writel(tmp, PHY_REG(phy_base, 0xf));
+
+ /* lpddr4 odt control by phy, enable cs0 odt */
+ if (sdram_params->base.dramtype == LPDDR4)
+ clrsetbits_le32(PHY_REG(phy_base, 0x20), 0x7 << 4,
+ (1 << 6) | (1 << 4));
+ /* for ca training ca vref choose range1 */
+ setbits_le32(PHY_REG(phy_base, 0x1e), BIT(6));
+ setbits_le32(PHY_REG(phy_base, 0x1f), BIT(6));
+ /* for wr training PHY_0x7c[5], choose range0 */
+ clrbits_le32(PHY_REG(phy_base, 0x7c), BIT(5));
+}
+
+static int update_refresh_reg(struct dram_info *dram)
+{
+ void __iomem *pctl_base = dram->pctl;
+ u32 ret;
+
+ ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
+ writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
+
+ return 0;
+}
+
+/*
+ * rank = 1: cs0
+ * rank = 2: cs1
+ */
+int read_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 dramtype)
+{
+ u32 ret;
+ u32 i, temp;
+ u32 dqmap;
+
+ void __iomem *pctl_base = dram->pctl;
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ struct dq_map_info *map_info;
+
+ map_info = (struct dq_map_info *)((void *)common_info +
+ index->dq_map_index.offset * 4);
+
+ if (dramtype == LPDDR2)
+ dqmap = map_info->lp2_dq0_7_map;
+ else
+ dqmap = map_info->lp3_dq0_7_map;
+
+ pctl_read_mr(pctl_base, rank, mr_num);
+
+ ret = (readl(&dram->ddrgrf->ddr_grf_status[0]) & 0xff);
+
+ if (dramtype != LPDDR4) {
+ temp = 0;
+ for (i = 0; i < 8; i++) {
+ temp = temp | (((ret >> i) & 0x1) <<
+ ((dqmap >> (i * 4)) & 0xf));
+ }
+ } else {
+ temp = (readl(&dram->ddrgrf->ddr_grf_status[1]) & 0xff);
+ }
+
+ return temp;
+}
+
+/* before call this function autorefresh should be disabled */
+void send_a_refresh(struct dram_info *dram)
+{
+ void __iomem *pctl_base = dram->pctl;
+
+ while (readl(pctl_base + DDR_PCTL2_DBGSTAT) & 0x3)
+ continue;
+ writel(0x3, pctl_base + DDR_PCTL2_DBGCMD);
+}
+
+static void enter_sr(struct dram_info *dram, u32 en)
+{
+ void __iomem *pctl_base = dram->pctl;
+
+ if (en) {
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
+ while (1) {
+ if (((readl(pctl_base + DDR_PCTL2_STAT) &
+ PCTL2_SELFREF_TYPE_MASK) ==
+ PCTL2_SELFREF_TYPE_SR_NOT_AUTO) &&
+ ((readl(pctl_base + DDR_PCTL2_STAT) &
+ PCTL2_OPERATING_MODE_MASK) ==
+ PCTL2_OPERATING_MODE_SR))
+ break;
+ }
+ } else {
+ clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
+ while ((readl(pctl_base + DDR_PCTL2_STAT) &
+ PCTL2_OPERATING_MODE_MASK) == PCTL2_OPERATING_MODE_SR)
+ continue;
+ }
+}
+
+void record_dq_prebit(struct dram_info *dram)
+{
+ u32 group, i, tmp;
+ void __iomem *phy_base = dram->phy;
+
+ for (group = 0; group < 4; group++) {
+ for (i = 0; i < ARRAY_SIZE(dq_sel); i++) {
+ /* l_loop_invdelaysel */
+ writel(dq_sel[i][0], PHY_REG(phy_base,
+ grp_addr[group] + 0x2c));
+ tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2e));
+ writel(tmp, PHY_REG(phy_base,
+ grp_addr[group] + dq_sel[i][1]));
+
+ /* r_loop_invdelaysel */
+ writel(dq_sel[i][0], PHY_REG(phy_base,
+ grp_addr[group] + 0x2d));
+ tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2f));
+ writel(tmp, PHY_REG(phy_base,
+ grp_addr[group] + dq_sel[i][2]));
+ }
+ }
+}
+
+static void update_dq_rx_prebit(struct dram_info *dram)
+{
+ void __iomem *phy_base = dram->phy;
+
+ clrsetbits_le32(PHY_REG(phy_base, 0x70), BIT(1) | BIT(6) | BIT(4),
+ BIT(4));
+ udelay(1);
+ clrbits_le32(PHY_REG(phy_base, 0x70), BIT(4));
+}
+
+static void update_dq_tx_prebit(struct dram_info *dram)
+{
+ void __iomem *phy_base = dram->phy;
+
+ clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
+ setbits_le32(PHY_REG(phy_base, 0x2), BIT(3));
+ setbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
+ udelay(1);
+ clrbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
+}
+
+static void update_ca_prebit(struct dram_info *dram)
+{
+ void __iomem *phy_base = dram->phy;
+
+ clrbits_le32(PHY_REG(phy_base, 0x25), BIT(2));
+ setbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
+ udelay(1);
+ clrbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
+}
+
+/*
+ * dir: 0: de-skew = delta_*
+ * 1: de-skew = reg val - delta_*
+ * delta_dir: value for differential signal: clk/
+ * delta_sig: value for single signal: ca/cmd
+ */
+static void modify_ca_deskew(struct dram_info *dram, u32 dir, int delta_dif,
+ int delta_sig, u32 cs, u32 dramtype)
+{
+ void __iomem *phy_base = dram->phy;
+ u32 i, cs_en, tmp;
+ u32 dfi_lp_stat = 0;
+
+ if (cs == 0)
+ cs_en = 1;
+ else if (cs == 2)
+ cs_en = 2;
+ else
+ cs_en = 3;
+
+ if (dramtype == LPDDR4 &&
+ ((readl(PHY_REG(phy_base, 0x60)) & BIT(5)) == 0)) {
+ dfi_lp_stat = 1;
+ setbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
+ }
+ enter_sr(dram, 1);
+
+ for (i = 0; i < 0x20; i++) {
+ if (dir == DESKEW_MDF_ABS_VAL)
+ tmp = delta_sig;
+ else
+ tmp = readl(PHY_REG(phy_base, 0x150 + i)) +
+ delta_sig;
+ writel(tmp, PHY_REG(phy_base, 0x150 + i));
+ }
+
+ if (dir == DESKEW_MDF_ABS_VAL)
+ tmp = delta_dif;
+ else
+ tmp = readl(PHY_REG(phy_base, 0x150 + 0x17)) -
+ delta_sig + delta_dif;
+ writel(tmp, PHY_REG(phy_base, 0x150 + 0x17));
+ writel(tmp, PHY_REG(phy_base, 0x150 + 0x18));
+ if (dramtype == LPDDR4) {
+ writel(tmp, PHY_REG(phy_base, 0x150 + 0x4));
+ writel(tmp, PHY_REG(phy_base, 0x150 + 0xa));
+
+ clrbits_le32(PHY_REG(phy_base, 0x10), cs_en << 6);
+ update_ca_prebit(dram);
+ }
+ enter_sr(dram, 0);
+
+ if (dfi_lp_stat)
+ clrbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
+}
+
+static u32 get_min_value(struct dram_info *dram, u32 signal, u32 rank)
+{
+ u32 i, j, offset = 0;
+ u32 min = 0x3f;
+ void __iomem *phy_base = dram->phy;
+ u32 byte_en;
+
+ if (signal == SKEW_TX_SIGNAL)
+ offset = 8;
+
+ if (signal == SKEW_CA_SIGNAL) {
+ for (i = 0; i < 0x20; i++)
+ min = MIN(min, readl(PHY_REG(phy_base, 0x150 + i)));
+ } else {
+ byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
+ for (j = offset; j < offset + rank * 4; j++) {
+ if (!((byte_en >> (j % 4)) & 1))
+ continue;
+ for (i = 0; i < 11; i++)
+ min = MIN(min,
+ readl(PHY_REG(phy_base,
+ dqs_dq_skew_adr[j] +
+ i)));
+ }
+ }
+
+ return min;
+}
+
+static u32 low_power_update(struct dram_info *dram, u32 en)
+{
+ void __iomem *pctl_base = dram->pctl;
+ u32 lp_stat = 0;
+
+ if (en) {
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, en & 0xf);
+ } else {
+ lp_stat = readl(pctl_base + DDR_PCTL2_PWRCTL) & 0xf;
+ clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 0xf);
+ }
+
+ return lp_stat;
+}
+
+/*
+ * signal:
+ * dir: 0: de-skew = delta_*
+ * 1: de-skew = reg val - delta_*
+ * delta_dir: value for differential signal: dqs
+ * delta_sig: value for single signal: dq/dm
+ */
+static void modify_dq_deskew(struct dram_info *dram, u32 signal, u32 dir,
+ int delta_dif, int delta_sig, u32 rank)
+{
+ void __iomem *phy_base = dram->phy;
+ u32 i, j, tmp, offset;
+ u32 byte_en;
+
+ byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
+
+ if (signal == SKEW_RX_SIGNAL)
+ offset = 0;
+ else
+ offset = 8;
+
+ for (j = offset; j < (offset + rank * 4); j++) {
+ if (!((byte_en >> (j % 4)) & 1))
+ continue;
+ for (i = 0; i < 0x9; i++) {
+ if (dir == DESKEW_MDF_ABS_VAL)
+ tmp = delta_sig;
+ else
+ tmp = delta_sig + readl(PHY_REG(phy_base,
+ dqs_dq_skew_adr[j] +
+ i));
+ writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + i));
+ }
+ if (dir == DESKEW_MDF_ABS_VAL)
+ tmp = delta_dif;
+ else
+ tmp = delta_dif + readl(PHY_REG(phy_base,
+ dqs_dq_skew_adr[j] + 9));
+ writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 9));
+ writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 0xa));
+ }
+ if (signal == SKEW_RX_SIGNAL)
+ update_dq_rx_prebit(dram);
+ else
+ update_dq_tx_prebit(dram);
+}
+
+static int data_training_rg(struct dram_info *dram, u32 cs, u32 dramtype)
+{
+ void __iomem *phy_base = dram->phy;
+ u32 ret;
+ u32 dis_auto_zq = 0;
+ u32 odt_val_up, odt_val_dn;
+ u32 i, j;
+
+ odt_val_dn = readl(PHY_REG(phy_base, 0x110));
+ odt_val_up = readl(PHY_REG(phy_base, 0x111));
+
+ if (dramtype != LPDDR4) {
+ for (i = 0; i < 4; i++) {
+ j = 0x110 + i * 0x10;
+ writel(PHY_DDR4_LPDDR3_RTT_294ohm,
+ PHY_REG(phy_base, j));
+ writel(PHY_DDR4_LPDDR3_RTT_DISABLE,
+ PHY_REG(phy_base, j + 0x1));
+ }
+ }
+ dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+ /* use normal read mode for data training */
+ clrbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
+
+ if (dramtype == DDR4)
+ setbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
+
+ /* choose training cs */
+ clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
+ /* enable gate training */
+ clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
+ udelay(50);
+ ret = readl(PHY_REG(phy_base, 0x91));
+ /* disable gate training */
+ clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
+ clrbits_le32(PHY_REG(phy_base, 2), 0x30);
+ pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+ ret = (ret & 0x2f) ^ (readl(PHY_REG(phy_base, 0xf)) & 0xf);
+
+ if (dramtype != LPDDR4) {
+ for (i = 0; i < 4; i++) {
+ j = 0x110 + i * 0x10;
+ writel(odt_val_dn, PHY_REG(phy_base, j));
+ writel(odt_val_up, PHY_REG(phy_base, j + 0x1));
+ }
+ }
+ return ret;
+}
+
+static int data_training_wl(struct dram_info *dram, u32 cs, u32 dramtype,
+ u32 rank)
+{
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ u32 dis_auto_zq = 0;
+ u32 tmp;
+ u32 cur_fsp;
+ u32 timeout_us = 1000;
+
+ dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+ clrbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
+
+ cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+ tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_INIT3) &
+ 0xffff;
+ writel(tmp & 0xff, PHY_REG(phy_base, 0x3));
+
+ /* disable another cs's output */
+ if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
+ pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp | (1 << 12),
+ dramtype);
+ if (dramtype == DDR3 || dramtype == DDR4)
+ writel(0x40 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
+ else
+ writel(0x80 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
+
+ /* choose cs */
+ clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
+ ((0x2 >> cs) << 6) | (0 << 2));
+ /* enable write leveling */
+ clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
+ ((0x2 >> cs) << 6) | (1 << 2));
+
+ while (1) {
+ if ((readl(PHY_REG(phy_base, 0x92)) & 0xf) ==
+ (readl(PHY_REG(phy_base, 0xf)) & 0xf))
+ break;
+
+ udelay(1);
+ if (timeout_us-- == 0) {
+ printascii("error: write leveling timeout\n");
+ while (1)
+ ;
+ }
+ }
+
+ /* disable write leveling */
+ clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
+ ((0x2 >> cs) << 6) | (0 << 2));
+ clrsetbits_le32(PHY_REG(phy_base, 2), 0x3 << 6, 0 << 6);
+
+ /* enable another cs's output */
+ if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
+ pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp & ~(1 << 12),
+ dramtype);
+
+ pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+ return 0;
+}
+
+char pattern[32] = {
+ 0xaa, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa,
+ 0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0x55,
+ 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55,
+ 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa
+};
+
+static int data_training_rd(struct dram_info *dram, u32 cs, u32 dramtype,
+ u32 mhz)
+{
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ u32 trefi_1x, trfc_1x;
+ u32 dis_auto_zq = 0;
+ u32 timeout_us = 1000;
+ u32 dqs_default;
+ u32 cur_fsp;
+ u32 vref_inner;
+ u32 i;
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ struct dq_map_info *map_info;
+
+ vref_inner = readl(PHY_REG(phy_base, 0x128)) & 0xff;
+ if (dramtype == DDR3 && vref_inner == 0x80) {
+ for (i = 0; i < 4; i++)
+ writel(vref_inner - 0xa,
+ PHY_REG(phy_base, 0x118 + i * 0x10));
+
+ /* reg_rx_vref_value_update */
+ setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+ clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+ }
+
+ map_info = (struct dq_map_info *)((void *)common_info +
+ index->dq_map_index.offset * 4);
+ /* only 1cs a time, 0:cs0 1 cs1 */
+ if (cs > 1)
+ return -1;
+
+ dqs_default = 0xf;
+ dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+ cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+ /* config refresh timing */
+ trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+ DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
+ trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+ DDR_PCTL2_RFSHTMG) & 0x3ff;
+ /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
+ clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
+ /* reg_phy_trfc */
+ clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
+ /* reg_max_refi_cnt */
+ clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
+
+ /* choose training cs */
+ clrsetbits_le32(PHY_REG(phy_base, 0x71), 0x3 << 6, (0x2 >> cs) << 6);
+
+ /* set dq map for ddr4 */
+ if (dramtype == DDR4) {
+ setbits_le32(PHY_REG(phy_base, 0x70), BIT(7));
+ for (i = 0; i < 4; i++) {
+ writel((map_info->ddr4_dq_map[cs * 2] >>
+ ((i % 4) * 8)) & 0xff,
+ PHY_REG(phy_base, 0x238 + i));
+ writel((map_info->ddr4_dq_map[cs * 2 + 1] >>
+ ((i % 4) * 8)) & 0xff,
+ PHY_REG(phy_base, 0x2b8 + i));
+ }
+ }
+
+ /* cha_l reg_l_rd_train_dqs_default[5:0] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x230), 0x3f, dqs_default);
+ /* cha_h reg_h_rd_train_dqs_default[5:0] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x234), 0x3f, dqs_default);
+ /* chb_l reg_l_rd_train_dqs_default[5:0] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x2b0), 0x3f, dqs_default);
+ /* chb_h reg_h_rd_train_dqs_default[5:0] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x2b4), 0x3f, dqs_default);
+
+ /* Choose the read train auto mode */
+ clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x1);
+ /* Enable the auto train of the read train */
+ clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x3);
+
+ /* Wait the train done. */
+ while (1) {
+ if ((readl(PHY_REG(phy_base, 0x93)) >> 7) & 0x1)
+ break;
+
+ udelay(1);
+ if (timeout_us-- == 0) {
+ printascii("error: read training timeout\n");
+ return -1;
+ }
+ }
+
+ /* Check the read train state */
+ if ((readl(PHY_REG(phy_base, 0x240)) & 0x3) ||
+ (readl(PHY_REG(phy_base, 0x2c0)) & 0x3)) {
+ printascii("error: read training error\n");
+ return -1;
+ }
+
+ /* Exit the Read Training by setting */
+ clrbits_le32(PHY_REG(phy_base, 0x70), BIT(1));
+
+ pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+ if (dramtype == DDR3 && vref_inner == 0x80) {
+ for (i = 0; i < 4; i++)
+ writel(vref_inner,
+ PHY_REG(phy_base, 0x118 + i * 0x10));
+
+ /* reg_rx_vref_value_update */
+ setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+ clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+ }
+
+ return 0;
+}
+
+static int data_training_wr(struct dram_info *dram, u32 cs, u32 dramtype,
+ u32 mhz, u32 dst_fsp)
+{
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ u32 trefi_1x, trfc_1x;
+ u32 dis_auto_zq = 0;
+ u32 timeout_us = 1000;
+ u32 cur_fsp;
+ u32 mr_tmp, cl, cwl, phy_fsp, offset = 0;
+
+ if (dramtype == LPDDR3 && mhz <= 400) {
+ phy_fsp = (readl(PHY_REG(phy_base, 0xc)) >> 0x2) & 0x3;
+ offset = (phy_fsp == 0) ? 0x5 : 0x387 + (phy_fsp - 1) * 3;
+ cl = readl(PHY_REG(phy_base, offset));
+ cwl = readl(PHY_REG(phy_base, offset + 2));
+
+ clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, 0x8);
+ clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, 0x4);
+ pctl_write_mr(dram->pctl, 3, 2, 0x6, dramtype);
+ }
+
+ dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
+
+ /* PHY_0x7b[7:0] reg_train_col_addr[7:0] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x7b), 0xff, 0x0);
+ /* PHY_0x7c[4:2] reg_train_ba_addr[2:0] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x7 << 2, 0x0 << 2);
+ /* PHY_0x7c[1:0] reg_train_col_addr[9:8] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3, 0x0);
+ /* PHY_0x7d[7:0] reg_train_row_addr[7:0] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x7d), 0xff, 0x0);
+ /* PHY_0x7e[7:0] reg_train_row_addr[15:8] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x7e), 0xff, 0x0);
+
+ /* PHY_0x71[3] wrtrain_check_data_value_random_gen */
+ clrbits_le32(PHY_REG(phy_base, 0x71), BIT(3));
+
+ /* config refresh timing */
+ cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+ trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+ DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
+ trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+ DDR_PCTL2_RFSHTMG) & 0x3ff;
+ /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
+ clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
+ clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
+ /* reg_phy_trfc */
+ clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
+ /* reg_max_refi_cnt */
+ clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
+
+ /* choose training cs */
+ clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3 << 6, (0x2 >> cs) << 6);
+
+ /* PHY_0x7a [4] reg_wr_train_dqs_default_bypass */
+ /* 0: Use the write-leveling value. */
+ /* 1: use reg0x233 0x237 0x2b3 0x2b7 */
+ setbits_le32(PHY_REG(phy_base, 0x7a), BIT(4));
+
+ /* PHY_0x7a [0] reg_dq_wr_train_auto */
+ setbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
+
+ /* PHY_0x7a [1] reg_dq_wr_train_en */
+ setbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
+
+ send_a_refresh(dram);
+
+ while (1) {
+ if ((readl(PHY_REG(phy_base, 0x92)) >> 7) & 0x1)
+ break;
+
+ udelay(1);
+ if (timeout_us-- == 0) {
+ printascii("error: write training timeout\n");
+ while (1)
+ ;
+ }
+ }
+
+ /* Check the write train state */
+ if ((readl(PHY_REG(phy_base, 0x90)) >> 5) & 0x7) {
+ printascii("error: write training error\n");
+ return -1;
+ }
+
+ /* PHY_0x7a [1] reg_dq_wr_train_en */
+ clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
+
+ pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
+
+ /* save LPDDR4 write vref to fsp_param for dfs */
+ if (dramtype == LPDDR4) {
+ fsp_param[dst_fsp].vref_dq[cs] =
+ ((readl(PHY_REG(phy_base, 0x384)) & 0x3f) +
+ (readl(PHY_REG(phy_base, 0x385)) & 0x3f)) / 2;
+ /* add range info */
+ fsp_param[dst_fsp].vref_dq[cs] |=
+ ((readl(PHY_REG(phy_base, 0x7c)) & BIT(5)) << 1);
+ }
+
+ if (dramtype == LPDDR3 && mhz <= 400) {
+ clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, cl);
+ clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, cwl);
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+ DDR_PCTL2_INIT3);
+ pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
+ dramtype);
+ }
+
+ return 0;
+}
+
+static int data_training(struct dram_info *dram, u32 cs,
+ struct rv1126_sdram_params *sdram_params, u32 dst_fsp,
+ u32 training_flag)
+{
+ u32 ret = 0;
+
+ if (training_flag == FULL_TRAINING)
+ training_flag = READ_GATE_TRAINING | WRITE_LEVELING |
+ WRITE_TRAINING | READ_TRAINING;
+
+ if ((training_flag & WRITE_LEVELING) == WRITE_LEVELING) {
+ ret = data_training_wl(dram, cs,
+ sdram_params->base.dramtype,
+ sdram_params->ch.cap_info.rank);
+ if (ret != 0)
+ goto out;
+ }
+
+ if ((training_flag & READ_GATE_TRAINING) == READ_GATE_TRAINING) {
+ ret = data_training_rg(dram, cs,
+ sdram_params->base.dramtype);
+ if (ret != 0)
+ goto out;
+ }
+
+ if ((training_flag & READ_TRAINING) == READ_TRAINING) {
+ ret = data_training_rd(dram, cs,
+ sdram_params->base.dramtype,
+ sdram_params->base.ddr_freq);
+ if (ret != 0)
+ goto out;
+ }
+
+ if ((training_flag & WRITE_TRAINING) == WRITE_TRAINING) {
+ ret = data_training_wr(dram, cs,
+ sdram_params->base.dramtype,
+ sdram_params->base.ddr_freq, dst_fsp);
+ if (ret != 0)
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static int get_wrlvl_val(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ int i, j, clk_skew;
+ void __iomem *phy_base = dram->phy;
+ u32 lp_stat;
+ int ret;
+
+ lp_stat = low_power_update(dram, 0);
+
+ clk_skew = 0x1f;
+ modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, clk_skew, 3,
+ sdram_params->base.dramtype);
+
+ ret = data_training(dram, 0, sdram_params, 0, WRITE_LEVELING);
+ if (sdram_params->ch.cap_info.rank == 2)
+ ret |= data_training(dram, 1, sdram_params, 0, WRITE_LEVELING);
+
+ for (j = 0; j < 2; j++)
+ for (i = 0; i < 4; i++)
+ wrlvl_result[j][i] =
+ (readl(PHY_REG(phy_base, wrlvl_result_offset[j][i])) & 0x3f) -
+ clk_skew;
+
+ low_power_update(dram, lp_stat);
+
+ return ret;
+}
+
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+static void init_rw_trn_result_struct(struct rw_trn_result *result,
+ void __iomem *phy_base, u8 cs_num)
+{
+ int i;
+
+ result->cs_num = cs_num;
+ result->byte_en = readb(PHY_REG(dram_info.phy, 0xf)) &
+ PHY_DQ_WIDTH_MASK;
+ for (i = 0; i < FSP_NUM; i++)
+ result->fsp_mhz[i] = 0;
+}
+
+static void save_rw_trn_min_max(void __iomem *phy_base,
+ struct cs_rw_trn_result *rd_result,
+ struct cs_rw_trn_result *wr_result,
+ u8 byte_en)
+{
+ u16 phy_ofs;
+ u8 dqs;
+ u8 dq;
+
+ for (dqs = 0; dqs < BYTE_NUM; dqs++) {
+ if ((byte_en & BIT(dqs)) == 0)
+ continue;
+
+ /* Channel A or B (low or high 16 bit) */
+ phy_ofs = dqs < 2 ? 0x230 : 0x2b0;
+ /* low or high 8 bit */
+ phy_ofs += (dqs & 0x1) == 0 ? 0 : 0x9;
+ for (dq = 0; dq < 8; dq++) {
+ rd_result->dqs[dqs].dq_min[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + 0x15 + dq));
+ rd_result->dqs[dqs].dq_max[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + 0x27 + dq));
+ wr_result->dqs[dqs].dq_min[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + 0x3d + dq));
+ wr_result->dqs[dqs].dq_max[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + 0x4f + dq));
+ }
+ }
+}
+
+static void save_rw_trn_deskew(void __iomem *phy_base,
+ struct fsp_rw_trn_result *result, u8 cs_num,
+ int min_val, bool rw)
+{
+ u16 phy_ofs;
+ u8 cs;
+ u8 dq;
+
+ result->min_val = min_val;
+
+ for (cs = 0; cs < cs_num; cs++) {
+ phy_ofs = cs == 0 ? 0x170 : 0x1a0;
+ phy_ofs += rw == SKEW_RX_SIGNAL ? 0x1 : 0x17;
+ for (dq = 0; dq < 8; dq++) {
+ result->cs[cs].dqs[0].dq_deskew[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + dq));
+ result->cs[cs].dqs[1].dq_deskew[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + 0xb + dq));
+ result->cs[cs].dqs[2].dq_deskew[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + 0x60 + dq));
+ result->cs[cs].dqs[3].dq_deskew[dq] =
+ readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + dq));
+ }
+
+ result->cs[cs].dqs[0].dqs_deskew =
+ readb(PHY_REG(phy_base, phy_ofs + 0x8));
+ result->cs[cs].dqs[1].dqs_deskew =
+ readb(PHY_REG(phy_base, phy_ofs + 0xb + 0x8));
+ result->cs[cs].dqs[2].dqs_deskew =
+ readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0x8));
+ result->cs[cs].dqs[3].dqs_deskew =
+ readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + 0x8));
+ }
+}
+
+static void save_rw_trn_result_to_ddr(struct rw_trn_result *result)
+{
+ result->flag = DDR_DQ_EYE_FLAG;
+ memcpy((void *)(RW_TRN_RESULT_ADDR), result, sizeof(*result));
+}
+#endif
+
+static int high_freq_training(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params,
+ u32 fsp)
+{
+ u32 i, j;
+ void __iomem *phy_base = dram->phy;
+ u32 dramtype = sdram_params->base.dramtype;
+ int min_val;
+ int dqs_skew, clk_skew, ca_skew;
+ u8 byte_en;
+ int ret;
+
+ byte_en = readl(PHY_REG(phy_base, 0xf)) & PHY_DQ_WIDTH_MASK;
+ dqs_skew = 0;
+ for (j = 0; j < sdram_params->ch.cap_info.rank; j++) {
+ for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) {
+ if ((byte_en & BIT(i)) != 0)
+ dqs_skew += wrlvl_result[j][i];
+ }
+ }
+ dqs_skew = dqs_skew /
+ (int)(sdram_params->ch.cap_info.rank * (1 << sdram_params->ch.cap_info.bw));
+
+ clk_skew = 0x20 - dqs_skew;
+ dqs_skew = 0x20;
+
+ if (dramtype == LPDDR4) {
+ min_val = 0xff;
+ for (j = 0; j < sdram_params->ch.cap_info.rank; j++)
+ for (i = 0; i < sdram_params->ch.cap_info.bw; i++)
+ min_val = MIN(wrlvl_result[j][i], min_val);
+
+ if (min_val < 0) {
+ clk_skew = -min_val;
+ ca_skew = -min_val;
+ } else {
+ clk_skew = 0;
+ ca_skew = 0;
+ }
+ } else if (dramtype == LPDDR3) {
+ ca_skew = clk_skew - 4;
+ } else {
+ ca_skew = clk_skew;
+ }
+ modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, ca_skew, 3,
+ dramtype);
+
+ writel(wrlvl_result[0][0] + clk_skew, PHY_REG(phy_base, 0x233));
+ writel(wrlvl_result[0][1] + clk_skew, PHY_REG(phy_base, 0x237));
+ writel(wrlvl_result[0][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
+ writel(wrlvl_result[0][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
+ ret = data_training(dram, 0, sdram_params, fsp, READ_GATE_TRAINING |
+ READ_TRAINING | WRITE_TRAINING);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+ rw_trn_result.fsp_mhz[fsp] = (u16)sdram_params->base.ddr_freq;
+ save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[0],
+ &rw_trn_result.wr_fsp[fsp].cs[0],
+ rw_trn_result.byte_en);
+#endif
+ if (sdram_params->ch.cap_info.rank == 2) {
+ writel(wrlvl_result[1][0] + clk_skew, PHY_REG(phy_base, 0x233));
+ writel(wrlvl_result[1][1] + clk_skew, PHY_REG(phy_base, 0x237));
+ writel(wrlvl_result[1][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
+ writel(wrlvl_result[1][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
+ ret |= data_training(dram, 1, sdram_params, fsp,
+ READ_GATE_TRAINING | READ_TRAINING |
+ WRITE_TRAINING);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+ save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[1],
+ &rw_trn_result.wr_fsp[fsp].cs[1],
+ rw_trn_result.byte_en);
+#endif
+ }
+ if (ret)
+ goto out;
+
+ record_dq_prebit(dram);
+
+ min_val = get_min_value(dram, SKEW_RX_SIGNAL,
+ sdram_params->ch.cap_info.rank) * -1;
+ modify_dq_deskew(dram, SKEW_RX_SIGNAL, DESKEW_MDF_DIFF_VAL,
+ min_val, min_val, sdram_params->ch.cap_info.rank);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+ save_rw_trn_deskew(phy_base, &rw_trn_result.rd_fsp[fsp],
+ rw_trn_result.cs_num, (u8)(min_val * (-1)),
+ SKEW_RX_SIGNAL);
+#endif
+
+ min_val = MIN(get_min_value(dram, SKEW_TX_SIGNAL,
+ sdram_params->ch.cap_info.rank),
+ get_min_value(dram, SKEW_CA_SIGNAL,
+ sdram_params->ch.cap_info.rank)) * -1;
+
+ /* clk = 0, rx all skew -7, tx - min_value */
+ modify_ca_deskew(dram, DESKEW_MDF_DIFF_VAL, min_val, min_val, 3,
+ dramtype);
+
+ modify_dq_deskew(dram, SKEW_TX_SIGNAL, DESKEW_MDF_DIFF_VAL,
+ min_val, min_val, sdram_params->ch.cap_info.rank);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+ save_rw_trn_deskew(phy_base, &rw_trn_result.wr_fsp[fsp],
+ rw_trn_result.cs_num, (u8)(min_val * (-1)),
+ SKEW_TX_SIGNAL);
+#endif
+
+ ret = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING);
+ if (sdram_params->ch.cap_info.rank == 2)
+ ret |= data_training(dram, 1, sdram_params, 0,
+ READ_GATE_TRAINING);
+out:
+ return ret;
+}
+
+static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
+{
+ writel(ddrconfig, &dram->msch->deviceconf);
+ clrsetbits_le32(&dram->grf->noc_con0, 0x3 << 0, 0 << 0);
+}
+
+static void update_noc_timing(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ void __iomem *pctl_base = dram->pctl;
+ u32 bw, bl;
+
+ bw = 8 << sdram_params->ch.cap_info.bw;
+ bl = ((readl(pctl_base + DDR_PCTL2_MSTR) >> 16) & 0xf) * 2;
+
+ /* update the noc timing related to data bus width */
+ if ((bw / 8 * bl) <= 16)
+ sdram_params->ch.noc_timings.ddrmode.b.burstsize = 0;
+ else if ((bw / 8 * bl) == 32)
+ sdram_params->ch.noc_timings.ddrmode.b.burstsize = 1;
+ else if ((bw / 8 * bl) == 64)
+ sdram_params->ch.noc_timings.ddrmode.b.burstsize = 2;
+ else
+ sdram_params->ch.noc_timings.ddrmode.b.burstsize = 3;
+
+ sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty =
+ (bl * bw / 8) > 16 ? (bl / 4) : (16 / (bl * bw / 8)) * bl / 4;
+
+ if (sdram_params->base.dramtype == LPDDR4) {
+ sdram_params->ch.noc_timings.ddrmode.b.mwrsize =
+ (bw == 16) ? 0x1 : 0x2;
+ sdram_params->ch.noc_timings.ddrtimingc0.b.wrtomwr =
+ 3 * sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty;
+ }
+
+ writel(sdram_params->ch.noc_timings.ddrtiminga0.d32,
+ &dram->msch->ddrtiminga0);
+ writel(sdram_params->ch.noc_timings.ddrtimingb0.d32,
+ &dram->msch->ddrtimingb0);
+ writel(sdram_params->ch.noc_timings.ddrtimingc0.d32,
+ &dram->msch->ddrtimingc0);
+ writel(sdram_params->ch.noc_timings.devtodev0.d32,
+ &dram->msch->devtodev0);
+ writel(sdram_params->ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
+ writel(sdram_params->ch.noc_timings.ddr4timing.d32,
+ &dram->msch->ddr4timing);
+}
+
+static int split_setup(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 dramtype = sdram_params->base.dramtype;
+ u32 split_size, split_mode;
+ u64 cs_cap[2], cap;
+
+ cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dramtype);
+ cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dramtype);
+ /* only support the larger cap is in low 16bit */
+ if (cap_info->cs0_high16bit_row < cap_info->cs0_row) {
+ cap = cs_cap[0] / (1 << (cap_info->cs0_row -
+ cap_info->cs0_high16bit_row));
+ } else if ((cap_info->cs1_high16bit_row < cap_info->cs1_row) &&
+ (cap_info->rank == 2)) {
+ if (!cap_info->cs1_high16bit_row)
+ cap = cs_cap[0];
+ else
+ cap = cs_cap[0] + cs_cap[1] / (1 << (cap_info->cs1_row -
+ cap_info->cs1_high16bit_row));
+ } else {
+ goto out;
+ }
+ split_size = (u32)(cap >> 24) & SPLIT_SIZE_MASK;
+ if (cap_info->bw == 2)
+ split_mode = SPLIT_MODE_32_L16_VALID;
+ else
+ split_mode = SPLIT_MODE_16_L8_VALID;
+
+ rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
+ (SPLIT_MODE_MASK << SPLIT_MODE_OFFSET) |
+ (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
+ (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
+ (split_mode << SPLIT_MODE_OFFSET) |
+ (0x0 << SPLIT_BYPASS_OFFSET) |
+ (split_size << SPLIT_SIZE_OFFSET));
+
+ rk_clrsetreg(BUS_SGRF_BASE_ADDR + SGRF_SOC_CON2,
+ MSCH_AXI_BYPASS_ALL_MASK << MSCH_AXI_BYPASS_ALL_SHIFT,
+ 0x0 << MSCH_AXI_BYPASS_ALL_SHIFT);
+
+out:
+ return 0;
+}
+
+static void split_bypass(struct dram_info *dram)
+{
+ if ((readl(&dram->ddrgrf->grf_ddrsplit_con) &
+ (1 << SPLIT_BYPASS_OFFSET)) != 0)
+ return;
+
+ /* bypass split */
+ rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
+ (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
+ (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
+ (0x1 << SPLIT_BYPASS_OFFSET) |
+ (0x0 << SPLIT_SIZE_OFFSET));
+}
+
+static void dram_all_config(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 dram_type = sdram_params->base.dramtype;
+ void __iomem *pctl_base = dram->pctl;
+ u32 sys_reg2 = 0;
+ u32 sys_reg3 = 0;
+ u64 cs_cap[2];
+ u32 cs_pst;
+
+ set_ddrconfig(dram, cap_info->ddrconfig);
+ sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
+ &sys_reg3, 0);
+ writel(sys_reg2, &dram->pmugrf->os_reg[2]);
+ writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+
+ cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
+ cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
+
+ if (cap_info->rank == 2) {
+ cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
+ 6 + 2;
+ if (cs_pst > 28)
+ cs_cap[0] = 1llu << cs_pst;
+ }
+
+ writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
+ (((cs_cap[0] >> 20) / 64) & 0xff),
+ &dram->msch->devicesize);
+ update_noc_timing(dram, sdram_params);
+}
+
+static void enable_low_power(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ void __iomem *pctl_base = dram->pctl;
+ u32 grf_lp_con;
+
+ writel(0x1f1f0617, &dram->ddrgrf->ddr_grf_con[1]);
+
+ if (sdram_params->base.dramtype == DDR4)
+ grf_lp_con = (0x7 << 16) | (1 << 1);
+ else if (sdram_params->base.dramtype == DDR3)
+ grf_lp_con = (0x7 << 16) | (1 << 0);
+ else
+ grf_lp_con = (0x7 << 16) | (1 << 2);
+
+ /* en lpckdis_en */
+ grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
+ writel(grf_lp_con, &dram->ddrgrf->ddr_grf_lp_con);
+
+ /* enable sr, pd */
+ if (dram->pd_idle == 0)
+ clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+ else
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
+ if (dram->sr_idle == 0)
+ clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+ else
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
+ setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
+}
+
+static void print_ddr_info(struct rv1126_sdram_params *sdram_params)
+{
+ u32 split;
+
+ if ((readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
+ (1 << SPLIT_BYPASS_OFFSET)) != 0)
+ split = 0;
+ else
+ split = readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
+ SPLIT_SIZE_MASK;
+
+ sdram_print_ddr_info(&sdram_params->ch.cap_info,
+ &sdram_params->base, split);
+}
+
+static int sdram_init_(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params, u32 post_init)
+{
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ u32 ddr4_vref;
+ u32 mr_tmp;
+
+ rkclk_configure_ddr(dram, sdram_params);
+
+ rkclk_ddr_reset(dram, 1, 1, 1, 1);
+ udelay(10);
+
+ rkclk_ddr_reset(dram, 1, 1, 1, 0);
+ phy_cfg(dram, sdram_params);
+
+ rkclk_ddr_reset(dram, 1, 1, 0, 0);
+ phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 1);
+
+ rkclk_ddr_reset(dram, 1, 0, 0, 0);
+ pctl_cfg(dram->pctl, &sdram_params->pctl_regs,
+ dram->sr_idle, dram->pd_idle);
+
+ if (sdram_params->ch.cap_info.bw == 2) {
+ /* 32bit interface use pageclose */
+ setbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
+ /* pageclose = 1, pageclose_timer = 0 will err in lp4 328MHz */
+ clrsetbits_le32(pctl_base + DDR_PCTL2_SCHED1, 0xff, 0x1 << 0);
+ } else {
+ clrbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
+ }
+
+#ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
+ u32 tmp, trefi;
+
+ tmp = readl(pctl_base + DDR_PCTL2_RFSHTMG);
+ trefi = (tmp >> 16) & 0xfff;
+ writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
+ pctl_base + DDR_PCTL2_RFSHTMG);
+#endif
+
+ /* set frequency_mode */
+ setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
+ /* set target_frequency to Frequency 0 */
+ clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, 0);
+
+ set_ds_odt(dram, sdram_params, 0);
+ sdram_params->ch.cap_info.ddrconfig = calculate_ddrconfig(sdram_params);
+ set_ctl_address_map(dram, sdram_params);
+
+ setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
+
+ rkclk_ddr_reset(dram, 0, 0, 0, 0);
+
+ while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0)
+ continue;
+
+ if (sdram_params->base.dramtype == LPDDR3) {
+ pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, LPDDR3);
+ } else if (sdram_params->base.dramtype == LPDDR4) {
+ mr_tmp = readl(pctl_base + DDR_PCTL2_INIT6);
+ /* MR11 */
+ pctl_write_mr(dram->pctl, 3, 11,
+ mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
+ LPDDR4);
+ /* MR12 */
+ pctl_write_mr(dram->pctl, 3, 12,
+ mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
+ LPDDR4);
+
+ mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
+ /* MR22 */
+ pctl_write_mr(dram->pctl, 3, 22,
+ mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
+ LPDDR4);
+ }
+
+ if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) != 0) {
+ if (post_init != 0)
+ printascii("DTT cs0 error\n");
+ return -1;
+ }
+
+ if (sdram_params->base.dramtype == LPDDR4) {
+ mr_tmp = read_mr(dram, 1, 14, LPDDR4);
+
+ if (mr_tmp != 0x4d)
+ return -1;
+ }
+
+ if (sdram_params->base.dramtype == LPDDR4) {
+ mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
+ /* MR14 */
+ pctl_write_mr(dram->pctl, 3, 14,
+ mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
+ LPDDR4);
+ }
+ if (post_init != 0 && sdram_params->ch.cap_info.rank == 2) {
+ if (data_training(dram, 1, sdram_params, 0,
+ READ_GATE_TRAINING) != 0) {
+ printascii("DTT cs1 error\n");
+ return -1;
+ }
+ }
+
+ if (sdram_params->base.dramtype == DDR4) {
+ ddr4_vref = readl(PHY_REG(phy_base, 0x105)) * 39;
+ pctl_write_vrefdq(dram->pctl, 0x3, ddr4_vref,
+ sdram_params->base.dramtype);
+ }
+
+ dram_all_config(dram, sdram_params);
+ enable_low_power(dram, sdram_params);
+
+ return 0;
+}
+
+static u64 dram_detect_cap(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params,
+ unsigned char channel)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ u32 mr8;
+
+ u32 bktmp;
+ u32 coltmp;
+ u32 rowtmp;
+ u32 cs;
+ u32 dram_type = sdram_params->base.dramtype;
+ u32 pwrctl;
+ u32 i, dq_map;
+ u32 byte1 = 0, byte0 = 0;
+ u32 tmp, byte;
+ struct sdram_head_info_index_v2 *index = (struct sdram_head_info_index_v2 *)common_info;
+ struct dq_map_info *map_info = (struct dq_map_info *)
+ ((void *)common_info + index->dq_map_index.offset * 4);
+
+ cap_info->bw = dram_type == DDR3 ? 0 : 1;
+ if (dram_type != LPDDR4) {
+ if (dram_type != DDR4) {
+ coltmp = 12;
+ bktmp = 3;
+ if (dram_type == LPDDR2)
+ rowtmp = 15;
+ else
+ rowtmp = 16;
+
+ if (sdram_detect_col(cap_info, coltmp) != 0)
+ goto cap_err;
+
+ sdram_detect_bank(cap_info, coltmp, bktmp);
+ if (dram_type != LPDDR3)
+ sdram_detect_dbw(cap_info, dram_type);
+ } else {
+ coltmp = 10;
+ bktmp = 4;
+ rowtmp = 17;
+
+ cap_info->col = 10;
+ cap_info->bk = 2;
+ sdram_detect_bg(cap_info, coltmp);
+ }
+
+ if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
+ goto cap_err;
+
+ sdram_detect_row_3_4(cap_info, coltmp, bktmp);
+ } else {
+ cap_info->col = 10;
+ cap_info->bk = 3;
+ mr8 = read_mr(dram, 1, 8, dram_type);
+ cap_info->dbw = ((mr8 >> 6) & 0x3) == 0 ? 1 : 0;
+ mr8 = (mr8 >> 2) & 0xf;
+ if (mr8 >= 0 && mr8 <= 6) {
+ cap_info->cs0_row = 14 + (mr8 + 1) / 2;
+ } else if (mr8 == 0xc) {
+ cap_info->cs0_row = 13;
+ } else {
+ printascii("Cap ERR: Fail to get cap of LPDDR4/X from MR8\n");
+ goto cap_err;
+ }
+ if (cap_info->dbw == 0)
+ cap_info->cs0_row++;
+ cap_info->row_3_4 = mr8 % 2 == 1 ? 1 : 0;
+ if (cap_info->cs0_row >= 17) {
+ printascii("Cap ERR: ");
+ printascii("RV1126 LPDDR4/X cannot support row >= 17\n");
+ goto cap_err;
+ // cap_info->cs0_row = 16;
+ // cap_info->row_3_4 = 0;
+ }
+ }
+
+ pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
+ writel(0, pctl_base + DDR_PCTL2_PWRCTL);
+
+ if (data_training(dram, 1, sdram_params, 0, READ_GATE_TRAINING) == 0)
+ cs = 1;
+ else
+ cs = 0;
+ cap_info->rank = cs + 1;
+
+ setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
+
+ tmp = data_training_rg(dram, 0, dram_type) & 0xf;
+
+ if (tmp == 0) {
+ cap_info->bw = 2;
+ } else {
+ if (dram_type == DDR3 || dram_type == DDR4) {
+ dq_map = 0;
+ byte = 0;
+ for (i = 0; i < 4; i++) {
+ if ((tmp & BIT(i)) == 0) {
+ dq_map |= byte << (i * 2);
+ byte++;
+ }
+ }
+ cap_info->bw = byte / 2;
+ for (i = 0; i < 4; i++) {
+ if ((tmp & BIT(i)) != 0) {
+ dq_map |= byte << (i * 2);
+ byte++;
+ }
+ }
+ clrsetbits_le32(&map_info->byte_map[0], 0xff << 24, dq_map << 24);
+ } else {
+ dq_map = readl(PHY_REG(phy_base, 0x4f));
+ for (i = 0; i < 4; i++) {
+ if (((dq_map >> (i * 2)) & 0x3) == 0)
+ byte0 = i;
+ if (((dq_map >> (i * 2)) & 0x3) == 1)
+ byte1 = i;
+ }
+ clrsetbits_le32(PHY_REG(phy_base, 0xf), PHY_DQ_WIDTH_MASK,
+ BIT(byte0) | BIT(byte1));
+ if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) == 0)
+ cap_info->bw = 1;
+ else
+ cap_info->bw = 0;
+ }
+ }
+ if (cap_info->bw > 0)
+ cap_info->dbw = 1;
+
+ writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
+
+ cap_info->cs0_high16bit_row = cap_info->cs0_row;
+ if (cs) {
+ cap_info->cs1_row = cap_info->cs0_row;
+ cap_info->cs1_high16bit_row = cap_info->cs0_row;
+ } else {
+ cap_info->cs1_row = 0;
+ cap_info->cs1_high16bit_row = 0;
+ }
+
+ if (dram_type == LPDDR3)
+ sdram_detect_dbw(cap_info, dram_type);
+
+ return 0;
+cap_err:
+ return -1;
+}
+
+static int dram_detect_cs1_row(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params,
+ unsigned char channel)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ void __iomem *pctl_base = dram->pctl;
+ u32 ret = 0;
+ void __iomem *test_addr;
+ u32 row, bktmp, coltmp, bw;
+ u64 cs0_cap;
+ u32 byte_mask;
+ u32 cs_pst;
+ u32 cs_add = 0;
+ u32 max_row;
+
+ if (cap_info->rank == 2) {
+ cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
+ 6 + 2;
+ if (cs_pst < 28)
+ cs_add = 1;
+
+ cs0_cap = 1 << cs_pst;
+
+ if (sdram_params->base.dramtype == DDR4) {
+ if (cap_info->dbw == 0)
+ bktmp = cap_info->bk + 2;
+ else
+ bktmp = cap_info->bk + 1;
+ } else {
+ bktmp = cap_info->bk;
+ }
+ bw = cap_info->bw;
+ coltmp = cap_info->col;
+
+ if (bw == 2)
+ byte_mask = 0xFFFF;
+ else
+ byte_mask = 0xFF;
+
+ max_row = (cs_pst == 31) ? 30 : 31;
+
+ max_row = max_row - bktmp - coltmp - bw - cs_add + 1;
+
+ row = (cap_info->cs0_row > max_row) ? max_row :
+ cap_info->cs0_row;
+
+ for (; row > 12; row--) {
+ test_addr = (void __iomem *)(CFG_SYS_SDRAM_BASE +
+ (u32)cs0_cap +
+ (1ul << (row + bktmp + coltmp +
+ cs_add + bw - 1ul)));
+
+ writel(0, CFG_SYS_SDRAM_BASE + (u32)cs0_cap);
+ writel(PATTERN, test_addr);
+
+ if (((readl(test_addr) & byte_mask) ==
+ (PATTERN & byte_mask)) &&
+ ((readl(CFG_SYS_SDRAM_BASE + (u32)cs0_cap) &
+ byte_mask) == 0)) {
+ ret = row;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/* return: 0 = success, other = fail */
+static int sdram_init_detect(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
+ u32 ret;
+ u32 sys_reg = 0;
+ u32 sys_reg3 = 0;
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ struct dq_map_info *map_info;
+
+ map_info = (struct dq_map_info *)((void *)common_info +
+ index->dq_map_index.offset * 4);
+
+ if (sdram_init_(dram, sdram_params, 0)) {
+ if (sdram_params->base.dramtype == DDR3) {
+ clrsetbits_le32(&map_info->byte_map[0], 0xff << 24,
+ ((0x1 << 6) | (0x3 << 4) | (0x2 << 2) |
+ (0x0 << 0)) << 24);
+ if (sdram_init_(dram, sdram_params, 0))
+ return -1;
+ } else {
+ return -1;
+ }
+ }
+
+ if (sdram_params->base.dramtype == DDR3) {
+ writel(PATTERN, CFG_SYS_SDRAM_BASE);
+ if (readl(CFG_SYS_SDRAM_BASE) != PATTERN)
+ return -1;
+ }
+
+ split_bypass(dram);
+ if (dram_detect_cap(dram, sdram_params, 0) != 0)
+ return -1;
+
+ pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
+ sdram_params->base.dramtype);
+ ret = sdram_init_(dram, sdram_params, 1);
+ if (ret != 0)
+ goto out;
+
+ cap_info->cs1_row =
+ dram_detect_cs1_row(dram, sdram_params, 0);
+ if (cap_info->cs1_row) {
+ sys_reg = readl(&dram->pmugrf->os_reg[2]);
+ sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
+ SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
+ sys_reg, sys_reg3, 0);
+ writel(sys_reg, &dram->pmugrf->os_reg[2]);
+ writel(sys_reg3, &dram->pmugrf->os_reg[3]);
+ }
+
+ sdram_detect_high_row(cap_info);
+ split_setup(dram, sdram_params);
+out:
+ return ret;
+}
+
+struct rv1126_sdram_params *get_default_sdram_config(u32 freq_mhz)
+{
+ u32 i;
+ u32 offset = 0;
+ struct ddr2_3_4_lp2_3_info *ddr_info;
+
+ if (!freq_mhz) {
+ ddr_info = get_ddr_drv_odt_info(sdram_configs[0].base.dramtype);
+ if (ddr_info)
+ freq_mhz =
+ (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
+ DDR_FREQ_MASK;
+ else
+ freq_mhz = 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sdram_configs); i++) {
+ if (sdram_configs[i].base.ddr_freq == 0 ||
+ freq_mhz < sdram_configs[i].base.ddr_freq)
+ break;
+ }
+ offset = i == 0 ? 0 : i - 1;
+
+ return &sdram_configs[offset];
+}
+
+static const u16 pctl_need_update_reg[] = {
+ DDR_PCTL2_RFSHTMG,
+ DDR_PCTL2_INIT3,
+ DDR_PCTL2_INIT4,
+ DDR_PCTL2_INIT6,
+ DDR_PCTL2_INIT7,
+ DDR_PCTL2_DRAMTMG0,
+ DDR_PCTL2_DRAMTMG1,
+ DDR_PCTL2_DRAMTMG2,
+ DDR_PCTL2_DRAMTMG3,
+ DDR_PCTL2_DRAMTMG4,
+ DDR_PCTL2_DRAMTMG5,
+ DDR_PCTL2_DRAMTMG6,
+ DDR_PCTL2_DRAMTMG7,
+ DDR_PCTL2_DRAMTMG8,
+ DDR_PCTL2_DRAMTMG9,
+ DDR_PCTL2_DRAMTMG12,
+ DDR_PCTL2_DRAMTMG13,
+ DDR_PCTL2_DRAMTMG14,
+ DDR_PCTL2_ZQCTL0,
+ DDR_PCTL2_DFITMG0,
+ DDR_PCTL2_ODTCFG
+};
+
+static const u16 phy_need_update_reg[] = {
+ 0x14,
+ 0x18,
+ 0x1c
+};
+
+static void pre_set_rate(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params,
+ u32 dst_fsp, u32 dst_fsp_lp4)
+{
+ u32 i, j, find;
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ u32 phy_offset;
+ u32 mr_tmp;
+ u32 dramtype = sdram_params->base.dramtype;
+
+ sw_set_req(dram);
+ /* pctl timing update */
+ for (i = 0, find = 0; i < ARRAY_SIZE(pctl_need_update_reg); i++) {
+ for (j = find; sdram_params->pctl_regs.pctl[j][0] != 0xFFFFFFFF;
+ j++) {
+ if (sdram_params->pctl_regs.pctl[j][0] ==
+ pctl_need_update_reg[i]) {
+ writel(sdram_params->pctl_regs.pctl[j][1],
+ pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ pctl_need_update_reg[i]);
+ find = j;
+ break;
+ }
+ }
+ }
+
+#ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
+ u32 tmp, trefi;
+
+ tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
+ trefi = (tmp >> 16) & 0xfff;
+ writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
+ pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
+#endif
+
+ sw_set_ack(dram);
+
+ /* phy timing update */
+ if (dst_fsp == 0)
+ phy_offset = 0;
+ else
+ phy_offset = PHY_REG(0, 0x387 - 5 + (dst_fsp - 1) * 3);
+ /* cl cwl al update */
+ for (i = 0, find = 0; i < ARRAY_SIZE(phy_need_update_reg); i++) {
+ for (j = find; sdram_params->phy_regs.phy[j][0] != 0xFFFFFFFF;
+ j++) {
+ if (sdram_params->phy_regs.phy[j][0] ==
+ phy_need_update_reg[i]) {
+ writel(sdram_params->phy_regs.phy[j][1],
+ phy_base + phy_offset +
+ phy_need_update_reg[i]);
+ find = j;
+ break;
+ }
+ }
+ }
+
+ set_ds_odt(dram, sdram_params, dst_fsp);
+ if (dramtype == LPDDR4) {
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT4);
+ /* MR13 */
+ pctl_write_mr(dram->pctl, 3, 13,
+ ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
+ PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
+ ((0x2 << 6) >> dst_fsp_lp4), dramtype);
+ writel(((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
+ PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
+ ((0x2 << 6) >> dst_fsp_lp4),
+ PHY_REG(phy_base, 0x1b));
+ /* MR3 */
+ pctl_write_mr(dram->pctl, 3, 3,
+ mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT &
+ PCTL2_MR_MASK,
+ dramtype);
+ writel(mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK,
+ PHY_REG(phy_base, 0x19));
+
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT3);
+ /* MR1 */
+ pctl_write_mr(dram->pctl, 3, 1,
+ mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT &
+ PCTL2_MR_MASK,
+ dramtype);
+ writel(mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & PCTL2_MR_MASK,
+ PHY_REG(phy_base, 0x17));
+ /* MR2 */
+ pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
+ dramtype);
+ writel(mr_tmp & PCTL2_MR_MASK,
+ PHY_REG(phy_base, 0x18));
+
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT6);
+ /* MR11 */
+ pctl_write_mr(dram->pctl, 3, 11,
+ mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
+ dramtype);
+ writel(mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
+ PHY_REG(phy_base, 0x1a));
+ /* MR12 */
+ pctl_write_mr(dram->pctl, 3, 12,
+ mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
+ dramtype);
+
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT7);
+ /* MR22 */
+ pctl_write_mr(dram->pctl, 3, 22,
+ mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
+ dramtype);
+ writel(mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
+ PHY_REG(phy_base, 0x1d));
+ /* MR14 */
+ pctl_write_mr(dram->pctl, 3, 14,
+ mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
+ dramtype);
+ writel(mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
+ PHY_REG(phy_base, 0x1c));
+ }
+
+ update_noc_timing(dram, sdram_params);
+}
+
+static void save_fsp_param(struct dram_info *dram, u32 dst_fsp,
+ struct rv1126_sdram_params *sdram_params)
+{
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+ struct rv1126_fsp_param *p_fsp_param = &fsp_param[dst_fsp];
+ u32 temp, temp1;
+ struct ddr2_3_4_lp2_3_info *ddr_info;
+
+ ddr_info = get_ddr_drv_odt_info(sdram_params->base.dramtype);
+
+ p_fsp_param->freq_mhz = sdram_params->base.ddr_freq;
+
+ if (sdram_params->base.dramtype == LPDDR4) {
+ p_fsp_param->rd_odt_up_en = 0;
+ p_fsp_param->rd_odt_down_en = 1;
+ } else {
+ p_fsp_param->rd_odt_up_en =
+ ODT_INFO_PULLUP_EN(ddr_info->odt_info);
+ p_fsp_param->rd_odt_down_en =
+ ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
+ }
+
+ if (p_fsp_param->rd_odt_up_en)
+ p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x111));
+ else if (p_fsp_param->rd_odt_down_en)
+ p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x110));
+ else
+ p_fsp_param->rd_odt = 0;
+ p_fsp_param->wr_dq_drv = readl(PHY_REG(phy_base, 0x112));
+ p_fsp_param->wr_ca_drv = readl(PHY_REG(phy_base, 0x100));
+ p_fsp_param->wr_ckcs_drv = readl(PHY_REG(phy_base, 0x102));
+ p_fsp_param->vref_inner = readl(PHY_REG(phy_base, 0x128));
+ p_fsp_param->vref_out = readl(PHY_REG(phy_base, 0x105));
+
+ if (sdram_params->base.dramtype == DDR3) {
+ temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT3);
+ temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
+ p_fsp_param->ds_pdds = temp & DDR3_DS_MASK;
+ p_fsp_param->dq_odt = temp & DDR3_RTT_NOM_MASK;
+ p_fsp_param->ca_odt = p_fsp_param->dq_odt;
+ } else if (sdram_params->base.dramtype == DDR4) {
+ temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT3);
+ temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
+ p_fsp_param->ds_pdds = temp & DDR4_DS_MASK;
+ p_fsp_param->dq_odt = temp & DDR4_RTT_NOM_MASK;
+ p_fsp_param->ca_odt = p_fsp_param->dq_odt;
+ } else if (sdram_params->base.dramtype == LPDDR3) {
+ temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT4);
+ temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
+ p_fsp_param->ds_pdds = temp & 0xf;
+
+ p_fsp_param->dq_odt = lp3_odt_value;
+ p_fsp_param->ca_odt = p_fsp_param->dq_odt;
+ } else if (sdram_params->base.dramtype == LPDDR4) {
+ temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT4);
+ temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
+ p_fsp_param->ds_pdds = temp & LPDDR4_PDDS_MASK;
+
+ temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT6);
+ temp = (temp >> PCTL2_LPDDR4_MR11_SHIFT) & PCTL2_MR_MASK;
+ p_fsp_param->dq_odt = temp & LPDDR4_DQODT_MASK;
+ p_fsp_param->ca_odt = temp & LPDDR4_CAODT_MASK;
+
+ temp = MAX(readl(PHY_REG(phy_base, 0x3ae)),
+ readl(PHY_REG(phy_base, 0x3ce)));
+ temp1 = MIN(readl(PHY_REG(phy_base, 0x3be)),
+ readl(PHY_REG(phy_base, 0x3de)));
+ p_fsp_param->vref_ca[0] = (temp + temp1) / 2;
+ temp = MAX(readl(PHY_REG(phy_base, 0x3af)),
+ readl(PHY_REG(phy_base, 0x3cf)));
+ temp1 = MIN(readl(PHY_REG(phy_base, 0x3bf)),
+ readl(PHY_REG(phy_base, 0x3df)));
+ p_fsp_param->vref_ca[1] = (temp + temp1) / 2;
+ p_fsp_param->vref_ca[0] |=
+ (readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
+ p_fsp_param->vref_ca[1] |=
+ (readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
+
+ p_fsp_param->lp4_drv_pd_en = (readl(PHY_REG(phy_base, 0x114)) >>
+ 3) & 0x1;
+ }
+
+ p_fsp_param->noc_timings.ddrtiminga0 =
+ sdram_params->ch.noc_timings.ddrtiminga0;
+ p_fsp_param->noc_timings.ddrtimingb0 =
+ sdram_params->ch.noc_timings.ddrtimingb0;
+ p_fsp_param->noc_timings.ddrtimingc0 =
+ sdram_params->ch.noc_timings.ddrtimingc0;
+ p_fsp_param->noc_timings.devtodev0 =
+ sdram_params->ch.noc_timings.devtodev0;
+ p_fsp_param->noc_timings.ddrmode =
+ sdram_params->ch.noc_timings.ddrmode;
+ p_fsp_param->noc_timings.ddr4timing =
+ sdram_params->ch.noc_timings.ddr4timing;
+ p_fsp_param->noc_timings.agingx0 =
+ sdram_params->ch.noc_timings.agingx0;
+ p_fsp_param->noc_timings.aging0 =
+ sdram_params->ch.noc_timings.aging0;
+ p_fsp_param->noc_timings.aging1 =
+ sdram_params->ch.noc_timings.aging1;
+ p_fsp_param->noc_timings.aging2 =
+ sdram_params->ch.noc_timings.aging2;
+ p_fsp_param->noc_timings.aging3 =
+ sdram_params->ch.noc_timings.aging3;
+
+ p_fsp_param->flag = FSP_FLAG;
+}
+
+static void copy_fsp_param_to_ddr(void)
+{
+ memcpy((void *)FSP_PARAM_STORE_ADDR, (void *)&fsp_param,
+ sizeof(fsp_param));
+}
+
+static void pctl_modify_trfc(struct ddr_pctl_regs *pctl_regs,
+ struct sdram_cap_info *cap_info, u32 dram_type,
+ u32 freq)
+{
+ u64 cs0_cap;
+ u32 die_cap;
+ u32 trfc_ns, trfc4_ns;
+ u32 trfc, txsnr;
+ u32 txs_abort_fast = 0;
+ u32 tmp;
+
+ cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
+ die_cap = (u32)(cs0_cap >> (20 + (cap_info->bw - cap_info->dbw)));
+
+ switch (dram_type) {
+ case DDR3:
+ if (die_cap <= DIE_CAP_512MBIT)
+ trfc_ns = 90;
+ else if (die_cap <= DIE_CAP_1GBIT)
+ trfc_ns = 110;
+ else if (die_cap <= DIE_CAP_2GBIT)
+ trfc_ns = 160;
+ else if (die_cap <= DIE_CAP_4GBIT)
+ trfc_ns = 260;
+ else
+ trfc_ns = 350;
+ txsnr = MAX(5, ((trfc_ns + 10) * freq + 999) / 1000);
+ break;
+
+ case DDR4:
+ if (die_cap <= DIE_CAP_2GBIT) {
+ trfc_ns = 160;
+ trfc4_ns = 90;
+ } else if (die_cap <= DIE_CAP_4GBIT) {
+ trfc_ns = 260;
+ trfc4_ns = 110;
+ } else if (die_cap <= DIE_CAP_8GBIT) {
+ trfc_ns = 350;
+ trfc4_ns = 160;
+ } else {
+ trfc_ns = 550;
+ trfc4_ns = 260;
+ }
+ txsnr = ((trfc_ns + 10) * freq + 999) / 1000;
+ txs_abort_fast = ((trfc4_ns + 10) * freq + 999) / 1000;
+ break;
+
+ case LPDDR3:
+ if (die_cap <= DIE_CAP_4GBIT)
+ trfc_ns = 130;
+ else
+ trfc_ns = 210;
+ txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
+ break;
+
+ case LPDDR4:
+ if (die_cap <= DIE_CAP_2GBIT)
+ trfc_ns = 130;
+ else if (die_cap <= DIE_CAP_4GBIT)
+ trfc_ns = 180;
+ else if (die_cap <= DIE_CAP_8GBIT)
+ trfc_ns = 280;
+ else
+ trfc_ns = 380;
+ txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
+ break;
+
+ default:
+ return;
+ }
+ trfc = (trfc_ns * freq + 999) / 1000;
+
+ for (int i = 0; pctl_regs->pctl[i][0] != 0xffffffff; i++) {
+ switch (pctl_regs->pctl[i][0]) {
+ case DDR_PCTL2_RFSHTMG:
+ tmp = pctl_regs->pctl[i][1];
+ /* t_rfc_min */
+ tmp &= ~((u32)0x3ff);
+ tmp |= ((trfc + 1) / 2) & 0x3ff;
+ pctl_regs->pctl[i][1] = tmp;
+ break;
+
+ case DDR_PCTL2_DRAMTMG8:
+ if (dram_type == DDR3 || dram_type == DDR4) {
+ tmp = pctl_regs->pctl[i][1];
+ /* t_xs_x32 */
+ tmp &= ~((u32)0x7f);
+ tmp |= ((txsnr + 63) / 64) & 0x7f;
+
+ if (dram_type == DDR4) {
+ /* t_xs_abort_x32 */
+ tmp &= ~((u32)(0x7f << 16));
+ tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 16;
+ /* t_xs_fast_x32 */
+ tmp &= ~((u32)(0x7f << 24));
+ tmp |= (((txs_abort_fast + 63) / 64) & 0x7f) << 24;
+ }
+
+ pctl_regs->pctl[i][1] = tmp;
+ }
+ break;
+
+ case DDR_PCTL2_DRAMTMG14:
+ if (dram_type == LPDDR3 ||
+ dram_type == LPDDR4) {
+ tmp = pctl_regs->pctl[i][1];
+ /* t_xsr */
+ tmp &= ~((u32)0xfff);
+ tmp |= ((txsnr + 1) / 2) & 0xfff;
+ pctl_regs->pctl[i][1] = tmp;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void ddr_set_rate(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params,
+ u32 freq, u32 cur_freq, u32 dst_fsp,
+ u32 dst_fsp_lp4, u32 training_en)
+{
+ u32 dest_dll_off, cur_init3, dst_init3, cur_fsp, cur_dll_off;
+ u32 mr_tmp;
+ u32 lp_stat;
+ u32 dramtype = sdram_params->base.dramtype;
+ struct rv1126_sdram_params *sdram_params_new;
+ void __iomem *pctl_base = dram->pctl;
+ void __iomem *phy_base = dram->phy;
+
+ lp_stat = low_power_update(dram, 0);
+ sdram_params_new = get_default_sdram_config(freq);
+ sdram_params_new->ch.cap_info.rank = sdram_params->ch.cap_info.rank;
+ sdram_params_new->ch.cap_info.bw = sdram_params->ch.cap_info.bw;
+
+ pctl_modify_trfc(&sdram_params_new->pctl_regs,
+ &sdram_params->ch.cap_info, dramtype, freq);
+ pre_set_rate(dram, sdram_params_new, dst_fsp, dst_fsp_lp4);
+
+ while ((readl(pctl_base + DDR_PCTL2_STAT) &
+ PCTL2_OPERATING_MODE_MASK) ==
+ PCTL2_OPERATING_MODE_SR)
+ continue;
+
+ dest_dll_off = 0;
+ dst_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT3);
+ if ((dramtype == DDR3 && (dst_init3 & 1)) ||
+ (dramtype == DDR4 && !(dst_init3 & 1)))
+ dest_dll_off = 1;
+
+ cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
+ cur_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
+ DDR_PCTL2_INIT3);
+ cur_init3 &= PCTL2_MR_MASK;
+ cur_dll_off = 1;
+ if ((dramtype == DDR3 && !(cur_init3 & 1)) ||
+ (dramtype == DDR4 && (cur_init3 & 1)))
+ cur_dll_off = 0;
+
+ if (!cur_dll_off) {
+ if (dramtype == DDR3)
+ cur_init3 |= 1;
+ else
+ cur_init3 &= ~1;
+ pctl_write_mr(dram->pctl, 2, 1, cur_init3, dramtype);
+ }
+
+ setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
+ PCTL2_DIS_AUTO_REFRESH);
+ update_refresh_reg(dram);
+
+ enter_sr(dram, 1);
+
+ writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
+ PMUGRF_CON_DDRPHY_BUFFEREN_EN,
+ &dram->pmugrf->soc_con[0]);
+ sw_set_req(dram);
+ clrbits_le32(pctl_base + DDR_PCTL2_DFIMISC,
+ PCTL2_DFI_INIT_COMPLETE_EN);
+ sw_set_ack(dram);
+
+ sw_set_req(dram);
+ if ((dramtype == DDR3 || dramtype == DDR4) && dest_dll_off)
+ setbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
+ else
+ clrbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
+
+ setbits_le32(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_ZQCTL0,
+ PCTL2_DIS_SRX_ZQCL);
+ setbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_ZQCTL0,
+ PCTL2_DIS_SRX_ZQCL);
+ sw_set_ack(dram);
+
+ writel(DDR_MSCH_EN_MASK | (0x1 << DDR_MSCH_EN_SHIFT),
+ &dram->cru->clkgate_con[21]);
+ writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
+ (0x1 << CLK_DDR_UPCTL_EN_SHIFT) |
+ (0x1 << ACLK_DDR_UPCTL_EN_SHIFT),
+ BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
+
+ clrbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
+ rkclk_set_dpll(dram, freq * MHz / 2);
+ phy_pll_set(dram, freq * MHz, 0);
+ phy_pll_set(dram, freq * MHz, 1);
+ setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
+
+ writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
+ PMUGRF_CON_DDRPHY_BUFFEREN_DIS,
+ &dram->pmugrf->soc_con[0]);
+ writel(DDR_MSCH_EN_MASK | (0x0 << DDR_MSCH_EN_SHIFT),
+ &dram->cru->clkgate_con[21]);
+ writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
+ (0x0 << CLK_DDR_UPCTL_EN_SHIFT) |
+ (0x0 << ACLK_DDR_UPCTL_EN_SHIFT),
+ BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
+ while ((readl(pctl_base + DDR_PCTL2_DFISTAT) &
+ PCTL2_DFI_INIT_COMPLETE) != PCTL2_DFI_INIT_COMPLETE)
+ continue;
+
+ sw_set_req(dram);
+ setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
+ clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, dst_fsp);
+ sw_set_ack(dram);
+ update_refresh_reg(dram);
+ clrsetbits_le32(PHY_REG(phy_base, 0xc), 0x3 << 2, dst_fsp << 2);
+
+ enter_sr(dram, 0);
+
+ setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+ clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
+
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_INIT4);
+ if (dramtype == LPDDR3) {
+ pctl_write_mr(dram->pctl, 3, 1,
+ (dst_init3 >> PCTL2_LPDDR234_MR1_SHIFT) &
+ PCTL2_MR_MASK,
+ dramtype);
+ pctl_write_mr(dram->pctl, 3, 2, dst_init3 & PCTL2_MR_MASK,
+ dramtype);
+ pctl_write_mr(dram->pctl, 3, 3,
+ (mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT) &
+ PCTL2_MR_MASK,
+ dramtype);
+ pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, dramtype);
+ } else if ((dramtype == DDR3) || (dramtype == DDR4)) {
+ pctl_write_mr(dram->pctl, 3, 1, dst_init3 & PCTL2_MR_MASK,
+ dramtype);
+ if (!dest_dll_off) {
+ pctl_write_mr(dram->pctl, 3, 0,
+ ((dst_init3 >> PCTL2_DDR34_MR0_SHIFT) &
+ PCTL2_MR_MASK) | DDR3_DLL_RESET,
+ dramtype);
+ udelay(2);
+ }
+ pctl_write_mr(dram->pctl, 3, 0,
+ (dst_init3 >> PCTL2_DDR34_MR0_SHIFT &
+ PCTL2_MR_MASK) & (~DDR3_DLL_RESET),
+ dramtype);
+ pctl_write_mr(dram->pctl, 3, 2,
+ ((mr_tmp >> PCTL2_DDR34_MR2_SHIFT) &
+ PCTL2_MR_MASK), dramtype);
+ if (dramtype == DDR4) {
+ pctl_write_mr(dram->pctl, 3, 3, mr_tmp & PCTL2_MR_MASK,
+ dramtype);
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT6);
+ pctl_write_mr(dram->pctl, 3, 4,
+ (mr_tmp >> PCTL2_DDR4_MR4_SHIFT) &
+ PCTL2_MR_MASK,
+ dramtype);
+ pctl_write_mr(dram->pctl, 3, 5,
+ mr_tmp >> PCTL2_DDR4_MR5_SHIFT &
+ PCTL2_MR_MASK,
+ dramtype);
+
+ mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
+ DDR_PCTL2_INIT7);
+ pctl_write_mr(dram->pctl, 3, 6,
+ mr_tmp >> PCTL2_DDR4_MR6_SHIFT &
+ PCTL2_MR_MASK,
+ dramtype);
+ }
+ } else if (dramtype == LPDDR4) {
+ pctl_write_mr(dram->pctl, 3, 13,
+ ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
+ PCTL2_MR_MASK) & (~(BIT(7)))) |
+ dst_fsp_lp4 << 7, dramtype);
+ }
+ clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
+ PCTL2_DIS_AUTO_REFRESH);
+ update_refresh_reg(dram);
+
+ /* training */
+ high_freq_training(dram, sdram_params_new, dst_fsp);
+ low_power_update(dram, lp_stat);
+
+ save_fsp_param(dram, dst_fsp, sdram_params_new);
+}
+
+static void ddr_set_rate_for_fsp(struct dram_info *dram,
+ struct rv1126_sdram_params *sdram_params)
+{
+ struct ddr2_3_4_lp2_3_info *ddr_info;
+ u32 f0;
+ u32 dramtype = sdram_params->base.dramtype;
+ u32 f1, f2, f3;
+
+ ddr_info = get_ddr_drv_odt_info(dramtype);
+ if (!ddr_info)
+ return;
+
+ f0 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
+ DDR_FREQ_MASK;
+
+ memset((void *)FSP_PARAM_STORE_ADDR, 0, sizeof(fsp_param));
+ memset((void *)&fsp_param, 0, sizeof(fsp_param));
+
+ f1 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F1_SHIFT) &
+ DDR_FREQ_MASK;
+ f2 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F2_SHIFT) &
+ DDR_FREQ_MASK;
+ f3 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F3_SHIFT) &
+ DDR_FREQ_MASK;
+
+ if (get_wrlvl_val(dram, sdram_params))
+ printascii("get wrlvl value fail\n");
+
+ if (IS_ENABLED(CONFIG_RAM_ROCKCHIP_DEBUG)) {
+ printascii("change to: ");
+ printdec(f1);
+ printascii("MHz\n");
+ }
+ ddr_set_rate(&dram_info, sdram_params, f1,
+ sdram_params->base.ddr_freq, 1, 1, 1);
+
+ if (IS_ENABLED(CONFIG_RAM_ROCKCHIP_DEBUG)) {
+ printascii("change to: ");
+ printdec(f2);
+ printascii("MHz\n");
+ }
+ ddr_set_rate(&dram_info, sdram_params, f2, f1, 2, 0, 1);
+
+ if (IS_ENABLED(CONFIG_RAM_ROCKCHIP_DEBUG)) {
+ printascii("change to: ");
+ printdec(f3);
+ printascii("MHz\n");
+ }
+ ddr_set_rate(&dram_info, sdram_params, f3, f2, 3, 1, 1);
+
+ if (IS_ENABLED(CONFIG_RAM_ROCKCHIP_DEBUG)) {
+ printascii("change to: ");
+ printdec(f0);
+ printascii("MHz(final freq)\n");
+ }
+ ddr_set_rate(&dram_info, sdram_params, f0, f3, 0, 0, 1);
+}
+
+int get_uart_config(void)
+{
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ struct global_info *gbl_info;
+
+ gbl_info = (struct global_info *)((void *)common_info +
+ index->global_index.offset * 4);
+
+ return gbl_info->uart_info;
+}
+
+/* return: 0 = success, other = fail */
+static int rv1126_dmc_init(struct udevice *dev)
+{
+ struct rv1126_sdram_params *sdram_params;
+ int ret = 0;
+ struct sdram_head_info_index_v2 *index =
+ (struct sdram_head_info_index_v2 *)common_info;
+ struct global_info *gbl_info;
+
+ dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
+ dram_info.pctl = (void *)UPCTL2_BASE_ADDR;
+ dram_info.grf = (void *)GRF_BASE_ADDR;
+ dram_info.cru = (void *)CRU_BASE_ADDR;
+ dram_info.msch = (void *)SERVER_MSCH_BASE_ADDR;
+ dram_info.ddrgrf = (void *)DDR_GRF_BASE_ADDR;
+ dram_info.pmugrf = (void *)PMU_GRF_BASE_ADDR;
+
+#ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
+ printascii("extended temp support\n");
+#endif
+ if (index->version_info != 2 ||
+ (index->global_index.size != sizeof(struct global_info) / 4) ||
+ (index->ddr3_index.size !=
+ sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
+ (index->ddr4_index.size !=
+ sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
+ (index->lp3_index.size !=
+ sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
+ (index->lp4_index.size != (sizeof(struct lp4_info) / 4)) ||
+ (index->lp4x_index.size != (sizeof(struct lp4_info) / 4)) ||
+ index->global_index.offset == 0 ||
+ index->ddr3_index.offset == 0 ||
+ index->ddr4_index.offset == 0 ||
+ index->lp3_index.offset == 0 ||
+ index->lp4_index.offset == 0 ||
+ index->lp4x_index.offset == 0) {
+ printascii("common info error\n");
+ goto error;
+ }
+
+ gbl_info = (struct global_info *)((void *)common_info +
+ index->global_index.offset * 4);
+
+ dram_info.sr_idle = SR_INFO(gbl_info->sr_pd_info);
+ dram_info.pd_idle = PD_INFO(gbl_info->sr_pd_info);
+
+ sdram_params = &sdram_configs[0];
+ if (sdram_params->base.dramtype == DDR3 ||
+ sdram_params->base.dramtype == DDR4) {
+ if (DDR_2T_INFO(gbl_info->info_2t))
+ sdram_params->pctl_regs.pctl[0][1] |= 0x1 << 10;
+ else
+ sdram_params->pctl_regs.pctl[0][1] &=
+ ~(0x1 << 10);
+ }
+ ret = sdram_init_detect(&dram_info, sdram_params);
+ if (ret) {
+ sdram_print_dram_type(sdram_params->base.dramtype);
+ printascii(", ");
+ printdec(sdram_params->base.ddr_freq);
+ printascii("MHz\n");
+ goto error;
+ }
+ print_ddr_info(sdram_params);
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+ init_rw_trn_result_struct(&rw_trn_result, dram_info.phy,
+ (u8)sdram_params->ch.cap_info.rank);
+#endif
+
+ ddr_set_rate_for_fsp(&dram_info, sdram_params);
+ copy_fsp_param_to_ddr();
+
+#if defined(CONFIG_CMD_DDR_TEST_TOOL)
+ save_rw_trn_result_to_ddr(&rw_trn_result);
+#endif
+
+ if (IS_ENABLED(CONFIG_RAM_ROCKCHIP_DEBUG))
+ printascii("out\n");
+
+ return ret;
+error:
+ printascii("error\n");
+ return (-1);
+}
+
+#endif
+
+static int rv1126_dmc_probe(struct udevice *dev)
+{
+#if defined(CONFIG_TPL_BUILD) || \
+ (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+ if (rv1126_dmc_init(dev))
+ return 0;
+#else
+ struct dram_info *priv = dev_get_priv(dev);
+
+ priv->pmugrf = syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF);
+ debug("%s: grf=%p\n", __func__, priv->pmugrf);
+ priv->info.base = CFG_SYS_SDRAM_BASE;
+ priv->info.size =
+ rockchip_sdram_size((phys_addr_t)&priv->pmugrf->os_reg[2]);
+#endif
+ return 0;
+}
+
+static int rv1126_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+ struct dram_info *priv = dev_get_priv(dev);
+
+ *info = priv->info;
+
+ return 0;
+}
+
+static struct ram_ops rv1126_dmc_ops = {
+ .get_info = rv1126_dmc_get_info,
+};
+
+static const struct udevice_id rv1126_dmc_ids[] = {
+ { .compatible = "rockchip,rv1126-dmc" },
+ { }
+};
+
+U_BOOT_DRIVER(dmc_rv1126) = {
+ .name = "rockchip_rv1126_dmc",
+ .id = UCLASS_RAM,
+ .of_match = rv1126_dmc_ids,
+ .ops = &rv1126_dmc_ops,
+ .probe = rv1126_dmc_probe,
+ .priv_auto = sizeof(struct dram_info),
+};
diff --git a/drivers/reboot-mode/Kconfig b/drivers/reboot-mode/Kconfig
index 63ea18c..d57baac 100644
--- a/drivers/reboot-mode/Kconfig
+++ b/drivers/reboot-mode/Kconfig
@@ -30,4 +30,11 @@
a device in a specific mode by using a register(s) that can be controlled
outside U-Boot (e.g. Kernel).
+config REBOOT_MODE_NVMEM
+ bool "Use NVMEM reboot mode"
+ depends on DM_REBOOT_MODE && NVMEM
+ help
+ Use any kind of non-volatile memory (EEPROM, RTC, etc) to control the
+ reboot mode.
+
endmenu
diff --git a/drivers/reboot-mode/Makefile b/drivers/reboot-mode/Makefile
index 2c13780..48c8ab7 100644
--- a/drivers/reboot-mode/Makefile
+++ b/drivers/reboot-mode/Makefile
@@ -7,3 +7,4 @@
obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode-uclass.o
obj-$(CONFIG_DM_REBOOT_MODE_GPIO) += reboot-mode-gpio.o
obj-$(CONFIG_DM_REBOOT_MODE_RTC) += reboot-mode-rtc.o
+obj-$(CONFIG_REBOOT_MODE_NVMEM) += reboot-mode-nvmem.o
diff --git a/drivers/reboot-mode/reboot-mode-nvmem.c b/drivers/reboot-mode/reboot-mode-nvmem.c
new file mode 100644
index 0000000..da41ca4
--- /dev/null
+++ b/drivers/reboot-mode/reboot-mode-nvmem.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <nvmem.h>
+#include <reboot-mode/reboot-mode.h>
+
+/**
+ * struct nvmem_reboot_mode_priv - Private data for the nvmem reboot mode device
+ * @cell: The nvmem cell to store the mode in
+ */
+struct nvmem_reboot_mode_priv {
+ struct nvmem_cell cell;
+};
+
+static int reboot_mode_get(struct udevice *dev, u32 *mode)
+{
+ struct nvmem_reboot_mode_priv *priv = dev_get_priv(dev);
+
+ return nvmem_cell_read(&priv->cell, mode, sizeof(*mode));
+}
+
+static int reboot_mode_set(struct udevice *dev, u32 mode)
+{
+ struct nvmem_reboot_mode_priv *priv = dev_get_priv(dev);
+
+ return nvmem_cell_write(&priv->cell, &mode, sizeof(mode));
+}
+
+static const struct reboot_mode_ops nvmem_reboot_mode_ops = {
+ .get = reboot_mode_get,
+ .set = reboot_mode_set,
+};
+
+static int reboot_mode_probe(struct udevice *dev)
+{
+ struct nvmem_reboot_mode_priv *priv = dev_get_priv(dev);
+
+ return nvmem_cell_get_by_name(dev, "reboot-mode", &priv->cell);
+}
+
+static const struct udevice_id nvmem_reboot_mode_ids[] = {
+ { .compatible = "nvmem-reboot-mode" },
+ { }
+};
+
+U_BOOT_DRIVER(nvmem_reboot_mode) = {
+ .name = "nvmem-reboot-mode",
+ .id = UCLASS_REBOOT_MODE,
+ .of_match = nvmem_reboot_mode_ids,
+ .probe = reboot_mode_probe,
+ .priv_auto = sizeof(struct nvmem_reboot_mode_priv),
+ .ops = &nvmem_reboot_mode_ops,
+};
diff --git a/drivers/rtc/abx80x.c b/drivers/rtc/abx80x.c
index 528b06c..823aff0 100644
--- a/drivers/rtc/abx80x.c
+++ b/drivers/rtc/abx80x.c
@@ -17,6 +17,7 @@
#include <i2c.h>
#include <rtc.h>
#include <log.h>
+#include <linux/bitfield.h>
#define ABX8XX_REG_HTH 0x00
#define ABX8XX_REG_SC 0x01
@@ -88,6 +89,16 @@
#define ABX8XX_TRICKLE_STANDARD_DIODE 0x8
#define ABX8XX_TRICKLE_SCHOTTKY_DIODE 0x4
+#define ABX8XX_REG_EXTRAM 0x3f
+#define ABX8XX_EXTRAM_XADS GENMASK(1, 0)
+
+#define ABX8XX_SRAM_BASE 0x40
+#define ABX8XX_SRAM_WIN_SIZE 0x40U
+#define ABX8XX_RAM_SIZE 256
+
+#define RAM_ADDR_LOWER GENMASK(5, 0)
+#define RAM_ADDR_UPPER GENMASK(7, 6)
+
static u8 trickle_resistors[] = {0, 3, 6, 11};
enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
@@ -112,29 +123,52 @@
[ABX80X] = {.pn = 0}
};
-static int abx80x_rtc_read8(struct udevice *dev, unsigned int reg)
+static int abx80x_rtc_xfer(struct udevice *dev, unsigned int offset,
+ u8 *val, unsigned int bytes, bool write)
{
- int ret = 0;
- u8 buf;
+ int ret;
- if (reg > 0xff)
+ if (offset + bytes > ABX8XX_RAM_SIZE)
return -EINVAL;
- ret = dm_i2c_read(dev, reg, &buf, sizeof(buf));
- if (ret < 0)
- return ret;
+ while (bytes) {
+ u8 extram, reg, len, lower, upper;
- return buf;
+ lower = FIELD_GET(RAM_ADDR_LOWER, offset);
+ upper = FIELD_GET(RAM_ADDR_UPPER, offset);
+ extram = FIELD_PREP(ABX8XX_EXTRAM_XADS, upper);
+ reg = ABX8XX_SRAM_BASE + lower;
+ len = min(lower + bytes, ABX8XX_SRAM_WIN_SIZE) - lower;
+
+ ret = dm_i2c_reg_write(dev, ABX8XX_REG_EXTRAM, extram);
+ if (ret)
+ return ret;
+
+ if (write)
+ ret = dm_i2c_write(dev, reg, val, len);
+ else
+ ret = dm_i2c_read(dev, reg, val, len);
+ if (ret)
+ return ret;
+
+ offset += len;
+ val += len;
+ bytes -= len;
+ }
+
+ return 0;
}
-static int abx80x_rtc_write8(struct udevice *dev, unsigned int reg, int val)
+static int abx80x_rtc_read(struct udevice *dev, unsigned int offset, u8 *val,
+ unsigned int bytes)
{
- u8 buf = (u8)val;
+ return abx80x_rtc_xfer(dev, offset, val, bytes, false);
+}
- if (reg > 0xff)
- return -EINVAL;
-
- return dm_i2c_write(dev, reg, &buf, sizeof(buf));
+static int abx80x_rtc_write(struct udevice *dev, unsigned int offset,
+ const u8 *val, unsigned int bytes)
+{
+ return abx80x_rtc_xfer(dev, offset, (u8 *)val, bytes, true);
}
static int abx80x_is_rc_mode(struct udevice *dev)
@@ -334,9 +368,9 @@
static const struct rtc_ops abx80x_rtc_ops = {
.get = abx80x_rtc_read_time,
.set = abx80x_rtc_set_time,
- .reset = abx80x_rtc_reset,
- .read8 = abx80x_rtc_read8,
- .write8 = abx80x_rtc_write8
+ .reset = abx80x_rtc_reset,
+ .read = abx80x_rtc_read,
+ .write = abx80x_rtc_write,
};
static int abx80x_dt_trickle_cfg(struct udevice *dev)
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index d1b40c6..d8d6de5 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -6,6 +6,13 @@
ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_DM_SCSI) += scsi-uclass.o
obj-$(CONFIG_SCSI) += scsi.o
+
+ifdef CONFIG_SCSI
+ifdef CONFIG_DM_SCSI
+obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += scsi_bootdev.o
+endif
+endif
+
endif
ifdef CONFIG_SPL_BUILD
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index a020a7d..6caeb3f 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -4,8 +4,11 @@
* Denis Peter, MPL AG Switzerland
*/
+#define LOG_CATEGORY UCLASS_SCSI
+
#include <common.h>
#include <blk.h>
+#include <bootdev.h>
#include <bootstage.h>
#include <dm.h>
#include <env.h>
@@ -558,7 +561,7 @@
struct udevice *bdev;
struct blk_desc bd;
struct blk_desc *bdesc;
- char str[10];
+ char str[10], *name;
/*
* detect the scsi driver to get information about its geometry (block
@@ -574,12 +577,16 @@
* block devices created
*/
snprintf(str, sizeof(str), "id%dlun%d", id, lun);
- ret = blk_create_devicef(dev, "scsi_blk", str, UCLASS_SCSI, -1,
+ name = strdup(str);
+ if (!name)
+ return log_msg_ret("nam", -ENOMEM);
+ ret = blk_create_devicef(dev, "scsi_blk", name, UCLASS_SCSI, -1,
bd.blksz, bd.lba, &bdev);
if (ret) {
debug("Can't create device\n");
return ret;
}
+ device_set_name_alloced(bdev);
bdesc = dev_get_uclass_plat(bdev);
bdesc->target = id;
@@ -598,7 +605,11 @@
ret = blk_probe_or_unbind(bdev);
if (ret < 0)
/* TODO: undo create */
- return ret;
+ return log_msg_ret("pro", ret);
+
+ ret = bootdev_setup_sibling_blk(bdev, "scsi_bootdev");
+ if (ret)
+ return log_msg_ret("bd", ret);
if (verbose) {
printf(" Device %d: ", bdesc->devnum);
@@ -638,12 +649,23 @@
if (verbose)
printf("scanning bus for devices...\n");
- blk_unbind_all(UCLASS_SCSI);
-
ret = uclass_get(UCLASS_SCSI, &uc);
if (ret)
return ret;
+ /* remove all children of the SCSI devices */
+ uclass_foreach_dev(dev, uc) {
+ log_debug("unbind %s\n", dev->name);
+ ret = device_chld_remove(dev, NULL, DM_REMOVE_NORMAL);
+ if (!ret)
+ ret = device_chld_unbind(dev, NULL);
+ if (ret) {
+ if (verbose)
+ printf("unable to unbind devices (%dE)\n", ret);
+ return log_msg_ret("unb", ret);
+ }
+ }
+
uclass_foreach_dev(dev, uc) {
ret = scsi_scan_dev(dev, verbose);
if (ret)
diff --git a/drivers/scsi/scsi_bootdev.c b/drivers/scsi/scsi_bootdev.c
new file mode 100644
index 0000000..991013f
--- /dev/null
+++ b/drivers/scsi/scsi_bootdev.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootdevice for USB
+ *
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <bootdev.h>
+#include <dm.h>
+#include <init.h>
+#include <scsi.h>
+
+static int scsi_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_4_SCAN_FAST;
+
+ return 0;
+}
+
+static int scsi_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ if (IS_ENABLED(CONFIG_PCI)) {
+ ret = pci_init();
+ if (ret)
+ return log_msg_ret("pci", ret);
+ }
+
+ ret = scsi_scan(true);
+ if (ret)
+ return log_msg_ret("scs", ret);
+
+ return 0;
+}
+
+struct bootdev_ops scsi_bootdev_ops = {
+};
+
+static const struct udevice_id scsi_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-scsi" },
+ { }
+};
+
+U_BOOT_DRIVER(scsi_bootdev) = {
+ .name = "scsi_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &scsi_bootdev_ops,
+ .bind = scsi_bootdev_bind,
+ .of_match = scsi_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(scsi_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_SCSI,
+ .hunt = scsi_bootdev_hunt,
+ .drv = DM_DRIVER_REF(scsi_bootdev),
+};
diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
index 772dd6f..eab9537 100644
--- a/drivers/serial/ns16550.c
+++ b/drivers/serial/ns16550.c
@@ -52,9 +52,9 @@
#endif
#endif
-#ifndef CONFIG_SYS_NS16550_IER
-#define CONFIG_SYS_NS16550_IER 0x00
-#endif /* CONFIG_SYS_NS16550_IER */
+#ifndef CFG_SYS_NS16550_IER
+#define CFG_SYS_NS16550_IER 0x00
+#endif /* CFG_SYS_NS16550_IER */
static inline void serial_out_shift(void *addr, int shift, int value)
{
@@ -251,7 +251,7 @@
while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT))
;
- serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
+ serial_out(CFG_SYS_NS16550_IER, &com_port->ier);
#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_OMAP_SERIAL)
serial_out(0x7, &com_port->mdr1); /* mode select reset TL16C750*/
#endif
@@ -275,7 +275,7 @@
#if !CONFIG_IS_ENABLED(NS16550_MIN_FUNCTIONS)
void ns16550_reinit(struct ns16550 *com_port, int baud_divisor)
{
- serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
+ serial_out(CFG_SYS_NS16550_IER, &com_port->ier);
ns16550_setbrg(com_port, 0);
serial_out(UART_MCRVAL, &com_port->mcr);
serial_out(ns16550_getfcr(com_port), &com_port->fcr);
@@ -340,7 +340,7 @@
*/
baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
CONFIG_BAUDRATE);
- serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
+ serial_dout(&com_port->ier, CFG_SYS_NS16550_IER);
serial_dout(&com_port->mcr, UART_MCRVAL);
serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
diff --git a/drivers/serial/serial_omap.c b/drivers/serial/serial_omap.c
index 904f7d2..26310b0 100644
--- a/drivers/serial/serial_omap.c
+++ b/drivers/serial/serial_omap.c
@@ -21,8 +21,8 @@
#ifdef CONFIG_DEBUG_UART_OMAP
-#ifndef CONFIG_SYS_NS16550_IER
-#define CONFIG_SYS_NS16550_IER 0x00
+#ifndef CFG_SYS_NS16550_IER
+#define CFG_SYS_NS16550_IER 0x00
#endif
#define UART_MCRVAL 0x00
@@ -71,7 +71,7 @@
baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
CONFIG_BAUDRATE);
- serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
+ serial_dout(&com_port->ier, CFG_SYS_NS16550_IER);
serial_dout(&com_port->mdr1, 0x7);
serial_dout(&com_port->mcr, UART_MCRVAL);
serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c
index 07a59ec..ecb6ba8 100644
--- a/drivers/serial/usbtty.c
+++ b/drivers/serial/usbtty.c
@@ -45,8 +45,8 @@
#define GSERIAL_RX_ENDPOINT 1
#define NUM_ACM_INTERFACES 2
#define NUM_GSERIAL_INTERFACES 1
-#define CONFIG_USBD_DATA_INTERFACE_STR "Bulk Data Interface"
-#define CONFIG_USBD_CTRL_INTERFACE_STR "Control Interface"
+#define CFG_USBD_DATA_INTERFACE_STR "Bulk Data Interface"
+#define CFG_USBD_CTRL_INTERFACE_STR "Control Interface"
/*
* Buffers to hold input and output data
@@ -97,9 +97,9 @@
static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];
static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)];
static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)];
-static u8 wstrConfiguration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)];
-static u8 wstrDataInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
-static u8 wstrCtrlInterface[2 + 2*(sizeof(CONFIG_USBD_DATA_INTERFACE_STR)-1)];
+static u8 wstrConfiguration[2 + 2*(sizeof(CFG_USBD_CONFIGURATION_STR)-1)];
+static u8 wstrDataInterface[2 + 2*(sizeof(CFG_USBD_DATA_INTERFACE_STR)-1)];
+static u8 wstrCtrlInterface[2 + 2*(sizeof(CFG_USBD_DATA_INTERFACE_STR)-1)];
/* Standard USB Data Structures */
static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES];
@@ -206,7 +206,7 @@
.bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize
- = cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+ = cpu_to_le16(CFG_USBD_SERIAL_INT_PKTSIZE),
.bInterval = 0xFF,
},
@@ -233,7 +233,7 @@
.bmAttributes =
USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize =
- cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+ cpu_to_le16(CFG_USBD_SERIAL_BULK_PKTSIZE),
.bInterval = 0xFF,
},
{
@@ -244,7 +244,7 @@
.bmAttributes =
USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize =
- cpu_to_le16(CONFIG_USBD_SERIAL_BULK_PKTSIZE),
+ cpu_to_le16(CFG_USBD_SERIAL_BULK_PKTSIZE),
.bInterval = 0xFF,
},
},
@@ -312,7 +312,7 @@
.bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize =
- cpu_to_le16(CONFIG_USBD_SERIAL_OUT_PKTSIZE),
+ cpu_to_le16(CFG_USBD_SERIAL_OUT_PKTSIZE),
.bInterval= 0xFF,
},
{
@@ -322,7 +322,7 @@
.bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize =
- cpu_to_le16(CONFIG_USBD_SERIAL_IN_PKTSIZE),
+ cpu_to_le16(CFG_USBD_SERIAL_IN_PKTSIZE),
.bInterval = 0xFF,
},
{
@@ -332,7 +332,7 @@
.bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize =
- cpu_to_le16(CONFIG_USBD_SERIAL_INT_PKTSIZE),
+ cpu_to_le16(CFG_USBD_SERIAL_INT_PKTSIZE),
.bInterval = 0xFF,
},
},
@@ -594,20 +594,20 @@
string = (struct usb_string_descriptor *) wstrConfiguration;
string->bLength = sizeof(wstrConfiguration);
string->bDescriptorType = USB_DT_STRING;
- str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData);
+ str2wide (CFG_USBD_CONFIGURATION_STR, string->wData);
usbtty_string_table[STR_CONFIG]=string;
string = (struct usb_string_descriptor *) wstrDataInterface;
string->bLength = sizeof(wstrDataInterface);
string->bDescriptorType = USB_DT_STRING;
- str2wide (CONFIG_USBD_DATA_INTERFACE_STR, string->wData);
+ str2wide (CFG_USBD_DATA_INTERFACE_STR, string->wData);
usbtty_string_table[STR_DATA_INTERFACE]=string;
string = (struct usb_string_descriptor *) wstrCtrlInterface;
string->bLength = sizeof(wstrCtrlInterface);
string->bDescriptorType = USB_DT_STRING;
- str2wide (CONFIG_USBD_CTRL_INTERFACE_STR, string->wData);
+ str2wide (CFG_USBD_CTRL_INTERFACE_STR, string->wData);
usbtty_string_table[STR_CTRL_INTERFACE]=string;
/* Now, initialize the string table for ep0 handling */
diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index ac4d220..b176a79 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -20,36 +20,17 @@
#include <usb/udc.h>
#include <version.h>
-/* If no VendorID/ProductID is defined in config.h, pretend to be Linux
- * DO NOT Reuse this Vendor/Product setup with protocol incompatible devices */
-
-#ifndef CONFIG_USBD_VENDORID
-#define CONFIG_USBD_VENDORID 0x0525 /* Linux/NetChip */
-#endif
-#ifndef CONFIG_USBD_PRODUCTID_GSERIAL
-#define CONFIG_USBD_PRODUCTID_GSERIAL 0xa4a6 /* gserial */
-#endif
-#ifndef CONFIG_USBD_PRODUCTID_CDCACM
-#define CONFIG_USBD_PRODUCTID_CDCACM 0xa4a7 /* CDC ACM */
-#endif
-#ifndef CONFIG_USBD_MANUFACTURER
-#define CONFIG_USBD_MANUFACTURER "Das U-Boot"
-#endif
-#ifndef CONFIG_USBD_PRODUCT_NAME
-#define CONFIG_USBD_PRODUCT_NAME U_BOOT_VERSION
+#ifndef CFG_USBD_CONFIGURATION_STR
+#define CFG_USBD_CONFIGURATION_STR "TTY via USB"
#endif
-#ifndef CONFIG_USBD_CONFIGURATION_STR
-#define CONFIG_USBD_CONFIGURATION_STR "TTY via USB"
-#endif
-
-#define CONFIG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT
-#define CONFIG_USBD_SERIAL_OUT_PKTSIZE UDC_OUT_PACKET_SIZE
-#define CONFIG_USBD_SERIAL_IN_ENDPOINT UDC_IN_ENDPOINT
-#define CONFIG_USBD_SERIAL_IN_PKTSIZE UDC_IN_PACKET_SIZE
-#define CONFIG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT
-#define CONFIG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE
-#define CONFIG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE
+#define CFG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT
+#define CFG_USBD_SERIAL_OUT_PKTSIZE UDC_OUT_PACKET_SIZE
+#define CFG_USBD_SERIAL_IN_ENDPOINT UDC_IN_ENDPOINT
+#define CFG_USBD_SERIAL_IN_PKTSIZE UDC_IN_PACKET_SIZE
+#define CFG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT
+#define CFG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE
+#define CFG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE
#define USBTTY_DEVICE_CLASS COMMUNICATIONS_DEVICE_CLASS
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 64ceed1..cdd2304 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -461,6 +461,14 @@
Enable Soft SPI driver. This driver is to use GPIO simulate
the SPI protocol.
+config SPI_SN_F_OSPI
+ tristate "Socionext F_OSPI SPI flash controller"
+ depends on SPI_MEM
+ help
+ This enables support for the Socionext F_OSPI controller
+ for connecting an SPI flash memory over up to 8-bit wide bus.
+ It supports indirect access mode only.
+
config SPI_SUNXI
bool "Allwinner SoC SPI controllers"
default ARCH_SUNXI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 674d81c..95dba9a 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -67,6 +67,7 @@
obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o
obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
obj-$(CONFIG_SPI_SIFIVE) += spi-sifive.o
+obj-$(CONFIG_SPI_SN_F_OSPI) += spi-sn-f-ospi.o
obj-$(CONFIG_SPI_SUNXI) += spi-sunxi.o
obj-$(CONFIG_SH_QSPI) += sh_qspi.o
obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o
diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c
index 47002f8..4d714ad 100644
--- a/drivers/spi/bcm63xx_hsspi.c
+++ b/drivers/spi/bcm63xx_hsspi.c
@@ -210,7 +210,7 @@
* claimed. This way, the dummy CS is restored to its inactive value when
* transfers are issued and the desired CS is preserved in its active value
* all the time. This hack is also used in the upstream linux driver and
- * allows keeping CS active between trasnfers even if the HW doesn't give
+ * allows keeping CS active between transfers even if the HW doesn't give
* this possibility.
*/
static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen,
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index ab0a681..328dfb0 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -307,7 +307,13 @@
priv->is_decoded_cs);
if (op->data.dir == SPI_MEM_DATA_IN && op->data.buf.in) {
- if (!op->addr.nbytes)
+ /*
+ * Performing reads in DAC mode forces to read minimum 4 bytes
+ * which is unsupported on some flash devices during register
+ * reads, prefer STIG mode for such small reads.
+ */
+ if (!op->addr.nbytes ||
+ op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
mode = CQSPI_STIG_READ;
else
mode = CQSPI_READ;
@@ -392,7 +398,7 @@
plat->is_dma = dev_read_bool(bus, "cdns,is-dma");
- /* All other paramters are embedded in the child node */
+ /* All other parameters are embedded in the child node */
subnode = dev_read_first_subnode(bus);
if (!ofnode_valid(subnode)) {
printf("Error: subnode with SPI flash config missing!\n");
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index d1f8913..21fe2e6 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -479,6 +479,19 @@
/* 0 means 1 byte. */
reg |= (((rxlen - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK)
<< CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
+
+ /* setup ADDR BIT field */
+ if (op->addr.nbytes) {
+ writel(op->addr.val, priv->regbase + CQSPI_REG_CMDADDRESS);
+ /*
+ * address bytes are zero indexed
+ */
+ reg |= (((op->addr.nbytes - 1) &
+ CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) <<
+ CQSPI_REG_CMDCTRL_ADD_BYTES_LSB);
+ reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+ }
+
status = cadence_qspi_apb_exec_flash_cmd(reg_base, reg);
if (status != 0)
return status;
diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
index 62444e4..8e5cc55 100644
--- a/drivers/spi/fsl_dspi.c
+++ b/drivers/spi/fsl_dspi.c
@@ -491,7 +491,7 @@
dm_spi_bus = dev_get_uclass_priv(bus);
- /* cpu speical pin muxing configure */
+ /* cpu special pin muxing configure */
cpu_dspi_port_conf();
/* get input clk frequency */
@@ -600,7 +600,7 @@
plat->speed_hz = fdtdec_get_int(blob,
node, "spi-max-frequency", FSL_DSPI_DEFAULT_SCK_FREQ);
- debug("DSPI: regs=%pa, max-frequency=%d, endianess=%s, num-cs=%d\n",
+ debug("DSPI: regs=%pa, max-frequency=%d, endianness=%s, num-cs=%d\n",
&plat->regs_addr, plat->speed_hz,
plat->flags & DSPI_FLAG_REGMAP_ENDIAN_BIG ? "be" : "le",
plat->num_chipselect);
diff --git a/drivers/spi/mtk_snfi_spi.c b/drivers/spi/mtk_snfi_spi.c
index 5ea6277..3decb37 100644
--- a/drivers/spi/mtk_snfi_spi.c
+++ b/drivers/spi/mtk_snfi_spi.c
@@ -153,7 +153,7 @@
/*
* The output data will always be copied to the beginning of
- * the GPRAM. Uses word write for better performace.
+ * the GPRAM. Uses word write for better performance.
*
* Trailing bytes in the last word are not cared.
*/
@@ -180,7 +180,7 @@
/*
* Read aligned data from GPRAM to buffer first.
- * Uses word read for better performace.
+ * Uses word read for better performance.
*/
i = 0;
while (pos < end) {
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
index b1dce04..52882e8 100644
--- a/drivers/spi/mvebu_a3700_spi.c
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -84,7 +84,7 @@
* The XFER_RDY flag is checked every time before accessing SPI_DOUT
* and SPI_DIN register.
*
- * The number of transfers to be triggerred is decided by @bytelen.
+ * The number of transfers to be triggered is decided by @bytelen.
*
* Return: 0 - cool
* -ETIMEDOUT - XFER_RDY flag timeout
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index ea9cc3d..840660f 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -101,8 +101,8 @@
#define reg_read readl
#define reg_write(a, v) writel(v, a)
-#if !defined(CONFIG_SYS_SPI_MXC_WAIT)
-#define CONFIG_SYS_SPI_MXC_WAIT (CONFIG_SYS_HZ/100) /* 10 ms */
+#if !defined(CFG_SYS_SPI_MXC_WAIT)
+#define CFG_SYS_SPI_MXC_WAIT (CONFIG_SYS_HZ/100) /* 10 ms */
#endif
#define MAX_CS_COUNT 4
@@ -371,7 +371,7 @@
status = reg_read(®s->stat);
/* Wait until the TC (Transfer completed) bit is set */
while ((status & MXC_CSPICTRL_TC) == 0) {
- if (get_timer(ts) > CONFIG_SYS_SPI_MXC_WAIT) {
+ if (get_timer(ts) > CFG_SYS_SPI_MXC_WAIT) {
printf("spi_xchg_single: Timeout!\n");
return -1;
}
diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c
index ea38a0f..1cbb5d4 100644
--- a/drivers/spi/omap3_spi.c
+++ b/drivers/spi/omap3_spi.c
@@ -142,7 +142,7 @@
}
}
- /* Disable the channel to prevent furher receiving */
+ /* Disable the channel to prevent further receiving */
if (i == (len - 1))
omap3_spi_set_enable(priv, OMAP3_MCSPI_CHCTRL_DIS);
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index cb80be7..66b20fc 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -485,7 +485,7 @@
/*
* In case that there's a transmit-component, we need to wait
* until the control goes idle before we can disable the SPI
- * control logic (as this will implictly flush the FIFOs).
+ * control logic (as this will implicitly flush the FIFOs).
*/
if (out) {
ret = rkspi_wait_till_not_busy(regs);
diff --git a/drivers/spi/sh_qspi.c b/drivers/spi/sh_qspi.c
index 5ba8a8e..861423b 100644
--- a/drivers/spi/sh_qspi.c
+++ b/drivers/spi/sh_qspi.c
@@ -6,6 +6,8 @@
* Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
*/
+#define LOG_CATEGORY UCLASS_SPI
+
#include <common.h>
#include <console.h>
#include <malloc.h>
@@ -160,7 +162,7 @@
}
if (bitlen % 8) {
- printf("%s: bitlen is not 8bit alined %d", __func__, bitlen);
+ log_warning("bitlen is not 8bit aligned %d", bitlen);
return 1;
}
diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index a3c9633..4b6ea9f 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -270,7 +270,7 @@
flashes[cs].ahb_decoded_sz = priv->info->min_decoded_sz;
/*
- * If commnad mode or normal mode is used, the start address of a
+ * If command mode or normal mode is used, the start address of a
* decoded range should be multiple of its related flash size.
* Namely, the total decoded size from flash 0 to flash N should
* be multiple of the size of flash (N + 1).
@@ -404,7 +404,7 @@
flashes[cs].ahb_decoded_sz = 0;
/*
- * If commnad mode or normal mode is used, the start address of a
+ * If command mode or normal mode is used, the start address of a
* decoded range should be multiple of its related flash size.
* Namely, the total decoded size from flash 0 to flash N should
* be multiple of the size of flash (N + 1).
diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c
index cdea540..7b64532 100644
--- a/drivers/spi/spi-qup.c
+++ b/drivers/spi/spi-qup.c
@@ -233,7 +233,7 @@
}
/*
- * Function to check wheather Input or Output FIFO
+ * Function to check whether Input or Output FIFO
* has data to be serviced
*/
static int qup_spi_check_fifo_status(struct udevice *dev, u32 reg_addr)
diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c
index 0a00df0..ea372a0 100644
--- a/drivers/spi/spi-sifive.c
+++ b/drivers/spi/spi-sifive.c
@@ -350,7 +350,7 @@
if (speed > spi->freq)
speed = spi->freq;
- /* Cofigure max speed */
+ /* Configure max speed */
scale = (DIV_ROUND_UP(spi->freq >> 1, speed) - 1)
& SIFIVE_SPI_SCKDIV_DIV_MASK;
writel(scale, spi->regs + SIFIVE_SPI_REG_SCKDIV);
diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c
new file mode 100644
index 0000000..ebf2903
--- /dev/null
+++ b/drivers/spi/spi-sn-f-ospi.c
@@ -0,0 +1,686 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Socionext SPI flash controller F_OSPI driver
+ * Copyright (C) 2021 Socionext Inc.
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <spi.h>
+#include <spi-mem.h>
+
+/* Registers */
+#define OSPI_PROT_CTL_INDIR 0x00
+#define OSPI_PROT_MODE_DATA_MASK GENMASK(31, 30)
+#define OSPI_PROT_MODE_ALT_MASK GENMASK(29, 28)
+#define OSPI_PROT_MODE_ADDR_MASK GENMASK(27, 26)
+#define OSPI_PROT_MODE_CODE_MASK GENMASK(25, 24)
+#define OSPI_PROT_MODE_SINGLE 0
+#define OSPI_PROT_MODE_DUAL 1
+#define OSPI_PROT_MODE_QUAD 2
+#define OSPI_PROT_MODE_OCTAL 3
+#define OSPI_PROT_DATA_RATE_DATA BIT(23)
+#define OSPI_PROT_DATA_RATE_ALT BIT(22)
+#define OSPI_PROT_DATA_RATE_ADDR BIT(21)
+#define OSPI_PROT_DATA_RATE_CODE BIT(20)
+#define OSPI_PROT_SDR 0
+#define OSPI_PROT_DDR 1
+#define OSPI_PROT_BIT_POS_DATA BIT(19)
+#define OSPI_PROT_BIT_POS_ALT BIT(18)
+#define OSPI_PROT_BIT_POS_ADDR BIT(17)
+#define OSPI_PROT_BIT_POS_CODE BIT(16)
+#define OSPI_PROT_SAMP_EDGE BIT(12)
+#define OSPI_PROT_DATA_UNIT_MASK GENMASK(11, 10)
+#define OSPI_PROT_DATA_UNIT_1B 0
+#define OSPI_PROT_DATA_UNIT_2B 1
+#define OSPI_PROT_DATA_UNIT_4B 3
+#define OSPI_PROT_TRANS_DIR_WRITE BIT(9)
+#define OSPI_PROT_DATA_EN BIT(8)
+#define OSPI_PROT_ALT_SIZE_MASK GENMASK(7, 5)
+#define OSPI_PROT_ADDR_SIZE_MASK GENMASK(4, 2)
+#define OSPI_PROT_CODE_SIZE_MASK GENMASK(1, 0)
+
+#define OSPI_CLK_CTL 0x10
+#define OSPI_CLK_CTL_BOOT_INT_CLK_EN BIT(16)
+#define OSPI_CLK_CTL_PHA BIT(12)
+#define OSPI_CLK_CTL_PHA_180 0
+#define OSPI_CLK_CTL_PHA_90 1
+#define OSPI_CLK_CTL_DIV GENMASK(9, 8)
+#define OSPI_CLK_CTL_DIV_1 0
+#define OSPI_CLK_CTL_DIV_2 1
+#define OSPI_CLK_CTL_DIV_4 2
+#define OSPI_CLK_CTL_DIV_8 3
+#define OSPI_CLK_CTL_INT_CLK_EN BIT(0)
+
+#define OSPI_CS_CTL1 0x14
+#define OSPI_CS_CTL2 0x18
+#define OSPI_SSEL 0x20
+#define OSPI_CMD_IDX_INDIR 0x40
+#define OSPI_ADDR 0x50
+#define OSPI_ALT_INDIR 0x60
+#define OSPI_DMY_INDIR 0x70
+#define OSPI_DAT 0x80
+#define OSPI_DAT_SWP_INDIR 0x90
+
+#define OSPI_DAT_SIZE_INDIR 0xA0
+#define OSPI_DAT_SIZE_EN BIT(15)
+#define OSPI_DAT_SIZE_MASK GENMASK(10, 0)
+#define OSPI_DAT_SIZE_MAX (OSPI_DAT_SIZE_MASK + 1)
+
+#define OSPI_TRANS_CTL 0xC0
+#define OSPI_TRANS_CTL_STOP_REQ BIT(1) /* RW1AC */
+#define OSPI_TRANS_CTL_START_REQ BIT(0) /* RW1AC */
+
+#define OSPI_ACC_MODE 0xC4
+#define OSPI_ACC_MODE_BOOT_DISABLE BIT(0)
+
+#define OSPI_SWRST 0xD0
+#define OSPI_SWRST_INDIR_WRITE_FIFO BIT(9) /* RW1AC */
+#define OSPI_SWRST_INDIR_READ_FIFO BIT(8) /* RW1AC */
+
+#define OSPI_STAT 0xE0
+#define OSPI_STAT_IS_AXI_WRITING BIT(10)
+#define OSPI_STAT_IS_AXI_READING BIT(9)
+#define OSPI_STAT_IS_SPI_INT_CLK_STOP BIT(4)
+#define OSPI_STAT_IS_SPI_IDLE BIT(3)
+
+#define OSPI_IRQ 0xF0
+#define OSPI_IRQ_CS_DEASSERT BIT(8)
+#define OSPI_IRQ_WRITE_BUF_READY BIT(2)
+#define OSPI_IRQ_READ_BUF_READY BIT(1)
+#define OSPI_IRQ_CS_TRANS_COMP BIT(0)
+#define OSPI_IRQ_ALL \
+ (OSPI_IRQ_CS_DEASSERT | OSPI_IRQ_WRITE_BUF_READY \
+ | OSPI_IRQ_READ_BUF_READY | OSPI_IRQ_CS_TRANS_COMP)
+
+#define OSPI_IRQ_STAT_EN 0xF4
+#define OSPI_IRQ_SIG_EN 0xF8
+
+/* Parameters */
+#define OSPI_NUM_CS 4
+#define OSPI_DUMMY_CYCLE_MAX 255
+#define OSPI_WAIT_MAX_MSEC 100
+
+struct f_ospi {
+ void __iomem *base;
+ struct udevice *dev;
+ struct clk clk;
+
+ u32 mode;
+ u32 max_speed_hz;
+ u32 num_cs;
+ u32 chip_select;
+};
+
+static u32 f_ospi_get_dummy_cycle(const struct spi_mem_op *op)
+{
+ return (op->dummy.nbytes * 8) / op->dummy.buswidth;
+}
+
+static void f_ospi_clear_irq(struct f_ospi *ospi)
+{
+ writel(OSPI_IRQ_CS_DEASSERT | OSPI_IRQ_CS_TRANS_COMP,
+ ospi->base + OSPI_IRQ);
+}
+
+static void f_ospi_enable_irq_status(struct f_ospi *ospi, u32 irq_bits)
+{
+ u32 val;
+
+ val = readl(ospi->base + OSPI_IRQ_STAT_EN);
+ val |= irq_bits;
+ writel(val, ospi->base + OSPI_IRQ_STAT_EN);
+}
+
+static void f_ospi_disable_irq_status(struct f_ospi *ospi, u32 irq_bits)
+{
+ u32 val;
+
+ val = readl(ospi->base + OSPI_IRQ_STAT_EN);
+ val &= ~irq_bits;
+ writel(val, ospi->base + OSPI_IRQ_STAT_EN);
+}
+
+static void f_ospi_disable_irq_output(struct f_ospi *ospi, u32 irq_bits)
+{
+ u32 val;
+
+ val = readl(ospi->base + OSPI_IRQ_SIG_EN);
+ val &= ~irq_bits;
+ writel(val, ospi->base + OSPI_IRQ_SIG_EN);
+}
+
+static int f_ospi_prepare_config(struct f_ospi *ospi)
+{
+ u32 val, stat0, stat1;
+
+ /* G4: Disable internal clock */
+ val = readl(ospi->base + OSPI_CLK_CTL);
+ val &= ~(OSPI_CLK_CTL_BOOT_INT_CLK_EN | OSPI_CLK_CTL_INT_CLK_EN);
+ writel(val, ospi->base + OSPI_CLK_CTL);
+
+ /* G5: Wait for stop */
+ stat0 = OSPI_STAT_IS_AXI_WRITING | OSPI_STAT_IS_AXI_READING;
+ stat1 = OSPI_STAT_IS_SPI_IDLE | OSPI_STAT_IS_SPI_INT_CLK_STOP;
+
+ return readl_poll_timeout(ospi->base + OSPI_STAT,
+ val, (val & (stat0 | stat1)) == stat1,
+ OSPI_WAIT_MAX_MSEC);
+}
+
+static int f_ospi_unprepare_config(struct f_ospi *ospi)
+{
+ u32 val;
+
+ /* G11: Enable internal clock */
+ val = readl(ospi->base + OSPI_CLK_CTL);
+ val |= OSPI_CLK_CTL_BOOT_INT_CLK_EN | OSPI_CLK_CTL_INT_CLK_EN;
+ writel(val, ospi->base + OSPI_CLK_CTL);
+
+ /* G12: Wait for clock to start */
+ return readl_poll_timeout(ospi->base + OSPI_STAT,
+ val, !(val & OSPI_STAT_IS_SPI_INT_CLK_STOP),
+ OSPI_WAIT_MAX_MSEC);
+}
+
+static void f_ospi_config_clk(struct f_ospi *ospi, u32 device_hz)
+{
+ long rate_hz = clk_get_rate(&ospi->clk);
+ u32 div = DIV_ROUND_UP(rate_hz, device_hz);
+ u32 div_reg;
+ u32 val;
+
+ if (rate_hz < device_hz) {
+ dev_warn(ospi->dev, "Device frequency too large: %d\n",
+ device_hz);
+ div_reg = OSPI_CLK_CTL_DIV_1;
+ } else {
+ if (div == 1) {
+ div_reg = OSPI_CLK_CTL_DIV_1;
+ } else if (div == 2) {
+ div_reg = OSPI_CLK_CTL_DIV_2;
+ } else if (div <= 4) {
+ div_reg = OSPI_CLK_CTL_DIV_4;
+ } else if (div <= 8) {
+ div_reg = OSPI_CLK_CTL_DIV_8;
+ } else {
+ dev_warn(ospi->dev, "Device frequency too small: %d\n",
+ device_hz);
+ div_reg = OSPI_CLK_CTL_DIV_8;
+ }
+ }
+
+ /*
+ * G7: Set clock mode
+ * clock phase is fixed at 180 degrees and configure edge direction
+ * instead.
+ */
+ val = readl(ospi->base + OSPI_CLK_CTL);
+
+ val &= ~(OSPI_CLK_CTL_PHA | OSPI_CLK_CTL_DIV);
+ val |= FIELD_PREP(OSPI_CLK_CTL_PHA, OSPI_CLK_CTL_PHA_180)
+ | FIELD_PREP(OSPI_CLK_CTL_DIV, div_reg);
+
+ writel(val, ospi->base + OSPI_CLK_CTL);
+}
+
+static void f_ospi_config_dll(struct f_ospi *ospi)
+{
+ /* G8: Configure DLL, nothing */
+}
+
+static u8 f_ospi_get_mode(struct f_ospi *ospi, int width, int data_size)
+{
+ u8 mode = OSPI_PROT_MODE_SINGLE;
+
+ switch (width) {
+ case 1:
+ mode = OSPI_PROT_MODE_SINGLE;
+ break;
+ case 2:
+ mode = OSPI_PROT_MODE_DUAL;
+ break;
+ case 4:
+ mode = OSPI_PROT_MODE_QUAD;
+ break;
+ case 8:
+ mode = OSPI_PROT_MODE_OCTAL;
+ break;
+ default:
+ if (data_size)
+ dev_err(ospi->dev, "Invalid buswidth: %d\n", width);
+ break;
+ }
+
+ return mode;
+}
+
+static void f_ospi_config_indir_protocol(struct f_ospi *ospi,
+ const struct spi_mem_op *op)
+{
+ u8 mode;
+ u32 prot = 0, val;
+ int unit;
+
+ /* Set one chip select */
+ writel(BIT(ospi->chip_select), ospi->base + OSPI_SSEL);
+
+ mode = f_ospi_get_mode(ospi, op->cmd.buswidth, 1);
+ prot |= FIELD_PREP(OSPI_PROT_MODE_CODE_MASK, mode);
+
+ mode = f_ospi_get_mode(ospi, op->addr.buswidth, op->addr.nbytes);
+ prot |= FIELD_PREP(OSPI_PROT_MODE_ADDR_MASK, mode);
+
+ mode = f_ospi_get_mode(ospi, op->data.buswidth, op->data.nbytes);
+ prot |= FIELD_PREP(OSPI_PROT_MODE_DATA_MASK, mode);
+
+ prot |= FIELD_PREP(OSPI_PROT_DATA_RATE_DATA, OSPI_PROT_SDR);
+ prot |= FIELD_PREP(OSPI_PROT_DATA_RATE_ALT, OSPI_PROT_SDR);
+ prot |= FIELD_PREP(OSPI_PROT_DATA_RATE_ADDR, OSPI_PROT_SDR);
+ prot |= FIELD_PREP(OSPI_PROT_DATA_RATE_CODE, OSPI_PROT_SDR);
+
+ if (ospi->mode & SPI_LSB_FIRST)
+ prot |= OSPI_PROT_BIT_POS_DATA | OSPI_PROT_BIT_POS_ALT
+ | OSPI_PROT_BIT_POS_ADDR | OSPI_PROT_BIT_POS_CODE;
+
+ if (ospi->mode & SPI_CPHA)
+ prot |= OSPI_PROT_SAMP_EDGE;
+
+ /* Examine nbytes % 4 */
+ switch (op->data.nbytes & 0x3) {
+ case 0:
+ unit = OSPI_PROT_DATA_UNIT_4B;
+ val = 0;
+ break;
+ case 2:
+ unit = OSPI_PROT_DATA_UNIT_2B;
+ val = OSPI_DAT_SIZE_EN | (op->data.nbytes - 1);
+ break;
+ default:
+ unit = OSPI_PROT_DATA_UNIT_1B;
+ val = OSPI_DAT_SIZE_EN | (op->data.nbytes - 1);
+ break;
+ }
+ prot |= FIELD_PREP(OSPI_PROT_DATA_UNIT_MASK, unit);
+
+ switch (op->data.dir) {
+ case SPI_MEM_DATA_IN:
+ prot |= OSPI_PROT_DATA_EN;
+ break;
+
+ case SPI_MEM_DATA_OUT:
+ prot |= OSPI_PROT_TRANS_DIR_WRITE | OSPI_PROT_DATA_EN;
+ break;
+
+ case SPI_MEM_NO_DATA:
+ prot |= OSPI_PROT_TRANS_DIR_WRITE;
+ break;
+
+ default:
+ dev_warn(ospi->dev, "Unsupported direction");
+ break;
+ }
+
+ prot |= FIELD_PREP(OSPI_PROT_ADDR_SIZE_MASK, op->addr.nbytes);
+ prot |= FIELD_PREP(OSPI_PROT_CODE_SIZE_MASK, 1); /* 1byte */
+
+ writel(prot, ospi->base + OSPI_PROT_CTL_INDIR);
+ writel(val, ospi->base + OSPI_DAT_SIZE_INDIR);
+}
+
+static int f_ospi_indir_prepare_op(struct f_ospi *ospi,
+ const struct spi_mem_op *op)
+{
+ u32 irq_stat_en;
+ int ret;
+
+ ret = f_ospi_prepare_config(ospi);
+ if (ret)
+ return ret;
+
+ f_ospi_config_clk(ospi, ospi->max_speed_hz);
+
+ f_ospi_config_indir_protocol(ospi, op);
+
+ writel(f_ospi_get_dummy_cycle(op), ospi->base + OSPI_DMY_INDIR);
+ writel(op->addr.val, ospi->base + OSPI_ADDR);
+ writel(op->cmd.opcode, ospi->base + OSPI_CMD_IDX_INDIR);
+
+ f_ospi_clear_irq(ospi);
+
+ switch (op->data.dir) {
+ case SPI_MEM_DATA_IN:
+ irq_stat_en = OSPI_IRQ_READ_BUF_READY | OSPI_IRQ_CS_TRANS_COMP;
+ break;
+
+ case SPI_MEM_DATA_OUT:
+ irq_stat_en = OSPI_IRQ_WRITE_BUF_READY | OSPI_IRQ_CS_TRANS_COMP;
+ break;
+
+ case SPI_MEM_NO_DATA:
+ irq_stat_en = OSPI_IRQ_CS_TRANS_COMP;
+ break;
+
+ default:
+ dev_warn(ospi->dev, "Unsupported direction");
+ irq_stat_en = 0;
+ }
+
+ f_ospi_disable_irq_status(ospi, ~irq_stat_en);
+ f_ospi_enable_irq_status(ospi, irq_stat_en);
+
+ return f_ospi_unprepare_config(ospi);
+}
+
+static void f_ospi_indir_start_xfer(struct f_ospi *ospi)
+{
+ /* Write only 1, auto cleared */
+ writel(OSPI_TRANS_CTL_START_REQ, ospi->base + OSPI_TRANS_CTL);
+}
+
+static void f_ospi_indir_stop_xfer(struct f_ospi *ospi)
+{
+ /* Write only 1, auto cleared */
+ writel(OSPI_TRANS_CTL_STOP_REQ, ospi->base + OSPI_TRANS_CTL);
+}
+
+static int f_ospi_indir_wait_xfer_complete(struct f_ospi *ospi)
+{
+ u32 val;
+
+ return readl_poll_timeout(ospi->base + OSPI_IRQ, val,
+ val & OSPI_IRQ_CS_TRANS_COMP,
+ OSPI_WAIT_MAX_MSEC);
+}
+
+static int f_ospi_indir_read(struct f_ospi *ospi,
+ const struct spi_mem_op *op)
+{
+ u8 *buf = op->data.buf.in;
+ u32 val;
+ int i, ret;
+
+ /* E1-2: Prepare transfer operation */
+ ret = f_ospi_indir_prepare_op(ospi, op);
+ if (ret)
+ goto out;
+
+ f_ospi_indir_start_xfer(ospi);
+
+ /* E3-4: Wait for ready and read data */
+ for (i = 0; i < op->data.nbytes; i++) {
+ ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val,
+ val & OSPI_IRQ_READ_BUF_READY,
+ OSPI_WAIT_MAX_MSEC);
+ if (ret)
+ goto out;
+
+ buf[i] = readl(ospi->base + OSPI_DAT) & 0xFF;
+ }
+
+ /* E5-6: Stop transfer if data size is nothing */
+ if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN))
+ f_ospi_indir_stop_xfer(ospi);
+
+ /* E7-8: Wait for completion and clear */
+ ret = f_ospi_indir_wait_xfer_complete(ospi);
+ if (ret)
+ goto out;
+
+ writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ);
+
+ /* E9: Do nothing if data size is valid */
+ if (readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN)
+ goto out;
+
+ /* E10-11: Reset and check read fifo */
+ writel(OSPI_SWRST_INDIR_READ_FIFO, ospi->base + OSPI_SWRST);
+
+ ret = readl_poll_timeout(ospi->base + OSPI_SWRST, val,
+ !(val & OSPI_SWRST_INDIR_READ_FIFO),
+ OSPI_WAIT_MAX_MSEC);
+out:
+ return ret;
+}
+
+static int f_ospi_indir_write(struct f_ospi *ospi,
+ const struct spi_mem_op *op)
+{
+ u8 *buf = (u8 *)op->data.buf.out;
+ u32 val;
+ int i, ret;
+
+ /* F1-3: Prepare transfer operation */
+ ret = f_ospi_indir_prepare_op(ospi, op);
+ if (ret)
+ goto out;
+
+ f_ospi_indir_start_xfer(ospi);
+
+ if (!(readl(ospi->base + OSPI_PROT_CTL_INDIR) & OSPI_PROT_DATA_EN))
+ goto nodata;
+
+ /* F4-5: Wait for buffer ready and write data */
+ for (i = 0; i < op->data.nbytes; i++) {
+ ret = readl_poll_timeout(ospi->base + OSPI_IRQ, val,
+ val & OSPI_IRQ_WRITE_BUF_READY,
+ OSPI_WAIT_MAX_MSEC);
+ if (ret)
+ goto out;
+
+ writel(buf[i], ospi->base + OSPI_DAT);
+ }
+
+ /* F6-7: Stop transfer if data size is nothing */
+ if (!(readl(ospi->base + OSPI_DAT_SIZE_INDIR) & OSPI_DAT_SIZE_EN))
+ f_ospi_indir_stop_xfer(ospi);
+
+nodata:
+ /* F8-9: Wait for completion and clear */
+ ret = f_ospi_indir_wait_xfer_complete(ospi);
+ if (ret)
+ goto out;
+
+ writel(OSPI_IRQ_CS_TRANS_COMP, ospi->base + OSPI_IRQ);
+out:
+ return ret;
+}
+
+static int f_ospi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
+{
+ struct f_ospi *ospi = dev_get_priv(slave->dev->parent);
+ struct dm_spi_slave_plat *slave_plat;
+ int err = 0;
+
+ slave_plat = dev_get_parent_plat(slave->dev);
+ ospi->chip_select = slave_plat->cs;
+
+ switch (op->data.dir) {
+ case SPI_MEM_DATA_IN:
+ err = f_ospi_indir_read(ospi, op);
+ break;
+
+ case SPI_MEM_DATA_OUT:
+ fallthrough;
+ case SPI_MEM_NO_DATA:
+ err = f_ospi_indir_write(ospi, op);
+ break;
+
+ default:
+ dev_warn(ospi->dev, "Unsupported direction");
+ err = -EOPNOTSUPP;
+ }
+
+ return err;
+}
+
+static bool f_ospi_supports_op_width(const struct spi_mem_op *op)
+{
+ u8 width_available[] = { 0, 1, 2, 4, 8 };
+ u8 width_op[] = { op->cmd.buswidth, op->addr.buswidth,
+ op->dummy.buswidth, op->data.buswidth };
+ bool is_match_found;
+ int i, j;
+
+ for (i = 0; i < ARRAY_SIZE(width_op); i++) {
+ is_match_found = false;
+
+ for (j = 0; j < ARRAY_SIZE(width_available); j++) {
+ if (width_op[i] == width_available[j]) {
+ is_match_found = true;
+ break;
+ }
+ }
+
+ if (!is_match_found)
+ return false;
+ }
+
+ return true;
+}
+
+static bool f_ospi_supports_op(struct spi_slave *slave,
+ const struct spi_mem_op *op)
+{
+ if (f_ospi_get_dummy_cycle(op) > OSPI_DUMMY_CYCLE_MAX)
+ return false;
+
+ if (op->addr.nbytes > 4)
+ return false;
+
+ if (!f_ospi_supports_op_width(op))
+ return false;
+
+ return true;
+}
+
+static int f_ospi_adjust_op_size(struct spi_slave *slave, struct spi_mem_op *op)
+{
+ op->data.nbytes = min((int)op->data.nbytes, (int)(OSPI_DAT_SIZE_MAX));
+
+ return 0;
+}
+
+static const struct spi_controller_mem_ops f_ospi_mem_ops = {
+ .adjust_op_size = f_ospi_adjust_op_size,
+ .supports_op = f_ospi_supports_op,
+ .exec_op = f_ospi_exec_op,
+};
+
+static int f_ospi_set_speed(struct udevice *bus, u32 speed)
+{
+ struct f_ospi *ospi = dev_get_priv(bus);
+
+ ospi->max_speed_hz = speed;
+
+ return 0;
+}
+
+static int f_ospi_set_mode(struct udevice *bus, u32 mode)
+{
+ struct f_ospi *ospi = dev_get_priv(bus);
+
+ ospi->mode = mode;
+
+ return 0;
+}
+
+static int f_ospi_init(struct f_ospi *ospi)
+{
+ int ret;
+
+ ret = f_ospi_prepare_config(ospi);
+ if (ret)
+ return ret;
+
+ /* Disable boot signal */
+ writel(OSPI_ACC_MODE_BOOT_DISABLE, ospi->base + OSPI_ACC_MODE);
+
+ f_ospi_config_dll(ospi);
+
+ /* Disable IRQ */
+ f_ospi_clear_irq(ospi);
+ f_ospi_disable_irq_status(ospi, OSPI_IRQ_ALL);
+ f_ospi_disable_irq_output(ospi, OSPI_IRQ_ALL);
+
+ return f_ospi_unprepare_config(ospi);
+}
+
+static int f_ospi_of_to_plat(struct udevice *dev)
+{
+ struct f_ospi *ospi = dev_get_priv(dev);
+
+ ospi->base = dev_read_addr_ptr(dev);
+ ospi->num_cs = dev_read_u32_default(dev, "num-cs", OSPI_NUM_CS);
+
+ return 0;
+}
+
+static int f_ospi_probe(struct udevice *dev)
+{
+ struct f_ospi *ospi = dev_get_priv(dev);
+ int ret;
+
+ ospi->dev = dev;
+
+ ret = clk_get_by_index(dev, 0, &ospi->clk);
+ if (ret < 0) {
+ dev_err(dev, "Failed to get clock\n");
+ goto err_put_ctlr;
+ }
+
+ ret = clk_enable(&ospi->clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable the clock\n");
+ goto err_put_ctlr;
+ }
+
+ ret = f_ospi_init(ospi);
+ if (ret)
+ goto err_disable_clk;
+
+ return 0;
+
+err_disable_clk:
+ clk_disable(&ospi->clk);
+
+err_put_ctlr:
+ dev_err(dev, "Socionext F_OSPI probe failed\n");
+ return ret;
+}
+
+static int f_ospi_remove(struct udevice *dev)
+{
+ struct f_ospi *ospi = dev_get_priv(dev);
+
+ clk_disable(&ospi->clk);
+
+ return 0;
+}
+
+static const struct dm_spi_ops f_ospi_ops = {
+ .set_speed = f_ospi_set_speed,
+ .set_mode = f_ospi_set_mode,
+ .mem_ops = &f_ospi_mem_ops,
+};
+
+static const struct udevice_id f_ospi_dt_ids[] = {
+ { .compatible = "socionext,f-ospi" },
+ {}
+};
+
+U_BOOT_DRIVER(f_ospi) = {
+ .name = "sn-f-ospi",
+ .id = UCLASS_SPI,
+ .of_match = f_ospi_dt_ids,
+ .of_to_plat = f_ospi_of_to_plat,
+ .ops = &f_ospi_ops,
+ .probe = f_ospi_probe,
+ .remove = f_ospi_remove,
+ .priv_auto = sizeof(struct f_ospi),
+};
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index b21031d..9a9b697 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -73,7 +73,7 @@
for (idx = 0; idx < service_cnt; idx++, service++) {
tee_optee_ta_uuid_to_octets(loc_uuid, &service->uuid);
- if (!memcmp(uuid, loc_uuid, sizeof(uuid)))
+ if (!memcmp(uuid, loc_uuid, sizeof(*uuid)))
return service;
}
@@ -92,7 +92,8 @@
if (!service)
continue;
- ret = device_bind_driver(dev, service->driver_name, service->driver_name, NULL);
+ ret = device_bind_driver_to_node(dev, service->driver_name, service->driver_name,
+ dev_ofnode(dev), NULL);
if (ret) {
dev_warn(dev, "%s was not bound: %d, ignored\n", service->driver_name, ret);
continue;
@@ -846,9 +847,10 @@
* Discovery of TAs on the TEE bus is not supported in U-Boot:
* only bind the drivers associated to the supported OP-TEE TA
*/
- ret = device_bind_driver(dev, "optee-rng", "optee-rng", NULL);
+ ret = device_bind_driver_to_node(dev, "optee-rng", "optee-rng",
+ dev_ofnode(dev), NULL);
if (ret)
- dev_warn(dev, "ftpm_tee failed to bind: %d\n", ret);
+ dev_warn(dev, "optee-rng failed to bind: %d\n", ret);
}
return 0;
diff --git a/drivers/timer/mpc83xx_timer.c b/drivers/timer/mpc83xx_timer.c
index 410bf72..7814cb6 100644
--- a/drivers/timer/mpc83xx_timer.c
+++ b/drivers/timer/mpc83xx_timer.c
@@ -20,8 +20,8 @@
DECLARE_GLOBAL_DATA_PTR;
-#ifndef CONFIG_SYS_WATCHDOG_FREQ
-#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
+#ifndef CFG_SYS_WATCHDOG_FREQ
+#define CFG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2)
#endif
/**
@@ -175,7 +175,7 @@
priv->timestamp++;
#if defined(CONFIG_WATCHDOG) || defined(CONFIG_HW_WATCHDOG)
- if (CONFIG_SYS_WATCHDOG_FREQ && (priv->timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0)
+ if (CFG_SYS_WATCHDOG_FREQ && (priv->timestamp % (CFG_SYS_WATCHDOG_FREQ)) == 0)
schedule();
#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */
diff --git a/drivers/timer/orion-timer.c b/drivers/timer/orion-timer.c
index 810a03d..9cab27f 100644
--- a/drivers/timer/orion-timer.c
+++ b/drivers/timer/orion-timer.c
@@ -25,7 +25,8 @@
static bool early_init_done(void *base)
{
- if (readl(base + TIMER_CTRL) & TIMER0_EN)
+ if ((readl(base + TIMER_CTRL) & TIMER0_EN) &&
+ (readl(base + TIMER0_RELOAD) == ~0))
return true;
return false;
}
diff --git a/drivers/tpm/tpm2_ftpm_tee.c b/drivers/tpm/tpm2_ftpm_tee.c
index 3c4c129..c61ff2c 100644
--- a/drivers/tpm/tpm2_ftpm_tee.c
+++ b/drivers/tpm/tpm2_ftpm_tee.c
@@ -18,10 +18,13 @@
#include <log.h>
#include <tpm-v2.h>
#include <tee.h>
+#include <tee/optee_service.h>
#include "tpm_tis.h"
#include "tpm2_ftpm_tee.h"
+OPTEE_SERVICE_DRIVER(optee_ftpm, TA_FTPM_UUID, "ftpm_tee");
+
/**
* ftpm_tee_transceive() - send fTPM commands and retrieve fTPM response.
* @sendbuf - address of the data to send, byte by byte
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h
index 069888f..8a38832 100644
--- a/drivers/ufs/ufs.h
+++ b/drivers/ufs/ufs.h
@@ -898,7 +898,7 @@
#define RESET_LEVEL 0xFF
#define ATTR_SET_TYPE_MASK UFS_MASK(0xFF, 16)
-#define CONFIG_RESULT_CODE_MASK 0xFF
+#define CFG_RESULT_CODE_MASK 0xFF
#define GENERIC_ERROR_CODE_MASK 0xFF
#define ufshcd_writel(hba, val, reg) \
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8efd461..ebe6bf9 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -105,6 +105,16 @@
Say Y here if you want to use a USB keyboard for U-Boot command line
input.
+config USB_ONBOARD_HUB
+ bool "Onboard USB hub support"
+ depends on DM_USB
+ ---help---
+ Say Y here if you want to support discrete onboard USB hubs that
+ don't require an additional control bus for initialization, but
+ need some non-trivial form of initialization, such as enabling a
+ power regulator. An example for such a hub is the Microchip
+ USB2514B.
+
if USB_KEYBOARD
config USB_KEYBOARD_FN_KEYS
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index d9a89a1..b9258d7 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -322,7 +322,7 @@
if (num != 0) {
struct ept_queue_head *head = ci_get_qh(num, in);
- head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT;
+ head->config = CFG_MAX_PKT(maxpacket) | CFG_ZLT;
ci_flush_qh(num);
}
writel(n, &udc->epctrl[num]);
@@ -959,11 +959,11 @@
*/
head = controller.epts + i;
if (i < 2)
- head->config = CONFIG_MAX_PKT(EP0_MAX_PACKET_SIZE)
- | CONFIG_ZLT | CONFIG_IOS;
+ head->config = CFG_MAX_PKT(EP0_MAX_PACKET_SIZE)
+ | CFG_ZLT | CFG_IOS;
else
- head->config = CONFIG_MAX_PKT(EP_MAX_PACKET_SIZE)
- | CONFIG_ZLT;
+ head->config = CFG_MAX_PKT(EP_MAX_PACKET_SIZE)
+ | CFG_ZLT;
head->next = TERMINATE;
head->info = 0;
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 95cc079..bea2f9f 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -128,9 +128,9 @@
unsigned reserved_4;
};
-#define CONFIG_MAX_PKT(n) ((n) << 16)
-#define CONFIG_ZLT (1 << 29) /* stop on zero-len xfer */
-#define CONFIG_IOS (1 << 15) /* IRQ on setup */
+#define CFG_MAX_PKT(n) ((n) << 16)
+#define CFG_ZLT (1 << 29) /* stop on zero-len xfer */
+#define CFG_IOS (1 << 15) /* IRQ on setup */
struct ept_queue_item {
unsigned next;
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 77988f7..2bf7ed8 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -236,6 +236,14 @@
return 0;
}
+static int dwc2_gadget_pullup(struct usb_gadget *g, int is_on)
+{
+ clrsetbits_le32(®->dctl, SOFT_DISCONNECT,
+ is_on ? 0 : SOFT_DISCONNECT);
+
+ return 0;
+}
+
#if !CONFIG_IS_ENABLED(DM_USB_GADGET)
/*
Register entry point for the peripheral controller driver.
@@ -805,6 +813,7 @@
}
static const struct usb_gadget_ops dwc2_udc_ops = {
+ .pullup = dwc2_gadget_pullup,
/* current versions must always be self-powered */
#if CONFIG_IS_ENABLED(DM_USB_GADGET)
.udc_start = dwc2_gadget_start,
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 07b1681..6d97b4b 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -421,6 +421,7 @@
static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
{
+ g_dnl_unregister();
do_reset(NULL, 0, 0, NULL);
}
@@ -495,7 +496,6 @@
do_exit_on_complete(ep, req);
}
-#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
static void do_acmd_complete(struct usb_ep *ep, struct usb_request *req)
{
/* When usb dequeue complete will be called
@@ -505,7 +505,6 @@
if (req->status == 0)
fastboot_acmd_complete();
}
-#endif
static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
{
@@ -544,13 +543,11 @@
case FASTBOOT_COMMAND_REBOOT_FASTBOOTD:
case FASTBOOT_COMMAND_REBOOT_RECOVERY:
fastboot_func->in_req->complete = compl_do_reset;
- g_dnl_trigger_detach();
break;
-#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
case FASTBOOT_COMMAND_ACMD:
- fastboot_func->in_req->complete = do_acmd_complete;
+ if (CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT))
+ fastboot_func->in_req->complete = do_acmd_complete;
break;
-#endif
}
}
diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
index 5ae5b62..9ea43f2 100644
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -868,7 +868,7 @@
jump_to_image_no_args(&spl_image);
#else
/* In U-Boot, allow jumps to scripts */
- image_source_script(sdp_func->jmp_address, NULL, NULL);
+ cmd_source_script(sdp_func->jmp_address, NULL, NULL);
#endif
}
diff --git a/drivers/usb/host/ehci-faraday.c b/drivers/usb/host/ehci-faraday.c
index b61b538..85a3526 100644
--- a/drivers/usb/host/ehci-faraday.c
+++ b/drivers/usb/host/ehci-faraday.c
@@ -16,8 +16,8 @@
#include "ehci.h"
-#ifndef CONFIG_USB_EHCI_BASE_LIST
-#define CONFIG_USB_EHCI_BASE_LIST { CONFIG_USB_EHCI_BASE }
+#ifndef CFG_USB_EHCI_BASE_LIST
+#define CFG_USB_EHCI_BASE_LIST { CONFIG_USB_EHCI_BASE }
#endif
union ehci_faraday_regs {
@@ -93,7 +93,7 @@
struct ehci_hccr *hccr;
struct ehci_hcor *hcor;
union ehci_faraday_regs *regs;
- uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST;
+ uint32_t base_list[] = CFG_USB_EHCI_BASE_LIST;
if (index < 0 || index >= ARRAY_SIZE(base_list))
return -1;
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index b02ee89..11d7767 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -578,8 +578,8 @@
#ifdef CONFIG_USB_ULPI
/* if board file does not set a ULPI reference frequency we default to 24MHz */
-#ifndef CONFIG_ULPI_REF_CLK
-#define CONFIG_ULPI_REF_CLK 24000000
+#ifndef CFG_ULPI_REF_CLK
+#define CFG_ULPI_REF_CLK 24000000
#endif
/* set up the ULPI USB controller with the parameters provided */
@@ -594,7 +594,7 @@
/* set up ULPI reference clock on pllp_out4 */
clock_enable(PERIPH_ID_DEV2_OUT);
- clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CONFIG_ULPI_REF_CLK);
+ clock_set_pllout(CLOCK_ID_PERIPH, PLL_OUT4, CFG_ULPI_REF_CLK);
/* reset ULPI phy */
if (dm_gpio_is_valid(&config->phy_reset_gpio)) {
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 956e2a4..28f7ca9 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -271,19 +271,23 @@
/* init low_level USB */
printf("Bus %s: ", bus->name);
-#ifdef CONFIG_SANDBOX
/*
* For Sandbox, we need scan the device tree each time when we
* start the USB stack, in order to re-create the emulated USB
* devices and bind drivers for them before we actually do the
* driver probe.
+ *
+ * For USB onboard HUB, we need to do some non-trivial init
+ * like enabling a power regulator, before enumeration.
*/
- ret = dm_scan_fdt_dev(bus);
- if (ret) {
- printf("Sandbox USB device scan failed (%d)\n", ret);
- continue;
+ if (IS_ENABLED(CONFIG_SANDBOX) ||
+ IS_ENABLED(CONFIG_USB_ONBOARD_HUB)) {
+ ret = dm_scan_fdt_dev(bus);
+ if (ret) {
+ printf("USB device scan from fdt failed (%d)", ret);
+ continue;
+ }
}
-#endif
ret = device_probe(bus);
if (ret == -ENODEV) { /* No such device. */
@@ -559,6 +563,8 @@
if (!str)
return -ENOMEM;
ret = device_bind_driver(parent, "usb_dev_generic_drv", str, devp);
+ if (!ret)
+ device_set_name_alloced(*devp);
error:
debug("%s: No match found: %d\n", __func__, ret);
diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c
index b85f699..32919f9 100644
--- a/drivers/usb/host/usb_bootdev.c
+++ b/drivers/usb/host/usb_bootdev.c
@@ -11,40 +11,21 @@
#include <dm.h>
#include <usb.h>
-static int usb_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
- struct bootflow *bflow)
-{
- struct udevice *blk;
- int ret;
-
- ret = bootdev_get_sibling_blk(dev, &blk);
- /*
- * If there is no media, indicate that no more partitions should be
- * checked
- */
- if (ret == -EOPNOTSUPP)
- ret = -ESHUTDOWN;
- if (ret)
- return log_msg_ret("blk", ret);
- assert(blk);
- ret = bootdev_find_in_blk(dev, blk, iter, bflow);
- if (ret)
- return log_msg_ret("find", ret);
-
- return 0;
-}
-
static int usb_bootdev_bind(struct udevice *dev)
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
- ucp->prio = BOOTDEVP_3_SCAN_SLOW;
+ ucp->prio = BOOTDEVP_5_SCAN_SLOW;
return 0;
}
+static int usb_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ return usb_init();
+}
+
struct bootdev_ops usb_bootdev_ops = {
- .get_bootflow = usb_get_bootflow,
};
static const struct udevice_id usb_bootdev_ids[] = {
@@ -59,3 +40,10 @@
.bind = usb_bootdev_bind,
.of_match = usb_bootdev_ids,
};
+
+BOOTDEV_HUNTER(usb_bootdev_hunter) = {
+ .prio = BOOTDEVP_5_SCAN_SLOW,
+ .uclass = UCLASS_USB,
+ .hunt = usb_bootdev_hunt,
+ .drv = DM_DRIVER_REF(usb_bootdev),
+};
diff --git a/drivers/usb/musb-new/linux-compat.h b/drivers/usb/musb-new/linux-compat.h
index 6d9f19d..8829567 100644
--- a/drivers/usb/musb-new/linux-compat.h
+++ b/drivers/usb/musb-new/linux-compat.h
@@ -16,11 +16,11 @@
* Map U-Boot config options to Linux ones
*/
#ifdef CONFIG_OMAP34XX
-#define CONFIG_SOC_OMAP3430
+#define CFG_SOC_OMAP3430
#endif
#ifdef CONFIG_OMAP44XX
-#define CONFIG_ARCH_OMAP4
+#define CFG_ARCH_OMAP4
#endif
#endif /* __LINUX_COMPAT_H__ */
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
index fc7af74..a42d98e 100644
--- a/drivers/usb/musb-new/musb_core.c
+++ b/drivers/usb/musb-new/musb_core.c
@@ -1525,8 +1525,8 @@
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
- defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
+#if defined(CONFIG_SOC_OMAP2430) || defined(CFG_SOC_OMAP3430) || \
+ defined(CFG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
static irqreturn_t generic_interrupt(int irq, void *__hci)
{
diff --git a/drivers/usb/musb-new/musb_core.h b/drivers/usb/musb-new/musb_core.h
index 821d0e0..adfd81b 100644
--- a/drivers/usb/musb-new/musb_core.h
+++ b/drivers/usb/musb-new/musb_core.h
@@ -151,7 +151,7 @@
*/
#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_SOC_OMAP2430) \
- || defined(CONFIG_SOC_OMAP3430) || defined(CONFIG_ARCH_OMAP4)
+ || defined(CFG_SOC_OMAP3430) || defined(CFG_ARCH_OMAP4)
/* REVISIT indexed access seemed to
* misbehave (on DaVinci) for at least peripheral IN ...
*/
diff --git a/drivers/usb/musb-new/omap2430.c b/drivers/usb/musb-new/omap2430.c
index 7d15b94..42e7abd 100644
--- a/drivers/usb/musb-new/omap2430.c
+++ b/drivers/usb/musb-new/omap2430.c
@@ -46,6 +46,15 @@
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
+#ifdef CONFIG_DM_USB_GADGET
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
+{
+ struct musb_host_data *host = dev_get_priv(dev);
+
+ host->host->isr(0, host->host);
+ return 0;
+}
+#endif
static int omap2430_musb_init(struct musb *musb)
{
@@ -214,37 +223,45 @@
static int omap2430_musb_probe(struct udevice *dev)
{
-#ifdef CONFIG_USB_MUSB_HOST
- struct musb_host_data *host = dev_get_priv(dev);
-#else
- struct musb *musbp;
-#endif
struct omap2430_musb_plat *plat = dev_get_plat(dev);
- struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
struct omap_musb_board_data *otg_board_data;
int ret = 0;
void *base = dev_read_addr_ptr(dev);
-
- priv->desc_before_addr = true;
+ struct musb *musbp;
otg_board_data = &plat->otg_board_data;
-#ifdef CONFIG_USB_MUSB_HOST
- host->host = musb_init_controller(&plat->plat,
- (struct device *)otg_board_data,
- plat->base);
- if (!host->host) {
- return -EIO;
+ if (CONFIG_IS_ENABLED(USB_MUSB_HOST)) {
+ struct musb_host_data *host = dev_get_priv(dev);
+ struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
+
+ priv->desc_before_addr = true;
+
+ host->host = musb_init_controller(&plat->plat,
+ (struct device *)otg_board_data,
+ plat->base);
+ if (!host->host)
+ return -EIO;
+
+ return musb_lowlevel_init(host);
+ } else if (CONFIG_IS_ENABLED(DM_USB_GADGET)) {
+ struct musb_host_data *host = dev_get_priv(dev);
+
+ host->host = musb_init_controller(&plat->plat,
+ (struct device *)otg_board_data,
+ plat->base);
+ if (!host->host)
+ return -EIO;
+
+ return usb_add_gadget_udc((struct device *)otg_board_data, &host->host->g);
}
- ret = musb_lowlevel_init(host);
-#else
musbp = musb_register(&plat->plat, (struct device *)otg_board_data,
plat->base);
if (IS_ERR_OR_NULL(musbp))
return -EINVAL;
-#endif
- return ret;
+
+ return 0;
}
static int omap2430_musb_remove(struct udevice *dev)
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index 1790170..4676cab 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -118,7 +118,7 @@
{
u16 csr;
int result = 1;
- int timeout = CONFIG_USB_MUSB_TIMEOUT;
+ int timeout = MUSB_TIMEOUT;
while (result > 0) {
csr = readw(&musbr->txcsr);
@@ -180,7 +180,7 @@
static int wait_until_txep_ready(struct usb_device *dev, u8 ep)
{
u16 csr;
- int timeout = CONFIG_USB_MUSB_TIMEOUT;
+ int timeout = MUSB_TIMEOUT;
do {
if (check_stall(ep, 1)) {
@@ -212,7 +212,7 @@
static int wait_until_rxep_ready(struct usb_device *dev, u8 ep)
{
u16 csr;
- int timeout = CONFIG_USB_MUSB_TIMEOUT;
+ int timeout = MUSB_TIMEOUT;
do {
if (check_stall(ep, 0)) {
diff --git a/drivers/usb/musb/musb_hcd.h b/drivers/usb/musb/musb_hcd.h
index 7eb65e6..a492e99 100644
--- a/drivers/usb/musb/musb_hcd.h
+++ b/drivers/usb/musb/musb_hcd.h
@@ -16,9 +16,7 @@
extern unsigned char new[];
#endif
-#ifndef CONFIG_USB_MUSB_TIMEOUT
-# define CONFIG_USB_MUSB_TIMEOUT 100000
-#endif
+#define MUSB_TIMEOUT 100000
/* This defines the endpoint number used for control transfers */
#define MUSB_CONTROL_EP 0
diff --git a/drivers/usb/ulpi/omap-ulpi-viewport.c b/drivers/usb/ulpi/omap-ulpi-viewport.c
index 8b930e3..8d71db0 100644
--- a/drivers/usb/ulpi/omap-ulpi-viewport.c
+++ b/drivers/usb/ulpi/omap-ulpi-viewport.c
@@ -22,7 +22,7 @@
*/
static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask)
{
- int timeout = CONFIG_USB_ULPI_TIMEOUT;
+ int timeout = CFG_USB_ULPI_TIMEOUT;
while (--timeout) {
if (!(readl(ulpi_vp->viewport_addr) & mask))
diff --git a/drivers/usb/ulpi/ulpi-viewport.c b/drivers/usb/ulpi/ulpi-viewport.c
index 3bb152b..55a6280 100644
--- a/drivers/usb/ulpi/ulpi-viewport.c
+++ b/drivers/usb/ulpi/ulpi-viewport.c
@@ -34,7 +34,7 @@
*/
static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask)
{
- int timeout = CONFIG_USB_ULPI_TIMEOUT;
+ int timeout = CFG_USB_ULPI_TIMEOUT;
/* Wait for the bits in mask to become zero. */
while (--timeout) {
diff --git a/drivers/usb/ulpi/ulpi.c b/drivers/usb/ulpi/ulpi.c
index dd0da0e..b5d2c2c 100644
--- a/drivers/usb/ulpi/ulpi.c
+++ b/drivers/usb/ulpi/ulpi.c
@@ -207,7 +207,7 @@
static int __ulpi_reset_wait(struct ulpi_viewport *ulpi_vp)
{
u32 val;
- int timeout = CONFIG_USB_ULPI_TIMEOUT;
+ int timeout = CFG_USB_ULPI_TIMEOUT;
/* Wait for the RESET bit to become zero */
while (--timeout) {
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f539977..440b161 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -112,10 +112,13 @@
config VIDEO_ANSI
bool "Support ANSI escape sequences in video console"
- default y
+ default y if EFI_LOADER
help
Enable ANSI escape sequence decoding for a more fully functional
- console.
+ console. Functionality includes changing the text colour and moving
+ the cursor. These date from the 1970s and are still widely used today
+ to control a text terminal. U-Boot implements these by decoding the
+ sequences and performing the appropriate operation.
config VIDEO_MIPI_DSI
bool "Support MIPI DSI interface"
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 6859c9f..9cac9a6 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -584,18 +584,24 @@
return NULL;
}
-void vidconsole_list_fonts(void)
+int console_truetype_get_font(struct udevice *dev, int seq,
+ struct vidfont_info *info)
{
struct font_info *tab;
+ int i;
- for (tab = font_table; tab->begin; tab++) {
- if (abs(tab->begin - tab->end) > 4)
- printf("%s\n", tab->name);
+ for (i = 0, tab = font_table; tab->begin; tab++, i++) {
+ if (i == seq && font_valid(tab)) {
+ info->name = tab->name;
+ return 0;
+ }
}
+
+ return -ENOENT;
}
/**
- * vidconsole_add_metrics() - Add a new font/size combination
+ * truetype_add_metrics() - Add a new font/size combination
*
* @dev: Video console device to update
* @font_name: Name of font
@@ -604,8 +610,8 @@
* @return 0 if OK, -EPERM if stbtt failed, -E2BIG if the the metrics table is
* full
*/
-static int vidconsole_add_metrics(struct udevice *dev, const char *font_name,
- uint font_size, const void *font_data)
+static int truetype_add_metrics(struct udevice *dev, const char *font_name,
+ uint font_size, const void *font_data)
{
struct console_tt_priv *priv = dev_get_priv(dev);
struct console_tt_metrics *met;
@@ -674,7 +680,8 @@
vc_priv->tab_width_frac = VID_TO_POS(met->font_size) * 8 / 2;
}
-int vidconsole_select_font(struct udevice *dev, const char *name, uint size)
+static int truetype_select_font(struct udevice *dev, const char *name,
+ uint size)
{
struct console_tt_priv *priv = dev_get_priv(dev);
struct console_tt_metrics *met;
@@ -684,7 +691,7 @@
if (!size)
size = CONFIG_CONSOLE_TRUETYPE_SIZE;
if (!name)
- name = priv->cur_met->font_name;
+ name = font_table->name;
met = find_metrics(dev, name, size);
if (!met) {
@@ -693,8 +700,10 @@
!strcmp(name, tab->name)) {
int ret;
- ret = vidconsole_add_metrics(dev,
- tab->name, size, tab->begin);
+ ret = truetype_add_metrics(dev,
+ tab->name,
+ size,
+ tab->begin);
if (ret < 0)
return log_msg_ret("add", ret);
@@ -715,7 +724,7 @@
return 0;
}
-const char *vidconsole_get_font(struct udevice *dev, uint *sizep)
+const char *vidconsole_get_font_size(struct udevice *dev, uint *sizep)
{
struct console_tt_priv *priv = dev_get_priv(dev);
struct console_tt_metrics *met = priv->cur_met;
@@ -745,7 +754,7 @@
return -EBFONT;
}
- ret = vidconsole_add_metrics(dev, tab->name, font_size, tab->begin);
+ ret = truetype_add_metrics(dev, tab->name, font_size, tab->begin);
if (ret < 0)
return log_msg_ret("add", ret);
priv->cur_met = &priv->metrics[ret];
@@ -763,6 +772,8 @@
.set_row = console_truetype_set_row,
.backspace = console_truetype_backspace,
.entry_start = console_truetype_entry_start,
+ .get_font = console_truetype_get_font,
+ .select_font = truetype_select_font,
};
U_BOOT_DRIVER(vidconsole_truetype) = {
diff --git a/drivers/video/sunxi/sunxi_dw_hdmi.c b/drivers/video/sunxi/sunxi_dw_hdmi.c
index 19ed80b..4f5d098 100644
--- a/drivers/video/sunxi/sunxi_dw_hdmi.c
+++ b/drivers/video/sunxi/sunxi_dw_hdmi.c
@@ -56,10 +56,10 @@
return 1;
}
-static void sunxi_dw_hdmi_phy_init(void)
+static void sunxi_dw_hdmi_phy_init(struct dw_hdmi *hdmi)
{
struct sunxi_hdmi_phy * const phy =
- (struct sunxi_hdmi_phy *)(SUNXI_HDMI_BASE + HDMI_PHY_OFFS);
+ (struct sunxi_hdmi_phy *)(hdmi->ioaddr + HDMI_PHY_OFFS);
unsigned long tmo;
u32 tmp;
@@ -113,10 +113,10 @@
writel(0x42494E47, &phy->unscramble);
}
-static void sunxi_dw_hdmi_phy_set(uint clock, int phy_div)
+static void sunxi_dw_hdmi_phy_set(struct dw_hdmi *hdmi, uint clock, int phy_div)
{
struct sunxi_hdmi_phy * const phy =
- (struct sunxi_hdmi_phy *)(SUNXI_HDMI_BASE + HDMI_PHY_OFFS);
+ (struct sunxi_hdmi_phy *)(hdmi->ioaddr + HDMI_PHY_OFFS);
int div = sunxi_dw_hdmi_get_divider(clock);
u32 tmp;
@@ -270,7 +270,7 @@
int phy_div;
sunxi_dw_hdmi_pll_set(mpixelclock / 1000, &phy_div);
- sunxi_dw_hdmi_phy_set(mpixelclock, phy_div);
+ sunxi_dw_hdmi_phy_set(hdmi, mpixelclock, phy_div);
return 0;
}
@@ -291,10 +291,10 @@
static int sunxi_dw_hdmi_enable(struct udevice *dev, int panel_bpp,
const struct display_timing *edid)
{
- struct sunxi_hdmi_phy * const phy =
- (struct sunxi_hdmi_phy *)(SUNXI_HDMI_BASE + HDMI_PHY_OFFS);
- struct display_plat *uc_plat = dev_get_uclass_plat(dev);
struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
+ struct sunxi_hdmi_phy * const phy =
+ (struct sunxi_hdmi_phy *)(priv->hdmi.ioaddr + HDMI_PHY_OFFS);
+ struct display_plat *uc_plat = dev_get_uclass_plat(dev);
int ret;
ret = dw_hdmi_enable(&priv->hdmi, edid);
@@ -316,7 +316,7 @@
* again or othwerwise BSP driver won't work. Dummy read is
* needed or otherwise last write doesn't get written correctly.
*/
- (void)readb(SUNXI_HDMI_BASE);
+ (void)readb(priv->hdmi.ioaddr);
writel(0, &phy->unscramble);
return 0;
@@ -345,13 +345,7 @@
/* Clock on */
setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
- sunxi_dw_hdmi_phy_init();
-
- priv->hdmi.ioaddr = SUNXI_HDMI_BASE;
- priv->hdmi.i2c_clk_high = 0xd8;
- priv->hdmi.i2c_clk_low = 0xfe;
- priv->hdmi.reg_io_width = 1;
- priv->hdmi.phy_set = sunxi_dw_hdmi_phy_cfg;
+ sunxi_dw_hdmi_phy_init(&priv->hdmi);
ret = dw_hdmi_phy_wait_for_hpd(&priv->hdmi);
if (ret < 0) {
@@ -364,20 +358,37 @@
return 0;
}
+static int sunxi_dw_hdmi_of_to_plat(struct udevice *dev)
+{
+ struct sunxi_dw_hdmi_priv *priv = dev_get_priv(dev);
+ struct dw_hdmi *hdmi = &priv->hdmi;
+
+ hdmi->ioaddr = (ulong)dev_read_addr(dev);
+ hdmi->i2c_clk_high = 0xd8;
+ hdmi->i2c_clk_low = 0xfe;
+ hdmi->reg_io_width = 1;
+ hdmi->phy_set = sunxi_dw_hdmi_phy_cfg;
+
+ return 0;
+}
+
static const struct dm_display_ops sunxi_dw_hdmi_ops = {
.read_edid = sunxi_dw_hdmi_read_edid,
.enable = sunxi_dw_hdmi_enable,
.mode_valid = sunxi_dw_hdmi_mode_valid,
};
-U_BOOT_DRIVER(sunxi_dw_hdmi) = {
- .name = "sunxi_dw_hdmi",
- .id = UCLASS_DISPLAY,
- .ops = &sunxi_dw_hdmi_ops,
- .probe = sunxi_dw_hdmi_probe,
- .priv_auto = sizeof(struct sunxi_dw_hdmi_priv),
+static const struct udevice_id sunxi_dw_hdmi_ids[] = {
+ { .compatible = "allwinner,sun8i-a83t-dw-hdmi" },
+ { }
};
-U_BOOT_DRVINFO(sunxi_dw_hdmi) = {
- .name = "sunxi_dw_hdmi"
+U_BOOT_DRIVER(sunxi_dw_hdmi) = {
+ .name = "sunxi_dw_hdmi",
+ .id = UCLASS_DISPLAY,
+ .of_match = sunxi_dw_hdmi_ids,
+ .probe = sunxi_dw_hdmi_probe,
+ .of_to_plat = sunxi_dw_hdmi_of_to_plat,
+ .priv_auto = sizeof(struct sunxi_dw_hdmi_priv),
+ .ops = &sunxi_dw_hdmi_ops,
};
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 6bdfb6e..72a13d3 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -19,11 +19,6 @@
#include <video_font.h> /* Bitmap font for code page 437 */
#include <linux/ctype.h>
-/* By default we scroll by a single line */
-#ifndef CONFIG_CONSOLE_SCROLL_LINES
-#define CONFIG_CONSOLE_SCROLL_LINES 1
-#endif
-
int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
@@ -557,6 +552,39 @@
}
}
+void vidconsole_list_fonts(struct udevice *dev)
+{
+ struct vidfont_info info;
+ int ret, i;
+
+ for (i = 0, ret = 0; !ret; i++) {
+ ret = vidconsole_get_font(dev, i, &info);
+ if (!ret)
+ printf("%s\n", info.name);
+ }
+}
+
+int vidconsole_get_font(struct udevice *dev, int seq,
+ struct vidfont_info *info)
+{
+ struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+
+ if (!ops->get_font)
+ return -ENOSYS;
+
+ return ops->get_font(dev, seq, info);
+}
+
+int vidconsole_select_font(struct udevice *dev, const char *name, uint size)
+{
+ struct vidconsole_ops *ops = vidconsole_get_ops(dev);
+
+ if (!ops->select_font)
+ return -ENOSYS;
+
+ return ops->select_font(dev, name, size);
+}
+
/* Set up the number of rows and colours (rotated drivers override this) */
static int vidconsole_pre_probe(struct udevice *dev)
{
diff --git a/drivers/video/videomodes.c b/drivers/video/videomodes.c
index 69ef736..35955a5 100644
--- a/drivers/video/videomodes.c
+++ b/drivers/video/videomodes.c
@@ -7,8 +7,7 @@
/************************************************************************
Get Parameters for the video mode:
- The default video mode can be defined in CONFIG_SYS_DEFAULT_VIDEO_MODE.
- If undefined, default video mode is set to 0x301
+ The default video mode is set to 0x301
Parameters can be set via the variable "videomode" in the environment.
2 diferent ways are possible:
"videomode=301" - 301 is a hexadecimal number describing the VESA
diff --git a/drivers/video/videomodes.h b/drivers/video/videomodes.h
index aefe4ef..405f4e1 100644
--- a/drivers/video/videomodes.h
+++ b/drivers/video/videomodes.h
@@ -6,10 +6,6 @@
#include <edid.h>
-#ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE
-#define CONFIG_SYS_DEFAULT_VIDEO_MODE 0x301
-#endif
-
/* Some mode definitions */
#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
index da4f2f26..91af412 100644
--- a/drivers/virtio/virtio-uclass.c
+++ b/drivers/virtio/virtio-uclass.c
@@ -18,6 +18,7 @@
#define LOG_CATEGORY UCLASS_VIRTIO
#include <common.h>
+#include <bootdev.h>
#include <dm.h>
#include <log.h>
#include <malloc.h>
@@ -163,7 +164,7 @@
return ret;
if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) {
debug("(%s): device refuses features %x\n", vdev->name, status);
- return -ENODEV;
+ return -EINVAL;
}
return 0;
@@ -214,6 +215,7 @@
struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev);
char dev_name[30], *str;
struct udevice *vdev;
+ const char *name;
int ret;
if (uc_priv->device >= VIRTIO_ID_MAX_NUM) {
@@ -222,20 +224,19 @@
return 0;
}
- if (!virtio_drv_name[uc_priv->device]) {
+ name = virtio_drv_name[uc_priv->device];
+ if (!name) {
debug("(%s): underlying virtio device driver unavailable\n",
udev->name);
return 0;
}
- snprintf(dev_name, sizeof(dev_name), "%s#%d",
- virtio_drv_name[uc_priv->device], dev_seq(udev));
+ snprintf(dev_name, sizeof(dev_name), "%s#%d", name, dev_seq(udev));
str = strdup(dev_name);
if (!str)
return -ENOMEM;
- ret = device_bind_driver(udev, virtio_drv_name[uc_priv->device],
- str, &vdev);
+ ret = device_bind_driver(udev, name, str, &vdev);
if (ret == -ENOENT) {
debug("(%s): no driver configured\n", udev->name);
return 0;
@@ -246,6 +247,12 @@
}
device_set_name_alloced(vdev);
+ if (uc_priv->device == VIRTIO_ID_BLOCK) {
+ ret = bootdev_setup_for_dev(udev, name);
+ if (ret)
+ return log_msg_ret("bootdev", ret);
+ }
+
INIT_LIST_HEAD(&uc_priv->vqs);
return 0;
@@ -349,6 +356,26 @@
return 0;
}
+static int virtio_bootdev_bind(struct udevice *dev)
+{
+ struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
+
+ ucp->prio = BOOTDEVP_4_SCAN_FAST;
+
+ return 0;
+}
+
+static int virtio_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ ret = uclass_probe_all(UCLASS_VIRTIO);
+ if (ret && ret != -ENOENT)
+ return log_msg_ret("vir", ret);
+
+ return 0;
+}
+
UCLASS_DRIVER(virtio) = {
.name = "virtio",
.id = UCLASS_VIRTIO,
@@ -360,3 +387,26 @@
.child_post_probe = virtio_uclass_child_post_probe,
.per_device_auto = sizeof(struct virtio_dev_priv),
};
+
+struct bootdev_ops virtio_bootdev_ops = {
+};
+
+static const struct udevice_id virtio_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-virtio" },
+ { }
+};
+
+U_BOOT_DRIVER(virtio_bootdev) = {
+ .name = "virtio_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &virtio_bootdev_ops,
+ .bind = virtio_bootdev_bind,
+ .of_match = virtio_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(virtio_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_VIRTIO,
+ .hunt = virtio_bootdev_hunt,
+ .drv = DM_DRIVER_REF(virtio_bootdev),
+};
diff --git a/drivers/virtio/virtio_sandbox.c b/drivers/virtio/virtio_sandbox.c
index 5484ae3..b34f1d6 100644
--- a/drivers/virtio/virtio_sandbox.c
+++ b/drivers/virtio/virtio_sandbox.c
@@ -161,24 +161,13 @@
/* fake some information for testing */
priv->device_features = BIT_ULL(VIRTIO_F_VERSION_1);
- uc_priv->device = VIRTIO_ID_RNG;
+ uc_priv->device = dev_read_u32_default(udev, "virtio-type",
+ VIRTIO_ID_RNG);
uc_priv->vendor = ('u' << 24) | ('b' << 16) | ('o' << 8) | 't';
return 0;
}
-/* check virtio device driver's remove routine was called to reset the device */
-static int virtio_sandbox_child_post_remove(struct udevice *vdev)
-{
- u8 status;
-
- virtio_get_status(vdev, &status);
- if (status)
- panic("virtio device was not reset\n");
-
- return 0;
-}
-
static const struct dm_virtio_ops virtio_sandbox1_ops = {
.get_config = virtio_sandbox_get_config,
.set_config = virtio_sandbox_set_config,
@@ -203,7 +192,6 @@
.of_match = virtio_sandbox1_ids,
.ops = &virtio_sandbox1_ops,
.probe = virtio_sandbox_probe,
- .child_post_remove = virtio_sandbox_child_post_remove,
.priv_auto = sizeof(struct virtio_sandbox_priv),
};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f1b1cf6..b5ac8f7 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -30,6 +30,7 @@
default 128000 if ARCH_MX7 || ARCH_VF610
default 30000 if ARCH_SOCFPGA
default 16000 if ARCH_SUNXI
+ default 5376 if ULP_WATCHDOG
default 60000
help
Watchdog timeout in msec
diff --git a/drivers/watchdog/imx_watchdog.c b/drivers/watchdog/imx_watchdog.c
index 3586246..894158b 100644
--- a/drivers/watchdog/imx_watchdog.c
+++ b/drivers/watchdog/imx_watchdog.c
@@ -68,13 +68,8 @@
/*
* The timer watchdog can be set between
- * 0.5 and 128 Seconds. If not defined
- * in configuration file, sets 128 Seconds
+ * 0.5 and 128 Seconds.
*/
-#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
-#define CONFIG_WATCHDOG_TIMEOUT_MSECS 128000
-#endif
-
timeout = max_t(u64, timeout, TIMEOUT_MIN);
timeout = min_t(u64, timeout, TIMEOUT_MAX);
timeout = lldiv(timeout, 500) - 1;
diff --git a/drivers/watchdog/ulp_wdog.c b/drivers/watchdog/ulp_wdog.c
index e081054..c21aa3a 100644
--- a/drivers/watchdog/ulp_wdog.c
+++ b/drivers/watchdog/ulp_wdog.c
@@ -25,10 +25,6 @@
u32 clk_rate;
};
-#ifndef CONFIG_WATCHDOG_TIMEOUT_MSECS
-#define CONFIG_WATCHDOG_TIMEOUT_MSECS 0x1500
-#endif
-
#define REFRESH_WORD0 0xA602 /* 1st refresh word */
#define REFRESH_WORD1 0xB480 /* 2nd refresh word */
diff --git a/env/Kconfig b/env/Kconfig
index f73f0b8..c409ea7 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -244,6 +244,13 @@
This value is also in units of bytes, but must also be aligned to
an MMC sector boundary.
+ CONFIG_ENV_MMC_USE_DT (optional):
+
+ These define forces the configuration by the config node in device
+ tree with partition name: "u-boot,mmc-env-partition" or with
+ offset: "u-boot,mmc-env-offset", "u-boot,mmc-env-offset-redundant".
+ CONFIG_ENV_OFFSET and CONFIG_ENV_OFFSET_REDUND are not used.
+
config ENV_IS_IN_NAND
bool "Environment in a NAND device"
depends on !CHAIN_OF_TRUST
@@ -652,6 +659,15 @@
partition 0 or the first boot partition, which is 1 or some other defined
partition.
+config ENV_MMC_USE_DT
+ bool "Read partition name and offset in DT"
+ depends on ENV_IS_IN_MMC && OF_CONTROL
+ help
+ Only use the device tree to get the environment location in MMC
+ device, with partition name or with offset.
+ The 2 defines CONFIG_ENV_OFFSET, CONFIG_ENV_OFFSET_REDUND
+ are not used as fallback.
+
config USE_DEFAULT_ENV_FILE
bool "Create default environment from file"
help
diff --git a/env/env.c b/env/env.c
index 69848fb..06078c7 100644
--- a/env/env.c
+++ b/env/env.c
@@ -311,11 +311,15 @@
if (drv) {
int ret;
- if (!drv->erase)
+ if (!drv->erase) {
+ printf("not possible\n");
return -ENODEV;
+ }
- if (!env_has_inited(drv->location))
+ if (!env_has_inited(drv->location)) {
+ printf("not initialized\n");
return -ENODEV;
+ }
printf("Erasing Environment on %s... ", drv->name);
ret = drv->erase();
diff --git a/env/mmc.c b/env/mmc.c
index c28f4c6..8576141 100644
--- a/env/mmc.c
+++ b/env/mmc.c
@@ -21,8 +21,23 @@
#include <errno.h>
#include <dm/ofnode.h>
-#define __STR(X) #X
-#define STR(X) __STR(X)
+#define ENV_MMC_INVALID_OFFSET ((s64)-1)
+
+#if defined(CONFIG_ENV_MMC_USE_DT)
+/* ENV offset is invalid when not defined in Device Tree */
+#define ENV_MMC_OFFSET ENV_MMC_INVALID_OFFSET
+#define ENV_MMC_OFFSET_REDUND ENV_MMC_INVALID_OFFSET
+
+#else
+/* Default ENV offset when not defined in Device Tree */
+#define ENV_MMC_OFFSET CONFIG_ENV_OFFSET
+
+#if defined(CONFIG_ENV_OFFSET_REDUND)
+#define ENV_MMC_OFFSET_REDUND CONFIG_ENV_OFFSET_REDUND
+#else
+#define ENV_MMC_OFFSET_REDUND ENV_MMC_INVALID_OFFSET
+#endif
+#endif
DECLARE_GLOBAL_DATA_PTR;
@@ -35,7 +50,7 @@
#if (defined(CONFIG_SYS_REDUNDAND_ENVIRONMENT) && \
(CONFIG_SYS_MMC_ENV_PART == 1) && \
(CONFIG_ENV_OFFSET == CONFIG_ENV_OFFSET_REDUND))
-#define ENV_MMC_HWPART_REDUND
+#define ENV_MMC_HWPART_REDUND 1
#endif
#if CONFIG_IS_ENABLED(OF_CONTROL)
@@ -56,8 +71,18 @@
if (ret < 0)
return ret;
- if (!strncmp((const char *)info.name, str, sizeof(info.name)))
+ if (str && !strncmp((const char *)info.name, str, sizeof(info.name)))
break;
+#ifdef CONFIG_PARTITION_TYPE_GUID
+ if (!str) {
+ const efi_guid_t env_guid = PARTITION_U_BOOT_ENVIRONMENT;
+ efi_guid_t type_guid;
+
+ uuid_str_to_bin(info.type_guid, type_guid.b, UUID_STR_FORMAT_GUID);
+ if (!memcmp(&env_guid, &type_guid, sizeof(efi_guid_t)))
+ break;
+ }
+#endif
}
/* round up to info.blksz */
@@ -92,28 +117,34 @@
err = mmc_offset_try_partition(str, copy, &val);
if (!err)
return val;
+ debug("env partition '%s' not found (%d)", str, err);
}
- defvalue = CONFIG_ENV_OFFSET;
+ /* try the GPT partition with "U-Boot ENV" TYPE GUID */
+ if (IS_ENABLED(CONFIG_PARTITION_TYPE_GUID)) {
+ err = mmc_offset_try_partition(NULL, copy, &val);
+ if (!err)
+ return val;
+ }
+
+ defvalue = ENV_MMC_OFFSET;
propname = dt_prop.offset;
-#if defined(CONFIG_ENV_OFFSET_REDUND)
- if (copy) {
- defvalue = CONFIG_ENV_OFFSET_REDUND;
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT) && copy) {
+ defvalue = ENV_MMC_OFFSET_REDUND;
propname = dt_prop.offset_redund;
}
-#endif
+
return ofnode_conf_read_int(propname, defvalue);
}
#else
static inline s64 mmc_offset(int copy)
{
- s64 offset = CONFIG_ENV_OFFSET;
+ s64 offset = ENV_MMC_OFFSET;
-#if defined(CONFIG_ENV_OFFSET_REDUND)
- if (copy)
- offset = CONFIG_ENV_OFFSET_REDUND;
-#endif
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT) && copy)
+ offset = ENV_MMC_OFFSET_REDUND;
+
return offset;
}
#endif
@@ -122,6 +153,11 @@
{
s64 offset = mmc_offset(copy);
+ if (offset == ENV_MMC_INVALID_OFFSET) {
+ printf("Invalid ENV offset in MMC, copy=%d\n", copy);
+ return -ENOENT;
+ }
+
if (offset < 0)
offset += mmc->capacity;
@@ -149,8 +185,24 @@
return ret;
}
+
+static bool mmc_set_env_part_init(struct mmc *mmc)
+{
+ env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart;
+ if (mmc_set_env_part(mmc, mmc_get_env_part(mmc)))
+ return false;
+
+ return true;
+}
+
+static int mmc_set_env_part_restore(struct mmc *mmc)
+{
+ return mmc_set_env_part(mmc, env_mmc_orig_hwpart);
+}
#else
static inline int mmc_set_env_part(struct mmc *mmc, uint part) {return 0; };
+static bool mmc_set_env_part_init(struct mmc *mmc) {return true; }
+static inline int mmc_set_env_part_restore(struct mmc *mmc) {return 0; };
#endif
static const char *init_mmc_for_env(struct mmc *mmc)
@@ -167,8 +219,7 @@
if (mmc_init(mmc))
return "MMC init failed";
#endif
- env_mmc_orig_hwpart = mmc_get_blk_desc(mmc)->hwpart;
- if (mmc_set_env_part(mmc, mmc_get_env_part(mmc)))
+ if (!mmc_set_env_part_init(mmc))
return "MMC partition switch failed";
return NULL;
@@ -176,11 +227,7 @@
static void fini_mmc_for_env(struct mmc *mmc)
{
-#ifdef CONFIG_SYS_MMC_ENV_PART
- int dev = mmc_get_env_dev();
-
- blk_select_hwpart_devnum(UCLASS_MMC, dev, env_mmc_orig_hwpart);
-#endif
+ mmc_set_env_part_restore(mmc);
}
#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_SPL_BUILD)
@@ -217,21 +264,20 @@
if (ret)
goto fini;
-#ifdef CONFIG_ENV_OFFSET_REDUND
- if (gd->env_valid == ENV_VALID)
- copy = 1;
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) {
+ if (gd->env_valid == ENV_VALID)
+ copy = 1;
-#ifdef ENV_MMC_HWPART_REDUND
- ret = mmc_set_env_part(mmc, copy + 1);
- if (ret)
- goto fini;
-#endif
+ if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) {
+ ret = mmc_set_env_part(mmc, copy + 1);
+ if (ret)
+ goto fini;
+ }
-#endif
-
- if (mmc_get_env_addr(mmc, copy, &offset)) {
- ret = 1;
- goto fini;
+ if (mmc_get_env_addr(mmc, copy, &offset)) {
+ ret = 1;
+ goto fini;
+ }
}
printf("Writing to %sMMC(%d)... ", copy ? "redundant " : "", dev);
@@ -243,12 +289,12 @@
ret = 0;
-#ifdef CONFIG_ENV_OFFSET_REDUND
- gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
-#endif
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT))
+ gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
fini:
fini_mmc_for_env(mmc);
+
return ret;
}
@@ -292,23 +338,23 @@
printf("\n");
ret = erase_env(mmc, CONFIG_ENV_SIZE, offset);
-#ifdef CONFIG_ENV_OFFSET_REDUND
- copy = 1;
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) {
+ copy = 1;
-#ifdef ENV_MMC_HWPART_REDUND
- ret = mmc_set_env_part(mmc, copy + 1);
- if (ret)
- goto fini;
-#endif
+ if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) {
+ ret = mmc_set_env_part(mmc, copy + 1);
+ if (ret)
+ goto fini;
+ }
- if (mmc_get_env_addr(mmc, copy, &offset)) {
- ret = CMD_RET_FAILURE;
- goto fini;
+ if (mmc_get_env_addr(mmc, copy, &offset)) {
+ ret = CMD_RET_FAILURE;
+ goto fini;
+ }
+
+ ret |= erase_env(mmc, CONFIG_ENV_SIZE, offset);
}
- ret |= erase_env(mmc, CONFIG_ENV_SIZE, offset);
-#endif
-
fini:
fini_mmc_for_env(mmc);
return ret;
@@ -329,10 +375,14 @@
return (n == blk_cnt) ? 0 : -1;
}
-#ifdef CONFIG_ENV_OFFSET_REDUND
+#if defined(ENV_IS_EMBEDDED)
static int env_mmc_load(void)
{
-#if !defined(ENV_IS_EMBEDDED)
+ return 0;
+}
+#elif defined(CONFIG_SYS_REDUNDAND_ENVIRONMENT)
+static int env_mmc_load(void)
+{
struct mmc *mmc;
u32 offset1, offset2;
int read1_fail = 0, read2_fail = 0;
@@ -359,19 +409,19 @@
goto fini;
}
-#ifdef ENV_MMC_HWPART_REDUND
- ret = mmc_set_env_part(mmc, 1);
- if (ret)
- goto fini;
-#endif
+ if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) {
+ ret = mmc_set_env_part(mmc, 1);
+ if (ret)
+ goto fini;
+ }
read1_fail = read_env(mmc, CONFIG_ENV_SIZE, offset1, tmp_env1);
-#ifdef ENV_MMC_HWPART_REDUND
- ret = mmc_set_env_part(mmc, 2);
- if (ret)
- goto fini;
-#endif
+ if (IS_ENABLED(ENV_MMC_HWPART_REDUND)) {
+ ret = mmc_set_env_part(mmc, 2);
+ if (ret)
+ goto fini;
+ }
read2_fail = read_env(mmc, CONFIG_ENV_SIZE, offset2, tmp_env2);
@@ -384,13 +434,11 @@
if (ret)
env_set_default(errmsg, 0);
-#endif
return ret;
}
-#else /* ! CONFIG_ENV_OFFSET_REDUND */
+#else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
static int env_mmc_load(void)
{
-#if !defined(ENV_IS_EMBEDDED)
ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
struct mmc *mmc;
u32 offset;
@@ -429,10 +477,10 @@
err:
if (ret)
env_set_default(errmsg, 0);
-#endif
+
return ret;
}
-#endif /* CONFIG_ENV_OFFSET_REDUND */
+#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
U_BOOT_ENV_LOCATION(mmc) = {
.location = ENVL_MMC,
diff --git a/env/ubi.c b/env/ubi.c
index eb21c4f..445d34f 100644
--- a/env/ubi.c
+++ b/env/ubi.c
@@ -28,6 +28,12 @@
DECLARE_GLOBAL_DATA_PTR;
+#if CONFIG_SYS_REDUNDAND_ENVIRONMENT
+#define ENV_UBI_VOLUME_REDUND CONFIG_ENV_UBI_VOLUME_REDUND
+#else
+#define ENV_UBI_VOLUME_REDUND "invalid"
+#endif
+
#ifdef CONFIG_CMD_SAVEENV
#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
static int env_ubi_save(void)
@@ -177,9 +183,43 @@
}
#endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
+static int env_ubi_erase(void)
+{
+ ALLOC_CACHE_ALIGN_BUFFER(char, env_buf, CONFIG_ENV_SIZE);
+ int ret = 0;
+
+ if (ubi_part(CONFIG_ENV_UBI_PART, UBI_VID_OFFSET)) {
+ printf("\n** Cannot find mtd partition \"%s\"\n",
+ CONFIG_ENV_UBI_PART);
+ return 1;
+ }
+
+ memset(env_buf, 0x0, CONFIG_ENV_SIZE);
+
+ if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME,
+ (void *)env_buf, CONFIG_ENV_SIZE)) {
+ printf("\n** Unable to erase env to %s:%s **\n",
+ CONFIG_ENV_UBI_PART,
+ CONFIG_ENV_UBI_VOLUME);
+ ret = 1;
+ }
+ if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) {
+ if (ubi_volume_write(ENV_UBI_VOLUME_REDUND,
+ (void *)env_buf, CONFIG_ENV_SIZE)) {
+ printf("\n** Unable to erase env to %s:%s **\n",
+ CONFIG_ENV_UBI_PART,
+ ENV_UBI_VOLUME_REDUND);
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
U_BOOT_ENV_LOCATION(ubi) = {
.location = ENVL_UBI,
ENV_NAME("UBI")
.load = env_ubi_load,
.save = env_save_ptr(env_ubi_save),
+ .erase = ENV_ERASE_PTR(env_ubi_erase),
};
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3f0d9f1..7eaa7e9 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -541,34 +541,39 @@
int read_extent_data(struct btrfs_fs_info *fs_info, char *data, u64 logical,
u64 *len, int mirror)
{
- u64 offset = 0;
+ u64 orig_len = *len;
+ u64 cur = logical;
struct btrfs_multi_bio *multi = NULL;
struct btrfs_device *device;
int ret = 0;
- u64 max_len = *len;
- ret = btrfs_map_block(fs_info, READ, logical, len, &multi, mirror,
- NULL);
- if (ret) {
- fprintf(stderr, "Couldn't map the block %llu\n",
- logical + offset);
- goto err;
- }
- device = multi->stripes[0].dev;
+ while (cur < logical + orig_len) {
+ u64 cur_len = logical + orig_len - cur;
- if (*len > max_len)
- *len = max_len;
- if (!device->desc || !device->part) {
- ret = -EIO;
- goto err;
- }
-
- ret = __btrfs_devread(device->desc, device->part, data, *len,
- multi->stripes[0].physical);
- if (ret != *len)
- ret = -EIO;
- else
+ ret = btrfs_map_block(fs_info, READ, cur, &cur_len, &multi,
+ mirror, NULL);
+ if (ret) {
+ error("Couldn't map the block %llu", cur);
+ goto err;
+ }
+ device = multi->stripes[0].dev;
+ if (!device->desc || !device->part) {
+ error("devid %llu is missing", device->devid);
+ ret = -EIO;
+ goto err;
+ }
+ ret = __btrfs_devread(device->desc, device->part,
+ data + (cur - logical), cur_len,
+ multi->stripes[0].physical);
+ if (ret != cur_len) {
+ error("read failed on devid %llu physical %llu",
+ device->devid, multi->stripes[0].physical);
+ ret = -EIO;
+ goto err;
+ }
+ cur += cur_len;
ret = 0;
+ }
err:
kfree(multi);
return ret;
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index a945904..2da93da 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -1243,8 +1243,8 @@
return ret;
}
-int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
- loff_t maxsize, loff_t *actread)
+int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
+ loff_t *actread)
{
fsdata fsdata;
fat_itr *itr;
@@ -1261,12 +1261,12 @@
if (ret)
goto out_free_both;
- debug("reading %s at pos %llu\n", filename, pos);
+ debug("reading %s at pos %llu\n", filename, offset);
/* For saving default max clustersize memory allocated to malloc pool */
dir_entry *dentptr = itr->dent;
- ret = get_contents(&fsdata, dentptr, pos, buffer, maxsize, actread);
+ ret = get_contents(&fsdata, dentptr, offset, buf, len, actread);
out_free_both:
free(fsdata.fatbuf);
@@ -1280,25 +1280,13 @@
loff_t actread;
int ret;
- ret = file_fat_read_at(filename, 0, buffer, maxsize, &actread);
+ ret = fat_read_file(filename, buffer, 0, maxsize, &actread);
if (ret)
return ret;
else
return actread;
}
-int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len,
- loff_t *actread)
-{
- int ret;
-
- ret = file_fat_read_at(filename, offset, buf, len, actread);
- if (ret)
- printf("** Unable to read file %s **\n", filename);
-
- return ret;
-}
-
typedef struct {
struct fs_dir_stream parent;
struct fs_dirent dirent;
diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c
index 4226621..1430e67 100644
--- a/fs/squashfs/sqfs.c
+++ b/fs/squashfs/sqfs.c
@@ -100,7 +100,7 @@
static int sqfs_frag_lookup(u32 inode_fragment_index,
struct squashfs_fragment_block_entry *e)
{
- u64 start, n_blks, src_len, table_offset, start_block;
+ u64 start, end, exp_tbl, n_blks, src_len, table_offset, start_block;
unsigned char *metadata_buffer, *metadata, *table;
struct squashfs_fragment_block_entry *entries;
struct squashfs_super_block *sblk = ctxt.sblk;
@@ -115,11 +115,17 @@
if (inode_fragment_index >= get_unaligned_le32(&sblk->fragments))
return -EINVAL;
- start = get_unaligned_le64(&sblk->fragment_table_start) /
- ctxt.cur_dev->blksz;
+ start = get_unaligned_le64(&sblk->fragment_table_start);
+ end = get_unaligned_le64(&sblk->id_table_start);
+ exp_tbl = get_unaligned_le64(&sblk->export_table_start);
+
+ if (exp_tbl > start && exp_tbl < end)
+ end = exp_tbl;
+
n_blks = sqfs_calc_n_blks(sblk->fragment_table_start,
- sblk->export_table_start,
- &table_offset);
+ cpu_to_le64(end), &table_offset);
+
+ start /= ctxt.cur_dev->blksz;
/* Allocate a proper sized buffer to store the fragment index table */
table = malloc_cache_aligned(n_blks * ctxt.cur_dev->blksz);
diff --git a/fs/squashfs/sqfs_decompressor.c b/fs/squashfs/sqfs_decompressor.c
index d69ddb2..6b3e01c 100644
--- a/fs/squashfs/sqfs_decompressor.c
+++ b/fs/squashfs/sqfs_decompressor.c
@@ -40,7 +40,7 @@
#endif
#if IS_ENABLED(CONFIG_ZSTD)
case SQFS_COMP_ZSTD:
- ctxt->zstd_workspace = malloc(ZSTD_DCtxWorkspaceBound());
+ ctxt->zstd_workspace = malloc(zstd_dctx_workspace_bound());
if (!ctxt->zstd_workspace)
return -ENOMEM;
break;
@@ -99,11 +99,14 @@
size_t wsize;
int ret;
- wsize = ZSTD_DCtxWorkspaceBound();
- ctx = ZSTD_initDCtx(ctxt->zstd_workspace, wsize);
- ret = ZSTD_decompressDCtx(ctx, dest, dest_len, source, src_len);
+ wsize = zstd_dctx_workspace_bound();
- return ZSTD_isError(ret);
+ ctx = zstd_init_dctx(ctxt->zstd_workspace, wsize);
+ if (!ctx)
+ return -EINVAL;
+ ret = zstd_decompress_dctx(ctx, dest, dest_len, source, src_len);
+
+ return zstd_is_error(ret);
}
#endif /* CONFIG_ZSTD */
@@ -140,7 +143,7 @@
case SQFS_COMP_ZSTD:
ret = sqfs_zstd_decompress(ctxt, dest, *dest_len, source, src_len);
if (ret) {
- printf("ZSTD Error code: %d\n", ZSTD_getErrorCode(ret));
+ printf("ZSTD Error code: %d\n", zstd_get_error_code(ret));
return -EINVAL;
}
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 0fcf709..dd0bdf2 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -462,14 +462,6 @@
int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc);
/**
- * gpio_hog_probe_all() - probe all gpio devices with
- * gpio-hog subnodes.
- *
- * @return: Returns return value from device_probe()
- */
-int gpio_hog_probe_all(void);
-
-/**
* gpio_lookup_name - Look up a GPIO name and return its details
*
* This is used to convert a named GPIO into a device, offset and GPIO
diff --git a/include/axp_pmic.h b/include/axp_pmic.h
index 01ebba6..4ac6486 100644
--- a/include/axp_pmic.h
+++ b/include/axp_pmic.h
@@ -26,6 +26,18 @@
#define AXP_PMIC_SEC_DEVICE_ADDR 0x745
#define AXP_PMIC_SEC_RUNTIME_ADDR 0x3a
+enum {
+ AXP152_ID,
+ AXP202_ID,
+ AXP209_ID,
+ AXP221_ID,
+ AXP223_ID,
+ AXP803_ID,
+ AXP806_ID,
+ AXP809_ID,
+ AXP813_ID,
+};
+
int axp_set_dcdc1(unsigned int mvolt);
int axp_set_dcdc2(unsigned int mvolt);
int axp_set_dcdc3(unsigned int mvolt);
diff --git a/include/bootdev.h b/include/bootdev.h
index 9fc2198..b92ff4d 100644
--- a/include/bootdev.h
+++ b/include/bootdev.h
@@ -11,6 +11,7 @@
struct bootflow;
struct bootflow_iter;
+struct bootstd_priv;
struct udevice;
/**
@@ -20,19 +21,87 @@
*
* Smallest value is the highest priority. By default, bootdevs are scanned from
* highest to lowest priority
+ *
+ * BOOTDEVP_0_NONE: Invalid value, do not use
+ * @BOOTDEVP_6_PRE_SCAN: Scan bootdevs with this priority always, before
+ * starting any bootflow scan
+ * @BOOTDEVP_2_INTERNAL_FAST: Internal devices which don't need scanning and
+ * generally very quick to access, e.g. less than 100ms
+ * @BOOTDEVP_3_INTERNAL_SLOW: Internal devices which don't need scanning but
+ * take a significant fraction of a second to access
+ * @BOOTDEVP_4_SCAN_FAST: Extenal devices which need scanning or bus
+ * enumeration to find, but this enumeration happens quickly, typically under
+ * 100ms
+ * @BOOTDEVP_5_SCAN_SLOW: Extenal devices which need scanning or bus
+ * enumeration to find. The enumeration takes significant fraction of a second
+ * to complete
+ * @BOOTDEVP_6_NET_BASE: Basic network devices which are quickly and easily
+ * available. Typically used for an internal Ethernet device
+ * @BOOTDEVP_7_NET_FALLBACK: Secondary network devices which require extra time
+ * to start up, or are less desirable. Typically used for secondary Ethernet
+ * devices. Note that USB ethernet devices are found during USB enumeration,
+ * so do not use this priority
*/
enum bootdev_prio_t {
- BOOTDEVP_0_INTERNAL_FAST = 10,
- BOOTDEVP_1_INTERNAL_SLOW = 20,
- BOOTDEVP_2_SCAN_FAST = 30,
- BOOTDEVP_3_SCAN_SLOW = 40,
- BOOTDEVP_4_NET_BASE = 50,
- BOOTDEVP_5_NET_FALLBACK = 60,
- BOOTDEVP_6_SYSTEM = 70,
+ BOOTDEVP_0_NONE,
+ BOOTDEVP_1_PRE_SCAN,
+ BOOTDEVP_2_INTERNAL_FAST,
+ BOOTDEVP_3_INTERNAL_SLOW,
+ BOOTDEVP_4_SCAN_FAST,
+ BOOTDEVP_5_SCAN_SLOW,
+ BOOTDEVP_6_NET_BASE,
+ BOOTDEVP_7_NET_FALLBACK,
BOOTDEVP_COUNT,
};
+struct bootdev_hunter;
+
+/**
+ * bootdev_hunter_func - function to probe for bootdevs of a given type
+ *
+ * This should hunt around for bootdevs of the given type, binding them as it
+ * finds them. This may involve bus enumeration, etc.
+ *
+ * @info: Info structure describing this hunter
+ * @show: true to show information from the hunter
+ * Returns: 0 if OK, -ve on error
+ */
+typedef int (*bootdev_hunter_func)(struct bootdev_hunter *info, bool show);
+
+/**
+ * struct bootdev_hunter - information about how to hunt for bootdevs
+ *
+ * @prio: Scanning priority of this hunter
+ * @uclass: Uclass ID for the media associated with this bootdev
+ * @drv: bootdev driver for the things found by this hunter
+ * @hunt: Function to call to hunt for bootdevs of this type (NULL if none)
+ *
+ * Some bootdevs are not visible until other devices are enumerated. For
+ * example, USB bootdevs only appear when the USB bus is enumerated.
+ *
+ * On the other hand, we don't always want to enumerate all the buses just to
+ * find the first valid bootdev. Ideally we want to work through them in
+ * priority order, so that the fastest bootdevs are discovered first.
+ *
+ * This struct holds information about the bootdev so we can determine the probe
+ * order and how to hunt for bootdevs of this type
+ */
+struct bootdev_hunter {
+ enum bootdev_prio_t prio;
+ enum uclass_id uclass;
+ struct driver *drv;
+ bootdev_hunter_func hunt;
+};
+
+/* declare a new bootdev hunter */
+#define BOOTDEV_HUNTER(__name) \
+ ll_entry_declare(struct bootdev_hunter, __name, bootdev_hunter)
+
+/* access a bootdev hunter by name */
+#define BOOTDEV_HUNTER_GET(__name) \
+ ll_entry_get(struct bootdev_hunter, __name, bootdev_hunter)
+
/**
* struct bootdev_uc_plat - uclass information about a bootdev
*
@@ -50,7 +119,10 @@
/** struct bootdev_ops - Operations for the bootdev uclass */
struct bootdev_ops {
/**
- * get_bootflow() - get a bootflow
+ * get_bootflow() - get a bootflow (optional)
+ *
+ * If this is NULL then the default implementaton is used, which is
+ * default_get_bootflow()
*
* @dev: Bootflow device to check
* @iter: Provides current dev, part, method to get. Should update
@@ -171,40 +243,136 @@
* @label: Label to look up (e.g. "mmc1" or "mmc0")
* @devp: Returns the bootdev device found, or NULL if none (note it does not
* return the media device, but its bootdev child)
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
* Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
- * -ENOENT if there is no device with that number
+ * -ENOENT if there is no device with that number
*/
-int bootdev_find_by_label(const char *label, struct udevice **devp);
+int bootdev_find_by_label(const char *label, struct udevice **devp,
+ int *method_flagsp);
/**
* bootdev_find_by_any() - Find a bootdev by name, label or sequence
*
* @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
* @devp: returns the device found, on success
- * Return: 0 if OK, -ve on error
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
+ * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
+ * -ENOENT if there is no device with that number
*/
-int bootdev_find_by_any(const char *name, struct udevice **devp);
+int bootdev_find_by_any(const char *name, struct udevice **devp,
+ int *method_flagsp);
/**
- * bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan
+ * bootdev_setup_iter() - Set up iteration through bootdevs
*
- * This sets up the ordering information in @iter, based on the priority of each
- * bootdev and the bootdev-order property in the bootstd node
- *
- * If a single device is requested, no ordering is needed
+ * This sets up the an interation, based on the provided device or label. If
+ * neither is provided, the iteration is based on the priority of each bootdev,
+ * the * bootdev-order property in the bootstd node (or the boot_targets env
+ * var).
*
* @iter: Iterator to update with the order
+ * @label: label to scan, or NULL to scan all
* @devp: On entry, *devp is NULL to scan all, otherwise this is the (single)
* device to scan. Returns the first device to use, which is the passed-in
* @devp if it was non-NULL
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none
* Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
* on other error
*/
-int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp);
+int bootdev_setup_iter(struct bootflow_iter *iter, const char *label,
+ struct udevice **devp, int *method_flagsp);
+
+/**
+ * bootdev_list_hunters() - List the available bootdev hunters
+ *
+ * These provide a way to find new bootdevs by enumerating buses, etc. This
+ * function lists the available hunters
+ *
+ * @std: Pointer to bootstd private info
+ */
+void bootdev_list_hunters(struct bootstd_priv *std);
+
+/**
+ * bootdev_hunt() - Hunt for bootdevs matching a particular spec
+ *
+ * This runs the selected hunter (or all if @spec is NULL) to try to find new
+ * bootdevs.
+ *
+ * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must
+ * match a uclass name so that the hunter can be determined. Any trailing number
+ * is ignored
+ * @show: true to show each hunter before using it
+ * Returns: 0 if OK, -ve on error
+ */
+int bootdev_hunt(const char *spec, bool show);
+
+/**
+ * bootdev_hunt_prio() - Hunt for bootdevs of a particular priority
+ *
+ * This runs all hunters which can find bootdevs of the given priority.
+ *
+ * @prio: Priority to use
+ * @show: true to show each hunter as it is used
+ * Returns: 0 if OK, -ve on error
+ */
+int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show);
+
+/**
+ * bootdev_hunt_and_find_by_label() - Hunt for bootdevs by label
+ *
+ * Runs the hunter for the label, then tries to find the bootdev, possible
+ * created by the hunter
+ *
+ * @label: Label to look up (e.g. "mmc1" or "mmc0")
+ * @devp: Returns the bootdev device found, or NULL if none (note it does not
+ * return the media device, but its bootdev child)
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
+ * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
+ * -ENOENT if there is no device with that number
+ */
+int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
+ int *method_flagsp);
+
+/**
+ * bootdev_next_label() - Move to the next bootdev in the label sequence
+ *
+ * Looks through the remaining labels until it finds one that matches a bootdev.
+ * Bootdev scanners are used as needed. For example a label "mmc1" results in
+ * running the "mmc" bootdrv.
+ *
+ * @iter: Interation info, containing iter->cur_label
+ * @devp: New bootdev found, if any was found
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none
+ * Returns 0 if OK, -ENODEV if no bootdev was found
+ */
+int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
+ int *method_flagsp);
+
+/**
+ * bootdev_next_prio() - Find the next bootdev in priority order
+ *
+ * This moves @devp to the next bootdev with the current priority. If there is
+ * none, then it moves to the next priority and scans for new bootdevs there.
+ *
+ * @iter: Interation info, containing iter->cur_prio
+ * @devp: On entry this is the previous bootdev that was considered. On exit
+ * this is the new bootdev, if any was found
+ * Returns 0 on success (*devp is updated), -ENODEV if there are no more
+ * bootdevs at any priority
+ */
+int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp);
#if CONFIG_IS_ENABLED(BOOTSTD)
/**
- * bootdev_setup_for_dev() - Bind a new bootdev device
+ * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)
+ *
+ * Please use bootdev_setup_sibling_blk() instead since it supports multiple
+ * (child) block devices for each media device.
*
* Creates a bootdev device as a child of @parent. This should be called from
* the driver's bind() method or its uclass' post_bind() method.
diff --git a/include/bootflow.h b/include/bootflow.h
index 32dbbbb..f516bf8 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -7,8 +7,17 @@
#ifndef __bootflow_h
#define __bootflow_h
+#include <bootdev.h>
+#include <dm/ofnode_decl.h>
#include <linux/list.h>
+struct bootstd_priv;
+struct expo;
+
+enum {
+ BOOTFLOW_MAX_USED_DEVS = 16,
+};
+
/**
* enum bootflow_state_t - states that a particular bootflow can be in
*
@@ -39,7 +48,7 @@
* @glob_node: Points to siblings in the global list (all bootdev)
* @dev: Bootdevice device which produced this bootflow
* @blk: Block device which contains this bootflow, NULL if this is a network
- * device
+ * device or sandbox 'host' device
* @part: Partition number (0 for whole device)
* @fs_type: Filesystem type (FS_TYPE...) if this is fixed by the media, else 0.
* For example, the sandbox host-filesystem bootdev sets this to
@@ -49,9 +58,16 @@
* @state: Current state (enum bootflow_state_t)
* @subdir: Subdirectory to fetch files from (with trailing /), or NULL if none
* @fname: Filename of bootflow file (allocated)
+ * @logo: Logo to display for this bootflow (BMP format)
+ * @logo_size: Size of the logo in bytes
* @buf: Bootflow file contents (allocated)
* @size: Size of bootflow file in bytes
* @err: Error number received (0 if OK)
+ * @os_name: Name of the OS / distro being booted, or NULL if not known
+ * (allocated)
+ * @fdt_fname: Filename of FDT file
+ * @fdt_size: Size of FDT file
+ * @fdt_addr: Address of loaded fdt
*/
struct bootflow {
struct list_head bm_node;
@@ -65,26 +81,70 @@
enum bootflow_state_t state;
char *subdir;
char *fname;
+ void *logo;
+ uint logo_size;
char *buf;
int size;
int err;
+ char *os_name;
+ char *fdt_fname;
+ int fdt_size;
+ ulong fdt_addr;
};
/**
* enum bootflow_flags_t - flags for the bootflow iterator
*
* @BOOTFLOWF_FIXED: Only used fixed/internal media
- * @BOOTFLOWF_SHOW: Show each bootdev before scanning it
+ * @BOOTFLOWF_SHOW: Show each bootdev before scanning it; show each hunter
+ * before using it
* @BOOTFLOWF_ALL: Return bootflows with errors as well
- * @BOOTFLOWF_SINGLE_DEV: Just scan one bootmeth
- * @BOOTFLOWF_SKIP_GLOBAL: Don't scan global bootmeths
+ * @BOOTFLOWF_HUNT: Hunt for new bootdevs using the bootdrv hunters
+ *
+ * Internal flags:
+ * @BOOTFLOWF_SINGLE_DEV: (internal) Just scan one bootdev
+ * @BOOTFLOWF_SKIP_GLOBAL: (internal) Don't scan global bootmeths
+ * @BOOTFLOWF_SINGLE_UCLASS: (internal) Keep scanning through all devices in
+ * this uclass (used with things like "mmc")
+ * @BOOTFLOWF_SINGLE_MEDIA: (internal) Scan one media device in the uclass (used
+ * with things like "mmc1")
*/
enum bootflow_flags_t {
BOOTFLOWF_FIXED = 1 << 0,
BOOTFLOWF_SHOW = 1 << 1,
BOOTFLOWF_ALL = 1 << 2,
- BOOTFLOWF_SINGLE_DEV = 1 << 3,
- BOOTFLOWF_SKIP_GLOBAL = 1 << 4,
+ BOOTFLOWF_HUNT = 1 << 3,
+
+ /*
+ * flags used internally by standard boot - do not set these when
+ * calling bootflow_scan_bootdev() etc.
+ */
+ BOOTFLOWF_SINGLE_DEV = 1 << 16,
+ BOOTFLOWF_SKIP_GLOBAL = 1 << 17,
+ BOOTFLOWF_SINGLE_UCLASS = 1 << 18,
+ BOOTFLOWF_SINGLE_MEDIA = 1 << 19,
+};
+
+/**
+ * enum bootflow_meth_flags_t - flags controlling which bootmeths are used
+ *
+ * Used during iteration, e.g. by bootdev_find_by_label(), to determine which
+ * bootmeths are used for the current bootdev. The flags reset when the bootdev
+ * changes
+ *
+ * @BOOTFLOW_METHF_DHCP_ONLY: Only use dhcp (scripts and EFI)
+ * @BOOTFLOW_METHF_PXE_ONLY: Only use pxe (PXE boot)
+ * @BOOTFLOW_METHF_SINGLE_DEV: Scan only a single bootdev (used for labels like
+ * "3"). This is used if a sequence number is provided instead of a label
+ * @BOOTFLOW_METHF_SINGLE_UCLASS: Scan all bootdevs in this one uclass (used
+ * with things like "mmc"). If this is not set, then the bootdev has an integer
+ * value in the label (like "mmc2")
+ */
+enum bootflow_meth_flags_t {
+ BOOTFLOW_METHF_DHCP_ONLY = 1 << 0,
+ BOOTFLOW_METHF_PXE_ONLY = 1 << 1,
+ BOOTFLOW_METHF_SINGLE_DEV = 1 << 2,
+ BOOTFLOW_METHF_SINGLE_UCLASS = 1 << 3,
};
/**
@@ -107,25 +167,31 @@
* @flags: Flags to use (see enum bootflow_flags_t). If BOOTFLOWF_GLOBAL_FIRST is
* enabled then the global bootmeths are being scanned, otherwise we have
* moved onto the bootdevs
- * @dev: Current bootdev, NULL if none
+ * @dev: Current bootdev, NULL if none. This is only ever updated in
+ * bootflow_iter_set_dev()
* @part: Current partition number (0 for whole device)
* @method: Current bootmeth
* @max_part: Maximum hardware partition number in @dev, 0 if there is no
* partition table
+ * @first_bootable: First bootable partition, or 0 if none
* @err: Error obtained from checking the last iteration. This is used to skip
* forward (e.g. to skip the current partition because it is not valid)
* -ESHUTDOWN: try next bootdev
- * @num_devs: Number of bootdevs in @dev_order
- * @cur_dev: Current bootdev number, an index into @dev_order[]
- * @dev_order: List of bootdevs to scan, in order of priority. The scan starts
- * with the first one on the list
+ * @num_devs: Number of bootdevs in @dev_used
+ * @max_devs: Maximum number of entries in @dev_used
+ * @dev_used: List of bootdevs used during iteration
+ * @labels: List of labels to scan for bootdevs
+ * @cur_label: Current label being processed
* @num_methods: Number of bootmeth devices in @method_order
* @cur_method: Current method number, an index into @method_order
* @first_glob_method: First global method, if any, else -1
+ * @cur_prio: Current priority being scanned
* @method_order: List of bootmeth devices to use, in order. The normal methods
* appear first, then the global ones, if any
* @doing_global: true if we are iterating through the global bootmeths (which
* happens before the normal ones)
+ * @method_flags: flags controlling which methods should be used for this @dev
+ * (enum bootflow_meth_flags_t)
*/
struct bootflow_iter {
int flags;
@@ -133,15 +199,20 @@
int part;
struct udevice *method;
int max_part;
+ int first_bootable;
int err;
int num_devs;
- int cur_dev;
- struct udevice **dev_order;
+ int max_devs;
+ struct udevice *dev_used[BOOTFLOW_MAX_USED_DEVS];
+ const char *const *labels;
+ int cur_label;
int num_methods;
int cur_method;
int first_glob_method;
+ enum bootdev_prio_t cur_prio;
struct udevice **method_order;
bool doing_global;
+ int method_flags;
};
/**
@@ -186,36 +257,23 @@
const struct udevice *bmeth);
/**
- * bootflow_scan_bootdev() - find the first bootflow in a bootdev
+ * bootflow_scan_first() - find the first bootflow for a device or label
*
* If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too
*
* @dev: Boot device to scan, NULL to work through all of them until it
* finds one that can supply a bootflow
+ * @label: Label to control the scan, NULL to work through all devices
+ * until it finds one that can supply a bootflow
* @iter: Place to store private info (inited by this call)
- * @flags: Flags for iterator (enum bootflow_flags_t)
+ * @flags: Flags for iterator (enum bootflow_flags_t). Note that if @dev
+ * is NULL, then BOOTFLOWF_SKIP_GLOBAL is set automatically by this function
* @bflow: Place to put the bootflow if found
* Return: 0 if found, -ENODEV if no device, other -ve on other error
* (iteration can continue)
*/
-int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
- int flags, struct bootflow *bflow);
-
-/**
- * bootflow_scan_first() - find the first bootflow
- *
- * This works through the available bootdev devices until it finds one that
- * can supply a bootflow. It then returns that
- *
- * If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too
- *
- * @iter: Place to store private info (inited by this call), with
- * @flags: Flags for bootdev (enum bootflow_flags_t)
- * @bflow: Place to put the bootflow if found
- * Return: 0 if found, -ENODEV if no device, other -ve on other error (iteration
- * can continue)
- */
-int bootflow_scan_first(struct bootflow_iter *iter, int flags,
+int bootflow_scan_first(struct udevice *dev, const char *label,
+ struct bootflow_iter *iter, int flags,
struct bootflow *bflow);
/**
@@ -301,32 +359,70 @@
void bootflow_remove(struct bootflow *bflow);
/**
- * bootflow_iter_uses_blk_dev() - Check that a bootflow uses a block device
+ * bootflow_iter_check_blk() - Check that a bootflow uses a block device
*
* This checks the bootdev in the bootflow to make sure it uses a block device
*
* Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet)
*/
-int bootflow_iter_uses_blk_dev(const struct bootflow_iter *iter);
+int bootflow_iter_check_blk(const struct bootflow_iter *iter);
/**
- * bootflow_iter_uses_network() - Check that a bootflow uses a network device
+ * bootflow_iter_check_sf() - Check that a bootflow uses SPI FLASH
+ *
+ * This checks the bootdev in the bootflow to make sure it uses SPI flash
+ *
+ * Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet)
+ */
+int bootflow_iter_check_sf(const struct bootflow_iter *iter);
+
+/**
+ * bootflow_iter_check_net() - Check that a bootflow uses a network device
*
* This checks the bootdev in the bootflow to make sure it uses a network
* device
*
* Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. MMC)
*/
-int bootflow_iter_uses_network(const struct bootflow_iter *iter);
+int bootflow_iter_check_net(const struct bootflow_iter *iter);
/**
- * bootflow_iter_uses_system() - Check that a bootflow uses the bootstd device
+ * bootflow_iter_check_system() - Check that a bootflow uses the bootstd device
*
* This checks the bootdev in the bootflow to make sure it uses the bootstd
* device
*
* Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. MMC)
*/
-int bootflow_iter_uses_system(const struct bootflow_iter *iter);
+int bootflow_iter_check_system(const struct bootflow_iter *iter);
+
+/**
+ * bootflow_menu_new() - Create a new bootflow menu
+ *
+ * @expp: Returns the expo created
+ * Returns 0 on success, -ve on error
+ */
+int bootflow_menu_new(struct expo **expp);
+
+/**
+ * bootflow_menu_apply_theme() - Apply a theme to a bootmenu
+ *
+ * @exp: Expo to update
+ * @node: Node containing the theme information
+ * Returns 0 on success, -ve on error
+ */
+int bootflow_menu_apply_theme(struct expo *exp, ofnode node);
+
+/**
+ * bootflow_menu_run() - Create and run a menu of available bootflows
+ *
+ * @std: Bootstd information
+ * @text_mode: Uses a text-based menu suitable for a serial port
+ * @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
+ * @return 0 if an option was chosen, -EAGAIN if nothing was chosen, -ve on
+ * error
+ */
+int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
+ struct bootflow **bflowp);
#endif
diff --git a/include/bootmeth.h b/include/bootmeth.h
index 50ded05..b12dfd4 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -88,6 +88,22 @@
int (*read_bootflow)(struct udevice *dev, struct bootflow *bflow);
/**
+ * set_bootflow() - set the bootflow for a device
+ *
+ * This provides a bootflow file to the bootmeth, to see if it is valid.
+ * If it is, the bootflow is set up accordingly.
+ *
+ * @dev: Bootmethod device to use
+ * @bflow: On entry, provides bootdev.
+ * Returns updated bootflow if found
+ * @buf: Buffer containing the possible bootflow file
+ * @size: Size of file
+ * Return: 0 if OK, -ve on error
+ */
+ int (*set_bootflow)(struct udevice *dev, struct bootflow *bflow,
+ char *buf, int size);
+
+ /**
* read_file() - read a file needed for a bootflow
*
* Read a file from the same place as the bootflow came from
@@ -174,6 +190,23 @@
int bootmeth_read_bootflow(struct udevice *dev, struct bootflow *bflow);
/**
+ * bootmeth_set_bootflow() - set the bootflow for a device
+ *
+ * This provides a bootflow file to the bootmeth, to see if it is valid.
+ * If it is, the bootflow is set up accordingly.
+ *
+ * @dev: Bootmethod device to use
+ * @bflow: On entry, provides bootdev.
+ * Returns updated bootflow if found
+ * @buf: Buffer containing the possible bootflow file (must be allocated
+ * by caller to @size + 1 bytes)
+ * @size: Size of file
+ * Return: 0 if OK, -ve on error
+ */
+int bootmeth_set_bootflow(struct udevice *dev, struct bootflow *bflow,
+ char *buf, int size);
+
+/**
* bootmeth_read_file() - read a file needed for a bootflow
*
* Read a file from the same place as the bootflow came from
@@ -240,7 +273,7 @@
* caller before reading the file.
*
* @bflow: Information about file to try
- * @desc: Block descriptor to read from
+ * @desc: Block descriptor to read from (NULL for sandbox host)
* @prefix: Filename prefix to prepend to @fname (NULL for none)
* @fname: Filename to read
* Return: 0 if OK, -ENOMEM if not enough memory to allocate bflow->fname,
@@ -266,6 +299,22 @@
int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align);
/**
+ * bootmeth_alloc_other() - Allocate and read a file for a bootflow
+ *
+ * This reads an arbitrary file in the same directory as the bootflow,
+ * allocating memory for it. The buffer is one byte larger than the file length,
+ * so that it can be nul-terminated.
+ *
+ * @bflow: Information about file to read
+ * @fname: Filename to read from (within bootflow->subdir)
+ * @bufp: Returns a pointer to the allocated buffer
+ * @sizep: Returns the size of the buffer
+ * Return: 0 if OK, -ENOMEM if out of memory, other -ve on other error
+ */
+int bootmeth_alloc_other(struct bootflow *bflow, const char *fname,
+ void **bufp, uint *sizep);
+
+/**
* bootmeth_common_read_file() - Common handler for reading a file
*
* Reads a named file from the same location as the bootflow file.
diff --git a/include/bootstd.h b/include/bootstd.h
index 01be249..dddb3e1 100644
--- a/include/bootstd.h
+++ b/include/bootstd.h
@@ -9,6 +9,8 @@
#ifndef __bootstd_h
#define __bootstd_h
+#include <dm/ofnode_decl.h>
+
struct udevice;
/**
@@ -20,23 +22,32 @@
* @prefixes: NULL-terminated list of prefixes to use for bootflow filenames,
* e.g. "/", "/boot/"; NULL if none
* @bootdev_order: Order to use for bootdevs (or NULL if none), with each item
- * being a bootdev label, e.g. "mmc2", "mmc1";
+ * being a bootdev label, e.g. "mmc2", "mmc1" (NULL terminated)
+ * @env_order: Order as specified by the boot_targets env var (or NULL if none),
+ * with each item being a bootdev label, e.g. "mmc2", "mmc1" (NULL
+ * terminated)
* @cur_bootdev: Currently selected bootdev (for commands)
* @cur_bootflow: Currently selected bootflow (for commands)
* @glob_head: Head for the global list of all bootflows across all bootdevs
* @bootmeth_count: Number of bootmeth devices in @bootmeth_order
* @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
* @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none
+ * @theme: Node containing the theme information
+ * @hunters_used: Bitmask of used hunters, indexed by their position in the
+ * linker list. The bit is set if the hunter has been used already
*/
struct bootstd_priv {
const char **prefixes;
const char **bootdev_order;
+ const char **env_order;
struct udevice *cur_bootdev;
struct bootflow *cur_bootflow;
struct list_head glob_head;
int bootmeth_count;
struct udevice **bootmeth_order;
struct udevice *vbe_bootmeth;
+ ofnode theme;
+ uint hunters_used;
};
/**
@@ -47,9 +58,13 @@
* The list is alloced by the bootstd driver so should not be freed. That is the
* reason for all the const stuff in the function signature
*
- * Return: list of string points, terminated by NULL; or NULL if no boot order
+ * @dev: bootstd device
+ * @okp: returns true if OK, false if out of memory
+ * Return: list of string pointers, terminated by NULL; or NULL if no boot
+ * order. Note that this returns NULL in the case of an empty list
*/
-const char *const *const bootstd_get_bootdev_order(struct udevice *dev);
+const char *const *const bootstd_get_bootdev_order(struct udevice *dev,
+ bool *okp);
/**
* bootstd_get_prefixes() - Get the filename-prefixes list
diff --git a/include/charset.h b/include/charset.h
index 6e79d71..44034c7 100644
--- a/include/charset.h
+++ b/include/charset.h
@@ -178,7 +178,6 @@
*
* @s1: first string to compare
* @s2: second string to compare
- * @n: maximum number of u16 to compare
* Return: 0 if the first n u16 are the same in s1 and s2
* < 0 if the first different u16 in s1 is less than the
* corresponding u16 in s2
diff --git a/include/cli.h b/include/cli.h
index ba5b8eb..c777c90 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -7,6 +7,23 @@
#ifndef __CLI_H
#define __CLI_H
+#include <stdbool.h>
+
+/**
+ * struct cli_ch_state - state information for reading cmdline characters
+ *
+ * @esc_len: Number of escape characters read so far
+ * @esc_save: Escape characters collected so far
+ * @emit_upto: Next index to emit from esc_save
+ * @emitting: true if emitting from esc_save
+ */
+struct cli_ch_state {
+ int esc_len;
+ char esc_save[8];
+ int emit_upto;
+ bool emitting;
+};
+
/**
* Go into the command loop
*
@@ -154,5 +171,62 @@
void cli_init(void);
#define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())
+#define CTL_CH(c) ((c) - 'a' + 1)
+
+/**
+ * cli_ch_init() - Set up the initial state to process input characters
+ *
+ * @cch: State to set up
+ */
+void cli_ch_init(struct cli_ch_state *cch);
+
+/**
+ * cli_ch_process() - Process an input character
+ *
+ * When @ichar is 0, this function returns any characters from an invalid escape
+ * sequence which are still pending in the buffer
+ *
+ * Otherwise it processes the input character. If it is an escape character,
+ * then an escape sequence is started and the function returns 0. If we are in
+ * the middle of an escape sequence, the character is processed and may result
+ * in returning 0 (if more characters are needed) or a valid character (if
+ * @ichar finishes the sequence).
+ *
+ * If @ichar is a valid character and there is no escape sequence in progress,
+ * then it is returned as is.
+ *
+ * If the Enter key is pressed, '\n' is returned.
+ *
+ * Usage should be like this::
+ *
+ * struct cli_ch_state cch;
+ *
+ * cli_ch_init(cch);
+ * do
+ * {
+ * int ichar, ch;
+ *
+ * ichar = cli_ch_process(cch, 0);
+ * if (!ichar) {
+ * ch = getchar();
+ * ichar = cli_ch_process(cch, ch);
+ * }
+ * (handle the ichar character)
+ * } while (!done)
+ *
+ * If tstc() is used to look for keypresses, this function can be called with
+ * @ichar set to -ETIMEDOUT if there is no character after 5-10ms. This allows
+ * the ambgiuity between the Escape key and the arrow keys (which generate an
+ * escape character followed by other characters) to be resolved.
+ *
+ * @cch: Current state
+ * @ichar: Input character to process, or 0 if none, or -ETIMEDOUT if no
+ * character has been received within a small number of milliseconds (this
+ * cancels any existing escape sequence and allows pressing the Escape key to
+ * work)
+ * Returns: Resulting input character after processing, 0 if none, '\e' if
+ * an existing escape sequence was cancelled
+ */
+int cli_ch_process(struct cli_ch_state *cch, int ichar);
#endif
diff --git a/include/command.h b/include/command.h
index 966fd23..0db4898 100644
--- a/include/command.h
+++ b/include/command.h
@@ -18,8 +18,8 @@
#endif
/* Default to a width of 8 characters for help message command width */
-#ifndef CONFIG_SYS_HELP_CMD_WIDTH
-#define CONFIG_SYS_HELP_CMD_WIDTH 10
+#ifndef CFG_SYS_HELP_CMD_WIDTH
+#define CFG_SYS_HELP_CMD_WIDTH 10
#endif
#ifndef __ASSEMBLY__
@@ -279,6 +279,18 @@
* Return: 0 on success, or != 0 on error.
*/
int run_command_list(const char *cmd, int len, int flag);
+
+/**
+ * cmd_source_script() - Execute a script
+ *
+ * Executes a U-Boot script at a particular address in memory. The script should
+ * have a header (FIT or legacy) with the script type (IH_TYPE_SCRIPT).
+ *
+ * @addr: Address of script
+ * @fit_uname: FIT subimage name
+ * Return: result code (enum command_ret_t)
+ */
+int cmd_source_script(ulong addr, const char *fit_uname, const char *confname);
#endif /* __ASSEMBLY__ */
/*
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
index c3a2414..9d2a225 100644
--- a/include/config_distro_bootcmd.h
+++ b/include/config_distro_bootcmd.h
@@ -521,6 +521,9 @@
"if fstype ${devtype} " \
"${devnum}:${distro_bootpart} " \
"bootfstype; then " \
+ "part uuid ${devtype} " \
+ "${devnum}:${distro_bootpart} " \
+ "distro_bootpart_uuid ; " \
"run scan_dev_for_boot; " \
"fi; " \
"done; " \
diff --git a/include/configs/am62ax_evm.h b/include/configs/am62ax_evm.h
index 1bd900d..cdd639b 100644
--- a/include/configs/am62ax_evm.h
+++ b/include/configs/am62ax_evm.h
@@ -9,7 +9,6 @@
#define __CONFIG_AM62AX_EVM_H
#include <linux/sizes.h>
-#include <config_distro_bootcmd.h>
#include <environment/ti/mmc.h>
#include <environment/ti/k3_dfu.h>
@@ -55,12 +54,41 @@
"${bootdir}/${name_fit}\0" \
"partitions=" PARTS_DEFAULT
+#define BOOTENV_DEV_TI_MMC(devtypeu, devtypel, instance) \
+ DEFAULT_MMC_TI_ARGS \
+ EXTRA_ENV_AM62A7_BOARD_SETTINGS_MMC \
+ "bootcmd_ti_mmc=" \
+ "run findfdt; run envboot; run init_mmc;" \
+ "if test ${boot_fit} -eq 1; then;" \
+ "run get_fit_mmc; run get_overlaystring;" \
+ "run run_fit;" \
+ "else;" \
+ "run get_kern_mmc; run get_fdt_mmc;" \
+ "run get_overlay_mmc;" \
+ "run run_kern;" \
+ "fi;\0"
+
+#define BOOTENV_DEV_NAME_TI_MMC(devtyeu, devtypel, instance) \
+ "ti_mmc "
+
+#if CONFIG_IS_ENABLED(CMD_MMC)
+ #define BOOT_TARGET_MMC(func) \
+ func(TI_MMC, ti_mmc, na)
+#else
+ #define BOOT_TARGET_MMC(func)
+#endif /* CONFIG_IS_ENABLED(CMD_MMC) */
+
+#define BOOT_TARGET_DEVICES(func) \
+ BOOT_TARGET_MMC(func)
+
+#include <config_distro_bootcmd.h>
+
/* Incorporate settings into the U-Boot environment */
#define CFG_EXTRA_ENV_SETTINGS \
DEFAULT_LINUX_BOOT_ENV \
- DEFAULT_MMC_TI_ARGS \
+ DEFAULT_FIT_TI_ARGS \
EXTRA_ENV_AM62A7_BOARD_SETTINGS \
- EXTRA_ENV_AM62A7_BOARD_SETTINGS_MMC \
+ BOOTENV
/* Now for the remaining common defines */
#include <configs/ti_armv7_common.h>
diff --git a/include/configs/am62x_evm.h b/include/configs/am62x_evm.h
index 809d891..7fbefde 100644
--- a/include/configs/am62x_evm.h
+++ b/include/configs/am62x_evm.h
@@ -15,6 +15,29 @@
/* DDR Configuration */
#define CFG_SYS_SDRAM_BASE1 0x880000000
+#ifdef CONFIG_CMD_MMC
+#define DISTRO_BOOT_DEV_MMC(func) func(MMC, mmc, 0) func(MMC, mmc, 1)
+#else
+#define DISTRO_BOOT_DEV_MMC(func)
+#endif
+
+#ifdef CONFIG_CMD_PXE
+#define DISTRO_BOOT_DEV_PXE(func) func(PXE, pxe, na)
+#else
+#define DISTRO_BOOT_DEV_PXE(func)
+#endif
+
+#ifdef CONFIG_CMD_DHCP
+#define DISTRO_BOOT_DEV_DHCP(func) func(DHCP, dhcp, na)
+#else
+#define DISTRO_BOOT_DEV_DHCP(func)
+#endif
+
+#define BOOT_TARGET_DEVICES(func) \
+ DISTRO_BOOT_DEV_MMC(func) \
+ DISTRO_BOOT_DEV_PXE(func) \
+ DISTRO_BOOT_DEV_DHCP(func)
+
#define PARTS_DEFAULT \
/* Linux partitions */ \
"name=rootfs,start=0,size=-,uuid=${uuid_gpt_rootfs}\0"
@@ -59,7 +82,8 @@
DEFAULT_LINUX_BOOT_ENV \
DEFAULT_MMC_TI_ARGS \
EXTRA_ENV_AM625_BOARD_SETTINGS \
- EXTRA_ENV_AM625_BOARD_SETTINGS_MMC
+ EXTRA_ENV_AM625_BOARD_SETTINGS_MMC \
+ BOOTENV
/* Now for the remaining common defines */
#include <configs/ti_armv7_common.h>
diff --git a/include/configs/neural-compute-module-2.h b/include/configs/neural-compute-module-2.h
new file mode 100644
index 0000000..f0934ae
--- /dev/null
+++ b/include/configs/neural-compute-module-2.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#ifndef __NEURAL_COMPUTE_MODULE_2_H
+#define __NEURAL_COMPUTE_MODULE_2_H
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+ "stdout=serial,vidconsole\0" \
+ "stderr=serial,vidconsole\0"
+
+#include <configs/rv1126_common.h>
+
+#undef BOOT_TARGET_DEVICES
+
+#define BOOT_TARGET_DEVICES(func) \
+ func(MMC, mmc, 0) \
+ func(MMC, mmc, 1)
+
+#endif /* __NEURAL_COMPUTE_MODULE_2_H */
diff --git a/include/configs/odroid.h b/include/configs/odroid.h
index 560a23c..7255efc 100644
--- a/include/configs/odroid.h
+++ b/include/configs/odroid.h
@@ -17,6 +17,7 @@
#define CFG_SYS_PL310_BASE 0x10502000
#endif
+#define CFG_SYS_BOOTMAPSZ 0x10000000
#define CFG_SYS_SDRAM_BASE 0x40000000
#define SDRAM_BANK_SIZE (256 << 20) /* 256 MB */
#define PHYS_SDRAM_1 CFG_SYS_SDRAM_BASE
diff --git a/include/configs/pinephone-pro-rk3399.h b/include/configs/pinephone-pro-rk3399.h
new file mode 100644
index 0000000..78017d6
--- /dev/null
+++ b/include/configs/pinephone-pro-rk3399.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd
+ * Copyright (C) 2022 Peter Robinson <pbrobinson at gmail.com>
+ */
+
+#ifndef __PINEPHONE_PRO_RK3399_H
+#define __PINEPHONE_PRO_RK3399_H
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+ "stdin=serial,usbkbd\0" \
+ "stdout=serial,vidconsole\0" \
+ "stderr=serial,vidconsole\0"
+
+#include <configs/rk3399_common.h>
+
+#define SDRAM_BANK_SIZE (2UL << 30)
+
+#endif
diff --git a/include/configs/px30_common.h b/include/configs/px30_common.h
index 3f1595c..c0896e5 100644
--- a/include/configs/px30_common.h
+++ b/include/configs/px30_common.h
@@ -8,8 +8,7 @@
#include "rockchip-common.h"
-/* FIXME: ff020000 is pmu_mem (10k), while ff0e0000 is regular int_mem */
-#define CFG_IRAM_BASE 0xff020000
+#define CFG_IRAM_BASE 0xff0e0000
#define GICD_BASE 0xff131000
#define GICC_BASE 0xff132000
diff --git a/include/configs/ringneck_px30.h b/include/configs/ringneck_px30.h
new file mode 100644
index 0000000..c63c935
--- /dev/null
+++ b/include/configs/ringneck_px30.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2022 Theobroma Systems Design und Consulting GmbH
+ */
+
+#ifndef __RINGNECK_PX30_H
+#define __RINGNECK_PX30_H
+
+#include <configs/px30_common.h>
+
+#define ROCKCHIP_DEVICE_SETTINGS \
+ "stdout=serial,vidconsole\0" \
+ "stderr=serial,vidconsole\0"
+
+#endif
diff --git a/include/configs/rk3399_common.h b/include/configs/rk3399_common.h
index 95cb27c..3ef9ffa 100644
--- a/include/configs/rk3399_common.h
+++ b/include/configs/rk3399_common.h
@@ -48,15 +48,12 @@
#define ROCKCHIP_DEVICE_SETTINGS
#endif
-#include <config_distro_bootcmd.h>
-#include <environment/distro/sf.h>
#define CFG_EXTRA_ENV_SETTINGS \
ENV_MEM_LAYOUT_SETTINGS \
"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
"partitions=" PARTS_DEFAULT \
ROCKCHIP_DEVICE_SETTINGS \
- BOOTENV \
- BOOTENV_SF \
+ "boot_targets=" BOOT_TARGETS "\0" \
"altbootcmd=" \
"setenv boot_syslinux_conf extlinux/extlinux-rollback.conf;" \
"run distro_bootcmd\0"
diff --git a/include/configs/rockchip-common.h b/include/configs/rockchip-common.h
index 1f6b82f..0b23e4c 100644
--- a/include/configs/rockchip-common.h
+++ b/include/configs/rockchip-common.h
@@ -65,12 +65,14 @@
BOOT_TARGET_PXE(func) \
BOOT_TARGET_DHCP(func) \
BOOT_TARGET_SF(func)
+#define BOOT_TARGETS "mmc1 mmc0 nvme scsi usb pxe dhcp spi"
#else
#define BOOT_TARGET_DEVICES(func) \
BOOT_TARGET_MMC(func) \
BOOT_TARGET_USB(func) \
BOOT_TARGET_PXE(func) \
BOOT_TARGET_DHCP(func)
+#define BOOT_TARGETS "mmc1 mmc0 usb pxe dhcp"
#endif
#ifdef CONFIG_ARM64
diff --git a/include/configs/rv1126_common.h b/include/configs/rv1126_common.h
new file mode 100644
index 0000000..1ec1640
--- /dev/null
+++ b/include/configs/rv1126_common.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Rockchip Electronics Co., Ltd
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ */
+
+#ifndef __CONFIG_RV1126_COMMON_H
+#define __CONFIG_RV1126_COMMON_H
+
+#include "rockchip-common.h"
+
+#define CFG_SYS_HZ_CLOCK 24000000
+
+#define CFG_IRAM_BASE 0xff700000
+
+#define GICD_BASE 0xfeff1000
+#define GICC_BASE 0xfeff2000
+
+#define CFG_SYS_SDRAM_BASE 0
+#define SDRAM_MAX_SIZE 0xfd000000
+
+/* memory size > 128MB */
+#define ENV_MEM_LAYOUT_SETTINGS \
+ "scriptaddr=0x00000000\0" \
+ "pxefile_addr_r=0x00100000\0" \
+ "fdt_addr_r=0x08300000\0" \
+ "kernel_addr_r=0x02008000\0" \
+ "ramdisk_addr_r=0x0a200000\0"
+
+#include <config_distro_bootcmd.h>
+#define CFG_EXTRA_ENV_SETTINGS \
+ "fdt_high=0x0fffffff\0" \
+ "initrd_high=0x0fffffff\0" \
+ "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
+ "partitions=" PARTS_DEFAULT \
+ ENV_MEM_LAYOUT_SETTINGS \
+ ROCKCHIP_DEVICE_SETTINGS \
+ BOOTENV
+
+#endif /* __CONFIG_RV1126_COMMON_H */
diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h
index 9a4fe53..2211751 100644
--- a/include/configs/sdm845.h
+++ b/include/configs/sdm845.h
@@ -16,8 +16,9 @@
#define CFG_EXTRA_ENV_SETTINGS \
"bootm_size=0x4000000\0" \
"bootm_low=0x80000000\0" \
- "stdout=vidconsole\0" \
- "stderr=vidconsole\0" \
+ "stdin=serial\0" \
+ "stdout=serial,vidconsole\0" \
+ "stderr=serial,vidconsole\0" \
"preboot=source $prevbl_initrd_start_addr:prebootscript\0" \
"bootcmd=source $prevbl_initrd_start_addr:bootscript\0"
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 8032abe..d2d70f0 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -88,7 +88,7 @@
#endif /* !CONFIG_ARM64 */
#elif CONFIG_SUNXI_SRAM_ADDRESS == 0x20000
#ifdef CONFIG_MACH_SUN50I_H616
-#define LOW_LEVEL_SRAM_STACK 0x58000
+#define LOW_LEVEL_SRAM_STACK 0x52a00 /* below FEL buffers */
#else
/* end of SRAM A2 on H6 for now */
#define LOW_LEVEL_SRAM_STACK 0x00118000
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index 376f741..33e43c2 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -47,9 +47,9 @@
UCLASS_CPU, /* CPU, typically part of an SoC */
UCLASS_CROS_EC, /* Chrome OS EC */
UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */
- UCLASS_DSI_HOST, /* Display Serial Interface host */
UCLASS_DMA, /* Direct Memory Access */
UCLASS_DSA, /* Distributed (Ethernet) Switch Architecture */
+ UCLASS_DSI_HOST, /* Display Serial Interface host */
UCLASS_ECDSA, /* Elliptic curve cryptographic device */
UCLASS_EFI_LOADER, /* Devices created by UEFI applications */
UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */
@@ -101,6 +101,7 @@
UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */
UCLASS_PMIC, /* PMIC I/O device */
UCLASS_POWER_DOMAIN, /* (SoC) Power domains */
+ UCLASS_PVBLOCK, /* Xen virtual block device */
UCLASS_PWM, /* Pulse-width modulator */
UCLASS_PWRSEQ, /* Power sequence device */
UCLASS_QFW, /* QEMU firmware config device */
@@ -142,7 +143,6 @@
UCLASS_W1, /* Dallas 1-Wire bus */
UCLASS_W1_EEPROM, /* one-wire EEPROMs */
UCLASS_WDT, /* Watchdog Timer driver */
- UCLASS_PVBLOCK, /* Xen virtual block device */
UCLASS_COUNT,
UCLASS_INVALID = -1,
diff --git a/include/dm/util.h b/include/dm/util.h
index e10c606..4bb49e9 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -26,8 +26,12 @@
*/
int list_count_items(struct list_head *head);
-/* Dump out a tree of all devices */
-void dm_dump_tree(void);
+/**
+ * Dump out a tree of all devices
+ *
+ * @sort: Sort by uclass name
+ */
+void dm_dump_tree(bool sort);
/* Dump out a list of uclasses and their devices */
void dm_dump_uclass(void);
diff --git a/include/dt-bindings/clock/rockchip,rv1126-cru.h b/include/dt-bindings/clock/rockchip,rv1126-cru.h
new file mode 100644
index 0000000..e89a3a5
--- /dev/null
+++ b/include/dt-bindings/clock/rockchip,rv1126-cru.h
@@ -0,0 +1,632 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Rockchip Electronics Co. Ltd.
+ * Author: Finley Xiao <finley.xiao@rock-chips.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RV1126_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RV1126_H
+
+/* pmucru-clocks indices */
+
+/* pll clocks */
+#define PLL_GPLL 1
+
+/* sclk (special clocks) */
+#define CLK_OSC0_DIV32K 2
+#define CLK_RTC32K 3
+#define CLK_WIFI_DIV 4
+#define CLK_WIFI_OSC0 5
+#define CLK_WIFI 6
+#define CLK_PMU 7
+#define SCLK_UART1_DIV 8
+#define SCLK_UART1_FRACDIV 9
+#define SCLK_UART1_MUX 10
+#define SCLK_UART1 11
+#define CLK_I2C0 12
+#define CLK_I2C2 13
+#define CLK_CAPTURE_PWM0 14
+#define CLK_PWM0 15
+#define CLK_CAPTURE_PWM1 16
+#define CLK_PWM1 17
+#define CLK_SPI0 18
+#define DBCLK_GPIO0 19
+#define CLK_PMUPVTM 20
+#define CLK_CORE_PMUPVTM 21
+#define CLK_REF12M 22
+#define CLK_USBPHY_OTG_REF 23
+#define CLK_USBPHY_HOST_REF 24
+#define CLK_REF24M 25
+#define CLK_MIPIDSIPHY_REF 26
+
+/* pclk */
+#define PCLK_PDPMU 30
+#define PCLK_PMU 31
+#define PCLK_UART1 32
+#define PCLK_I2C0 33
+#define PCLK_I2C2 34
+#define PCLK_PWM0 35
+#define PCLK_PWM1 36
+#define PCLK_SPI0 37
+#define PCLK_GPIO0 38
+#define PCLK_PMUSGRF 39
+#define PCLK_PMUGRF 40
+#define PCLK_PMUCRU 41
+#define PCLK_CHIPVEROTP 42
+#define PCLK_PDPMU_NIU 43
+#define PCLK_PMUPVTM 44
+#define PCLK_SCRKEYGEN 45
+
+#define CLKPMU_NR_CLKS (PCLK_SCRKEYGEN + 1)
+
+/* cru-clocks indices */
+
+/* pll clocks */
+#define PLL_APLL 1
+#define PLL_DPLL 2
+#define PLL_CPLL 3
+#define PLL_HPLL 4
+
+/* sclk (special clocks) */
+#define ARMCLK 5
+#define USB480M 6
+#define CLK_CORE_CPUPVTM 7
+#define CLK_CPUPVTM 8
+#define CLK_SCR1 9
+#define CLK_SCR1_CORE 10
+#define CLK_SCR1_RTC 11
+#define CLK_SCR1_JTAG 12
+#define SCLK_UART0_DIV 13
+#define SCLK_UART0_FRAC 14
+#define SCLK_UART0_MUX 15
+#define SCLK_UART0 16
+#define SCLK_UART2_DIV 17
+#define SCLK_UART2_FRAC 18
+#define SCLK_UART2_MUX 19
+#define SCLK_UART2 20
+#define SCLK_UART3_DIV 21
+#define SCLK_UART3_FRAC 22
+#define SCLK_UART3_MUX 23
+#define SCLK_UART3 24
+#define SCLK_UART4_DIV 25
+#define SCLK_UART4_FRAC 26
+#define SCLK_UART4_MUX 27
+#define SCLK_UART4 28
+#define SCLK_UART5_DIV 29
+#define SCLK_UART5_FRAC 30
+#define SCLK_UART5_MUX 31
+#define SCLK_UART5 32
+#define CLK_I2C1 33
+#define CLK_I2C3 34
+#define CLK_I2C4 35
+#define CLK_I2C5 36
+#define CLK_SPI1 37
+#define CLK_CAPTURE_PWM2 38
+#define CLK_PWM2 39
+#define DBCLK_GPIO1 40
+#define DBCLK_GPIO2 41
+#define DBCLK_GPIO3 42
+#define DBCLK_GPIO4 43
+#define CLK_SARADC 44
+#define CLK_TIMER0 45
+#define CLK_TIMER1 46
+#define CLK_TIMER2 47
+#define CLK_TIMER3 48
+#define CLK_TIMER4 49
+#define CLK_TIMER5 50
+#define CLK_CAN 51
+#define CLK_NPU_TSADC 52
+#define CLK_NPU_TSADCPHY 53
+#define CLK_CPU_TSADC 54
+#define CLK_CPU_TSADCPHY 55
+#define CLK_CRYPTO_CORE 56
+#define CLK_CRYPTO_PKA 57
+#define MCLK_I2S0_TX_DIV 58
+#define MCLK_I2S0_TX_FRACDIV 59
+#define MCLK_I2S0_TX_MUX 60
+#define MCLK_I2S0_TX 61
+#define MCLK_I2S0_RX_DIV 62
+#define MCLK_I2S0_RX_FRACDIV 63
+#define MCLK_I2S0_RX_MUX 64
+#define MCLK_I2S0_RX 65
+#define MCLK_I2S0_TX_OUT2IO 66
+#define MCLK_I2S0_RX_OUT2IO 67
+#define MCLK_I2S1_DIV 68
+#define MCLK_I2S1_FRACDIV 69
+#define MCLK_I2S1_MUX 70
+#define MCLK_I2S1 71
+#define MCLK_I2S1_OUT2IO 72
+#define MCLK_I2S2_DIV 73
+#define MCLK_I2S2_FRACDIV 74
+#define MCLK_I2S2_MUX 75
+#define MCLK_I2S2 76
+#define MCLK_I2S2_OUT2IO 77
+#define MCLK_PDM 78
+#define SCLK_ADUPWM_DIV 79
+#define SCLK_AUDPWM_FRACDIV 80
+#define SCLK_AUDPWM_MUX 81
+#define SCLK_AUDPWM 82
+#define CLK_ACDCDIG_ADC 83
+#define CLK_ACDCDIG_DAC 84
+#define CLK_ACDCDIG_I2C 85
+#define CLK_VENC_CORE 86
+#define CLK_VDEC_CORE 87
+#define CLK_VDEC_CA 88
+#define CLK_VDEC_HEVC_CA 89
+#define CLK_RGA_CORE 90
+#define CLK_IEP_CORE 91
+#define CLK_ISP_DIV 92
+#define CLK_ISP_NP5 93
+#define CLK_ISP_NUX 94
+#define CLK_ISP 95
+#define CLK_CIF_OUT_DIV 96
+#define CLK_CIF_OUT_FRACDIV 97
+#define CLK_CIF_OUT_MUX 98
+#define CLK_CIF_OUT 99
+#define CLK_MIPICSI_OUT_DIV 100
+#define CLK_MIPICSI_OUT_FRACDIV 101
+#define CLK_MIPICSI_OUT_MUX 102
+#define CLK_MIPICSI_OUT 103
+#define CLK_ISPP_DIV 104
+#define CLK_ISPP_NP5 105
+#define CLK_ISPP_NUX 106
+#define CLK_ISPP 107
+#define CLK_SDMMC 108
+#define SCLK_SDMMC_DRV 109
+#define SCLK_SDMMC_SAMPLE 110
+#define CLK_SDIO 111
+#define SCLK_SDIO_DRV 112
+#define SCLK_SDIO_SAMPLE 113
+#define CLK_EMMC 114
+#define SCLK_EMMC_DRV 115
+#define SCLK_EMMC_SAMPLE 116
+#define CLK_NANDC 117
+#define SCLK_SFC 118
+#define CLK_USBHOST_UTMI_OHCI 119
+#define CLK_USBOTG_REF 120
+#define CLK_GMAC_DIV 121
+#define CLK_GMAC_RGMII_M0 122
+#define CLK_GMAC_SRC_M0 123
+#define CLK_GMAC_RGMII_M1 124
+#define CLK_GMAC_SRC_M1 125
+#define CLK_GMAC_SRC 126
+#define CLK_GMAC_REF 127
+#define CLK_GMAC_TX_SRC 128
+#define CLK_GMAC_TX_DIV5 129
+#define CLK_GMAC_TX_DIV50 130
+#define RGMII_MODE_CLK 131
+#define CLK_GMAC_RX_SRC 132
+#define CLK_GMAC_RX_DIV2 133
+#define CLK_GMAC_RX_DIV20 134
+#define RMII_MODE_CLK 135
+#define CLK_GMAC_TX_RX 136
+#define CLK_GMAC_PTPREF 137
+#define CLK_GMAC_ETHERNET_OUT 138
+#define CLK_DDRPHY 139
+#define CLK_DDR_MON 140
+#define TMCLK_DDR_MON 141
+#define CLK_NPU_DIV 142
+#define CLK_NPU_NP5 143
+#define CLK_CORE_NPU 144
+#define CLK_CORE_NPUPVTM 145
+#define CLK_NPUPVTM 146
+#define SCLK_DDRCLK 147
+#define CLK_OTP 148
+
+/* dclk */
+#define DCLK_DECOM 150
+#define DCLK_VOP_DIV 151
+#define DCLK_VOP_FRACDIV 152
+#define DCLK_VOP_MUX 153
+#define DCLK_VOP 154
+#define DCLK_CIF 155
+#define DCLK_CIFLITE 156
+
+/* aclk */
+#define ACLK_PDBUS 160
+#define ACLK_DMAC 161
+#define ACLK_DCF 162
+#define ACLK_SPINLOCK 163
+#define ACLK_DECOM 164
+#define ACLK_PDCRYPTO 165
+#define ACLK_CRYPTO 166
+#define ACLK_PDVEPU 167
+#define ACLK_VENC 168
+#define ACLK_PDVDEC 169
+#define ACLK_PDJPEG 170
+#define ACLK_VDEC 171
+#define ACLK_JPEG 172
+#define ACLK_PDVO 173
+#define ACLK_RGA 174
+#define ACLK_VOP 175
+#define ACLK_IEP 176
+#define ACLK_PDVI_DIV 177
+#define ACLK_PDVI_NP5 178
+#define ACLK_PDVI 179
+#define ACLK_ISP 180
+#define ACLK_CIF 181
+#define ACLK_CIFLITE 182
+#define ACLK_PDISPP_DIV 183
+#define ACLK_PDISPP_NP5 184
+#define ACLK_PDISPP 185
+#define ACLK_ISPP 186
+#define ACLK_PDPHP 187
+#define ACLK_PDUSB 188
+#define ACLK_USBOTG 189
+#define ACLK_PDGMAC 190
+#define ACLK_GMAC 191
+#define ACLK_PDNPU_DIV 192
+#define ACLK_PDNPU_NP5 193
+#define ACLK_PDNPU 194
+#define ACLK_NPU 195
+
+/* hclk */
+#define HCLK_PDCORE_NIU 200
+#define HCLK_PDUSB 201
+#define HCLK_PDCRYPTO 202
+#define HCLK_CRYPTO 203
+#define HCLK_PDAUDIO 204
+#define HCLK_I2S0 205
+#define HCLK_I2S1 206
+#define HCLK_I2S2 207
+#define HCLK_PDM 208
+#define HCLK_AUDPWM 209
+#define HCLK_PDVEPU 210
+#define HCLK_VENC 211
+#define HCLK_PDVDEC 212
+#define HCLK_PDJPEG 213
+#define HCLK_VDEC 214
+#define HCLK_JPEG 215
+#define HCLK_PDVO 216
+#define HCLK_RGA 217
+#define HCLK_VOP 218
+#define HCLK_IEP 219
+#define HCLK_PDVI 220
+#define HCLK_ISP 221
+#define HCLK_CIF 222
+#define HCLK_CIFLITE 223
+#define HCLK_PDISPP 224
+#define HCLK_ISPP 225
+#define HCLK_PDPHP 226
+#define HCLK_PDSDMMC 227
+#define HCLK_SDMMC 228
+#define HCLK_PDSDIO 229
+#define HCLK_SDIO 230
+#define HCLK_PDNVM 231
+#define HCLK_EMMC 232
+#define HCLK_NANDC 233
+#define HCLK_SFC 234
+#define HCLK_SFCXIP 235
+#define HCLK_PDBUS 236
+#define HCLK_USBHOST 237
+#define HCLK_USBHOST_ARB 238
+#define HCLK_PDNPU 239
+#define HCLK_NPU 240
+
+/* pclk */
+#define PCLK_CPUPVTM 245
+#define PCLK_PDBUS 246
+#define PCLK_DCF 247
+#define PCLK_WDT 248
+#define PCLK_MAILBOX 249
+#define PCLK_UART0 250
+#define PCLK_UART2 251
+#define PCLK_UART3 252
+#define PCLK_UART4 253
+#define PCLK_UART5 254
+#define PCLK_I2C1 255
+#define PCLK_I2C3 256
+#define PCLK_I2C4 257
+#define PCLK_I2C5 258
+#define PCLK_SPI1 259
+#define PCLK_PWM2 261
+#define PCLK_GPIO1 262
+#define PCLK_GPIO2 263
+#define PCLK_GPIO3 264
+#define PCLK_GPIO4 265
+#define PCLK_SARADC 266
+#define PCLK_TIMER 267
+#define PCLK_DECOM 268
+#define PCLK_CAN 269
+#define PCLK_NPU_TSADC 270
+#define PCLK_CPU_TSADC 271
+#define PCLK_ACDCDIG 272
+#define PCLK_PDVO 273
+#define PCLK_DSIHOST 274
+#define PCLK_PDVI 275
+#define PCLK_CSIHOST 276
+#define PCLK_PDGMAC 277
+#define PCLK_GMAC 278
+#define PCLK_PDDDR 279
+#define PCLK_DDR_MON 280
+#define PCLK_PDNPU 281
+#define PCLK_NPUPVTM 282
+#define PCLK_PDTOP 283
+#define PCLK_TOPCRU 284
+#define PCLK_TOPGRF 285
+#define PCLK_CPUEMADET 286
+#define PCLK_DDRPHY 287
+#define PCLK_DSIPHY 289
+#define PCLK_CSIPHY0 290
+#define PCLK_CSIPHY1 291
+#define PCLK_USBPHY_HOST 292
+#define PCLK_USBPHY_OTG 293
+#define PCLK_OTP 294
+
+#define CLK_NR_CLKS (PCLK_OTP + 1)
+
+/* pmu soft-reset indices */
+
+/* pmu_cru_softrst_con0 */
+#define SRST_PDPMU_NIU_P 0
+#define SRST_PMU_SGRF_P 1
+#define SRST_PMU_SGRF_REMAP_P 2
+#define SRST_I2C0_P 3
+#define SRST_I2C0 4
+#define SRST_I2C2_P 7
+#define SRST_I2C2 8
+#define SRST_UART1_P 9
+#define SRST_UART1 10
+#define SRST_PWM0_P 11
+#define SRST_PWM0 12
+#define SRST_PWM1_P 13
+#define SRST_PWM1 14
+#define SRST_DDR_FAIL_SAFE 15
+
+/* pmu_cru_softrst_con1 */
+#define SRST_GPIO0_P 17
+#define SRST_GPIO0_DB 18
+#define SRST_SPI0_P 19
+#define SRST_SPI0 20
+#define SRST_PMUGRF_P 21
+#define SRST_CHIPVEROTP_P 22
+#define SRST_PMUPVTM 24
+#define SRST_PMUPVTM_P 25
+#define SRST_PMUCRU_P 30
+
+/* soft-reset indices */
+
+/* cru_softrst_con0 */
+#define SRST_CORE0_PO 0
+#define SRST_CORE1_PO 1
+#define SRST_CORE2_PO 2
+#define SRST_CORE3_PO 3
+#define SRST_CORE0 4
+#define SRST_CORE1 5
+#define SRST_CORE2 6
+#define SRST_CORE3 7
+#define SRST_CORE0_DBG 8
+#define SRST_CORE1_DBG 9
+#define SRST_CORE2_DBG 10
+#define SRST_CORE3_DBG 11
+#define SRST_NL2 12
+#define SRST_CORE_NIU_A 13
+#define SRST_DBG_DAPLITE_P 14
+#define SRST_DAPLITE_P 15
+
+/* cru_softrst_con1 */
+#define SRST_PDBUS_NIU1_A 16
+#define SRST_PDBUS_NIU1_H 17
+#define SRST_PDBUS_NIU1_P 18
+#define SRST_PDBUS_NIU2_A 19
+#define SRST_PDBUS_NIU2_H 20
+#define SRST_PDBUS_NIU3_A 21
+#define SRST_PDBUS_NIU3_H 22
+#define SRST_PDBUS_HOLD_NIU1_A 23
+#define SRST_DBG_NIU_P 24
+#define SRST_PDCORE_NIIU_H 25
+#define SRST_MUC_NIU 26
+#define SRST_DCF_A 29
+#define SRST_DCF_P 30
+#define SRST_SYSTEM_SRAM_A 31
+
+/* cru_softrst_con2 */
+#define SRST_I2C1_P 32
+#define SRST_I2C1 33
+#define SRST_I2C3_P 34
+#define SRST_I2C3 35
+#define SRST_I2C4_P 36
+#define SRST_I2C4 37
+#define SRST_I2C5_P 38
+#define SRST_I2C5 39
+#define SRST_SPI1_P 40
+#define SRST_SPI1 41
+#define SRST_MCU_CORE 42
+#define SRST_PWM2_P 44
+#define SRST_PWM2 45
+#define SRST_SPINLOCK_A 46
+
+/* cru_softrst_con3 */
+#define SRST_UART0_P 48
+#define SRST_UART0 49
+#define SRST_UART2_P 50
+#define SRST_UART2 51
+#define SRST_UART3_P 52
+#define SRST_UART3 53
+#define SRST_UART4_P 54
+#define SRST_UART4 55
+#define SRST_UART5_P 56
+#define SRST_UART5 57
+#define SRST_WDT_P 58
+#define SRST_SARADC_P 59
+#define SRST_GRF_P 61
+#define SRST_TIMER_P 62
+#define SRST_MAILBOX_P 63
+
+/* cru_softrst_con4 */
+#define SRST_TIMER0 64
+#define SRST_TIMER1 65
+#define SRST_TIMER2 66
+#define SRST_TIMER3 67
+#define SRST_TIMER4 68
+#define SRST_TIMER5 69
+#define SRST_INTMUX_P 70
+#define SRST_GPIO1_P 72
+#define SRST_GPIO1_DB 73
+#define SRST_GPIO2_P 74
+#define SRST_GPIO2_DB 75
+#define SRST_GPIO3_P 76
+#define SRST_GPIO3_DB 77
+#define SRST_GPIO4_P 78
+#define SRST_GPIO4_DB 79
+
+/* cru_softrst_con5 */
+#define SRST_CAN_P 80
+#define SRST_CAN 81
+#define SRST_DECOM_A 85
+#define SRST_DECOM_P 86
+#define SRST_DECOM_D 87
+#define SRST_PDCRYPTO_NIU_A 88
+#define SRST_PDCRYPTO_NIU_H 89
+#define SRST_CRYPTO_A 90
+#define SRST_CRYPTO_H 91
+#define SRST_CRYPTO_CORE 92
+#define SRST_CRYPTO_PKA 93
+#define SRST_SGRF_P 95
+
+/* cru_softrst_con6 */
+#define SRST_PDAUDIO_NIU_H 96
+#define SRST_PDAUDIO_NIU_P 97
+#define SRST_I2S0_H 98
+#define SRST_I2S0_TX_M 99
+#define SRST_I2S0_RX_M 100
+#define SRST_I2S1_H 101
+#define SRST_I2S1_M 102
+#define SRST_I2S2_H 103
+#define SRST_I2S2_M 104
+#define SRST_PDM_H 105
+#define SRST_PDM_M 106
+#define SRST_AUDPWM_H 107
+#define SRST_AUDPWM 108
+#define SRST_ACDCDIG_P 109
+#define SRST_ACDCDIG 110
+
+/* cru_softrst_con7 */
+#define SRST_PDVEPU_NIU_A 112
+#define SRST_PDVEPU_NIU_H 113
+#define SRST_VENC_A 114
+#define SRST_VENC_H 115
+#define SRST_VENC_CORE 116
+#define SRST_PDVDEC_NIU_A 117
+#define SRST_PDVDEC_NIU_H 118
+#define SRST_VDEC_A 119
+#define SRST_VDEC_H 120
+#define SRST_VDEC_CORE 121
+#define SRST_VDEC_CA 122
+#define SRST_VDEC_HEVC_CA 123
+#define SRST_PDJPEG_NIU_A 124
+#define SRST_PDJPEG_NIU_H 125
+#define SRST_JPEG_A 126
+#define SRST_JPEG_H 127
+
+/* cru_softrst_con8 */
+#define SRST_PDVO_NIU_A 128
+#define SRST_PDVO_NIU_H 129
+#define SRST_PDVO_NIU_P 130
+#define SRST_RGA_A 131
+#define SRST_RGA_H 132
+#define SRST_RGA_CORE 133
+#define SRST_VOP_A 134
+#define SRST_VOP_H 135
+#define SRST_VOP_D 136
+#define SRST_TXBYTEHS_DSIHOST 137
+#define SRST_DSIHOST_P 138
+#define SRST_IEP_A 139
+#define SRST_IEP_H 140
+#define SRST_IEP_CORE 141
+#define SRST_ISP_RX_P 142
+
+/* cru_softrst_con9 */
+#define SRST_PDVI_NIU_A 144
+#define SRST_PDVI_NIU_H 145
+#define SRST_PDVI_NIU_P 146
+#define SRST_ISP 147
+#define SRST_CIF_A 148
+#define SRST_CIF_H 149
+#define SRST_CIF_D 150
+#define SRST_CIF_P 151
+#define SRST_CIF_I 152
+#define SRST_CIF_RX_P 153
+#define SRST_PDISPP_NIU_A 154
+#define SRST_PDISPP_NIU_H 155
+#define SRST_ISPP_A 156
+#define SRST_ISPP_H 157
+#define SRST_ISPP 158
+#define SRST_CSIHOST_P 159
+
+/* cru_softrst_con10 */
+#define SRST_PDPHPMID_NIU_A 160
+#define SRST_PDPHPMID_NIU_H 161
+#define SRST_PDNVM_NIU_H 163
+#define SRST_SDMMC_H 164
+#define SRST_SDIO_H 165
+#define SRST_EMMC_H 166
+#define SRST_SFC_H 167
+#define SRST_SFCXIP_H 168
+#define SRST_SFC 169
+#define SRST_NANDC_H 170
+#define SRST_NANDC 171
+#define SRST_PDSDMMC_H 173
+#define SRST_PDSDIO_H 174
+
+/* cru_softrst_con11 */
+#define SRST_PDUSB_NIU_A 176
+#define SRST_PDUSB_NIU_H 177
+#define SRST_USBHOST_H 178
+#define SRST_USBHOST_ARB_H 179
+#define SRST_USBHOST_UTMI 180
+#define SRST_USBOTG_A 181
+#define SRST_USBPHY_OTG_P 182
+#define SRST_USBPHY_HOST_P 183
+#define SRST_USBPHYPOR_OTG 184
+#define SRST_USBPHYPOR_HOST 185
+#define SRST_PDGMAC_NIU_A 188
+#define SRST_PDGMAC_NIU_P 189
+#define SRST_GMAC_A 190
+
+/* cru_softrst_con12 */
+#define SRST_DDR_DFICTL_P 193
+#define SRST_DDR_MON_P 194
+#define SRST_DDR_STANDBY_P 195
+#define SRST_DDR_GRF_P 196
+#define SRST_DDR_MSCH_P 197
+#define SRST_DDR_SPLIT_A 198
+#define SRST_DDR_MSCH 199
+#define SRST_DDR_DFICTL 202
+#define SRST_DDR_STANDBY 203
+#define SRST_NPUMCU_NIU 205
+#define SRST_DDRPHY_P 206
+#define SRST_DDRPHY 207
+
+/* cru_softrst_con13 */
+#define SRST_PDNPU_NIU_A 208
+#define SRST_PDNPU_NIU_H 209
+#define SRST_PDNPU_NIU_P 210
+#define SRST_NPU_A 211
+#define SRST_NPU_H 212
+#define SRST_NPU 213
+#define SRST_NPUPVTM_P 214
+#define SRST_NPUPVTM 215
+#define SRST_NPU_TSADC_P 216
+#define SRST_NPU_TSADC 217
+#define SRST_NPU_TSADCPHY 218
+#define SRST_CIFLITE_A 220
+#define SRST_CIFLITE_H 221
+#define SRST_CIFLITE_D 222
+#define SRST_CIFLITE_RX_P 223
+
+/* cru_softrst_con14 */
+#define SRST_TOPNIU_P 224
+#define SRST_TOPCRU_P 225
+#define SRST_TOPGRF_P 226
+#define SRST_CPUEMADET_P 227
+#define SRST_CSIPHY0_P 228
+#define SRST_CSIPHY1_P 229
+#define SRST_DSIPHY_P 230
+#define SRST_CPU_TSADC_P 232
+#define SRST_CPU_TSADC 233
+#define SRST_CPU_TSADCPHY 234
+#define SRST_CPUPVTM_P 235
+#define SRST_CPUPVTM 236
+
+#endif
diff --git a/include/dt-bindings/power/rockchip,rv1126-power.h b/include/dt-bindings/power/rockchip,rv1126-power.h
new file mode 100644
index 0000000..38a68e0
--- /dev/null
+++ b/include/dt-bindings/power/rockchip,rv1126-power.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __DT_BINDINGS_POWER_RV1126_POWER_H__
+#define __DT_BINDINGS_POWER_RV1126_POWER_H__
+
+/* VD_CORE */
+#define RV1126_PD_CPU_0 0
+#define RV1126_PD_CPU_1 1
+#define RV1126_PD_CPU_2 2
+#define RV1126_PD_CPU_3 3
+#define RV1126_PD_CORE_ALIVE 4
+
+/* VD_PMU */
+#define RV1126_PD_PMU 5
+#define RV1126_PD_PMU_ALIVE 6
+
+/* VD_NPU */
+#define RV1126_PD_NPU 7
+
+/* VD_VEPU */
+#define RV1126_PD_VEPU 8
+
+/* VD_LOGIC */
+#define RV1126_PD_VI 9
+#define RV1126_PD_VO 10
+#define RV1126_PD_ISPP 11
+#define RV1126_PD_VDPU 12
+#define RV1126_PD_CRYPTO 13
+#define RV1126_PD_DDR 14
+#define RV1126_PD_NVM 15
+#define RV1126_PD_SDIO 16
+#define RV1126_PD_USB 17
+#define RV1126_PD_LOGIC_ALIVE 18
+
+#endif
diff --git a/include/env_callback.h b/include/env_callback.h
index 85e7fe2..a9a14f2 100644
--- a/include/env_callback.h
+++ b/include/env_callback.h
@@ -14,8 +14,8 @@
#define ENV_CALLBACK_VAR ".callbacks"
/* Board configs can define additional static callback bindings */
-#ifndef CONFIG_ENV_CALLBACK_LIST_STATIC
-#define CONFIG_ENV_CALLBACK_LIST_STATIC
+#ifndef CFG_ENV_CALLBACK_LIST_STATIC
+#define CFG_ENV_CALLBACK_LIST_STATIC
#endif
#ifdef CONFIG_SILENT_CONSOLE
@@ -80,7 +80,7 @@
SILENT_CALLBACK \
"stdin:console,stdout:console,stderr:console," \
"serial#:serialno," \
- CONFIG_ENV_CALLBACK_LIST_STATIC
+ CFG_ENV_CALLBACK_LIST_STATIC
#ifndef CONFIG_SPL_BUILD
void env_callback_init(struct env_entry *var_entry);
diff --git a/include/expo.h b/include/expo.h
new file mode 100644
index 0000000..d242f48
--- /dev/null
+++ b/include/expo.h
@@ -0,0 +1,522 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#ifndef __SCENE_H
+#define __SCENE_H
+
+#include <linux/list.h>
+
+struct udevice;
+
+/**
+ * enum expoact_type - types of actions reported by the expo
+ *
+ * @EXPOACT_NONE: no action
+ * @EXPOACT_POINT: menu item was highlighted (@id indicates which)
+ * @EXPOACT_SELECT: menu item was selected (@id indicates which)
+ * @EXPOACT_QUIT: request to exit the menu
+ */
+enum expoact_type {
+ EXPOACT_NONE,
+ EXPOACT_POINT,
+ EXPOACT_SELECT,
+ EXPOACT_QUIT,
+};
+
+/**
+ * struct expo_action - an action report by the expo
+ *
+ * @type: Action type (EXPOACT_NONE if there is no action)
+ * @select: Used for EXPOACT_POINT and EXPOACT_SELECT
+ * @id: ID number of the object affected.
+ */
+struct expo_action {
+ enum expoact_type type;
+ union {
+ struct {
+ int id;
+ } select;
+ };
+};
+
+/**
+ * struct expo - information about an expo
+ *
+ * A group of scenes which can be presented to the user, typically to obtain
+ * input or to make a selection.
+ *
+ * @name: Name of the expo (allocated)
+ * @display: Display to use (`UCLASS_VIDEO`), or NULL to use text mode
+ * @scene_id: Current scene ID (0 if none)
+ * @next_id: Next ID number to use, for automatic allocation
+ * @action: Action selected by user. At present only one is supported, with the
+ * type set to EXPOACT_NONE if there is no action
+ * @text_mode: true to use text mode for the menu (no vidconsole)
+ * @priv: Private data for the controller
+ * @scene_head: List of scenes
+ * @str_head: list of strings
+ */
+struct expo {
+ char *name;
+ struct udevice *display;
+ uint scene_id;
+ uint next_id;
+ struct expo_action action;
+ bool text_mode;
+ void *priv;
+ struct list_head scene_head;
+ struct list_head str_head;
+};
+
+/**
+ * struct expo_string - a string that can be used in an expo
+ *
+ * @id: ID number of the string
+ * @str: String
+ * @sibling: Node to link this object to its siblings
+ */
+struct expo_string {
+ uint id;
+ const char *str;
+ struct list_head sibling;
+};
+
+/**
+ * struct scene - information about a scene in an expo
+ *
+ * A collection of text/image/menu items in an expo
+ *
+ * @expo: Expo this scene is part of
+ * @name: Name of the scene (allocated)
+ * @id: ID number of the scene
+ * @title: Title of the scene (allocated)
+ * @sibling: Node to link this scene to its siblings
+ * @obj_head: List of objects in the scene
+ */
+struct scene {
+ struct expo *expo;
+ char *name;
+ uint id;
+ char *title;
+ struct list_head sibling;
+ struct list_head obj_head;
+};
+
+/**
+ * enum scene_obj_t - type of a scene object
+ *
+ * @SCENEOBJT_NONE: Used to indicate that the type does not matter
+ * @SCENEOBJT_IMAGE: Image data to render
+ * @SCENEOBJT_TEXT: Text line to render
+ * @SCENEOBJT_MENU: Menu containing items the user can select
+ */
+enum scene_obj_t {
+ SCENEOBJT_NONE = 0,
+ SCENEOBJT_IMAGE,
+ SCENEOBJT_TEXT,
+ SCENEOBJT_MENU,
+};
+
+/**
+ * struct scene_obj - information about an object in a scene
+ *
+ * @scene: Scene that this object relates to
+ * @name: Name of the object (allocated)
+ * @id: ID number of the object
+ * @type: Type of this object
+ * @x: x position, in pixels from left side
+ * @y: y position, in pixels from top
+ * @hide: true if the object should be hidden
+ * @sibling: Node to link this object to its siblings
+ */
+struct scene_obj {
+ struct scene *scene;
+ char *name;
+ uint id;
+ enum scene_obj_t type;
+ int x;
+ int y;
+ bool hide;
+ struct list_head sibling;
+};
+
+/**
+ * struct scene_obj_img - information about an image object in a scene
+ *
+ * This is a rectangular image which is blitted onto the display
+ *
+ * @obj: Basic object information
+ * @data: Image data in BMP format
+ */
+struct scene_obj_img {
+ struct scene_obj obj;
+ char *data;
+};
+
+/**
+ * struct scene_obj_txt - information about a text object in a scene
+ *
+ * This is a single-line text object
+ *
+ * @obj: Basic object information
+ * @str_id: ID of the text string to display
+ * @font_name: Name of font (allocated by caller)
+ * @font_size: Nominal size of font in pixels
+ */
+struct scene_obj_txt {
+ struct scene_obj obj;
+ uint str_id;
+ const char *font_name;
+ uint font_size;
+};
+
+/**
+ * struct scene_obj_menu - information about a menu object in a scene
+ *
+ * A menu has a number of items which can be selected by the user
+ *
+ * It also has:
+ *
+ * - a text/image object (@pointer_id) which points to the current item
+ * (@cur_item_id)
+ *
+ * - a preview object which shows an image related to the current item
+ *
+ * @obj: Basic object information
+ * @title_id: ID of the title text, or 0 if none
+ * @cur_item_id: ID of the current menu item, or 0 if none
+ * @pointer_id: ID of the object pointing to the current selection
+ * @item_head: List of items in the menu
+ */
+struct scene_obj_menu {
+ struct scene_obj obj;
+ uint title_id;
+ uint cur_item_id;
+ uint pointer_id;
+ struct list_head item_head;
+};
+
+/**
+ * enum scene_menuitem_flags_t - flags for menu items
+ *
+ * @SCENEMIF_GAP_BEFORE: Add a gap before this item
+ */
+enum scene_menuitem_flags_t {
+ SCENEMIF_GAP_BEFORE = 1 << 0,
+};
+
+/**
+ * struct scene_menitem - a menu item in a menu
+ *
+ * A menu item has:
+ *
+ * - text object holding the name (short) and description (can be longer)
+ * - a text object holding the keypress
+ *
+ * @name: Name of the item (this is allocated by this call)
+ * @id: ID number of the object
+ * @key_id: ID of text object to use as the keypress to show
+ * @label_id: ID of text object to use as the label text
+ * @desc_id: ID of text object to use as the description text
+ * @preview_id: ID of the preview object, or 0 if none
+ * @flags: Flags for this item
+ * @sibling: Node to link this item to its siblings
+ */
+struct scene_menitem {
+ char *name;
+ uint id;
+ uint key_id;
+ uint label_id;
+ uint desc_id;
+ uint preview_id;
+ uint flags;
+ struct list_head sibling;
+};
+
+/**
+ * expo_new() - create a new expo
+ *
+ * Allocates a new expo
+ *
+ * @name: Name of expo (this is allocated by this call)
+ * @priv: Private data for the controller
+ * @expp: Returns a pointer to the new expo on success
+ * Returns: 0 if OK, -ENOMEM if out of memory
+ */
+int expo_new(const char *name, void *priv, struct expo **expp);
+
+/**
+ * expo_destroy() - Destroy an expo and free all its memory
+ *
+ * @exp: Expo to destroy
+ */
+void expo_destroy(struct expo *exp);
+
+/**
+ * expo_str() - add a new string to an expo
+ *
+ * @exp: Expo to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @str: Pointer to text to display (allocated by caller)
+ * Returns: ID number for the object (typically @id), or -ve on error
+ */
+int expo_str(struct expo *exp, const char *name, uint id, const char *str);
+
+/**
+ * expo_get_str() - Get a string by ID
+ *
+ * @exp: Expo to use
+ * @id: String ID to look up
+ * @returns string, or NULL if not found
+ */
+const char *expo_get_str(struct expo *exp, uint id);
+
+/**
+ * expo_set_display() - set the display to use for a expo
+ *
+ * @exp: Expo to update
+ * @dev: Display to use (`UCLASS_VIDEO`), NULL to use text mode
+ * Returns: 0 (always)
+ */
+int expo_set_display(struct expo *exp, struct udevice *dev);
+
+/**
+ * expo_set_scene_id() - Set the current scene ID
+ *
+ * @exp: Expo to update
+ * @scene_id: New scene ID to use (0 to select no scene)
+ * Returns: 0 if OK, -ENOENT if there is no scene with that ID
+ */
+int expo_set_scene_id(struct expo *exp, uint scene_id);
+
+/**
+ * expo_render() - render the expo on the display / console
+ *
+ * @exp: Expo to render
+ *
+ * Returns: 0 if OK, -ECHILD if there is no current scene, -ENOENT if the
+ * current scene is not found, other error if something else goes wrong
+ */
+int expo_render(struct expo *exp);
+
+/**
+ * exp_set_text_mode() - Controls whether the expo renders in text mode
+ *
+ * @exp: Expo to update
+ * @text_mode: true to use text mode, false to use the console
+ */
+void exp_set_text_mode(struct expo *exp, bool text_mode);
+
+/**
+ * scene_new() - create a new scene in a expo
+ *
+ * The scene is given the ID @id which must be unique across all scenes, objects
+ * and items. The expo's @next_id is updated to at least @id + 1
+ *
+ * @exp: Expo to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new scene (0 to allocate one)
+ * @scnp: Returns a pointer to the new scene on success
+ * Returns: ID number for the scene (typically @id), or -ve on error
+ */
+int scene_new(struct expo *exp, const char *name, uint id, struct scene **scnp);
+
+/**
+ * expo_lookup_scene_id() - Look up a scene by ID
+ *
+ * @exp: Expo to check
+ * @scene_id: Scene ID to look up
+ * @returns pointer to scene if found, else NULL
+ */
+struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id);
+
+/**
+ * scene_title_set() - set the scene title
+ *
+ * @scn: Scene to update
+ * @title: Title to set, NULL if none (this is allocated by this call)
+ * Returns: 0 if OK, -ENOMEM if out of memory
+ */
+int scene_title_set(struct scene *scn, const char *title);
+
+/**
+ * scene_obj_count() - Count the number of objects in a scene
+ *
+ * @scn: Scene to check
+ * Returns: number of objects in the scene, 0 if none
+ */
+int scene_obj_count(struct scene *scn);
+
+/**
+ * scene_img() - add a new image to a scene
+ *
+ * @scn: Scene to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @data: Pointer to image data
+ * @imgp: If non-NULL, returns the new object
+ * Returns: ID number for the object (typically @id), or -ve on error
+ */
+int scene_img(struct scene *scn, const char *name, uint id, char *data,
+ struct scene_obj_img **imgp);
+
+/**
+ * scene_txt() - add a new text object to a scene
+ *
+ * @scn: Scene to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @str_id: ID of the string to use
+ * @txtp: If non-NULL, returns the new object
+ * Returns: ID number for the object (typically @id), or -ve on error
+ */
+int scene_txt(struct scene *scn, const char *name, uint id, uint str_id,
+ struct scene_obj_txt **txtp);
+
+/**
+ * scene_txt_str() - add a new string to expr and text object to a scene
+ *
+ * @scn: Scene to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @str_id: ID of the string to use
+ * @str: Pointer to text to display (allocated by caller)
+ * @txtp: If non-NULL, returns the new object
+ * Returns: ID number for the object (typically @id), or -ve on error
+ */
+int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id,
+ const char *str, struct scene_obj_txt **txtp);
+
+/**
+ * scene_menu() - create a menu
+ *
+ * @scn: Scene to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @menup: If non-NULL, returns the new object
+ * Returns: ID number for the object (typically @id), or -ve on error
+ */
+int scene_menu(struct scene *scn, const char *name, uint id,
+ struct scene_obj_menu **menup);
+
+/**
+ * scene_txt_set_font() - Set the font for an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @font_name: Font name to use (allocated by caller)
+ * @font_size: Font size to use (nominal height in pixels)
+ */
+int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
+ uint font_size);
+
+/**
+ * scene_obj_set_pos() - Set the postion of an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @x: x position, in pixels from left side
+ * @y: y position, in pixels from top
+ * Returns: 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_obj_set_pos(struct scene *scn, uint id, int x, int y);
+
+/**
+ * scene_obj_set_hide() - Set whether an object is hidden
+ *
+ * The update happens when the expo is next rendered.
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @hide: true to hide the object, false to show it
+ * Returns: 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_obj_set_hide(struct scene *scn, uint id, bool hide);
+
+/**
+ * scene_menu_set_title() - Set the title of a menu
+ *
+ * @scn: Scene to update
+ * @id: ID of menu object to update
+ * @title_id: ID of text object to use as the title
+ * Returns: 0 if OK, -ENOENT if @id is invalid, -EINVAL if @title_id is invalid
+ */
+int scene_menu_set_title(struct scene *scn, uint id, uint title_id);
+
+/**
+ * scene_menu_set_pointer() - Set the item pointer for a menu
+ *
+ * This is a visual indicator of the current item, typically a ">" character
+ * which sits next to the current item and moves when the user presses the
+ * up/down arrow keys
+ *
+ * @scn: Scene to update
+ * @id: ID of menu object to update
+ * @cur_item_id: ID of text or image object to use as a pointer to the current
+ * item
+ * Returns: 0 if OK, -ENOENT if @id is invalid, -EINVAL if @cur_item_id is invalid
+ */
+int scene_menu_set_pointer(struct scene *scn, uint id, uint cur_item_id);
+
+/**
+ * scene_obj_get_hw() - Get width and height of an object in a scene
+ *
+ * @scn: Scene to check
+ * @id: ID of menu object to check
+ * @widthp: If non-NULL, returns width of object in pixels
+ * Returns: Height of object in pixels
+ */
+int scene_obj_get_hw(struct scene *scn, uint id, int *widthp);
+
+/**
+ * scene_menuitem() - Add an item to a menu
+ *
+ * @scn: Scene to update
+ * @menu_id: ID of menu object to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @key_id: ID of text object to use as the keypress to show
+ * @label_id: ID of text object to use as the label text
+ * @desc_id: ID of text object to use as the description text
+ * @preview_id: ID of object to use as the preview (text or image)
+ * @flags: Flags for this item (enum scene_menuitem_flags_t)
+ * @itemp: If non-NULL, returns the new object
+ * Returns: ID number for the item (typically @id), or -ve on error
+ */
+int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id,
+ uint key_id, uint label_id, uint desc_id, uint preview_id,
+ uint flags, struct scene_menitem **itemp);
+
+/**
+ * scene_arrange() - Arrange the scene to deal with object sizes
+ *
+ * Updates any menus in the scene so that their objects are in the right place.
+ *
+ * @scn: Scene to arrange
+ * Returns: 0 if OK, -ve on error
+ */
+int scene_arrange(struct scene *scn);
+
+/**
+ * expo_send_key() - set a keypress to the expo
+ *
+ * @exp: Expo to receive the key
+ * @key: Key to send (ASCII or enum bootmenu_key)
+ * Returns: 0 if OK, -ECHILD if there is no current scene
+ */
+int expo_send_key(struct expo *exp, int key);
+
+/**
+ * expo_action_get() - read user input from the expo
+ *
+ * @exp: Expo to check
+ * @act: Returns action
+ * Returns: 0 if OK, -EAGAIN if there was no action to return
+ */
+int expo_action_get(struct expo *exp, struct expo_action *act);
+
+#endif /*__SCENE_H */
diff --git a/include/fastboot.h b/include/fastboot.h
index 57daaf1..07f4c8f 100644
--- a/include/fastboot.h
+++ b/include/fastboot.h
@@ -24,10 +24,8 @@
enum {
FASTBOOT_COMMAND_GETVAR = 0,
FASTBOOT_COMMAND_DOWNLOAD,
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
FASTBOOT_COMMAND_FLASH,
FASTBOOT_COMMAND_ERASE,
-#endif
FASTBOOT_COMMAND_BOOT,
FASTBOOT_COMMAND_CONTINUE,
FASTBOOT_COMMAND_REBOOT,
@@ -35,20 +33,12 @@
FASTBOOT_COMMAND_REBOOT_FASTBOOTD,
FASTBOOT_COMMAND_REBOOT_RECOVERY,
FASTBOOT_COMMAND_SET_ACTIVE,
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT)
FASTBOOT_COMMAND_OEM_FORMAT,
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF)
FASTBOOT_COMMAND_OEM_PARTCONF,
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS)
FASTBOOT_COMMAND_OEM_BOOTBUS,
-#endif
-#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
+ FASTBOOT_COMMAND_OEM_RUN,
FASTBOOT_COMMAND_ACMD,
FASTBOOT_COMMAND_UCMD,
-#endif
-
FASTBOOT_COMMAND_COUNT
};
@@ -173,7 +163,5 @@
*/
void fastboot_data_complete(char *response);
-#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT)
void fastboot_acmd_complete(void);
-#endif
#endif /* _FASTBOOT_H_ */
diff --git a/include/fat.h b/include/fat.h
index bd8e450..a9756fb 100644
--- a/include/fat.h
+++ b/include/fat.h
@@ -200,8 +200,6 @@
int file_fat_detectfs(void);
int fat_exists(const char *filename);
int fat_size(const char *filename, loff_t *size);
-int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
- loff_t maxsize, loff_t *actread);
int file_fat_read(const char *filename, void *buffer, int maxsize);
int fat_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info);
int fat_register_device(struct blk_desc *dev_desc, int part_no);
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 12355af..aa61a0f 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -555,15 +555,6 @@
int fdtdec_get_is_enabled(const void *blob, int node);
/**
- * Make sure we have a valid fdt available to control U-Boot.
- *
- * If not, a message is printed to the console if the console is ready.
- *
- * Return: 0 if all ok, -1 if not
- */
-int fdtdec_prepare_fdt(void);
-
-/**
* Checks that we have a valid fdt available to control U-Boot.
* However, if not then for the moment nothing is done, since this function
diff --git a/include/fm_eth.h b/include/fm_eth.h
index 6012a44..8b133e7 100644
--- a/include/fm_eth.h
+++ b/include/fm_eth.h
@@ -51,18 +51,18 @@
*/
#ifdef CONFIG_SYS_FMAN_V3
#ifdef CONFIG_TARGET_LS1046AFRWY
-#define CONFIG_SYS_FM1_DTSEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xfd000)
+#define CFG_SYS_FM1_DTSEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xfd000)
#else
-#define CONFIG_SYS_FM1_DTSEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xfc000)
+#define CFG_SYS_FM1_DTSEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xfc000)
#endif
-#define CONFIG_SYS_FM1_TGEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xfd000)
+#define CFG_SYS_FM1_TGEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xfd000)
#if (CFG_SYS_NUM_FMAN == 2)
-#define CONFIG_SYS_FM2_DTSEC_MDIO_ADDR (CFG_SYS_FSL_FM2_ADDR + 0xfc000)
-#define CONFIG_SYS_FM2_TGEC_MDIO_ADDR (CFG_SYS_FSL_FM2_ADDR + 0xfd000)
+#define CFG_SYS_FM2_DTSEC_MDIO_ADDR (CFG_SYS_FSL_FM2_ADDR + 0xfc000)
+#define CFG_SYS_FM2_TGEC_MDIO_ADDR (CFG_SYS_FSL_FM2_ADDR + 0xfd000)
#endif
#else
-#define CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xe1120)
-#define CONFIG_SYS_FM1_TGEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xf1000)
+#define CFG_SYS_FM1_DTSEC1_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xe1120)
+#define CFG_SYS_FM1_TGEC_MDIO_ADDR (CFG_SYS_FSL_FM1_ADDR + 0xf1000)
#endif
#define DEFAULT_FM_MDIO_NAME "FSL_MDIO0"
@@ -77,7 +77,7 @@
#ifdef CONFIG_SYS_FMAN_V3
#define FM_DTSEC_INFO_INITIALIZER(idx, n) \
{ \
- FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_DTSEC_MDIO_ADDR) \
+ FM_ETH_INFO_INITIALIZER(idx, CFG_SYS_FM1_DTSEC_MDIO_ADDR) \
.index = idx, \
.num = n - 1, \
.type = FM_ETH_1G_E, \
@@ -91,7 +91,7 @@
#ifdef CONFIG_FSL_FM_10GEC_REGULAR_NOTATION
#define FM_TGEC_INFO_INITIALIZER(idx, n) \
{ \
- FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_TGEC_MDIO_ADDR) \
+ FM_ETH_INFO_INITIALIZER(idx, CFG_SYS_FM1_TGEC_MDIO_ADDR) \
.index = idx, \
.num = n - 1, \
.type = FM_ETH_10G_E, \
@@ -105,7 +105,7 @@
#if (CFG_SYS_NUM_FMAN == 2)
#define FM_TGEC_INFO_INITIALIZER(idx, n) \
{ \
- FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM2_TGEC_MDIO_ADDR) \
+ FM_ETH_INFO_INITIALIZER(idx, CFG_SYS_FM2_TGEC_MDIO_ADDR) \
.index = idx, \
.num = n - 1, \
.type = FM_ETH_10G_E, \
@@ -118,7 +118,7 @@
#else
#define FM_TGEC_INFO_INITIALIZER(idx, n) \
{ \
- FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_TGEC_MDIO_ADDR) \
+ FM_ETH_INFO_INITIALIZER(idx, CFG_SYS_FM1_TGEC_MDIO_ADDR) \
.index = idx, \
.num = n - 1, \
.type = FM_ETH_10G_E, \
@@ -134,7 +134,7 @@
#if (CFG_SYS_NUM_FM1_10GEC >= 3)
#define FM_TGEC_INFO_INITIALIZER2(idx, n) \
{ \
- FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_TGEC_MDIO_ADDR) \
+ FM_ETH_INFO_INITIALIZER(idx, CFG_SYS_FM1_TGEC_MDIO_ADDR) \
.index = idx, \
.num = n - 1, \
.type = FM_ETH_10G_E, \
@@ -149,7 +149,7 @@
#else
#define FM_DTSEC_INFO_INITIALIZER(idx, n) \
{ \
- FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR) \
+ FM_ETH_INFO_INITIALIZER(idx, CFG_SYS_FM1_DTSEC1_MDIO_ADDR) \
.index = idx, \
.num = n - 1, \
.type = FM_ETH_1G_E, \
@@ -162,7 +162,7 @@
#define FM_TGEC_INFO_INITIALIZER(idx, n) \
{ \
- FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_TGEC_MDIO_ADDR) \
+ FM_ETH_INFO_INITIALIZER(idx, CFG_SYS_FM1_TGEC_MDIO_ADDR) \
.index = idx, \
.num = n - 1, \
.type = FM_ETH_10G_E, \
diff --git a/include/fpga.h b/include/fpga.h
index a4e1640..ed688cc 100644
--- a/include/fpga.h
+++ b/include/fpga.h
@@ -9,10 +9,6 @@
#ifndef _FPGA_H_
#define _FPGA_H_
-#ifndef CONFIG_MAX_FPGA_DEVICES
-#define CONFIG_MAX_FPGA_DEVICES 5
-#endif
-
/* fpga_xxxx function return value definitions */
#define FPGA_SUCCESS 0
#define FPGA_FAIL 1
diff --git a/include/fs_loader.h b/include/fs_loader.h
index 8de7cb1..5eb5b7a 100644
--- a/include/fs_loader.h
+++ b/include/fs_loader.h
@@ -52,4 +52,16 @@
int request_firmware_into_buf(struct udevice *dev,
const char *name,
void *buf, size_t size, u32 offset);
+
+/**
+ * get_fs_loader() - Get the chosen filesystem loader
+ * @dev: Where to store the device
+ *
+ * This gets a filesystem loader device based on the value of
+ * /chosen/firmware-loader. If no such property exists, it returns a
+ * firmware loader which is configured by environmental variables.
+ *
+ * Return: 0 on success, negative value on error
+ */
+int get_fs_loader(struct udevice **dev);
#endif
diff --git a/include/fsl_ddr.h b/include/fsl_ddr.h
index 24229f6..f336c6a 100644
--- a/include/fsl_ddr.h
+++ b/include/fsl_ddr.h
@@ -50,13 +50,12 @@
*
* All data structures have to be on the stack
*/
-#define CONFIG_SYS_DIMM_SLOTS_PER_CTLR CONFIG_DIMM_SLOTS_PER_CTLR
typedef struct {
generic_spd_eeprom_t
- spd_installed_dimms[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR];
+ spd_installed_dimms[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_DIMM_SLOTS_PER_CTLR];
struct dimm_params_s
- dimm_params[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_SYS_DIMM_SLOTS_PER_CTLR];
+ dimm_params[CONFIG_SYS_NUM_DDR_CTLRS][CONFIG_DIMM_SLOTS_PER_CTLR];
memctl_options_t memctl_opts[CONFIG_SYS_NUM_DDR_CTLRS];
common_timing_params_t common_timing_params[CONFIG_SYS_NUM_DDR_CTLRS];
fsl_ddr_cfg_regs_t fsl_ddr_config_reg[CONFIG_SYS_NUM_DDR_CTLRS];
diff --git a/include/fsl_ddr_sdram.h b/include/fsl_ddr_sdram.h
index a7272e4..c43f780 100644
--- a/include/fsl_ddr_sdram.h
+++ b/include/fsl_ddr_sdram.h
@@ -48,25 +48,25 @@
#if defined(CONFIG_SYS_FSL_DDR1)
#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (1)
typedef ddr1_spd_eeprom_t generic_spd_eeprom_t;
-#ifndef CONFIG_FSL_SDRAM_TYPE
-#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR1
+#ifndef CFG_FSL_SDRAM_TYPE
+#define CFG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR1
#endif
#elif defined(CONFIG_SYS_FSL_DDR2)
#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3)
typedef ddr2_spd_eeprom_t generic_spd_eeprom_t;
-#ifndef CONFIG_FSL_SDRAM_TYPE
-#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR2
+#ifndef CFG_FSL_SDRAM_TYPE
+#define CFG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR2
#endif
#elif defined(CONFIG_SYS_FSL_DDR3)
typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
-#ifndef CONFIG_FSL_SDRAM_TYPE
-#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR3
+#ifndef CFG_FSL_SDRAM_TYPE
+#define CFG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR3
#endif
#elif defined(CONFIG_SYS_FSL_DDR4)
#define FSL_DDR_MIN_TCKE_PULSE_WIDTH_DDR (3) /* FIXME */
typedef struct ddr4_spd_eeprom_s generic_spd_eeprom_t;
-#ifndef CONFIG_FSL_SDRAM_TYPE
-#define CONFIG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR4
+#ifndef CFG_FSL_SDRAM_TYPE
+#define CFG_FSL_SDRAM_TYPE SDRAM_TYPE_DDR4
#endif
#endif /* #if defined(CONFIG_SYS_FSL_DDR1) */
diff --git a/include/fsl_usb.h b/include/fsl_usb.h
index c0f076b..1abd1e5 100644
--- a/include/fsl_usb.h
+++ b/include/fsl_usb.h
@@ -40,24 +40,21 @@
u8 res_dc[0x334];
};
-#define CONFIG_SYS_FSL_USB_CTRL_PHY_EN (1 << 0)
-#define CONFIG_SYS_FSL_USB_DRVVBUS_CR_EN (1 << 1)
-#define CONFIG_SYS_FSL_USB_PWRFLT_CR_EN (1 << 1)
-#define CONFIG_SYS_FSL_USB_PLLPRG1_PHY_DIV (1 << 0)
-#define CONFIG_SYS_FSL_USB_PLLPRG2_PHY2_CLK_EN (1 << 0)
-#define CONFIG_SYS_FSL_USB_PLLPRG2_PHY1_CLK_EN (1 << 1)
-#define CONFIG_SYS_FSL_USB_PLLPRG2_FRAC_LPF_EN (1 << 13)
+#define CFG_SYS_FSL_USB_CTRL_PHY_EN (1 << 0)
+#define CFG_SYS_FSL_USB_DRVVBUS_CR_EN (1 << 1)
+#define CFG_SYS_FSL_USB_PWRFLT_CR_EN (1 << 1)
+#define CFG_SYS_FSL_USB_PLLPRG2_PHY2_CLK_EN (1 << 0)
+#define CFG_SYS_FSL_USB_PLLPRG2_PHY1_CLK_EN (1 << 1)
#ifdef CONFIG_SYS_FSL_SINGLE_SOURCE_CLK
-#define CONFIG_SYS_FSL_USB_PLLPRG2_REF_DIV_INTERNAL_CLK (5 << 4)
-#define CONFIG_SYS_FSL_USB_PLLPRG2_MFI_INTERNAL_CLK (6 << 16)
-#define CONFIG_SYS_FSL_USB_INTERNAL_SOC_CLK_EN (1 << 20)
+#define CFG_SYS_FSL_USB_PLLPRG2_REF_DIV_INTERNAL_CLK (5 << 4)
+#define CFG_SYS_FSL_USB_PLLPRG2_MFI_INTERNAL_CLK (6 << 16)
+#define CFG_SYS_FSL_USB_INTERNAL_SOC_CLK_EN (1 << 20)
#endif
-#define CONFIG_SYS_FSL_USB_PLLPRG2_REF_DIV (1 << 4)
-#define CONFIG_SYS_FSL_USB_PLLPRG2_MFI (5 << 16)
-#define CONFIG_SYS_FSL_USB_PLLPRG2_PLL_EN (1 << 21)
-#define CONFIG_SYS_FSL_USB_SYS_CLK_VALID (1 << 0)
-#define CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN (1 << 7)
-#define CONFIG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK (3 << 4)
+#define CFG_SYS_FSL_USB_PLLPRG2_REF_DIV (1 << 4)
+#define CFG_SYS_FSL_USB_PLLPRG2_MFI (5 << 16)
+#define CFG_SYS_FSL_USB_PLLPRG2_PLL_EN (1 << 21)
+#define CFG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_EN (1 << 7)
+#define CFG_SYS_FSL_USB_XCVRPRG_HS_DCNT_PROG_MASK (3 << 4)
#define INC_DCNT_THRESHOLD_25MV (0 << 4)
#define INC_DCNT_THRESHOLD_50MV (1 << 4)
@@ -74,14 +71,14 @@
u32 usb_enable_override;
u8 res[0xe4];
};
-#define CONFIG_SYS_FSL_USB_HS_DISCNCT_INC (3 << 22)
-#define CONFIG_SYS_FSL_USB_RX_AUTO_CAL_RD_WR_SEL (1 << 20)
-#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_0 13
-#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_WR_3 16
-#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_0 0
-#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_RD_3 3
-#define CONFIG_SYS_FSL_USB_ENABLE_OVERRIDE 1
-#define CONFIG_SYS_FSL_USB_SQUELCH_PROG_MASK 0x07
+#define CFG_SYS_FSL_USB_HS_DISCNCT_INC (3 << 22)
+#define CFG_SYS_FSL_USB_RX_AUTO_CAL_RD_WR_SEL (1 << 20)
+#define CFG_SYS_FSL_USB_SQUELCH_PROG_WR_0 13
+#define CFG_SYS_FSL_USB_SQUELCH_PROG_WR_3 16
+#define CFG_SYS_FSL_USB_SQUELCH_PROG_RD_0 0
+#define CFG_SYS_FSL_USB_SQUELCH_PROG_RD_3 3
+#define CFG_SYS_FSL_USB_ENABLE_OVERRIDE 1
+#define CFG_SYS_FSL_USB_SQUELCH_PROG_MASK 0x07
#endif
/* USB Erratum Checking code */
diff --git a/include/image.h b/include/image.h
index bed75ce..7717a4c 100644
--- a/include/image.h
+++ b/include/image.h
@@ -710,24 +710,18 @@
enum fit_load_op load_op, ulong *datap, ulong *lenp);
/**
- * image_source_script() - Execute a script
- * @addr: Address of script
- * @fit_uname: FIT subimage name
- * @confname: FIT config name. The subimage is chosen based on FIT_SCRIPT_PROP.
+ * image_locate_script() - Locate the raw script in an image
*
- * Executes a U-Boot script at a particular address in memory. The script should
- * have a header (FIT or legacy) with the script type (IH_TYPE_SCRIPT).
- *
- * If @fit_uname is the empty string, then the default image is used. If
- * @confname is the empty string, the default config is used. If @confname and
- * @fit_uname are both non-%NULL, then @confname is ignored. If @confname and
- * @fit_uname are both %NULL, then first the default config is tried, and then
- * the default image.
- *
- * Return: result code (enum command_ret_t)
+ * @buf: Address of image
+ * @size: Size of image in bytes
+ * @fit_uname: Node name of FIT image to read
+ * @confname: Node name of FIT config to read
+ * @datap: Returns pointer to raw script on success
+ * @lenp: Returns size of raw script on success
+ * @return 0 if OK, non-zero on error
*/
-int image_source_script(ulong addr, const char *fit_uname,
- const char *confname);
+int image_locate_script(void *buf, int size, const char *fit_uname,
+ const char *confname, char **datap, uint *lenp);
/**
* fit_get_node_from_config() - Look up an image a FIT by type
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 30f1545..2861b73 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -141,6 +141,7 @@
#define SPINOR_REG_ADDR_STR1V 0x00800000
#define SPINOR_REG_ADDR_CFR1V 0x00800002
#define SPINOR_REG_ADDR_CFR3V 0x00800004
+#define SPINOR_REG_ADDR_ARCFN 0x00000006
#define CFR3V_UNHYSA BIT(3) /* Uniform sectors or not */
#define CFR3V_PGMBUF BIT(4) /* Program buffer size */
@@ -189,12 +190,17 @@
#define SPINOR_OP_WR_ANY_REG 0x71 /* Write any register */
#define SPINOR_OP_S28_SE_4K 0x21
#define SPINOR_REG_CYPRESS_CFR2V 0x00800003
-#define SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24 0xb
+#define SPINOR_REG_CYPRESS_CFR2_MEMLAT_11_24 0xb
#define SPINOR_REG_CYPRESS_CFR3V 0x00800004
-#define SPINOR_REG_CYPRESS_CFR3V_PGSZ BIT(4) /* Page size. */
-#define SPINOR_REG_CYPRESS_CFR3V_UNISECT BIT(3) /* Uniform sector mode */
+#define SPINOR_REG_CYPRESS_CFR3_PGSZ BIT(4) /* Page size. */
+#define SPINOR_REG_CYPRESS_CFR3_UNISECT BIT(3) /* Uniform sector mode */
#define SPINOR_REG_CYPRESS_CFR5V 0x00800006
-#define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN 0x3
+#define SPINOR_REG_CYPRESS_CFR5_BIT6 BIT(6)
+#define SPINOR_REG_CYPRESS_CFR5_DDR BIT(1)
+#define SPINOR_REG_CYPRESS_CFR5_OPI BIT(0)
+#define SPINOR_REG_CYPRESS_CFR5_OCT_DTR_EN \
+ (SPINOR_REG_CYPRESS_CFR5_BIT6 | SPINOR_REG_CYPRESS_CFR5_DDR | \
+ SPINOR_REG_CYPRESS_CFR5_OPI)
#define SPINOR_OP_CYPRESS_RD_FAST 0xee
/* Supported SPI protocols */
diff --git a/include/linux/zstd.h b/include/linux/zstd.h
index aed20fc..3cf54d1 100644
--- a/include/linux/zstd.h
+++ b/include/linux/zstd.h
@@ -1,128 +1,97 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
/*
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * Copyright (c) Yann Collet, Facebook, Inc.
* All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of https://github.com/facebook/zstd) and
+ * the GPLv2 (found in the COPYING file in the root directory of
+ * https://github.com/facebook/zstd). You may select, at your option, one of the
+ * above-listed licenses.
*/
-#ifndef ZSTD_H
-#define ZSTD_H
-
-/* ====== Dependency ======*/
-#include <linux/types.h> /* size_t */
-
-
-/*-*****************************************************************************
- * Introduction
- *
- * zstd, short for Zstandard, is a fast lossless compression algorithm,
- * targeting real-time compression scenarios at zlib-level and better
- * compression ratios. The zstd compression library provides in-memory
- * compression and decompression functions. The library supports compression
- * levels from 1 up to ZSTD_maxCLevel() which is 22. Levels >= 20, labeled
- * ultra, should be used with caution, as they require more memory.
- * Compression can be done in:
- * - a single step, reusing a context (described as Explicit memory management)
- * - unbounded multiple steps (described as Streaming compression)
- * The compression ratio achievable on small data can be highly improved using
- * compression with a dictionary in:
- * - a single step (described as Simple dictionary API)
- * - a single step, reusing a dictionary (described as Fast dictionary API)
- ******************************************************************************/
-
-/*====== Helper functions ======*/
+#ifndef LINUX_ZSTD_H
+#define LINUX_ZSTD_H
/**
- * enum ZSTD_ErrorCode - zstd error codes
- *
- * Functions that return size_t can be checked for errors using ZSTD_isError()
- * and the ZSTD_ErrorCode can be extracted using ZSTD_getErrorCode().
+ * This is a kernel-style API that wraps the upstream zstd API, which cannot be
+ * used directly because the symbols aren't exported. It exposes the minimal
+ * functionality which is currently required by users of zstd in the kernel.
+ * Expose extra functions from lib/zstd/zstd.h as needed.
*/
-typedef enum {
- ZSTD_error_no_error,
- ZSTD_error_GENERIC,
- ZSTD_error_prefix_unknown,
- ZSTD_error_version_unsupported,
- ZSTD_error_parameter_unknown,
- ZSTD_error_frameParameter_unsupported,
- ZSTD_error_frameParameter_unsupportedBy32bits,
- ZSTD_error_frameParameter_windowTooLarge,
- ZSTD_error_compressionParameter_unsupported,
- ZSTD_error_init_missing,
- ZSTD_error_memory_allocation,
- ZSTD_error_stage_wrong,
- ZSTD_error_dstSize_tooSmall,
- ZSTD_error_srcSize_wrong,
- ZSTD_error_corruption_detected,
- ZSTD_error_checksum_wrong,
- ZSTD_error_tableLog_tooLarge,
- ZSTD_error_maxSymbolValue_tooLarge,
- ZSTD_error_maxSymbolValue_tooSmall,
- ZSTD_error_dictionary_corrupted,
- ZSTD_error_dictionary_wrong,
- ZSTD_error_dictionaryCreation_failed,
- ZSTD_error_maxCode
-} ZSTD_ErrorCode;
+
+/* ====== Dependency ====== */
+#include <linux/types.h>
+#include <linux/zstd_errors.h>
+#include <linux/zstd_lib.h>
+
+/* ====== Helper Functions ====== */
+/**
+ * zstd_compress_bound() - maximum compressed size in worst case scenario
+ * @src_size: The size of the data to compress.
+ *
+ * Return: The maximum compressed size in the worst case scenario.
+ */
+size_t zstd_compress_bound(size_t src_size);
/**
- * ZSTD_maxCLevel() - maximum compression level available
- *
- * Return: Maximum compression level available.
- */
-int ZSTD_maxCLevel(void);
-/**
- * ZSTD_compressBound() - maximum compressed size in worst case scenario
- * @srcSize: The size of the data to compress.
- *
- * Return: The maximum compressed size in the worst case scenario.
- */
-size_t ZSTD_compressBound(size_t srcSize);
-/**
- * ZSTD_isError() - tells if a size_t function result is an error code
+ * zstd_is_error() - tells if a size_t function result is an error code
* @code: The function result to check for error.
*
* Return: Non-zero iff the code is an error.
*/
-static __attribute__((unused)) unsigned int ZSTD_isError(size_t code)
-{
- return code > (size_t)-ZSTD_error_maxCode;
-}
-/**
- * ZSTD_getErrorCode() - translates an error function result to a ZSTD_ErrorCode
- * @functionResult: The result of a function for which ZSTD_isError() is true.
- *
- * Return: The ZSTD_ErrorCode corresponding to the functionResult or 0
- * if the functionResult isn't an error.
- */
-static __attribute__((unused)) ZSTD_ErrorCode ZSTD_getErrorCode(
- size_t functionResult)
-{
- if (!ZSTD_isError(functionResult))
- return (ZSTD_ErrorCode)0;
- return (ZSTD_ErrorCode)(0 - functionResult);
-}
+unsigned int zstd_is_error(size_t code);
/**
- * enum ZSTD_strategy - zstd compression search strategy
- *
- * From faster to stronger.
+ * enum zstd_error_code - zstd error codes
*/
-typedef enum {
- ZSTD_fast,
- ZSTD_dfast,
- ZSTD_greedy,
- ZSTD_lazy,
- ZSTD_lazy2,
- ZSTD_btlazy2,
- ZSTD_btopt,
- ZSTD_btopt2
-} ZSTD_strategy;
+typedef ZSTD_ErrorCode zstd_error_code;
/**
- * struct ZSTD_compressionParameters - zstd compression parameters
+ * zstd_get_error_code() - translates an error function result to an error code
+ * @code: The function result for which zstd_is_error(code) is true.
+ *
+ * Return: A unique error code for this error.
+ */
+zstd_error_code zstd_get_error_code(size_t code);
+
+/**
+ * zstd_get_error_name() - translates an error function result to a string
+ * @code: The function result for which zstd_is_error(code) is true.
+ *
+ * Return: An error string corresponding to the error code.
+ */
+const char *zstd_get_error_name(size_t code);
+
+/**
+ * zstd_min_clevel() - minimum allowed compression level
+ *
+ * Return: The minimum allowed compression level.
+ */
+int zstd_min_clevel(void);
+
+/**
+ * zstd_max_clevel() - maximum allowed compression level
+ *
+ * Return: The maximum allowed compression level.
+ */
+int zstd_max_clevel(void);
+
+/* ====== Parameter Selection ====== */
+
+/**
+ * enum zstd_strategy - zstd compression search strategy
+ *
+ * From faster to stronger. See zstd_lib.h.
+ */
+typedef ZSTD_strategy zstd_strategy;
+
+/**
+ * struct zstd_compression_parameters - zstd compression parameters
* @windowLog: Log of the largest match distance. Larger means more
* compression, and more memory needed during decompression.
- * @chainLog: Fully searched segment. Larger means more compression, slower,
- * and more memory (useless for fast).
+ * @chainLog: Fully searched segment. Larger means more compression,
+ * slower, and more memory (useless for fast).
* @hashLog: Dispatch table. Larger means more compression,
* slower, and more memory.
* @searchLog: Number of searches. Larger means more compression and slower.
@@ -131,1018 +100,349 @@
* @targetLength: Acceptable match size for optimal parser (only). Larger means
* more compression, and slower.
* @strategy: The zstd compression strategy.
- */
-typedef struct {
- unsigned int windowLog;
- unsigned int chainLog;
- unsigned int hashLog;
- unsigned int searchLog;
- unsigned int searchLength;
- unsigned int targetLength;
- ZSTD_strategy strategy;
-} ZSTD_compressionParameters;
-
-/**
- * struct ZSTD_frameParameters - zstd frame parameters
- * @contentSizeFlag: Controls whether content size will be present in the frame
- * header (when known).
- * @checksumFlag: Controls whether a 32-bit checksum is generated at the end
- * of the frame for error detection.
- * @noDictIDFlag: Controls whether dictID will be saved into the frame header
- * when using dictionary compression.
*
- * The default value is all fields set to 0.
+ * See zstd_lib.h.
*/
-typedef struct {
- unsigned int contentSizeFlag;
- unsigned int checksumFlag;
- unsigned int noDictIDFlag;
-} ZSTD_frameParameters;
+typedef ZSTD_compressionParameters zstd_compression_parameters;
/**
- * struct ZSTD_parameters - zstd parameters
+ * struct zstd_frame_parameters - zstd frame parameters
+ * @contentSizeFlag: Controls whether content size will be present in the
+ * frame header (when known).
+ * @checksumFlag: Controls whether a 32-bit checksum is generated at the
+ * end of the frame for error detection.
+ * @noDictIDFlag: Controls whether dictID will be saved into the frame
+ * header when using dictionary compression.
+ *
+ * The default value is all fields set to 0. See zstd_lib.h.
+ */
+typedef ZSTD_frameParameters zstd_frame_parameters;
+
+/**
+ * struct zstd_parameters - zstd parameters
* @cParams: The compression parameters.
* @fParams: The frame parameters.
*/
-typedef struct {
- ZSTD_compressionParameters cParams;
- ZSTD_frameParameters fParams;
-} ZSTD_parameters;
+typedef ZSTD_parameters zstd_parameters;
/**
- * ZSTD_getCParams() - returns ZSTD_compressionParameters for selected level
- * @compressionLevel: The compression level from 1 to ZSTD_maxCLevel().
- * @estimatedSrcSize: The estimated source size to compress or 0 if unknown.
- * @dictSize: The dictionary size or 0 if a dictionary isn't being used.
+ * zstd_get_params() - returns zstd_parameters for selected level
+ * @level: The compression level
+ * @estimated_src_size: The estimated source size to compress or 0
+ * if unknown.
*
- * Return: The selected ZSTD_compressionParameters.
+ * Return: The selected zstd_parameters.
*/
-ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel,
- unsigned long long estimatedSrcSize, size_t dictSize);
+zstd_parameters zstd_get_params(int level,
+ unsigned long long estimated_src_size);
+
+/* ====== Single-pass Compression ====== */
+
+typedef ZSTD_CCtx zstd_cctx;
/**
- * ZSTD_getParams() - returns ZSTD_parameters for selected level
- * @compressionLevel: The compression level from 1 to ZSTD_maxCLevel().
- * @estimatedSrcSize: The estimated source size to compress or 0 if unknown.
- * @dictSize: The dictionary size or 0 if a dictionary isn't being used.
- *
- * The same as ZSTD_getCParams() except also selects the default frame
- * parameters (all zero).
- *
- * Return: The selected ZSTD_parameters.
- */
-ZSTD_parameters ZSTD_getParams(int compressionLevel,
- unsigned long long estimatedSrcSize, size_t dictSize);
-
-/*-*************************************
- * Explicit memory management
- **************************************/
-
-/**
- * ZSTD_CCtxWorkspaceBound() - amount of memory needed to initialize a ZSTD_CCtx
- * @cParams: The compression parameters to be used for compression.
+ * zstd_cctx_workspace_bound() - max memory needed to initialize a zstd_cctx
+ * @parameters: The compression parameters to be used.
*
* If multiple compression parameters might be used, the caller must call
- * ZSTD_CCtxWorkspaceBound() for each set of parameters and use the maximum
+ * zstd_cctx_workspace_bound() for each set of parameters and use the maximum
* size.
*
- * Return: A lower bound on the size of the workspace that is passed to
- * ZSTD_initCCtx().
+ * Return: A lower bound on the size of the workspace that is passed to
+ * zstd_init_cctx().
*/
-size_t ZSTD_CCtxWorkspaceBound(ZSTD_compressionParameters cParams);
+size_t zstd_cctx_workspace_bound(const zstd_compression_parameters *parameters);
/**
- * struct ZSTD_CCtx - the zstd compression context
+ * zstd_init_cctx() - initialize a zstd compression context
+ * @workspace: The workspace to emplace the context into. It must outlive
+ * the returned context.
+ * @workspace_size: The size of workspace. Use zstd_cctx_workspace_bound() to
+ * determine how large the workspace must be.
*
- * When compressing many times it is recommended to allocate a context just once
- * and reuse it for each successive compression operation.
+ * Return: A zstd compression context or NULL on error.
*/
-typedef struct ZSTD_CCtx_s ZSTD_CCtx;
-/**
- * ZSTD_initCCtx() - initialize a zstd compression context
- * @workspace: The workspace to emplace the context into. It must outlive
- * the returned context.
- * @workspaceSize: The size of workspace. Use ZSTD_CCtxWorkspaceBound() to
- * determine how large the workspace must be.
- *
- * Return: A compression context emplaced into workspace.
- */
-ZSTD_CCtx *ZSTD_initCCtx(void *workspace, size_t workspaceSize);
+zstd_cctx *zstd_init_cctx(void *workspace, size_t workspace_size);
/**
- * ZSTD_compressCCtx() - compress src into dst
- * @ctx: The context. Must have been initialized with a workspace at
- * least as large as ZSTD_CCtxWorkspaceBound(params.cParams).
- * @dst: The buffer to compress src into.
- * @dstCapacity: The size of the destination buffer. May be any size, but
- * ZSTD_compressBound(srcSize) is guaranteed to be large enough.
- * @src: The data to compress.
- * @srcSize: The size of the data to compress.
- * @params: The parameters to use for compression. See ZSTD_getParams().
+ * zstd_compress_cctx() - compress src into dst with the initialized parameters
+ * @cctx: The context. Must have been initialized with zstd_init_cctx().
+ * @dst: The buffer to compress src into.
+ * @dst_capacity: The size of the destination buffer. May be any size, but
+ * ZSTD_compressBound(srcSize) is guaranteed to be large enough.
+ * @src: The data to compress.
+ * @src_size: The size of the data to compress.
+ * @parameters: The compression parameters to be used.
*
- * Return: The compressed size or an error, which can be checked using
- * ZSTD_isError().
+ * Return: The compressed size or an error, which can be checked using
+ * zstd_is_error().
*/
-size_t ZSTD_compressCCtx(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize, ZSTD_parameters params);
+size_t zstd_compress_cctx(zstd_cctx *cctx, void *dst, size_t dst_capacity,
+ const void *src, size_t src_size, const zstd_parameters *parameters);
+
+/* ====== Single-pass Decompression ====== */
+
+typedef ZSTD_DCtx zstd_dctx;
/**
- * ZSTD_DCtxWorkspaceBound() - amount of memory needed to initialize a ZSTD_DCtx
+ * zstd_dctx_workspace_bound() - max memory needed to initialize a zstd_dctx
*
* Return: A lower bound on the size of the workspace that is passed to
- * ZSTD_initDCtx().
+ * zstd_init_dctx().
*/
-size_t ZSTD_DCtxWorkspaceBound(void);
+size_t zstd_dctx_workspace_bound(void);
/**
- * struct ZSTD_DCtx - the zstd decompression context
+ * zstd_init_dctx() - initialize a zstd decompression context
+ * @workspace: The workspace to emplace the context into. It must outlive
+ * the returned context.
+ * @workspace_size: The size of workspace. Use zstd_dctx_workspace_bound() to
+ * determine how large the workspace must be.
*
- * When decompressing many times it is recommended to allocate a context just
- * once and reuse it for each successive decompression operation.
+ * Return: A zstd decompression context or NULL on error.
*/
-typedef struct ZSTD_DCtx_s ZSTD_DCtx;
-/**
- * ZSTD_initDCtx() - initialize a zstd decompression context
- * @workspace: The workspace to emplace the context into. It must outlive
- * the returned context.
- * @workspaceSize: The size of workspace. Use ZSTD_DCtxWorkspaceBound() to
- * determine how large the workspace must be.
- *
- * Return: A decompression context emplaced into workspace.
- */
-ZSTD_DCtx *ZSTD_initDCtx(void *workspace, size_t workspaceSize);
+zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size);
/**
- * ZSTD_decompressDCtx() - decompress zstd compressed src into dst
- * @ctx: The decompression context.
- * @dst: The buffer to decompress src into.
- * @dstCapacity: The size of the destination buffer. Must be at least as large
- * as the decompressed size. If the caller cannot upper bound the
- * decompressed size, then it's better to use the streaming API.
- * @src: The zstd compressed data to decompress. Multiple concatenated
- * frames and skippable frames are allowed.
- * @srcSize: The exact size of the data to decompress.
+ * zstd_decompress_dctx() - decompress zstd compressed src into dst
+ * @dctx: The decompression context.
+ * @dst: The buffer to decompress src into.
+ * @dst_capacity: The size of the destination buffer. Must be at least as large
+ * as the decompressed size. If the caller cannot upper bound the
+ * decompressed size, then it's better to use the streaming API.
+ * @src: The zstd compressed data to decompress. Multiple concatenated
+ * frames and skippable frames are allowed.
+ * @src_size: The exact size of the data to decompress.
*
- * Return: The decompressed size or an error, which can be checked using
- * ZSTD_isError().
+ * Return: The decompressed size or an error, which can be checked using
+ * zstd_is_error().
*/
-size_t ZSTD_decompressDCtx(ZSTD_DCtx *ctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize);
+size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
+ const void *src, size_t src_size);
-/*-************************
- * Simple dictionary API
- **************************/
+/* ====== Streaming Buffers ====== */
/**
- * ZSTD_compress_usingDict() - compress src into dst using a dictionary
- * @ctx: The context. Must have been initialized with a workspace at
- * least as large as ZSTD_CCtxWorkspaceBound(params.cParams).
- * @dst: The buffer to compress src into.
- * @dstCapacity: The size of the destination buffer. May be any size, but
- * ZSTD_compressBound(srcSize) is guaranteed to be large enough.
- * @src: The data to compress.
- * @srcSize: The size of the data to compress.
- * @dict: The dictionary to use for compression.
- * @dictSize: The size of the dictionary.
- * @params: The parameters to use for compression. See ZSTD_getParams().
- *
- * Compression using a predefined dictionary. The same dictionary must be used
- * during decompression.
- *
- * Return: The compressed size or an error, which can be checked using
- * ZSTD_isError().
- */
-size_t ZSTD_compress_usingDict(ZSTD_CCtx *ctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize, const void *dict, size_t dictSize,
- ZSTD_parameters params);
-
-/**
- * ZSTD_decompress_usingDict() - decompress src into dst using a dictionary
- * @ctx: The decompression context.
- * @dst: The buffer to decompress src into.
- * @dstCapacity: The size of the destination buffer. Must be at least as large
- * as the decompressed size. If the caller cannot upper bound the
- * decompressed size, then it's better to use the streaming API.
- * @src: The zstd compressed data to decompress. Multiple concatenated
- * frames and skippable frames are allowed.
- * @srcSize: The exact size of the data to decompress.
- * @dict: The dictionary to use for decompression. The same dictionary
- * must've been used to compress the data.
- * @dictSize: The size of the dictionary.
- *
- * Return: The decompressed size or an error, which can be checked using
- * ZSTD_isError().
- */
-size_t ZSTD_decompress_usingDict(ZSTD_DCtx *ctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize, const void *dict, size_t dictSize);
-
-/*-**************************
- * Fast dictionary API
- ***************************/
-
-/**
- * ZSTD_CDictWorkspaceBound() - memory needed to initialize a ZSTD_CDict
- * @cParams: The compression parameters to be used for compression.
- *
- * Return: A lower bound on the size of the workspace that is passed to
- * ZSTD_initCDict().
- */
-size_t ZSTD_CDictWorkspaceBound(ZSTD_compressionParameters cParams);
-
-/**
- * struct ZSTD_CDict - a digested dictionary to be used for compression
- */
-typedef struct ZSTD_CDict_s ZSTD_CDict;
-
-/**
- * ZSTD_initCDict() - initialize a digested dictionary for compression
- * @dictBuffer: The dictionary to digest. The buffer is referenced by the
- * ZSTD_CDict so it must outlive the returned ZSTD_CDict.
- * @dictSize: The size of the dictionary.
- * @params: The parameters to use for compression. See ZSTD_getParams().
- * @workspace: The workspace. It must outlive the returned ZSTD_CDict.
- * @workspaceSize: The workspace size. Must be at least
- * ZSTD_CDictWorkspaceBound(params.cParams).
- *
- * When compressing multiple messages / blocks with the same dictionary it is
- * recommended to load it just once. The ZSTD_CDict merely references the
- * dictBuffer, so it must outlive the returned ZSTD_CDict.
- *
- * Return: The digested dictionary emplaced into workspace.
- */
-ZSTD_CDict *ZSTD_initCDict(const void *dictBuffer, size_t dictSize,
- ZSTD_parameters params, void *workspace, size_t workspaceSize);
-
-/**
- * ZSTD_compress_usingCDict() - compress src into dst using a ZSTD_CDict
- * @ctx: The context. Must have been initialized with a workspace at
- * least as large as ZSTD_CCtxWorkspaceBound(cParams) where
- * cParams are the compression parameters used to initialize the
- * cdict.
- * @dst: The buffer to compress src into.
- * @dstCapacity: The size of the destination buffer. May be any size, but
- * ZSTD_compressBound(srcSize) is guaranteed to be large enough.
- * @src: The data to compress.
- * @srcSize: The size of the data to compress.
- * @cdict: The digested dictionary to use for compression.
- * @params: The parameters to use for compression. See ZSTD_getParams().
- *
- * Compression using a digested dictionary. The same dictionary must be used
- * during decompression.
- *
- * Return: The compressed size or an error, which can be checked using
- * ZSTD_isError().
- */
-size_t ZSTD_compress_usingCDict(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize, const ZSTD_CDict *cdict);
-
-
-/**
- * ZSTD_DDictWorkspaceBound() - memory needed to initialize a ZSTD_DDict
- *
- * Return: A lower bound on the size of the workspace that is passed to
- * ZSTD_initDDict().
- */
-size_t ZSTD_DDictWorkspaceBound(void);
-
-/**
- * struct ZSTD_DDict - a digested dictionary to be used for decompression
- */
-typedef struct ZSTD_DDict_s ZSTD_DDict;
-
-/**
- * ZSTD_initDDict() - initialize a digested dictionary for decompression
- * @dictBuffer: The dictionary to digest. The buffer is referenced by the
- * ZSTD_DDict so it must outlive the returned ZSTD_DDict.
- * @dictSize: The size of the dictionary.
- * @workspace: The workspace. It must outlive the returned ZSTD_DDict.
- * @workspaceSize: The workspace size. Must be at least
- * ZSTD_DDictWorkspaceBound().
- *
- * When decompressing multiple messages / blocks with the same dictionary it is
- * recommended to load it just once. The ZSTD_DDict merely references the
- * dictBuffer, so it must outlive the returned ZSTD_DDict.
- *
- * Return: The digested dictionary emplaced into workspace.
- */
-ZSTD_DDict *ZSTD_initDDict(const void *dictBuffer, size_t dictSize,
- void *workspace, size_t workspaceSize);
-
-/**
- * ZSTD_decompress_usingDDict() - decompress src into dst using a ZSTD_DDict
- * @ctx: The decompression context.
- * @dst: The buffer to decompress src into.
- * @dstCapacity: The size of the destination buffer. Must be at least as large
- * as the decompressed size. If the caller cannot upper bound the
- * decompressed size, then it's better to use the streaming API.
- * @src: The zstd compressed data to decompress. Multiple concatenated
- * frames and skippable frames are allowed.
- * @srcSize: The exact size of the data to decompress.
- * @ddict: The digested dictionary to use for decompression. The same
- * dictionary must've been used to compress the data.
- *
- * Return: The decompressed size or an error, which can be checked using
- * ZSTD_isError().
- */
-size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst,
- size_t dstCapacity, const void *src, size_t srcSize,
- const ZSTD_DDict *ddict);
-
-
-/*-**************************
- * Streaming
- ***************************/
-
-/**
- * struct ZSTD_inBuffer - input buffer for streaming
+ * struct zstd_in_buffer - input buffer for streaming
* @src: Start of the input buffer.
* @size: Size of the input buffer.
* @pos: Position where reading stopped. Will be updated.
* Necessarily 0 <= pos <= size.
+ *
+ * See zstd_lib.h.
*/
-typedef struct ZSTD_inBuffer_s {
- const void *src;
- size_t size;
- size_t pos;
-} ZSTD_inBuffer;
+typedef ZSTD_inBuffer zstd_in_buffer;
/**
- * struct ZSTD_outBuffer - output buffer for streaming
+ * struct zstd_out_buffer - output buffer for streaming
* @dst: Start of the output buffer.
* @size: Size of the output buffer.
* @pos: Position where writing stopped. Will be updated.
* Necessarily 0 <= pos <= size.
+ *
+ * See zstd_lib.h.
*/
-typedef struct ZSTD_outBuffer_s {
- void *dst;
- size_t size;
- size_t pos;
-} ZSTD_outBuffer;
+typedef ZSTD_outBuffer zstd_out_buffer;
+/* ====== Streaming Compression ====== */
-
-/*-*****************************************************************************
- * Streaming compression - HowTo
- *
- * A ZSTD_CStream object is required to track streaming operation.
- * Use ZSTD_initCStream() to initialize a ZSTD_CStream object.
- * ZSTD_CStream objects can be reused multiple times on consecutive compression
- * operations. It is recommended to re-use ZSTD_CStream in situations where many
- * streaming operations will be achieved consecutively. Use one separate
- * ZSTD_CStream per thread for parallel execution.
- *
- * Use ZSTD_compressStream() repetitively to consume input stream.
- * The function will automatically update both `pos` fields.
- * Note that it may not consume the entire input, in which case `pos < size`,
- * and it's up to the caller to present again remaining data.
- * It returns a hint for the preferred number of bytes to use as an input for
- * the next function call.
- *
- * At any moment, it's possible to flush whatever data remains within internal
- * buffer, using ZSTD_flushStream(). `output->pos` will be updated. There might
- * still be some content left within the internal buffer if `output->size` is
- * too small. It returns the number of bytes left in the internal buffer and
- * must be called until it returns 0.
- *
- * ZSTD_endStream() instructs to finish a frame. It will perform a flush and
- * write frame epilogue. The epilogue is required for decoders to consider a
- * frame completed. Similar to ZSTD_flushStream(), it may not be able to flush
- * the full content if `output->size` is too small. In which case, call again
- * ZSTD_endStream() to complete the flush. It returns the number of bytes left
- * in the internal buffer and must be called until it returns 0.
- ******************************************************************************/
+typedef ZSTD_CStream zstd_cstream;
/**
- * ZSTD_CStreamWorkspaceBound() - memory needed to initialize a ZSTD_CStream
- * @cParams: The compression parameters to be used for compression.
+ * zstd_cstream_workspace_bound() - memory needed to initialize a zstd_cstream
+ * @cparams: The compression parameters to be used for compression.
*
* Return: A lower bound on the size of the workspace that is passed to
- * ZSTD_initCStream() and ZSTD_initCStream_usingCDict().
+ * zstd_init_cstream().
*/
-size_t ZSTD_CStreamWorkspaceBound(ZSTD_compressionParameters cParams);
+size_t zstd_cstream_workspace_bound(const zstd_compression_parameters *cparams);
/**
- * struct ZSTD_CStream - the zstd streaming compression context
- */
-typedef struct ZSTD_CStream_s ZSTD_CStream;
-
-/*===== ZSTD_CStream management functions =====*/
-/**
- * ZSTD_initCStream() - initialize a zstd streaming compression context
- * @params: The zstd compression parameters.
- * @pledgedSrcSize: If params.fParams.contentSizeFlag == 1 then the caller must
- * pass the source size (zero means empty source). Otherwise,
- * the caller may optionally pass the source size, or zero if
- * unknown.
- * @workspace: The workspace to emplace the context into. It must outlive
- * the returned context.
- * @workspaceSize: The size of workspace.
- * Use ZSTD_CStreamWorkspaceBound(params.cParams) to determine
- * how large the workspace must be.
+ * zstd_init_cstream() - initialize a zstd streaming compression context
+ * @parameters The zstd parameters to use for compression.
+ * @pledged_src_size: If params.fParams.contentSizeFlag == 1 then the caller
+ * must pass the source size (zero means empty source).
+ * Otherwise, the caller may optionally pass the source
+ * size, or zero if unknown.
+ * @workspace: The workspace to emplace the context into. It must outlive
+ * the returned context.
+ * @workspace_size: The size of workspace.
+ * Use zstd_cstream_workspace_bound(params->cparams) to
+ * determine how large the workspace must be.
*
- * Return: The zstd streaming compression context.
+ * Return: The zstd streaming compression context or NULL on error.
*/
-ZSTD_CStream *ZSTD_initCStream(ZSTD_parameters params,
- unsigned long long pledgedSrcSize, void *workspace,
- size_t workspaceSize);
+zstd_cstream *zstd_init_cstream(const zstd_parameters *parameters,
+ unsigned long long pledged_src_size, void *workspace, size_t workspace_size);
/**
- * ZSTD_initCStream_usingCDict() - initialize a streaming compression context
- * @cdict: The digested dictionary to use for compression.
- * @pledgedSrcSize: Optionally the source size, or zero if unknown.
- * @workspace: The workspace to emplace the context into. It must outlive
- * the returned context.
- * @workspaceSize: The size of workspace. Call ZSTD_CStreamWorkspaceBound()
- * with the cParams used to initialize the cdict to determine
- * how large the workspace must be.
- *
- * Return: The zstd streaming compression context.
- */
-ZSTD_CStream *ZSTD_initCStream_usingCDict(const ZSTD_CDict *cdict,
- unsigned long long pledgedSrcSize, void *workspace,
- size_t workspaceSize);
-
-/*===== Streaming compression functions =====*/
-/**
- * ZSTD_resetCStream() - reset the context using parameters from creation
- * @zcs: The zstd streaming compression context to reset.
- * @pledgedSrcSize: Optionally the source size, or zero if unknown.
+ * zstd_reset_cstream() - reset the context using parameters from creation
+ * @cstream: The zstd streaming compression context to reset.
+ * @pledged_src_size: Optionally the source size, or zero if unknown.
*
* Resets the context using the parameters from creation. Skips dictionary
- * loading, since it can be reused. If `pledgedSrcSize` is non-zero the frame
+ * loading, since it can be reused. If `pledged_src_size` is non-zero the frame
* content size is always written into the frame header.
*
- * Return: Zero or an error, which can be checked using ZSTD_isError().
+ * Return: Zero or an error, which can be checked using
+ * zstd_is_error().
*/
-size_t ZSTD_resetCStream(ZSTD_CStream *zcs, unsigned long long pledgedSrcSize);
+size_t zstd_reset_cstream(zstd_cstream *cstream,
+ unsigned long long pledged_src_size);
+
/**
- * ZSTD_compressStream() - streaming compress some of input into output
- * @zcs: The zstd streaming compression context.
- * @output: Destination buffer. `output->pos` is updated to indicate how much
- * compressed data was written.
- * @input: Source buffer. `input->pos` is updated to indicate how much data was
- * read. Note that it may not consume the entire input, in which case
- * `input->pos < input->size`, and it's up to the caller to present
- * remaining data again.
+ * zstd_compress_stream() - streaming compress some of input into output
+ * @cstream: The zstd streaming compression context.
+ * @output: Destination buffer. `output->pos` is updated to indicate how much
+ * compressed data was written.
+ * @input: Source buffer. `input->pos` is updated to indicate how much data
+ * was read. Note that it may not consume the entire input, in which
+ * case `input->pos < input->size`, and it's up to the caller to
+ * present remaining data again.
*
* The `input` and `output` buffers may be any size. Guaranteed to make some
* forward progress if `input` and `output` are not empty.
*
- * Return: A hint for the number of bytes to use as the input for the next
- * function call or an error, which can be checked using
- * ZSTD_isError().
+ * Return: A hint for the number of bytes to use as the input for the next
+ * function call or an error, which can be checked using
+ * zstd_is_error().
*/
-size_t ZSTD_compressStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output,
- ZSTD_inBuffer *input);
+size_t zstd_compress_stream(zstd_cstream *cstream, zstd_out_buffer *output,
+ zstd_in_buffer *input);
+
/**
- * ZSTD_flushStream() - flush internal buffers into output
- * @zcs: The zstd streaming compression context.
- * @output: Destination buffer. `output->pos` is updated to indicate how much
- * compressed data was written.
+ * zstd_flush_stream() - flush internal buffers into output
+ * @cstream: The zstd streaming compression context.
+ * @output: Destination buffer. `output->pos` is updated to indicate how much
+ * compressed data was written.
*
- * ZSTD_flushStream() must be called until it returns 0, meaning all the data
- * has been flushed. Since ZSTD_flushStream() causes a block to be ended,
+ * zstd_flush_stream() must be called until it returns 0, meaning all the data
+ * has been flushed. Since zstd_flush_stream() causes a block to be ended,
* calling it too often will degrade the compression ratio.
*
- * Return: The number of bytes still present within internal buffers or an
- * error, which can be checked using ZSTD_isError().
+ * Return: The number of bytes still present within internal buffers or an
+ * error, which can be checked using zstd_is_error().
*/
-size_t ZSTD_flushStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output);
+size_t zstd_flush_stream(zstd_cstream *cstream, zstd_out_buffer *output);
+
/**
- * ZSTD_endStream() - flush internal buffers into output and end the frame
- * @zcs: The zstd streaming compression context.
- * @output: Destination buffer. `output->pos` is updated to indicate how much
- * compressed data was written.
+ * zstd_end_stream() - flush internal buffers into output and end the frame
+ * @cstream: The zstd streaming compression context.
+ * @output: Destination buffer. `output->pos` is updated to indicate how much
+ * compressed data was written.
*
- * ZSTD_endStream() must be called until it returns 0, meaning all the data has
+ * zstd_end_stream() must be called until it returns 0, meaning all the data has
* been flushed and the frame epilogue has been written.
*
- * Return: The number of bytes still present within internal buffers or an
- * error, which can be checked using ZSTD_isError().
+ * Return: The number of bytes still present within internal buffers or an
+ * error, which can be checked using zstd_is_error().
*/
-size_t ZSTD_endStream(ZSTD_CStream *zcs, ZSTD_outBuffer *output);
+size_t zstd_end_stream(zstd_cstream *cstream, zstd_out_buffer *output);
+
+/* ====== Streaming Decompression ====== */
+
+typedef ZSTD_DStream zstd_dstream;
/**
- * ZSTD_CStreamInSize() - recommended size for the input buffer
+ * zstd_dstream_workspace_bound() - memory needed to initialize a zstd_dstream
+ * @max_window_size: The maximum window size allowed for compressed frames.
*
- * Return: The recommended size for the input buffer.
+ * Return: A lower bound on the size of the workspace that is passed
+ * to zstd_init_dstream().
*/
-size_t ZSTD_CStreamInSize(void);
-/**
- * ZSTD_CStreamOutSize() - recommended size for the output buffer
- *
- * When the output buffer is at least this large, it is guaranteed to be large
- * enough to flush at least one complete compressed block.
- *
- * Return: The recommended size for the output buffer.
- */
-size_t ZSTD_CStreamOutSize(void);
-
-
-
-/*-*****************************************************************************
- * Streaming decompression - HowTo
- *
- * A ZSTD_DStream object is required to track streaming operations.
- * Use ZSTD_initDStream() to initialize a ZSTD_DStream object.
- * ZSTD_DStream objects can be re-used multiple times.
- *
- * Use ZSTD_decompressStream() repetitively to consume your input.
- * The function will update both `pos` fields.
- * If `input->pos < input->size`, some input has not been consumed.
- * It's up to the caller to present again remaining data.
- * If `output->pos < output->size`, decoder has flushed everything it could.
- * Returns 0 iff a frame is completely decoded and fully flushed.
- * Otherwise it returns a suggested next input size that will never load more
- * than the current frame.
- ******************************************************************************/
+size_t zstd_dstream_workspace_bound(size_t max_window_size);
/**
- * ZSTD_DStreamWorkspaceBound() - memory needed to initialize a ZSTD_DStream
- * @maxWindowSize: The maximum window size allowed for compressed frames.
+ * zstd_init_dstream() - initialize a zstd streaming decompression context
+ * @max_window_size: The maximum window size allowed for compressed frames.
+ * @workspace: The workspace to emplace the context into. It must outlive
+ * the returned context.
+ * @workspaceSize: The size of workspace.
+ * Use zstd_dstream_workspace_bound(max_window_size) to
+ * determine how large the workspace must be.
*
- * Return: A lower bound on the size of the workspace that is passed to
- * ZSTD_initDStream() and ZSTD_initDStream_usingDDict().
+ * Return: The zstd streaming decompression context.
*/
-size_t ZSTD_DStreamWorkspaceBound(size_t maxWindowSize);
+zstd_dstream *zstd_init_dstream(size_t max_window_size, void *workspace,
+ size_t workspace_size);
/**
- * struct ZSTD_DStream - the zstd streaming decompression context
- */
-typedef struct ZSTD_DStream_s ZSTD_DStream;
-/*===== ZSTD_DStream management functions =====*/
-/**
- * ZSTD_initDStream() - initialize a zstd streaming decompression context
- * @maxWindowSize: The maximum window size allowed for compressed frames.
- * @workspace: The workspace to emplace the context into. It must outlive
- * the returned context.
- * @workspaceSize: The size of workspace.
- * Use ZSTD_DStreamWorkspaceBound(maxWindowSize) to determine
- * how large the workspace must be.
- *
- * Return: The zstd streaming decompression context.
- */
-ZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace,
- size_t workspaceSize);
-/**
- * ZSTD_initDStream_usingDDict() - initialize streaming decompression context
- * @maxWindowSize: The maximum window size allowed for compressed frames.
- * @ddict: The digested dictionary to use for decompression.
- * @workspace: The workspace to emplace the context into. It must outlive
- * the returned context.
- * @workspaceSize: The size of workspace.
- * Use ZSTD_DStreamWorkspaceBound(maxWindowSize) to determine
- * how large the workspace must be.
- *
- * Return: The zstd streaming decompression context.
- */
-ZSTD_DStream *ZSTD_initDStream_usingDDict(size_t maxWindowSize,
- const ZSTD_DDict *ddict, void *workspace, size_t workspaceSize);
-
-/*===== Streaming decompression functions =====*/
-/**
- * ZSTD_resetDStream() - reset the context using parameters from creation
- * @zds: The zstd streaming decompression context to reset.
+ * zstd_reset_dstream() - reset the context using parameters from creation
+ * @dstream: The zstd streaming decompression context to reset.
*
* Resets the context using the parameters from creation. Skips dictionary
* loading, since it can be reused.
*
- * Return: Zero or an error, which can be checked using ZSTD_isError().
+ * Return: Zero or an error, which can be checked using zstd_is_error().
*/
-size_t ZSTD_resetDStream(ZSTD_DStream *zds);
+size_t zstd_reset_dstream(zstd_dstream *dstream);
+
/**
- * ZSTD_decompressStream() - streaming decompress some of input into output
- * @zds: The zstd streaming decompression context.
- * @output: Destination buffer. `output.pos` is updated to indicate how much
- * decompressed data was written.
- * @input: Source buffer. `input.pos` is updated to indicate how much data was
- * read. Note that it may not consume the entire input, in which case
- * `input.pos < input.size`, and it's up to the caller to present
- * remaining data again.
+ * zstd_decompress_stream() - streaming decompress some of input into output
+ * @dstream: The zstd streaming decompression context.
+ * @output: Destination buffer. `output.pos` is updated to indicate how much
+ * decompressed data was written.
+ * @input: Source buffer. `input.pos` is updated to indicate how much data was
+ * read. Note that it may not consume the entire input, in which case
+ * `input.pos < input.size`, and it's up to the caller to present
+ * remaining data again.
*
* The `input` and `output` buffers may be any size. Guaranteed to make some
* forward progress if `input` and `output` are not empty.
- * ZSTD_decompressStream() will not consume the last byte of the frame until
+ * zstd_decompress_stream() will not consume the last byte of the frame until
* the entire frame is flushed.
*
- * Return: Returns 0 iff a frame is completely decoded and fully flushed.
- * Otherwise returns a hint for the number of bytes to use as the input
- * for the next function call or an error, which can be checked using
- * ZSTD_isError(). The size hint will never load more than the frame.
+ * Return: Returns 0 iff a frame is completely decoded and fully flushed.
+ * Otherwise returns a hint for the number of bytes to use as the
+ * input for the next function call or an error, which can be checked
+ * using zstd_is_error(). The size hint will never load more than the
+ * frame.
*/
-size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output,
- ZSTD_inBuffer *input);
+size_t zstd_decompress_stream(zstd_dstream *dstream, zstd_out_buffer *output,
+ zstd_in_buffer *input);
+
+/* ====== Frame Inspection Functions ====== */
/**
- * ZSTD_DStreamInSize() - recommended size for the input buffer
+ * zstd_find_frame_compressed_size() - returns the size of a compressed frame
+ * @src: Source buffer. It should point to the start of a zstd encoded
+ * frame or a skippable frame.
+ * @src_size: The size of the source buffer. It must be at least as large as the
+ * size of the frame.
*
- * Return: The recommended size for the input buffer.
+ * Return: The compressed size of the frame pointed to by `src` or an error,
+ * which can be check with zstd_is_error().
+ * Suitable to pass to ZSTD_decompress() or similar functions.
*/
-size_t ZSTD_DStreamInSize(void);
-/**
- * ZSTD_DStreamOutSize() - recommended size for the output buffer
- *
- * When the output buffer is at least this large, it is guaranteed to be large
- * enough to flush at least one complete decompressed block.
- *
- * Return: The recommended size for the output buffer.
- */
-size_t ZSTD_DStreamOutSize(void);
-
-
-/* --- Constants ---*/
-#define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */
-#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
-
-#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
-#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
-
-#define ZSTD_WINDOWLOG_MAX_32 27
-#define ZSTD_WINDOWLOG_MAX_64 27
-#define ZSTD_WINDOWLOG_MAX \
- ((unsigned int)(sizeof(size_t) == 4 \
- ? ZSTD_WINDOWLOG_MAX_32 \
- : ZSTD_WINDOWLOG_MAX_64))
-#define ZSTD_WINDOWLOG_MIN 10
-#define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX
-#define ZSTD_HASHLOG_MIN 6
-#define ZSTD_CHAINLOG_MAX (ZSTD_WINDOWLOG_MAX+1)
-#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
-#define ZSTD_HASHLOG3_MAX 17
-#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
-#define ZSTD_SEARCHLOG_MIN 1
-/* only for ZSTD_fast, other strategies are limited to 6 */
-#define ZSTD_SEARCHLENGTH_MAX 7
-/* only for ZSTD_btopt, other strategies are limited to 4 */
-#define ZSTD_SEARCHLENGTH_MIN 3
-#define ZSTD_TARGETLENGTH_MIN 4
-#define ZSTD_TARGETLENGTH_MAX 999
-
-/* for static allocation */
-#define ZSTD_FRAMEHEADERSIZE_MAX 18
-#define ZSTD_FRAMEHEADERSIZE_MIN 6
-static const size_t ZSTD_frameHeaderSize_prefix = 5;
-static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN;
-static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
-/* magic number + skippable frame length */
-static const size_t ZSTD_skippableHeaderSize = 8;
-
-
-/*-*************************************
- * Compressed size functions
- **************************************/
+size_t zstd_find_frame_compressed_size(const void *src, size_t src_size);
/**
- * ZSTD_findFrameCompressedSize() - returns the size of a compressed frame
- * @src: Source buffer. It should point to the start of a zstd encoded frame
- * or a skippable frame.
- * @srcSize: The size of the source buffer. It must be at least as large as the
- * size of the frame.
- *
- * Return: The compressed size of the frame pointed to by `src` or an error,
- * which can be check with ZSTD_isError().
- * Suitable to pass to ZSTD_decompress() or similar functions.
- */
-size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize);
-
-/*-*************************************
- * Decompressed size functions
- **************************************/
-/**
- * ZSTD_getFrameContentSize() - returns the content size in a zstd frame header
- * @src: It should point to the start of a zstd encoded frame.
- * @srcSize: The size of the source buffer. It must be at least as large as the
- * frame header. `ZSTD_frameHeaderSize_max` is always large enough.
- *
- * Return: The frame content size stored in the frame header if known.
- * `ZSTD_CONTENTSIZE_UNKNOWN` if the content size isn't stored in the
- * frame header. `ZSTD_CONTENTSIZE_ERROR` on invalid input.
- */
-unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
-
-/**
- * ZSTD_findDecompressedSize() - returns decompressed size of a series of frames
- * @src: It should point to the start of a series of zstd encoded and/or
- * skippable frames.
- * @srcSize: The exact size of the series of frames.
- *
- * If any zstd encoded frame in the series doesn't have the frame content size
- * set, `ZSTD_CONTENTSIZE_UNKNOWN` is returned. But frame content size is always
- * set when using ZSTD_compress(). The decompressed size can be very large.
- * If the source is untrusted, the decompressed size could be wrong or
- * intentionally modified. Always ensure the result fits within the
- * application's authorized limits. ZSTD_findDecompressedSize() handles multiple
- * frames, and so it must traverse the input to read each frame header. This is
- * efficient as most of the data is skipped, however it does mean that all frame
- * data must be present and valid.
- *
- * Return: Decompressed size of all the data contained in the frames if known.
- * `ZSTD_CONTENTSIZE_UNKNOWN` if the decompressed size is unknown.
- * `ZSTD_CONTENTSIZE_ERROR` if an error occurred.
- */
-unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize);
-
-/*-*************************************
- * Advanced compression functions
- **************************************/
-/**
- * ZSTD_checkCParams() - ensure parameter values remain within authorized range
- * @cParams: The zstd compression parameters.
- *
- * Return: Zero or an error, which can be checked using ZSTD_isError().
- */
-size_t ZSTD_checkCParams(ZSTD_compressionParameters cParams);
-
-/**
- * ZSTD_adjustCParams() - optimize parameters for a given srcSize and dictSize
- * @srcSize: Optionally the estimated source size, or zero if unknown.
- * @dictSize: Optionally the estimated dictionary size, or zero if unknown.
- *
- * Return: The optimized parameters.
- */
-ZSTD_compressionParameters ZSTD_adjustCParams(
- ZSTD_compressionParameters cParams, unsigned long long srcSize,
- size_t dictSize);
-
-/*--- Advanced decompression functions ---*/
-
-/**
- * ZSTD_isFrame() - returns true iff the buffer starts with a valid frame
- * @buffer: The source buffer to check.
- * @size: The size of the source buffer, must be at least 4 bytes.
- *
- * Return: True iff the buffer starts with a zstd or skippable frame identifier.
- */
-unsigned int ZSTD_isFrame(const void *buffer, size_t size);
-
-/**
- * ZSTD_getDictID_fromDict() - returns the dictionary id stored in a dictionary
- * @dict: The dictionary buffer.
- * @dictSize: The size of the dictionary buffer.
- *
- * Return: The dictionary id stored within the dictionary or 0 if the
- * dictionary is not a zstd dictionary. If it returns 0 the
- * dictionary can still be loaded as a content-only dictionary.
- */
-unsigned int ZSTD_getDictID_fromDict(const void *dict, size_t dictSize);
-
-/**
- * ZSTD_getDictID_fromDDict() - returns the dictionary id stored in a ZSTD_DDict
- * @ddict: The ddict to find the id of.
- *
- * Return: The dictionary id stored within `ddict` or 0 if the dictionary is not
- * a zstd dictionary. If it returns 0 `ddict` will be loaded as a
- * content-only dictionary.
- */
-unsigned int ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict);
-
-/**
- * ZSTD_getDictID_fromFrame() - returns the dictionary id stored in a zstd frame
- * @src: Source buffer. It must be a zstd encoded frame.
- * @srcSize: The size of the source buffer. It must be at least as large as the
- * frame header. `ZSTD_frameHeaderSize_max` is always large enough.
- *
- * Return: The dictionary id required to decompress the frame stored within
- * `src` or 0 if the dictionary id could not be decoded. It can return
- * 0 if the frame does not require a dictionary, the dictionary id
- * wasn't stored in the frame, `src` is not a zstd frame, or `srcSize`
- * is too small.
- */
-unsigned int ZSTD_getDictID_fromFrame(const void *src, size_t srcSize);
-
-/**
- * struct ZSTD_frameParams - zstd frame parameters stored in the frame header
- * @frameContentSize: The frame content size, or 0 if not present.
+ * struct zstd_frame_params - zstd frame parameters stored in the frame header
+ * @frameContentSize: The frame content size, or ZSTD_CONTENTSIZE_UNKNOWN if not
+ * present.
* @windowSize: The window size, or 0 if the frame is a skippable frame.
+ * @blockSizeMax: The maximum block size.
+ * @frameType: The frame type (zstd or skippable)
+ * @headerSize: The size of the frame header.
* @dictID: The dictionary id, or 0 if not present.
* @checksumFlag: Whether a checksum was used.
+ *
+ * See zstd_lib.h.
*/
-typedef struct {
- unsigned long long frameContentSize;
- unsigned int windowSize;
- unsigned int dictID;
- unsigned int checksumFlag;
-} ZSTD_frameParams;
+typedef ZSTD_frameHeader zstd_frame_header;
/**
- * ZSTD_getFrameParams() - extracts parameters from a zstd or skippable frame
- * @fparamsPtr: On success the frame parameters are written here.
- * @src: The source buffer. It must point to a zstd or skippable frame.
- * @srcSize: The size of the source buffer. `ZSTD_frameHeaderSize_max` is
- * always large enough to succeed.
+ * zstd_get_frame_header() - extracts parameters from a zstd or skippable frame
+ * @params: On success the frame parameters are written here.
+ * @src: The source buffer. It must point to a zstd or skippable frame.
+ * @src_size: The size of the source buffer.
*
- * Return: 0 on success. If more data is required it returns how many bytes
- * must be provided to make forward progress. Otherwise it returns
- * an error, which can be checked using ZSTD_isError().
+ * Return: 0 on success. If more data is required it returns how many bytes
+ * must be provided to make forward progress. Otherwise it returns
+ * an error, which can be checked using zstd_is_error().
*/
-size_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src,
- size_t srcSize);
-
-/*-*****************************************************************************
- * Buffer-less and synchronous inner streaming functions
- *
- * This is an advanced API, giving full control over buffer management, for
- * users which need direct control over memory.
- * But it's also a complex one, with many restrictions (documented below).
- * Prefer using normal streaming API for an easier experience
- ******************************************************************************/
-
-/*-*****************************************************************************
- * Buffer-less streaming compression (synchronous mode)
- *
- * A ZSTD_CCtx object is required to track streaming operations.
- * Use ZSTD_initCCtx() to initialize a context.
- * ZSTD_CCtx object can be re-used multiple times within successive compression
- * operations.
- *
- * Start by initializing a context.
- * Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary
- * compression,
- * or ZSTD_compressBegin_advanced(), for finer parameter control.
- * It's also possible to duplicate a reference context which has already been
- * initialized, using ZSTD_copyCCtx()
- *
- * Then, consume your input using ZSTD_compressContinue().
- * There are some important considerations to keep in mind when using this
- * advanced function :
- * - ZSTD_compressContinue() has no internal buffer. It uses externally provided
- * buffer only.
- * - Interface is synchronous : input is consumed entirely and produce 1+
- * (or more) compressed blocks.
- * - Caller must ensure there is enough space in `dst` to store compressed data
- * under worst case scenario. Worst case evaluation is provided by
- * ZSTD_compressBound().
- * ZSTD_compressContinue() doesn't guarantee recover after a failed
- * compression.
- * - ZSTD_compressContinue() presumes prior input ***is still accessible and
- * unmodified*** (up to maximum distance size, see WindowLog).
- * It remembers all previous contiguous blocks, plus one separated memory
- * segment (which can itself consists of multiple contiguous blocks)
- * - ZSTD_compressContinue() detects that prior input has been overwritten when
- * `src` buffer overlaps. In which case, it will "discard" the relevant memory
- * section from its history.
- *
- * Finish a frame with ZSTD_compressEnd(), which will write the last block(s)
- * and optional checksum. It's possible to use srcSize==0, in which case, it
- * will write a final empty block to end the frame. Without last block mark,
- * frames will be considered unfinished (corrupted) by decoders.
- *
- * `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress some new
- * frame.
- ******************************************************************************/
-
-/*===== Buffer-less streaming compression functions =====*/
-size_t ZSTD_compressBegin(ZSTD_CCtx *cctx, int compressionLevel);
-size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx *cctx, const void *dict,
- size_t dictSize, int compressionLevel);
-size_t ZSTD_compressBegin_advanced(ZSTD_CCtx *cctx, const void *dict,
- size_t dictSize, ZSTD_parameters params,
- unsigned long long pledgedSrcSize);
-size_t ZSTD_copyCCtx(ZSTD_CCtx *cctx, const ZSTD_CCtx *preparedCCtx,
- unsigned long long pledgedSrcSize);
-size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx *cctx, const ZSTD_CDict *cdict,
- unsigned long long pledgedSrcSize);
-size_t ZSTD_compressContinue(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize);
-size_t ZSTD_compressEnd(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize);
-
-
-
-/*-*****************************************************************************
- * Buffer-less streaming decompression (synchronous mode)
- *
- * A ZSTD_DCtx object is required to track streaming operations.
- * Use ZSTD_initDCtx() to initialize a context.
- * A ZSTD_DCtx object can be re-used multiple times.
- *
- * First typical operation is to retrieve frame parameters, using
- * ZSTD_getFrameParams(). It fills a ZSTD_frameParams structure which provide
- * important information to correctly decode the frame, such as the minimum
- * rolling buffer size to allocate to decompress data (`windowSize`), and the
- * dictionary ID used.
- * Note: content size is optional, it may not be present. 0 means unknown.
- * Note that these values could be wrong, either because of data malformation,
- * or because an attacker is spoofing deliberate false information. As a
- * consequence, check that values remain within valid application range,
- * especially `windowSize`, before allocation. Each application can set its own
- * limit, depending on local restrictions. For extended interoperability, it is
- * recommended to support at least 8 MB.
- * Frame parameters are extracted from the beginning of the compressed frame.
- * Data fragment must be large enough to ensure successful decoding, typically
- * `ZSTD_frameHeaderSize_max` bytes.
- * Result: 0: successful decoding, the `ZSTD_frameParams` structure is filled.
- * >0: `srcSize` is too small, provide at least this many bytes.
- * errorCode, which can be tested using ZSTD_isError().
- *
- * Start decompression, with ZSTD_decompressBegin() or
- * ZSTD_decompressBegin_usingDict(). Alternatively, you can copy a prepared
- * context, using ZSTD_copyDCtx().
- *
- * Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue()
- * alternatively.
- * ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize'
- * to ZSTD_decompressContinue().
- * ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will
- * fail.
- *
- * The result of ZSTD_decompressContinue() is the number of bytes regenerated
- * within 'dst' (necessarily <= dstCapacity). It can be zero, which is not an
- * error; it just means ZSTD_decompressContinue() has decoded some metadata
- * item. It can also be an error code, which can be tested with ZSTD_isError().
- *
- * ZSTD_decompressContinue() needs previous data blocks during decompression, up
- * to `windowSize`. They should preferably be located contiguously, prior to
- * current block. Alternatively, a round buffer of sufficient size is also
- * possible. Sufficient size is determined by frame parameters.
- * ZSTD_decompressContinue() is very sensitive to contiguity, if 2 blocks don't
- * follow each other, make sure that either the compressor breaks contiguity at
- * the same place, or that previous contiguous segment is large enough to
- * properly handle maximum back-reference.
- *
- * A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.
- * Context can then be reset to start a new decompression.
- *
- * Note: it's possible to know if next input to present is a header or a block,
- * using ZSTD_nextInputType(). This information is not required to properly
- * decode a frame.
- *
- * == Special case: skippable frames ==
- *
- * Skippable frames allow integration of user-defined data into a flow of
- * concatenated frames. Skippable frames will be ignored (skipped) by a
- * decompressor. The format of skippable frames is as follows:
- * a) Skippable frame ID - 4 Bytes, Little endian format, any value from
- * 0x184D2A50 to 0x184D2A5F
- * b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
- * c) Frame Content - any content (User Data) of length equal to Frame Size
- * For skippable frames ZSTD_decompressContinue() always returns 0.
- * For skippable frames ZSTD_getFrameParams() returns fparamsPtr->windowLog==0
- * what means that a frame is skippable.
- * Note: If fparamsPtr->frameContentSize==0, it is ambiguous: the frame might
- * actually be a zstd encoded frame with no content. For purposes of
- * decompression, it is valid in both cases to skip the frame using
- * ZSTD_findFrameCompressedSize() to find its size in bytes.
- * It also returns frame size as fparamsPtr->frameContentSize.
- ******************************************************************************/
-
-/*===== Buffer-less streaming decompression functions =====*/
-size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx);
-size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict,
- size_t dictSize);
-void ZSTD_copyDCtx(ZSTD_DCtx *dctx, const ZSTD_DCtx *preparedDCtx);
-size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx);
-size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize);
-typedef enum {
- ZSTDnit_frameHeader,
- ZSTDnit_blockHeader,
- ZSTDnit_block,
- ZSTDnit_lastBlock,
- ZSTDnit_checksum,
- ZSTDnit_skippableFrame
-} ZSTD_nextInputType_e;
-ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx);
-
-/*-*****************************************************************************
- * Block functions
- *
- * Block functions produce and decode raw zstd blocks, without frame metadata.
- * Frame metadata cost is typically ~18 bytes, which can be non-negligible for
- * very small blocks (< 100 bytes). User will have to take in charge required
- * information to regenerate data, such as compressed and content sizes.
- *
- * A few rules to respect:
- * - Compressing and decompressing require a context structure
- * + Use ZSTD_initCCtx() and ZSTD_initDCtx()
- * - It is necessary to init context before starting
- * + compression : ZSTD_compressBegin()
- * + decompression : ZSTD_decompressBegin()
- * + variants _usingDict() are also allowed
- * + copyCCtx() and copyDCtx() work too
- * - Block size is limited, it must be <= ZSTD_getBlockSizeMax()
- * + If you need to compress more, cut data into multiple blocks
- * + Consider using the regular ZSTD_compress() instead, as frame metadata
- * costs become negligible when source size is large.
- * - When a block is considered not compressible enough, ZSTD_compressBlock()
- * result will be zero. In which case, nothing is produced into `dst`.
- * + User must test for such outcome and deal directly with uncompressed data
- * + ZSTD_decompressBlock() doesn't accept uncompressed data as input!!!
- * + In case of multiple successive blocks, decoder must be informed of
- * uncompressed block existence to follow proper history. Use
- * ZSTD_insertBlock() in such a case.
- ******************************************************************************/
-
-/* Define for static allocation */
-#define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024)
-/*===== Raw zstd block functions =====*/
-size_t ZSTD_getBlockSizeMax(ZSTD_CCtx *cctx);
-size_t ZSTD_compressBlock(ZSTD_CCtx *cctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize);
-size_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity,
- const void *src, size_t srcSize);
-size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart,
- size_t blockSize);
+size_t zstd_get_frame_header(zstd_frame_header *params, const void *src,
+ size_t src_size);
struct abuf;
@@ -1155,4 +455,4 @@
*/
int zstd_decompress(struct abuf *in, struct abuf *out);
-#endif /* ZSTD_H */
+#endif /* LINUX_ZSTD_H */
diff --git a/include/linux/zstd_errors.h b/include/linux/zstd_errors.h
new file mode 100644
index 0000000..58b6dd4
--- /dev/null
+++ b/include/linux/zstd_errors.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_ERRORS_H_398273423
+#define ZSTD_ERRORS_H_398273423
+
+
+/*===== dependency =====*/
+#include <linux/types.h> /* size_t */
+
+
+/* ===== ZSTDERRORLIB_API : control library symbols visibility ===== */
+#define ZSTDERRORLIB_VISIBILITY
+#define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBILITY
+
+/*-*********************************************
+ * Error codes list
+ *-*********************************************
+ * Error codes _values_ are pinned down since v1.3.1 only.
+ * Therefore, don't rely on values if you may link to any version < v1.3.1.
+ *
+ * Only values < 100 are considered stable.
+ *
+ * note 1 : this API shall be used with static linking only.
+ * dynamic linking is not yet officially supported.
+ * note 2 : Prefer relying on the enum than on its value whenever possible
+ * This is the only supported way to use the error list < v1.3.1
+ * note 3 : ZSTD_isError() is always correct, whatever the library version.
+ **********************************************/
+typedef enum {
+ ZSTD_error_no_error = 0,
+ ZSTD_error_GENERIC = 1,
+ ZSTD_error_prefix_unknown = 10,
+ ZSTD_error_version_unsupported = 12,
+ ZSTD_error_frameParameter_unsupported = 14,
+ ZSTD_error_frameParameter_windowTooLarge = 16,
+ ZSTD_error_corruption_detected = 20,
+ ZSTD_error_checksum_wrong = 22,
+ ZSTD_error_dictionary_corrupted = 30,
+ ZSTD_error_dictionary_wrong = 32,
+ ZSTD_error_dictionaryCreation_failed = 34,
+ ZSTD_error_parameter_unsupported = 40,
+ ZSTD_error_parameter_outOfBound = 42,
+ ZSTD_error_tableLog_tooLarge = 44,
+ ZSTD_error_maxSymbolValue_tooLarge = 46,
+ ZSTD_error_maxSymbolValue_tooSmall = 48,
+ ZSTD_error_stage_wrong = 60,
+ ZSTD_error_init_missing = 62,
+ ZSTD_error_memory_allocation = 64,
+ ZSTD_error_workSpace_tooSmall= 66,
+ ZSTD_error_dstSize_tooSmall = 70,
+ ZSTD_error_srcSize_wrong = 72,
+ ZSTD_error_dstBuffer_null = 74,
+ /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */
+ ZSTD_error_frameIndex_tooLarge = 100,
+ ZSTD_error_seekableIO = 102,
+ ZSTD_error_dstBuffer_wrong = 104,
+ ZSTD_error_srcBuffer_wrong = 105,
+ ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */
+} ZSTD_ErrorCode;
+
+/*! ZSTD_getErrorCode() :
+ convert a `size_t` function result into a `ZSTD_ErrorCode` enum type,
+ which can be used to compare with enum list published above */
+ZSTDERRORLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult);
+ZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code); /*< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */
+
+
+
+#endif /* ZSTD_ERRORS_H_398273423 */
diff --git a/include/linux/zstd_lib.h b/include/linux/zstd_lib.h
new file mode 100644
index 0000000..25f5907
--- /dev/null
+++ b/include/linux/zstd_lib.h
@@ -0,0 +1,2549 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_H_235446
+#define ZSTD_H_235446
+
+/* ====== Dependency ======*/
+#include <linux/types.h> /* size_t */
+
+
+/* ===== ZSTDLIB_API : control library symbols visibility ===== */
+#ifndef ZSTDLIB_VISIBLE
+# if (__GNUC__ >= 4) && !defined(__MINGW32__)
+# define ZSTDLIB_VISIBLE __attribute__ ((visibility ("default")))
+# define ZSTDLIB_HIDDEN __attribute__ ((visibility ("hidden")))
+# else
+# define ZSTDLIB_VISIBLE
+# define ZSTDLIB_HIDDEN
+# endif
+#endif
+#define ZSTDLIB_API ZSTDLIB_VISIBLE
+
+
+/* *****************************************************************************
+ Introduction
+
+ zstd, short for Zstandard, is a fast lossless compression algorithm, targeting
+ real-time compression scenarios at zlib-level and better compression ratios.
+ The zstd compression library provides in-memory compression and decompression
+ functions.
+
+ The library supports regular compression levels from 1 up to ZSTD_maxCLevel(),
+ which is currently 22. Levels >= 20, labeled `--ultra`, should be used with
+ caution, as they require more memory. The library also offers negative
+ compression levels, which extend the range of speed vs. ratio preferences.
+ The lower the level, the faster the speed (at the cost of compression).
+
+ Compression can be done in:
+ - a single step (described as Simple API)
+ - a single step, reusing a context (described as Explicit context)
+ - unbounded multiple steps (described as Streaming compression)
+
+ The compression ratio achievable on small data can be highly improved using
+ a dictionary. Dictionary compression can be performed in:
+ - a single step (described as Simple dictionary API)
+ - a single step, reusing a dictionary (described as Bulk-processing
+ dictionary API)
+
+ Advanced experimental functions can be accessed using
+ `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h.
+
+ Advanced experimental APIs should never be used with a dynamically-linked
+ library. They are not "stable"; their definitions or signatures may change in
+ the future. Only static linking is allowed.
+*******************************************************************************/
+
+/*------ Version ------*/
+#define ZSTD_VERSION_MAJOR 1
+#define ZSTD_VERSION_MINOR 5
+#define ZSTD_VERSION_RELEASE 2
+#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
+
+/*! ZSTD_versionNumber() :
+ * Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */
+ZSTDLIB_API unsigned ZSTD_versionNumber(void);
+
+#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
+#define ZSTD_QUOTE(str) #str
+#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)
+#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
+
+/*! ZSTD_versionString() :
+ * Return runtime library version, like "1.4.5". Requires v1.3.0+. */
+ZSTDLIB_API const char* ZSTD_versionString(void);
+
+/* *************************************
+ * Default constant
+ ***************************************/
+#ifndef ZSTD_CLEVEL_DEFAULT
+# define ZSTD_CLEVEL_DEFAULT 3
+#endif
+
+/* *************************************
+ * Constants
+ ***************************************/
+
+/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */
+#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */
+#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */
+#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */
+#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0
+
+#define ZSTD_BLOCKSIZELOG_MAX 17
+#define ZSTD_BLOCKSIZE_MAX (1<<ZSTD_BLOCKSIZELOG_MAX)
+
+
+/* *************************************
+* Simple API
+***************************************/
+/*! ZSTD_compress() :
+ * Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
+ * Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
+ * @return : compressed size written into `dst` (<= `dstCapacity),
+ * or an error code if it fails (which can be tested using ZSTD_isError()). */
+ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ int compressionLevel);
+
+/*! ZSTD_decompress() :
+ * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.
+ * `dstCapacity` is an upper bound of originalSize to regenerate.
+ * If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data.
+ * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
+ * or an errorCode if it fails (which can be tested using ZSTD_isError()). */
+ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
+ const void* src, size_t compressedSize);
+
+/*! ZSTD_getFrameContentSize() : requires v1.3.0+
+ * `src` should point to the start of a ZSTD encoded frame.
+ * `srcSize` must be at least as large as the frame header.
+ * hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.
+ * @return : - decompressed size of `src` frame content, if known
+ * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
+ * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)
+ * note 1 : a 0 return value means the frame is valid but "empty".
+ * note 2 : decompressed size is an optional field, it may not be present, typically in streaming mode.
+ * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.
+ * In which case, it's necessary to use streaming mode to decompress data.
+ * Optionally, application can rely on some implicit limit,
+ * as ZSTD_decompress() only needs an upper bound of decompressed size.
+ * (For example, data could be necessarily cut into blocks <= 16 KB).
+ * note 3 : decompressed size is always present when compression is completed using single-pass functions,
+ * such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict().
+ * note 4 : decompressed size can be very large (64-bits value),
+ * potentially larger than what local system can handle as a single memory segment.
+ * In which case, it's necessary to use streaming mode to decompress data.
+ * note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified.
+ * Always ensure return value fits within application's authorized limits.
+ * Each application can set its own limits.
+ * note 6 : This function replaces ZSTD_getDecompressedSize() */
+#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)
+#define ZSTD_CONTENTSIZE_ERROR (0ULL - 2)
+ZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);
+
+/*! ZSTD_getDecompressedSize() :
+ * NOTE: This function is now obsolete, in favor of ZSTD_getFrameContentSize().
+ * Both functions work the same way, but ZSTD_getDecompressedSize() blends
+ * "empty", "unknown" and "error" results to the same return value (0),
+ * while ZSTD_getFrameContentSize() gives them separate return values.
+ * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */
+ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
+
+/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+
+ * `src` should point to the start of a ZSTD frame or skippable frame.
+ * `srcSize` must be >= first frame size
+ * @return : the compressed size of the first frame starting at `src`,
+ * suitable to pass as `srcSize` to `ZSTD_decompress` or similar,
+ * or an error code if input is invalid */
+ZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
+
+
+/*====== Helper functions ======*/
+#define ZSTD_COMPRESSBOUND(srcSize) ((srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0)) /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */
+ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */
+ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
+ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
+ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed, requires v1.4.0+ */
+ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
+ZSTDLIB_API int ZSTD_defaultCLevel(void); /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */
+
+
+/* *************************************
+* Explicit context
+***************************************/
+/*= Compression context
+ * When compressing many times,
+ * it is recommended to allocate a context just once,
+ * and re-use it for each successive compression operation.
+ * This will make workload friendlier for system's memory.
+ * Note : re-using context is just a speed / resource optimization.
+ * It doesn't change the compression ratio, which remains identical.
+ * Note 2 : In multi-threaded environments,
+ * use one different context per thread for parallel execution.
+ */
+typedef struct ZSTD_CCtx_s ZSTD_CCtx;
+ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
+ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx); /* accept NULL pointer */
+
+/*! ZSTD_compressCCtx() :
+ * Same as ZSTD_compress(), using an explicit ZSTD_CCtx.
+ * Important : in order to behave similarly to `ZSTD_compress()`,
+ * this function compresses at requested compression level,
+ * __ignoring any other parameter__ .
+ * If any advanced parameter was set using the advanced API,
+ * they will all be reset. Only `compressionLevel` remains.
+ */
+ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ int compressionLevel);
+
+/*= Decompression context
+ * When decompressing many times,
+ * it is recommended to allocate a context only once,
+ * and re-use it for each successive compression operation.
+ * This will make workload friendlier for system's memory.
+ * Use one context per thread for parallel execution. */
+typedef struct ZSTD_DCtx_s ZSTD_DCtx;
+ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
+ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx); /* accept NULL pointer */
+
+/*! ZSTD_decompressDCtx() :
+ * Same as ZSTD_decompress(),
+ * requires an allocated ZSTD_DCtx.
+ * Compatible with sticky parameters.
+ */
+ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize);
+
+
+/* *******************************************
+* Advanced compression API (Requires v1.4.0+)
+**********************************************/
+
+/* API design :
+ * Parameters are pushed one by one into an existing context,
+ * using ZSTD_CCtx_set*() functions.
+ * Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame.
+ * "sticky" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` !
+ * __They do not apply to "simple" one-shot variants such as ZSTD_compressCCtx()__ .
+ *
+ * It's possible to reset all parameters to "default" using ZSTD_CCtx_reset().
+ *
+ * This API supersedes all other "advanced" API entry points in the experimental section.
+ * In the future, we expect to remove from experimental API entry points which are redundant with this API.
+ */
+
+
+/* Compression strategies, listed from fastest to strongest */
+typedef enum { ZSTD_fast=1,
+ ZSTD_dfast=2,
+ ZSTD_greedy=3,
+ ZSTD_lazy=4,
+ ZSTD_lazy2=5,
+ ZSTD_btlazy2=6,
+ ZSTD_btopt=7,
+ ZSTD_btultra=8,
+ ZSTD_btultra2=9
+ /* note : new strategies _might_ be added in the future.
+ Only the order (from fast to strong) is guaranteed */
+} ZSTD_strategy;
+
+typedef enum {
+
+ /* compression parameters
+ * Note: When compressing with a ZSTD_CDict these parameters are superseded
+ * by the parameters used to construct the ZSTD_CDict.
+ * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */
+ ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table.
+ * Note that exact compression parameters are dynamically determined,
+ * depending on both compression level and srcSize (when known).
+ * Default level is ZSTD_CLEVEL_DEFAULT==3.
+ * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.
+ * Note 1 : it's possible to pass a negative compression level.
+ * Note 2 : setting a level does not automatically set all other compression parameters
+ * to default. Setting this will however eventually dynamically impact the compression
+ * parameters which have not been manually set. The manually set
+ * ones will 'stick'. */
+ /* Advanced compression parameters :
+ * It's possible to pin down compression parameters to some specific values.
+ * In which case, these values are no longer dynamically selected by the compressor */
+ ZSTD_c_windowLog=101, /* Maximum allowed back-reference distance, expressed as power of 2.
+ * This will set a memory budget for streaming decompression,
+ * with larger values requiring more memory
+ * and typically compressing more.
+ * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.
+ * Special: value 0 means "use default windowLog".
+ * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT
+ * requires explicitly allowing such size at streaming decompression stage. */
+ ZSTD_c_hashLog=102, /* Size of the initial probe table, as a power of 2.
+ * Resulting memory usage is (1 << (hashLog+2)).
+ * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.
+ * Larger tables improve compression ratio of strategies <= dFast,
+ * and improve speed of strategies > dFast.
+ * Special: value 0 means "use default hashLog". */
+ ZSTD_c_chainLog=103, /* Size of the multi-probe search table, as a power of 2.
+ * Resulting memory usage is (1 << (chainLog+2)).
+ * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX.
+ * Larger tables result in better and slower compression.
+ * This parameter is useless for "fast" strategy.
+ * It's still useful when using "dfast" strategy,
+ * in which case it defines a secondary probe table.
+ * Special: value 0 means "use default chainLog". */
+ ZSTD_c_searchLog=104, /* Number of search attempts, as a power of 2.
+ * More attempts result in better and slower compression.
+ * This parameter is useless for "fast" and "dFast" strategies.
+ * Special: value 0 means "use default searchLog". */
+ ZSTD_c_minMatch=105, /* Minimum size of searched matches.
+ * Note that Zstandard can still find matches of smaller size,
+ * it just tweaks its search algorithm to look for this size and larger.
+ * Larger values increase compression and decompression speed, but decrease ratio.
+ * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX.
+ * Note that currently, for all strategies < btopt, effective minimum is 4.
+ * , for all strategies > fast, effective maximum is 6.
+ * Special: value 0 means "use default minMatchLength". */
+ ZSTD_c_targetLength=106, /* Impact of this field depends on strategy.
+ * For strategies btopt, btultra & btultra2:
+ * Length of Match considered "good enough" to stop search.
+ * Larger values make compression stronger, and slower.
+ * For strategy fast:
+ * Distance between match sampling.
+ * Larger values make compression faster, and weaker.
+ * Special: value 0 means "use default targetLength". */
+ ZSTD_c_strategy=107, /* See ZSTD_strategy enum definition.
+ * The higher the value of selected strategy, the more complex it is,
+ * resulting in stronger and slower compression.
+ * Special: value 0 means "use default strategy". */
+ /* LDM mode parameters */
+ ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.
+ * This parameter is designed to improve compression ratio
+ * for large inputs, by finding large matches at long distance.
+ * It increases memory usage and window size.
+ * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB
+ * except when expressly set to a different value.
+ * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and
+ * compression strategy >= ZSTD_btopt (== compression level 16+) */
+ ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2.
+ * Larger values increase memory usage and compression ratio,
+ * but decrease compression speed.
+ * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX
+ * default: windowlog - 7.
+ * Special: value 0 means "automatically determine hashlog". */
+ ZSTD_c_ldmMinMatch=162, /* Minimum match size for long distance matcher.
+ * Larger/too small values usually decrease compression ratio.
+ * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.
+ * Special: value 0 means "use default value" (default: 64). */
+ ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution.
+ * Larger values improve collision resolution but decrease compression speed.
+ * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX.
+ * Special: value 0 means "use default value" (default: 3). */
+ ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table.
+ * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).
+ * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.
+ * Larger values improve compression speed.
+ * Deviating far from default value will likely result in a compression ratio decrease.
+ * Special: value 0 means "automatically determine hashRateLog". */
+
+ /* frame parameters */
+ ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1)
+ * Content size must be known at the beginning of compression.
+ * This is automatically the case when using ZSTD_compress2(),
+ * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */
+ ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */
+ ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */
+
+ /* multi-threading parameters */
+ /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).
+ * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.
+ * In a situation where it's unknown if the linked library supports multi-threading or not,
+ * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.
+ */
+ ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel.
+ * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :
+ * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,
+ * while compression is performed in parallel, within worker thread(s).
+ * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :
+ * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).
+ * More workers improve speed, but also increase memory usage.
+ * Default value is `0`, aka "single-threaded mode" : no worker is spawned,
+ * compression is performed inside Caller's thread, and all invocations are blocking */
+ ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1.
+ * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.
+ * 0 means default, which is dynamically determined based on compression parameters.
+ * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest.
+ * The minimum size is automatically and transparently enforced. */
+ ZSTD_c_overlapLog=402, /* Control the overlap size, as a fraction of window size.
+ * The overlap size is an amount of data reloaded from previous job at the beginning of a new job.
+ * It helps preserve compression ratio, while each job is compressed in parallel.
+ * This value is enforced only when nbWorkers >= 1.
+ * Larger values increase compression ratio, but decrease speed.
+ * Possible values range from 0 to 9 :
+ * - 0 means "default" : value will be determined by the library, depending on strategy
+ * - 1 means "no overlap"
+ * - 9 means "full overlap", using a full window size.
+ * Each intermediate rank increases/decreases load size by a factor 2 :
+ * 9: full window; 8: w/2; 7: w/4; 6: w/8; 5:w/16; 4: w/32; 3:w/64; 2:w/128; 1:no overlap; 0:default
+ * default value varies between 6 and 9, depending on strategy */
+
+ /* note : additional experimental parameters are also available
+ * within the experimental section of the API.
+ * At the time of this writing, they include :
+ * ZSTD_c_rsyncable
+ * ZSTD_c_format
+ * ZSTD_c_forceMaxWindow
+ * ZSTD_c_forceAttachDict
+ * ZSTD_c_literalCompressionMode
+ * ZSTD_c_targetCBlockSize
+ * ZSTD_c_srcSizeHint
+ * ZSTD_c_enableDedicatedDictSearch
+ * ZSTD_c_stableInBuffer
+ * ZSTD_c_stableOutBuffer
+ * ZSTD_c_blockDelimiters
+ * ZSTD_c_validateSequences
+ * ZSTD_c_useBlockSplitter
+ * ZSTD_c_useRowMatchFinder
+ * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
+ * note : never ever use experimentalParam? names directly;
+ * also, the enums values themselves are unstable and can still change.
+ */
+ ZSTD_c_experimentalParam1=500,
+ ZSTD_c_experimentalParam2=10,
+ ZSTD_c_experimentalParam3=1000,
+ ZSTD_c_experimentalParam4=1001,
+ ZSTD_c_experimentalParam5=1002,
+ ZSTD_c_experimentalParam6=1003,
+ ZSTD_c_experimentalParam7=1004,
+ ZSTD_c_experimentalParam8=1005,
+ ZSTD_c_experimentalParam9=1006,
+ ZSTD_c_experimentalParam10=1007,
+ ZSTD_c_experimentalParam11=1008,
+ ZSTD_c_experimentalParam12=1009,
+ ZSTD_c_experimentalParam13=1010,
+ ZSTD_c_experimentalParam14=1011,
+ ZSTD_c_experimentalParam15=1012
+} ZSTD_cParameter;
+
+typedef struct {
+ size_t error;
+ int lowerBound;
+ int upperBound;
+} ZSTD_bounds;
+
+/*! ZSTD_cParam_getBounds() :
+ * All parameters must belong to an interval with lower and upper bounds,
+ * otherwise they will either trigger an error or be automatically clamped.
+ * @return : a structure, ZSTD_bounds, which contains
+ * - an error status field, which must be tested using ZSTD_isError()
+ * - lower and upper bounds, both inclusive
+ */
+ZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam);
+
+/*! ZSTD_CCtx_setParameter() :
+ * Set one compression parameter, selected by enum ZSTD_cParameter.
+ * All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds().
+ * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
+ * Setting a parameter is generally only possible during frame initialization (before starting compression).
+ * Exception : when using multi-threading mode (nbWorkers >= 1),
+ * the following parameters can be updated _during_ compression (within same frame):
+ * => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.
+ * new parameters will be active for next job only (after a flush()).
+ * @return : an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value);
+
+/*! ZSTD_CCtx_setPledgedSrcSize() :
+ * Total input data size to be compressed as a single frame.
+ * Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag.
+ * This value will also be controlled at end of frame, and trigger an error if not respected.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame.
+ * In order to mean "unknown content size", pass constant ZSTD_CONTENTSIZE_UNKNOWN.
+ * ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame.
+ * Note 2 : pledgedSrcSize is only valid once, for the next frame.
+ * It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN.
+ * Note 3 : Whenever all input data is provided and consumed in a single round,
+ * for example with ZSTD_compress2(),
+ * or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),
+ * this value is automatically overridden by srcSize instead.
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);
+
+typedef enum {
+ ZSTD_reset_session_only = 1,
+ ZSTD_reset_parameters = 2,
+ ZSTD_reset_session_and_parameters = 3
+} ZSTD_ResetDirective;
+
+/*! ZSTD_CCtx_reset() :
+ * There are 2 different things that can be reset, independently or jointly :
+ * - The session : will stop compressing current frame, and make CCtx ready to start a new one.
+ * Useful after an error, or to interrupt any ongoing compression.
+ * Any internal data not yet flushed is cancelled.
+ * Compression parameters and dictionary remain unchanged.
+ * They will be used to compress next frame.
+ * Resetting session never fails.
+ * - The parameters : changes all parameters back to "default".
+ * This removes any reference to any dictionary too.
+ * Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)
+ * otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())
+ * - Both : similar to resetting the session, followed by resetting parameters.
+ */
+ZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);
+
+/*! ZSTD_compress2() :
+ * Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.
+ * ZSTD_compress2() always starts a new frame.
+ * Should cctx hold data from a previously unfinished frame, everything about it is forgotten.
+ * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
+ * - The function is always blocking, returns when compression is completed.
+ * Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
+ * @return : compressed size written into `dst` (<= `dstCapacity),
+ * or an error code if it fails (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize);
+
+
+/* *********************************************
+* Advanced decompression API (Requires v1.4.0+)
+************************************************/
+
+/* The advanced API pushes parameters one by one into an existing DCtx context.
+ * Parameters are sticky, and remain valid for all following frames
+ * using the same DCtx context.
+ * It's possible to reset parameters to default values using ZSTD_DCtx_reset().
+ * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().
+ * Therefore, no new decompression function is necessary.
+ */
+
+typedef enum {
+
+ ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which
+ * the streaming API will refuse to allocate memory buffer
+ * in order to protect the host from unreasonable memory requirements.
+ * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
+ * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).
+ * Special: value 0 means "use default maximum windowLog". */
+
+ /* note : additional experimental parameters are also available
+ * within the experimental section of the API.
+ * At the time of this writing, they include :
+ * ZSTD_d_format
+ * ZSTD_d_stableOutBuffer
+ * ZSTD_d_forceIgnoreChecksum
+ * ZSTD_d_refMultipleDDicts
+ * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
+ * note : never ever use experimentalParam? names directly
+ */
+ ZSTD_d_experimentalParam1=1000,
+ ZSTD_d_experimentalParam2=1001,
+ ZSTD_d_experimentalParam3=1002,
+ ZSTD_d_experimentalParam4=1003
+
+} ZSTD_dParameter;
+
+/*! ZSTD_dParam_getBounds() :
+ * All parameters must belong to an interval with lower and upper bounds,
+ * otherwise they will either trigger an error or be automatically clamped.
+ * @return : a structure, ZSTD_bounds, which contains
+ * - an error status field, which must be tested using ZSTD_isError()
+ * - both lower and upper bounds, inclusive
+ */
+ZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);
+
+/*! ZSTD_DCtx_setParameter() :
+ * Set one compression parameter, selected by enum ZSTD_dParameter.
+ * All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().
+ * Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).
+ * Setting a parameter is only possible during frame initialization (before starting decompression).
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);
+
+/*! ZSTD_DCtx_reset() :
+ * Return a DCtx to clean state.
+ * Session and parameters can be reset jointly or separately.
+ * Parameters can only be reset when no active frame is being decompressed.
+ * @return : 0, or an error code, which can be tested with ZSTD_isError()
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);
+
+
+/* **************************
+* Streaming
+****************************/
+
+typedef struct ZSTD_inBuffer_s {
+ const void* src; /*< start of input buffer */
+ size_t size; /*< size of input buffer */
+ size_t pos; /*< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
+} ZSTD_inBuffer;
+
+typedef struct ZSTD_outBuffer_s {
+ void* dst; /*< start of output buffer */
+ size_t size; /*< size of output buffer */
+ size_t pos; /*< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
+} ZSTD_outBuffer;
+
+
+
+/*-***********************************************************************
+* Streaming compression - HowTo
+*
+* A ZSTD_CStream object is required to track streaming operation.
+* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
+* ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
+* It is recommended to re-use ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.
+*
+* For parallel execution, use one separate ZSTD_CStream per thread.
+*
+* note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.
+*
+* Parameters are sticky : when starting a new compression on the same context,
+* it will re-use the same sticky parameters as previous compression session.
+* When in doubt, it's recommended to fully initialize the context before usage.
+* Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),
+* ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to
+* set more specific parameters, the pledged source size, or load a dictionary.
+*
+* Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to
+* consume input stream. The function will automatically update both `pos`
+* fields within `input` and `output`.
+* Note that the function may not consume the entire input, for example, because
+* the output buffer is already full, in which case `input.pos < input.size`.
+* The caller must check if input has been entirely consumed.
+* If not, the caller must make some room to receive more compressed data,
+* and then present again remaining input data.
+* note: ZSTD_e_continue is guaranteed to make some forward progress when called,
+* but doesn't guarantee maximal forward progress. This is especially relevant
+* when compressing with multiple threads. The call won't block if it can
+* consume some input, but if it can't it will wait for some, but not all,
+* output to be flushed.
+* @return : provides a minimum amount of data remaining to be flushed from internal buffers
+* or an error code, which can be tested using ZSTD_isError().
+*
+* At any moment, it's possible to flush whatever data might remain stuck within internal buffer,
+* using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.
+* Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).
+* In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.
+* You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the
+* operation.
+* note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will
+* block until the flush is complete or the output buffer is full.
+* @return : 0 if internal buffers are entirely flushed,
+* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
+* or an error code, which can be tested using ZSTD_isError().
+*
+* Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.
+* It will perform a flush and write frame epilogue.
+* The epilogue is required for decoders to consider a frame completed.
+* flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.
+* You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to
+* start a new frame.
+* note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will
+* block until the flush is complete or the output buffer is full.
+* @return : 0 if frame fully completed and fully flushed,
+* >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),
+* or an error code, which can be tested using ZSTD_isError().
+*
+* *******************************************************************/
+
+typedef ZSTD_CCtx ZSTD_CStream; /*< CCtx and CStream are now effectively same object (>= v1.3.0) */
+ /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */
+/*===== ZSTD_CStream management functions =====*/
+ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
+ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs); /* accept NULL pointer */
+
+/*===== Streaming compression functions =====*/
+typedef enum {
+ ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */
+ ZSTD_e_flush=1, /* flush any data provided so far,
+ * it creates (at least) one new block, that can be decoded immediately on reception;
+ * frame will continue: any future data can still reference previously compressed data, improving compression.
+ * note : multithreaded compression will block to flush as much output as possible. */
+ ZSTD_e_end=2 /* flush any remaining data _and_ close current frame.
+ * note that frame is only closed after compressed data is fully flushed (return value == 0).
+ * After that point, any additional data starts a new frame.
+ * note : each frame is independent (does not reference any content from previous frame).
+ : note : multithreaded compression will block to flush as much output as possible. */
+} ZSTD_EndDirective;
+
+/*! ZSTD_compressStream2() : Requires v1.4.0+
+ * Behaves about the same as ZSTD_compressStream, with additional control on end directive.
+ * - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()
+ * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)
+ * - output->pos must be <= dstCapacity, input->pos must be <= srcSize
+ * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.
+ * - endOp must be a valid directive
+ * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.
+ * - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,
+ * and then immediately returns, just indicating that there is some data remaining to be flushed.
+ * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.
+ * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.
+ * - @return provides a minimum amount of data remaining to be flushed from internal buffers
+ * or an error code, which can be tested using ZSTD_isError().
+ * if @return != 0, flush is not fully completed, there is still some data left within internal buffers.
+ * This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.
+ * For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.
+ * - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),
+ * only ZSTD_e_end or ZSTD_e_flush operations are allowed.
+ * Before starting a new compression job, or changing compression parameters,
+ * it is required to fully flush internal buffers.
+ */
+ZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,
+ ZSTD_outBuffer* output,
+ ZSTD_inBuffer* input,
+ ZSTD_EndDirective endOp);
+
+
+/* These buffer sizes are softly recommended.
+ * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output.
+ * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(),
+ * reducing the amount of memory shuffling and buffering, resulting in minor performance savings.
+ *
+ * However, note that these recommendations are from the perspective of a C caller program.
+ * If the streaming interface is invoked from some other language,
+ * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo,
+ * a major performance rule is to reduce crossing such interface to an absolute minimum.
+ * It's not rare that performance ends being spent more into the interface, rather than compression itself.
+ * In which cases, prefer using large buffers, as large as practical,
+ * for both input and output, to reduce the nb of roundtrips.
+ */
+ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /*< recommended size for input buffer */
+ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /*< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */
+
+
+/* *****************************************************************************
+ * This following is a legacy streaming API, available since v1.0+ .
+ * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().
+ * It is redundant, but remains fully supported.
+ * Streaming in combination with advanced parameters and dictionary compression
+ * can only be used through the new API.
+ ******************************************************************************/
+
+/*!
+ * Equivalent to:
+ *
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
+ * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
+ */
+ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
+/*!
+ * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).
+ * NOTE: The return value is different. ZSTD_compressStream() returns a hint for
+ * the next read size (if non-zero and not an error). ZSTD_compressStream2()
+ * returns the minimum nb of bytes left to flush (if non-zero and not an error).
+ */
+ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
+/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */
+ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
+/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */
+ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
+
+
+/*-***************************************************************************
+* Streaming decompression - HowTo
+*
+* A ZSTD_DStream object is required to track streaming operations.
+* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
+* ZSTD_DStream objects can be re-used multiple times.
+*
+* Use ZSTD_initDStream() to start a new decompression operation.
+* @return : recommended first input size
+* Alternatively, use advanced API to set specific properties.
+*
+* Use ZSTD_decompressStream() repetitively to consume your input.
+* The function will update both `pos` fields.
+* If `input.pos < input.size`, some input has not been consumed.
+* It's up to the caller to present again remaining data.
+* The function tries to flush all data decoded immediately, respecting output buffer size.
+* If `output.pos < output.size`, decoder has flushed everything it could.
+* But if `output.pos == output.size`, there might be some data left within internal buffers.,
+* In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.
+* Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.
+* @return : 0 when a frame is completely decoded and fully flushed,
+* or an error code, which can be tested using ZSTD_isError(),
+* or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :
+* the return value is a suggested next input size (just a hint for better latency)
+* that will never request more than the remaining frame size.
+* *******************************************************************************/
+
+typedef ZSTD_DCtx ZSTD_DStream; /*< DCtx and DStream are now effectively same object (>= v1.3.0) */
+ /* For compatibility with versions <= v1.2.0, prefer differentiating them. */
+/*===== ZSTD_DStream management functions =====*/
+ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
+ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds); /* accept NULL pointer */
+
+/*===== Streaming decompression functions =====*/
+
+/* This function is redundant with the advanced API and equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
+ * ZSTD_DCtx_refDDict(zds, NULL);
+ */
+ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
+
+ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
+
+ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
+ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
+
+
+/* ************************
+* Simple dictionary API
+***************************/
+/*! ZSTD_compress_usingDict() :
+ * Compression at an explicit compression level using a Dictionary.
+ * A dictionary can be any arbitrary data segment (also called a prefix),
+ * or a buffer with specified information (see zdict.h).
+ * Note : This function loads the dictionary, resulting in significant startup delay.
+ * It's intended for a dictionary used only once.
+ * Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */
+ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize,
+ int compressionLevel);
+
+/*! ZSTD_decompress_usingDict() :
+ * Decompression using a known Dictionary.
+ * Dictionary must be identical to the one used during compression.
+ * Note : This function loads the dictionary, resulting in significant startup delay.
+ * It's intended for a dictionary used only once.
+ * Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
+ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize);
+
+
+/* *********************************
+ * Bulk processing dictionary API
+ **********************************/
+typedef struct ZSTD_CDict_s ZSTD_CDict;
+
+/*! ZSTD_createCDict() :
+ * When compressing multiple messages or blocks using the same dictionary,
+ * it's recommended to digest the dictionary only once, since it's a costly operation.
+ * ZSTD_createCDict() will create a state from digesting a dictionary.
+ * The resulting state can be used for future compression operations with very limited startup cost.
+ * ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.
+ * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict.
+ * Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content.
+ * Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer,
+ * in which case the only thing that it transports is the @compressionLevel.
+ * This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively,
+ * expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */
+ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,
+ int compressionLevel);
+
+/*! ZSTD_freeCDict() :
+ * Function frees memory allocated by ZSTD_createCDict().
+ * If a NULL pointer is passed, no operation is performed. */
+ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
+
+/*! ZSTD_compress_usingCDict() :
+ * Compression using a digested Dictionary.
+ * Recommended when same dictionary is used multiple times.
+ * Note : compression level is _decided at dictionary creation time_,
+ * and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */
+ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict);
+
+
+typedef struct ZSTD_DDict_s ZSTD_DDict;
+
+/*! ZSTD_createDDict() :
+ * Create a digested dictionary, ready to start decompression operation without startup delay.
+ * dictBuffer can be released after DDict creation, as its content is copied inside DDict. */
+ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
+
+/*! ZSTD_freeDDict() :
+ * Function frees memory allocated with ZSTD_createDDict()
+ * If a NULL pointer is passed, no operation is performed. */
+ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
+
+/*! ZSTD_decompress_usingDDict() :
+ * Decompression using a digested Dictionary.
+ * Recommended when same dictionary is used multiple times. */
+ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_DDict* ddict);
+
+
+/* ******************************
+ * Dictionary helper functions
+ *******************************/
+
+/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+
+ * Provides the dictID stored within dictionary.
+ * if @return == 0, the dictionary is not conformant with Zstandard specification.
+ * It can still be loaded, but as a content-only dictionary. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
+
+/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+
+ * Provides the dictID of the dictionary loaded into `cdict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);
+
+/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+
+ * Provides the dictID of the dictionary loaded into `ddict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
+
+/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+
+ * Provides the dictID required to decompressed the frame stored within `src`.
+ * If @return == 0, the dictID could not be decoded.
+ * This could for one of the following reasons :
+ * - The frame does not require a dictionary to be decoded (most common case).
+ * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
+ * Note : this use case also happens when using a non-conformant dictionary.
+ * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
+ * - This is not a Zstandard frame.
+ * When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */
+ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
+
+
+/* *****************************************************************************
+ * Advanced dictionary and prefix API (Requires v1.4.0+)
+ *
+ * This API allows dictionaries to be used with ZSTD_compress2(),
+ * ZSTD_compressStream2(), and ZSTD_decompressDCtx(). Dictionaries are sticky, and
+ * only reset with the context is reset with ZSTD_reset_parameters or
+ * ZSTD_reset_session_and_parameters. Prefixes are single-use.
+ ******************************************************************************/
+
+
+/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+
+ * Create an internal CDict from `dict` buffer.
+ * Decompression will have to use same dictionary.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,
+ * meaning "return to no-dictionary mode".
+ * Note 1 : Dictionary is sticky, it will be used for all future compressed frames.
+ * To return to "no-dictionary" situation, load a NULL dictionary (or reset parameters).
+ * Note 2 : Loading a dictionary involves building tables.
+ * It's also a CPU consuming operation, with non-negligible impact on latency.
+ * Tables are dependent on compression parameters, and for this reason,
+ * compression parameters can no longer be changed after loading a dictionary.
+ * Note 3 :`dict` content will be copied internally.
+ * Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.
+ * In such a case, dictionary buffer must outlive its users.
+ * Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()
+ * to precisely select how dictionary content must be interpreted. */
+ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
+
+/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+
+ * Reference a prepared dictionary, to be used for all next compressed frames.
+ * Note that compression parameters are enforced from within CDict,
+ * and supersede any compression parameter previously set within CCtx.
+ * The parameters ignored are labelled as "superseded-by-cdict" in the ZSTD_cParameter enum docs.
+ * The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.
+ * The dictionary will remain valid for future compressed frames using same CCtx.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special : Referencing a NULL CDict means "return to no-dictionary mode".
+ * Note 1 : Currently, only one dictionary can be managed.
+ * Referencing a new dictionary effectively "discards" any previous one.
+ * Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */
+ZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
+
+/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+
+ * Reference a prefix (single-usage dictionary) for next compressed frame.
+ * A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).
+ * Decompression will need same prefix to properly regenerate data.
+ * Compressing with a prefix is similar in outcome as performing a diff and compressing it,
+ * but performs much faster, especially during decompression (compression speed is tunable with compression level).
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary
+ * Note 1 : Prefix buffer is referenced. It **must** outlive compression.
+ * Its content must remain unmodified during compression.
+ * Note 2 : If the intention is to diff some large src data blob with some prior version of itself,
+ * ensure that the window size is large enough to contain the entire source.
+ * See ZSTD_c_windowLog.
+ * Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.
+ * It's a CPU consuming operation, with non-negligible impact on latency.
+ * If there is a need to use the same prefix multiple times, consider loadDictionary instead.
+ * Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent).
+ * Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */
+ZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,
+ const void* prefix, size_t prefixSize);
+
+/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+
+ * Create an internal DDict from dict buffer,
+ * to be used to decompress next frames.
+ * The dictionary remains valid for all future frames, until explicitly invalidated.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,
+ * meaning "return to no-dictionary mode".
+ * Note 1 : Loading a dictionary involves building tables,
+ * which has a non-negligible impact on CPU usage and latency.
+ * It's recommended to "load once, use many times", to amortize the cost
+ * Note 2 :`dict` content will be copied internally, so `dict` can be released after loading.
+ * Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead.
+ * Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of
+ * how dictionary content is loaded and interpreted.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+
+/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+
+ * Reference a prepared dictionary, to be used to decompress next frames.
+ * The dictionary remains active for decompression of future frames using same DCtx.
+ *
+ * If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function
+ * will store the DDict references in a table, and the DDict used for decompression
+ * will be determined at decompression time, as per the dict ID in the frame.
+ * The memory for the table is allocated on the first call to refDDict, and can be
+ * freed with ZSTD_freeDCtx().
+ *
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : Currently, only one dictionary can be managed.
+ * Referencing a new dictionary effectively "discards" any previous one.
+ * Special: referencing a NULL DDict means "return to no-dictionary mode".
+ * Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
+
+/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+
+ * Reference a prefix (single-usage dictionary) to decompress next frame.
+ * This is the reverse operation of ZSTD_CCtx_refPrefix(),
+ * and must use the same prefix as the one used during compression.
+ * Prefix is **only used once**. Reference is discarded at end of frame.
+ * End of frame is reached when ZSTD_decompressStream() returns 0.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ * Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary
+ * Note 2 : Prefix buffer is referenced. It **must** outlive decompression.
+ * Prefix buffer must remain unmodified up to the end of frame,
+ * reached when ZSTD_decompressStream() returns 0.
+ * Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent).
+ * Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section)
+ * Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.
+ * A full dictionary is more costly, as it requires building tables.
+ */
+ZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,
+ const void* prefix, size_t prefixSize);
+
+/* === Memory management === */
+
+/*! ZSTD_sizeof_*() : Requires v1.4.0+
+ * These functions give the _current_ memory usage of selected object.
+ * Note that object memory usage can evolve (increase or decrease) over time. */
+ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
+ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
+ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
+ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
+ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
+ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
+
+#endif /* ZSTD_H_235446 */
+
+
+/* **************************************************************************************
+ * ADVANCED AND EXPERIMENTAL FUNCTIONS
+ ****************************************************************************************
+ * The definitions in the following section are considered experimental.
+ * They are provided for advanced scenarios.
+ * They should never be used with a dynamic library, as prototypes may change in the future.
+ * Use them only in association with static linking.
+ * ***************************************************************************************/
+
+#if !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
+#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
+
+/* This can be overridden externally to hide static symbols. */
+#ifndef ZSTDLIB_STATIC_API
+#define ZSTDLIB_STATIC_API ZSTDLIB_VISIBLE
+#endif
+
+/* Deprecation warnings :
+ * Should these warnings be a problem, it is generally possible to disable them,
+ * typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual.
+ * Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS.
+ */
+#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API /* disable deprecation warnings */
+#else
+# if (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__)
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __attribute__((deprecated(message)))
+# elif (__GNUC__ >= 3)
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __attribute__((deprecated))
+# else
+# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler")
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API
+# endif
+#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */
+
+/* **************************************************************************************
+ * experimental API (static linking only)
+ ****************************************************************************************
+ * The following symbols and constants
+ * are not planned to join "stable API" status in the near future.
+ * They can still change in future versions.
+ * Some of them are planned to remain in the static_only section indefinitely.
+ * Some of them might be removed in the future (especially when redundant with existing stable functions)
+ * ***************************************************************************************/
+
+#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1) /* minimum input size required to query frame header size */
+#define ZSTD_FRAMEHEADERSIZE_MIN(format) ((format) == ZSTD_f_zstd1 ? 6 : 2)
+#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* can be useful for static allocation */
+#define ZSTD_SKIPPABLEHEADERSIZE 8
+
+/* compression parameter bounds */
+#define ZSTD_WINDOWLOG_MAX_32 30
+#define ZSTD_WINDOWLOG_MAX_64 31
+#define ZSTD_WINDOWLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
+#define ZSTD_WINDOWLOG_MIN 10
+#define ZSTD_HASHLOG_MAX ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30)
+#define ZSTD_HASHLOG_MIN 6
+#define ZSTD_CHAINLOG_MAX_32 29
+#define ZSTD_CHAINLOG_MAX_64 30
+#define ZSTD_CHAINLOG_MAX ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64))
+#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
+#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
+#define ZSTD_SEARCHLOG_MIN 1
+#define ZSTD_MINMATCH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
+#define ZSTD_MINMATCH_MIN 3 /* only for ZSTD_btopt+, faster strategies are limited to 4 */
+#define ZSTD_TARGETLENGTH_MAX ZSTD_BLOCKSIZE_MAX
+#define ZSTD_TARGETLENGTH_MIN 0 /* note : comparing this constant to an unsigned results in a tautological test */
+#define ZSTD_STRATEGY_MIN ZSTD_fast
+#define ZSTD_STRATEGY_MAX ZSTD_btultra2
+
+
+#define ZSTD_OVERLAPLOG_MIN 0
+#define ZSTD_OVERLAPLOG_MAX 9
+
+#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27 /* by default, the streaming decoder will refuse any frame
+ * requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size,
+ * to preserve host's memory from unreasonable requirements.
+ * This limit can be overridden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).
+ * The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */
+
+
+/* LDM parameter bounds */
+#define ZSTD_LDM_HASHLOG_MIN ZSTD_HASHLOG_MIN
+#define ZSTD_LDM_HASHLOG_MAX ZSTD_HASHLOG_MAX
+#define ZSTD_LDM_MINMATCH_MIN 4
+#define ZSTD_LDM_MINMATCH_MAX 4096
+#define ZSTD_LDM_BUCKETSIZELOG_MIN 1
+#define ZSTD_LDM_BUCKETSIZELOG_MAX 8
+#define ZSTD_LDM_HASHRATELOG_MIN 0
+#define ZSTD_LDM_HASHRATELOG_MAX (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)
+
+/* Advanced parameter bounds */
+#define ZSTD_TARGETCBLOCKSIZE_MIN 64
+#define ZSTD_TARGETCBLOCKSIZE_MAX ZSTD_BLOCKSIZE_MAX
+#define ZSTD_SRCSIZEHINT_MIN 0
+
+
+/* --- Advanced types --- */
+
+typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;
+
+typedef struct {
+ unsigned int offset; /* The offset of the match. (NOT the same as the offset code)
+ * If offset == 0 and matchLength == 0, this sequence represents the last
+ * literals in the block of litLength size.
+ */
+
+ unsigned int litLength; /* Literal length of the sequence. */
+ unsigned int matchLength; /* Match length of the sequence. */
+
+ /* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0.
+ * In this case, we will treat the sequence as a marker for a block boundary.
+ */
+
+ unsigned int rep; /* Represents which repeat offset is represented by the field 'offset'.
+ * Ranges from [0, 3].
+ *
+ * Repeat offsets are essentially previous offsets from previous sequences sorted in
+ * recency order. For more detail, see doc/zstd_compression_format.md
+ *
+ * If rep == 0, then 'offset' does not contain a repeat offset.
+ * If rep > 0:
+ * If litLength != 0:
+ * rep == 1 --> offset == repeat_offset_1
+ * rep == 2 --> offset == repeat_offset_2
+ * rep == 3 --> offset == repeat_offset_3
+ * If litLength == 0:
+ * rep == 1 --> offset == repeat_offset_2
+ * rep == 2 --> offset == repeat_offset_3
+ * rep == 3 --> offset == repeat_offset_1 - 1
+ *
+ * Note: This field is optional. ZSTD_generateSequences() will calculate the value of
+ * 'rep', but repeat offsets do not necessarily need to be calculated from an external
+ * sequence provider's perspective. For example, ZSTD_compressSequences() does not
+ * use this 'rep' field at all (as of now).
+ */
+} ZSTD_Sequence;
+
+typedef struct {
+ unsigned windowLog; /*< largest match distance : larger == more compression, more memory needed during decompression */
+ unsigned chainLog; /*< fully searched segment : larger == more compression, slower, more memory (useless for fast) */
+ unsigned hashLog; /*< dispatch table : larger == faster, more memory */
+ unsigned searchLog; /*< nb of searches : larger == more compression, slower */
+ unsigned minMatch; /*< match length searched : larger == faster decompression, sometimes less compression */
+ unsigned targetLength; /*< acceptable match size for optimal parser (only) : larger == more compression, slower */
+ ZSTD_strategy strategy; /*< see ZSTD_strategy definition above */
+} ZSTD_compressionParameters;
+
+typedef struct {
+ int contentSizeFlag; /*< 1: content size will be in frame header (when known) */
+ int checksumFlag; /*< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */
+ int noDictIDFlag; /*< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */
+} ZSTD_frameParameters;
+
+typedef struct {
+ ZSTD_compressionParameters cParams;
+ ZSTD_frameParameters fParams;
+} ZSTD_parameters;
+
+typedef enum {
+ ZSTD_dct_auto = 0, /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
+ ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
+ ZSTD_dct_fullDict = 2 /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */
+} ZSTD_dictContentType_e;
+
+typedef enum {
+ ZSTD_dlm_byCopy = 0, /*< Copy dictionary content internally */
+ ZSTD_dlm_byRef = 1 /*< Reference dictionary content -- the dictionary buffer must outlive its users. */
+} ZSTD_dictLoadMethod_e;
+
+typedef enum {
+ ZSTD_f_zstd1 = 0, /* zstd frame format, specified in zstd_compression_format.md (default) */
+ ZSTD_f_zstd1_magicless = 1 /* Variant of zstd frame format, without initial 4-bytes magic number.
+ * Useful to save 4 bytes per generated frame.
+ * Decoder cannot recognise automatically this format, requiring this instruction. */
+} ZSTD_format_e;
+
+typedef enum {
+ /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */
+ ZSTD_d_validateChecksum = 0,
+ ZSTD_d_ignoreChecksum = 1
+} ZSTD_forceIgnoreChecksum_e;
+
+typedef enum {
+ /* Note: this enum controls ZSTD_d_refMultipleDDicts */
+ ZSTD_rmd_refSingleDDict = 0,
+ ZSTD_rmd_refMultipleDDicts = 1
+} ZSTD_refMultipleDDicts_e;
+
+typedef enum {
+ /* Note: this enum and the behavior it controls are effectively internal
+ * implementation details of the compressor. They are expected to continue
+ * to evolve and should be considered only in the context of extremely
+ * advanced performance tuning.
+ *
+ * Zstd currently supports the use of a CDict in three ways:
+ *
+ * - The contents of the CDict can be copied into the working context. This
+ * means that the compression can search both the dictionary and input
+ * while operating on a single set of internal tables. This makes
+ * the compression faster per-byte of input. However, the initial copy of
+ * the CDict's tables incurs a fixed cost at the beginning of the
+ * compression. For small compressions (< 8 KB), that copy can dominate
+ * the cost of the compression.
+ *
+ * - The CDict's tables can be used in-place. In this model, compression is
+ * slower per input byte, because the compressor has to search two sets of
+ * tables. However, this model incurs no start-up cost (as long as the
+ * working context's tables can be reused). For small inputs, this can be
+ * faster than copying the CDict's tables.
+ *
+ * - The CDict's tables are not used at all, and instead we use the working
+ * context alone to reload the dictionary and use params based on the source
+ * size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict().
+ * This method is effective when the dictionary sizes are very small relative
+ * to the input size, and the input size is fairly large to begin with.
+ *
+ * Zstd has a simple internal heuristic that selects which strategy to use
+ * at the beginning of a compression. However, if experimentation shows that
+ * Zstd is making poor choices, it is possible to override that choice with
+ * this enum.
+ */
+ ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */
+ ZSTD_dictForceAttach = 1, /* Never copy the dictionary. */
+ ZSTD_dictForceCopy = 2, /* Always copy the dictionary. */
+ ZSTD_dictForceLoad = 3 /* Always reload the dictionary */
+} ZSTD_dictAttachPref_e;
+
+typedef enum {
+ ZSTD_lcm_auto = 0, /*< Automatically determine the compression mode based on the compression level.
+ * Negative compression levels will be uncompressed, and positive compression
+ * levels will be compressed. */
+ ZSTD_lcm_huffman = 1, /*< Always attempt Huffman compression. Uncompressed literals will still be
+ * emitted if Huffman compression is not profitable. */
+ ZSTD_lcm_uncompressed = 2 /*< Always emit uncompressed literals. */
+} ZSTD_literalCompressionMode_e;
+
+typedef enum {
+ /* Note: This enum controls features which are conditionally beneficial. Zstd typically will make a final
+ * decision on whether or not to enable the feature (ZSTD_ps_auto), but setting the switch to ZSTD_ps_enable
+ * or ZSTD_ps_disable allow for a force enable/disable the feature.
+ */
+ ZSTD_ps_auto = 0, /* Let the library automatically determine whether the feature shall be enabled */
+ ZSTD_ps_enable = 1, /* Force-enable the feature */
+ ZSTD_ps_disable = 2 /* Do not use the feature */
+} ZSTD_paramSwitch_e;
+
+/* *************************************
+* Frame size functions
+***************************************/
+
+/*! ZSTD_findDecompressedSize() :
+ * `src` should point to the start of a series of ZSTD encoded and/or skippable frames
+ * `srcSize` must be the _exact_ size of this series
+ * (i.e. there should be a frame boundary at `src + srcSize`)
+ * @return : - decompressed size of all data in all successive frames
+ * - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN
+ * - if an error occurred: ZSTD_CONTENTSIZE_ERROR
+ *
+ * note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.
+ * When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.
+ * In which case, it's necessary to use streaming mode to decompress data.
+ * note 2 : decompressed size is always present when compression is done with ZSTD_compress()
+ * note 3 : decompressed size can be very large (64-bits value),
+ * potentially larger than what local system can handle as a single memory segment.
+ * In which case, it's necessary to use streaming mode to decompress data.
+ * note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.
+ * Always ensure result fits within application's authorized limits.
+ * Each application can set its own limits.
+ * note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to
+ * read each contained frame header. This is fast as most of the data is skipped,
+ * however it does mean that all frame data must be present and valid. */
+ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
+
+/*! ZSTD_decompressBound() :
+ * `src` should point to the start of a series of ZSTD encoded and/or skippable frames
+ * `srcSize` must be the _exact_ size of this series
+ * (i.e. there should be a frame boundary at `src + srcSize`)
+ * @return : - upper-bound for the decompressed size of all data in all successive frames
+ * - if an error occurred: ZSTD_CONTENTSIZE_ERROR
+ *
+ * note 1 : an error can occur if `src` contains an invalid or incorrectly formatted frame.
+ * note 2 : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.
+ * in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.
+ * note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
+ * upper-bound = # blocks * min(128 KB, Window_Size)
+ */
+ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
+
+/*! ZSTD_frameHeaderSize() :
+ * srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
+ * @return : size of the Frame Header,
+ * or an error code (if srcSize is too small) */
+ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
+
+typedef enum {
+ ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
+ ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */
+} ZSTD_sequenceFormat_e;
+
+/*! ZSTD_generateSequences() :
+ * Generate sequences using ZSTD_compress2, given a source buffer.
+ *
+ * Each block will end with a dummy sequence
+ * with offset == 0, matchLength == 0, and litLength == length of last literals.
+ * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0)
+ * simply acts as a block delimiter.
+ *
+ * zc can be used to insert custom compression params.
+ * This function invokes ZSTD_compress2
+ *
+ * The output of this function can be fed into ZSTD_compressSequences() with CCtx
+ * setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters
+ * @return : number of sequences generated
+ */
+
+ZSTDLIB_STATIC_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
+ size_t outSeqsSize, const void* src, size_t srcSize);
+
+/*! ZSTD_mergeBlockDelimiters() :
+ * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals
+ * by merging them into the literals of the next sequence.
+ *
+ * As such, the final generated result has no explicit representation of block boundaries,
+ * and the final last literals segment is not represented in the sequences.
+ *
+ * The output of this function can be fed into ZSTD_compressSequences() with CCtx
+ * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters
+ * @return : number of sequences left after merging
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
+
+/*! ZSTD_compressSequences() :
+ * Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst.
+ * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.)
+ * The entire source is compressed into a single frame.
+ *
+ * The compression behavior changes based on cctx params. In particular:
+ * If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain
+ * no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on
+ * the block size derived from the cctx, and sequences may be split. This is the default setting.
+ *
+ * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain
+ * block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided.
+ *
+ * If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined
+ * behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for
+ * specifics regarding offset/matchlength requirements) then the function will bail out and return an error.
+ *
+ * In addition to the two adjustable experimental params, there are other important cctx params.
+ * - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN.
+ * - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression.
+ * - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset
+ * is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md
+ *
+ * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused.
+ * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly,
+ * and cannot emit an RLE block that disagrees with the repcode history
+ * @return : final compressed size or a ZSTD error.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
+ const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
+ const void* src, size_t srcSize);
+
+
+/*! ZSTD_writeSkippableFrame() :
+ * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.
+ *
+ * Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number,
+ * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.
+ * As such, the parameter magicVariant controls the exact skippable frame magic number variant used, so
+ * the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.
+ *
+ * Returns an error if destination buffer is not large enough, if the source size is not representable
+ * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).
+ *
+ * @return : number of bytes written or a ZSTD error.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, unsigned magicVariant);
+
+/*! ZSTD_readSkippableFrame() :
+ * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
+ *
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
+ * in the magicVariant.
+ *
+ * Returns an error if destination buffer is not large enough, or if the frame is not skippable.
+ *
+ * @return : number of bytes written or a ZSTD error.
+ */
+ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
+ const void* src, size_t srcSize);
+
+/*! ZSTD_isSkippableFrame() :
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
+ */
+ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
+
+
+
+/* *************************************
+* Memory management
+***************************************/
+
+/*! ZSTD_estimate*() :
+ * These functions make it possible to estimate memory usage
+ * of a future {D,C}Ctx, before its creation.
+ *
+ * ZSTD_estimateCCtxSize() will provide a memory budget large enough
+ * for any compression level up to selected one.
+ * Note : Unlike ZSTD_estimateCStreamSize*(), this estimate
+ * does not include space for a window buffer.
+ * Therefore, the estimation is only guaranteed for single-shot compressions, not streaming.
+ * The estimate will assume the input may be arbitrarily large,
+ * which is the worst case.
+ *
+ * When srcSize can be bound by a known and rather "small" value,
+ * this fact can be used to provide a tighter estimation
+ * because the CCtx compression context will need less memory.
+ * This tighter estimation can be provided by more advanced functions
+ * ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(),
+ * and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter().
+ * Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits.
+ *
+ * Note 2 : only single-threaded compression is supported.
+ * ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);
+
+/*! ZSTD_estimateCStreamSize() :
+ * ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one.
+ * It will also consider src size to be arbitrarily "large", which is worst case.
+ * If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.
+ * ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.
+ * ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.
+ * Note : CStream size estimation is only correct for single-threaded compression.
+ * ZSTD_DStream memory budget depends on window Size.
+ * This information can be passed manually, using ZSTD_estimateDStreamSize,
+ * or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();
+ * Note : if streaming is init with function ZSTD_init?Stream_usingDict(),
+ * an internal ?Dict will be created, which additional size is not estimated here.
+ * In this case, get total size by adding ZSTD_estimate?DictSize */
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
+
+/*! ZSTD_estimate?DictSize() :
+ * ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict().
+ * ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().
+ * Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
+
+/*! ZSTD_initStatic*() :
+ * Initialize an object using a pre-allocated fixed-size buffer.
+ * workspace: The memory area to emplace the object into.
+ * Provided pointer *must be 8-bytes aligned*.
+ * Buffer must outlive object.
+ * workspaceSize: Use ZSTD_estimate*Size() to determine
+ * how large workspace must be to support target scenario.
+ * @return : pointer to object (same address as workspace, just different type),
+ * or NULL if error (size too small, incorrect alignment, etc.)
+ * Note : zstd will never resize nor malloc() when using a static buffer.
+ * If the object requires more memory than available,
+ * zstd will just error out (typically ZSTD_error_memory_allocation).
+ * Note 2 : there is no corresponding "free" function.
+ * Since workspace is allocated externally, it must be freed externally too.
+ * Note 3 : cParams : use ZSTD_getCParams() to convert a compression level
+ * into its associated cParams.
+ * Limitation 1 : currently not compatible with internal dictionary creation, triggered by
+ * ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict().
+ * Limitation 2 : static cctx currently not compatible with multi-threading.
+ * Limitation 3 : static dctx is incompatible with legacy support.
+ */
+ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
+ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /*< same as ZSTD_initStaticCCtx() */
+
+ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
+ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /*< same as ZSTD_initStaticDCtx() */
+
+ZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict(
+ void* workspace, size_t workspaceSize,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_compressionParameters cParams);
+
+ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict(
+ void* workspace, size_t workspaceSize,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType);
+
+
+/*! Custom memory allocation :
+ * These prototypes make it possible to pass your own allocation/free functions.
+ * ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below.
+ * All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones.
+ */
+typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
+typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
+typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
+static
+__attribute__((__unused__))
+ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /*< this constant defers to stdlib's functions */
+
+ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
+ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
+ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
+ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
+
+ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_compressionParameters cParams,
+ ZSTD_customMem customMem);
+
+/*! Thread pool :
+ * These prototypes make it possible to share a thread pool among multiple compression contexts.
+ * This can limit resources for applications with multiple threads where each one uses
+ * a threaded compression mode (via ZSTD_c_nbWorkers parameter).
+ * ZSTD_createThreadPool creates a new thread pool with a given number of threads.
+ * Note that the lifetime of such pool must exist while being used.
+ * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
+ * to use an internal thread pool).
+ * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
+ */
+typedef struct POOL_ctx_s ZSTD_threadPool;
+ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
+ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
+
+
+/*
+ * This API is temporary and is expected to change or disappear in the future!
+ */
+ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2(
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ const ZSTD_CCtx_params* cctxParams,
+ ZSTD_customMem customMem);
+
+ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced(
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_customMem customMem);
+
+
+/* *************************************
+* Advanced compression functions
+***************************************/
+
+/*! ZSTD_createCDict_byReference() :
+ * Create a digested dictionary for compression
+ * Dictionary content is just referenced, not duplicated.
+ * As a consequence, `dictBuffer` **must** outlive CDict,
+ * and its content must remain unmodified throughout the lifetime of CDict.
+ * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */
+ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
+
+/*! ZSTD_getCParams() :
+ * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
+ * `estimatedSrcSize` value is optional, select 0 if not known */
+ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
+
+/*! ZSTD_getParams() :
+ * same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
+ * All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
+ZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
+
+/*! ZSTD_checkCParams() :
+ * Ensure param values remain within authorized range.
+ * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
+ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
+
+/*! ZSTD_adjustCParams() :
+ * optimize params for a given `srcSize` and `dictSize`.
+ * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.
+ * `dictSize` must be `0` when there is no dictionary.
+ * cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
+ * This function never fails (wide contract) */
+ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
+
+/*! ZSTD_compress_advanced() :
+ * Note : this function is now DEPRECATED.
+ * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.
+ * This prototype will generate compilation warnings. */
+ZSTD_DEPRECATED("use ZSTD_compress2")
+size_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict,size_t dictSize,
+ ZSTD_parameters params);
+
+/*! ZSTD_compress_usingCDict_advanced() :
+ * Note : this function is now DEPRECATED.
+ * It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.
+ * This prototype will generate compilation warnings. */
+ZSTD_DEPRECATED("use ZSTD_compress2 with ZSTD_CCtx_loadDictionary")
+size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_CDict* cdict,
+ ZSTD_frameParameters fParams);
+
+
+/*! ZSTD_CCtx_loadDictionary_byReference() :
+ * Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.
+ * It saves some memory, but also requires that `dict` outlives its usage within `cctx` */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
+
+/*! ZSTD_CCtx_loadDictionary_advanced() :
+ * Same as ZSTD_CCtx_loadDictionary(), but gives finer control over
+ * how to load the dictionary (by copy ? by reference ?)
+ * and how to interpret it (automatic ? force raw mode ? full mode only ?) */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
+
+/*! ZSTD_CCtx_refPrefix_advanced() :
+ * Same as ZSTD_CCtx_refPrefix(), but gives finer control over
+ * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
+
+/* === experimental parameters === */
+/* these parameters can be used with ZSTD_setParameter()
+ * they are not guaranteed to remain supported in the future */
+
+ /* Enables rsyncable mode,
+ * which makes compressed files more rsync friendly
+ * by adding periodic synchronization points to the compressed data.
+ * The target average block size is ZSTD_c_jobSize / 2.
+ * It's possible to modify the job size to increase or decrease
+ * the granularity of the synchronization point.
+ * Once the jobSize is smaller than the window size,
+ * it will result in compression ratio degradation.
+ * NOTE 1: rsyncable mode only works when multithreading is enabled.
+ * NOTE 2: rsyncable performs poorly in combination with long range mode,
+ * since it will decrease the effectiveness of synchronization points,
+ * though mileage may vary.
+ * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s.
+ * If the selected compression level is already running significantly slower,
+ * the overall speed won't be significantly impacted.
+ */
+ #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1
+
+/* Select a compression format.
+ * The value must be of type ZSTD_format_e.
+ * See ZSTD_format_e enum definition for details */
+#define ZSTD_c_format ZSTD_c_experimentalParam2
+
+/* Force back-reference distances to remain < windowSize,
+ * even when referencing into Dictionary content (default:0) */
+#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3
+
+/* Controls whether the contents of a CDict
+ * are used in place, or copied into the working context.
+ * Accepts values from the ZSTD_dictAttachPref_e enum.
+ * See the comments on that enum for an explanation of the feature. */
+#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4
+
+/* Controlled with ZSTD_paramSwitch_e enum.
+ * Default is ZSTD_ps_auto.
+ * Set to ZSTD_ps_disable to never compress literals.
+ * Set to ZSTD_ps_enable to always compress literals. (Note: uncompressed literals
+ * may still be emitted if huffman is not beneficial to use.)
+ *
+ * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use
+ * literals compression based on the compression parameters - specifically,
+ * negative compression levels do not use literal compression.
+ */
+#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
+
+/* Tries to fit compressed block size to be around targetCBlockSize.
+ * No target when targetCBlockSize == 0.
+ * There is no guarantee on compressed block size (default:0) */
+#define ZSTD_c_targetCBlockSize ZSTD_c_experimentalParam6
+
+/* User's best guess of source size.
+ * Hint is not valid when srcSizeHint == 0.
+ * There is no guarantee that hint is close to actual source size,
+ * but compression ratio may regress significantly if guess considerably underestimates */
+#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7
+
+/* Controls whether the new and experimental "dedicated dictionary search
+ * structure" can be used. This feature is still rough around the edges, be
+ * prepared for surprising behavior!
+ *
+ * How to use it:
+ *
+ * When using a CDict, whether to use this feature or not is controlled at
+ * CDict creation, and it must be set in a CCtxParams set passed into that
+ * construction (via ZSTD_createCDict_advanced2()). A compression will then
+ * use the feature or not based on how the CDict was constructed; the value of
+ * this param, set in the CCtx, will have no effect.
+ *
+ * However, when a dictionary buffer is passed into a CCtx, such as via
+ * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control
+ * whether the CDict that is created internally can use the feature or not.
+ *
+ * What it does:
+ *
+ * Normally, the internal data structures of the CDict are analogous to what
+ * would be stored in a CCtx after compressing the contents of a dictionary.
+ * To an approximation, a compression using a dictionary can then use those
+ * data structures to simply continue what is effectively a streaming
+ * compression where the simulated compression of the dictionary left off.
+ * Which is to say, the search structures in the CDict are normally the same
+ * format as in the CCtx.
+ *
+ * It is possible to do better, since the CDict is not like a CCtx: the search
+ * structures are written once during CDict creation, and then are only read
+ * after that, while the search structures in the CCtx are both read and
+ * written as the compression goes along. This means we can choose a search
+ * structure for the dictionary that is read-optimized.
+ *
+ * This feature enables the use of that different structure.
+ *
+ * Note that some of the members of the ZSTD_compressionParameters struct have
+ * different semantics and constraints in the dedicated search structure. It is
+ * highly recommended that you simply set a compression level in the CCtxParams
+ * you pass into the CDict creation call, and avoid messing with the cParams
+ * directly.
+ *
+ * Effects:
+ *
+ * This will only have any effect when the selected ZSTD_strategy
+ * implementation supports this feature. Currently, that's limited to
+ * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2.
+ *
+ * Note that this means that the CDict tables can no longer be copied into the
+ * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be
+ * usable. The dictionary can only be attached or reloaded.
+ *
+ * In general, you should expect compression to be faster--sometimes very much
+ * so--and CDict creation to be slightly slower. Eventually, we will probably
+ * make this mode the default.
+ */
+#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8
+
+/* ZSTD_c_stableInBuffer
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable.
+ *
+ * Tells the compressor that the ZSTD_inBuffer will ALWAYS be the same
+ * between calls, except for the modifications that zstd makes to pos (the
+ * caller must not modify pos). This is checked by the compressor, and
+ * compression will fail if it ever changes. This means the only flush
+ * mode that makes sense is ZSTD_e_end, so zstd will error if ZSTD_e_end
+ * is not used. The data in the ZSTD_inBuffer in the range [src, src + pos)
+ * MUST not be modified during compression or you will get data corruption.
+ *
+ * When this flag is enabled zstd won't allocate an input window buffer,
+ * because the user guarantees it can reference the ZSTD_inBuffer until
+ * the frame is complete. But, it will still allocate an output buffer
+ * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also
+ * avoid the memcpy() from the input buffer to the input window buffer.
+ *
+ * NOTE: ZSTD_compressStream2() will error if ZSTD_e_end is not used.
+ * That means this flag cannot be used with ZSTD_compressStream().
+ *
+ * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using
+ * this flag is ALWAYS memory safe, and will never access out-of-bounds
+ * memory. However, compression WILL fail if you violate the preconditions.
+ *
+ * WARNING: The data in the ZSTD_inBuffer in the range [dst, dst + pos) MUST
+ * not be modified during compression or you will get data corruption. This
+ * is because zstd needs to reference data in the ZSTD_inBuffer to find
+ * matches. Normally zstd maintains its own window buffer for this purpose,
+ * but passing this flag tells zstd to use the user provided buffer.
+ */
+#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9
+
+/* ZSTD_c_stableOutBuffer
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable.
+ *
+ * Tells he compressor that the ZSTD_outBuffer will not be resized between
+ * calls. Specifically: (out.size - out.pos) will never grow. This gives the
+ * compressor the freedom to say: If the compressed data doesn't fit in the
+ * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to
+ * always decompress directly into the output buffer, instead of decompressing
+ * into an internal buffer and copying to the output buffer.
+ *
+ * When this flag is enabled zstd won't allocate an output buffer, because
+ * it can write directly to the ZSTD_outBuffer. It will still allocate the
+ * input window buffer (see ZSTD_c_stableInBuffer).
+ *
+ * Zstd will check that (out.size - out.pos) never grows and return an error
+ * if it does. While not strictly necessary, this should prevent surprises.
+ */
+#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10
+
+/* ZSTD_c_blockDelimiters
+ * Default is 0 == ZSTD_sf_noBlockDelimiters.
+ *
+ * For use with sequence compression API: ZSTD_compressSequences().
+ *
+ * Designates whether or not the given array of ZSTD_Sequence contains block delimiters
+ * and last literals, which are defined as sequences with offset == 0 and matchLength == 0.
+ * See the definition of ZSTD_Sequence for more specifics.
+ */
+#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11
+
+/* ZSTD_c_validateSequences
+ * Default is 0 == disabled. Set to 1 to enable sequence validation.
+ *
+ * For use with sequence compression API: ZSTD_compressSequences().
+ * Designates whether or not we validate sequences provided to ZSTD_compressSequences()
+ * during function execution.
+ *
+ * Without validation, providing a sequence that does not conform to the zstd spec will cause
+ * undefined behavior, and may produce a corrupted block.
+ *
+ * With validation enabled, a if sequence is invalid (see doc/zstd_compression_format.md for
+ * specifics regarding offset/matchlength requirements) then the function will bail out and
+ * return an error.
+ *
+ */
+#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12
+
+/* ZSTD_c_useBlockSplitter
+ * Controlled with ZSTD_paramSwitch_e enum.
+ * Default is ZSTD_ps_auto.
+ * Set to ZSTD_ps_disable to never use block splitter.
+ * Set to ZSTD_ps_enable to always use block splitter.
+ *
+ * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use
+ * block splitting based on the compression parameters.
+ */
+#define ZSTD_c_useBlockSplitter ZSTD_c_experimentalParam13
+
+/* ZSTD_c_useRowMatchFinder
+ * Controlled with ZSTD_paramSwitch_e enum.
+ * Default is ZSTD_ps_auto.
+ * Set to ZSTD_ps_disable to never use row-based matchfinder.
+ * Set to ZSTD_ps_enable to force usage of row-based matchfinder.
+ *
+ * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use
+ * the row-based matchfinder based on support for SIMD instructions and the window log.
+ * Note that this only pertains to compression strategies: greedy, lazy, and lazy2
+ */
+#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14
+
+/* ZSTD_c_deterministicRefPrefix
+ * Default is 0 == disabled. Set to 1 to enable.
+ *
+ * Zstd produces different results for prefix compression when the prefix is
+ * directly adjacent to the data about to be compressed vs. when it isn't.
+ * This is because zstd detects that the two buffers are contiguous and it can
+ * use a more efficient match finding algorithm. However, this produces different
+ * results than when the two buffers are non-contiguous. This flag forces zstd
+ * to always load the prefix in non-contiguous mode, even if it happens to be
+ * adjacent to the data, to guarantee determinism.
+ *
+ * If you really care about determinism when using a dictionary or prefix,
+ * like when doing delta compression, you should select this option. It comes
+ * at a speed penalty of about ~2.5% if the dictionary and data happened to be
+ * contiguous, and is free if they weren't contiguous. We don't expect that
+ * intentionally making the dictionary and data contiguous will be worth the
+ * cost to memcpy() the data.
+ */
+#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15
+
+/*! ZSTD_CCtx_getParameter() :
+ * Get the requested compression parameter value, selected by enum ZSTD_cParameter,
+ * and store it into int* value.
+ * @return : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
+
+
+/*! ZSTD_CCtx_params :
+ * Quick howto :
+ * - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure
+ * - ZSTD_CCtxParams_setParameter() : Push parameters one by one into
+ * an existing ZSTD_CCtx_params structure.
+ * This is similar to
+ * ZSTD_CCtx_setParameter().
+ * - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to
+ * an existing CCtx.
+ * These parameters will be applied to
+ * all subsequent frames.
+ * - ZSTD_compressStream2() : Do compression using the CCtx.
+ * - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer.
+ *
+ * This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
+ * for static allocation of CCtx for single-threaded compression.
+ */
+ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
+ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */
+
+/*! ZSTD_CCtxParams_reset() :
+ * Reset params to default values.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
+
+/*! ZSTD_CCtxParams_init() :
+ * Initializes the compression parameters of cctxParams according to
+ * compression level. All other parameters are reset to their default values.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
+
+/*! ZSTD_CCtxParams_init_advanced() :
+ * Initializes the compression and frame parameters of cctxParams according to
+ * params. All other parameters are reset to their default values.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
+
+/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+
+ * Similar to ZSTD_CCtx_setParameter.
+ * Set one compression parameter, selected by enum ZSTD_cParameter.
+ * Parameters must be applied to a ZSTD_CCtx using
+ * ZSTD_CCtx_setParametersUsingCCtxParams().
+ * @result : a code representing success or failure (which can be tested with
+ * ZSTD_isError()).
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
+
+/*! ZSTD_CCtxParams_getParameter() :
+ * Similar to ZSTD_CCtx_getParameter.
+ * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
+ * @result : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
+
+/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
+ * Apply a set of ZSTD_CCtx_params to the compression context.
+ * This can be done even after compression is started,
+ * if nbWorkers==0, this will have no impact until a new compression is started.
+ * if nbWorkers>=1, new parameters will be picked up at next job,
+ * with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
+ ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
+
+/*! ZSTD_compressStream2_simpleArgs() :
+ * Same as ZSTD_compressStream2(),
+ * but using only integral types as arguments.
+ * This variant might be helpful for binders from dynamic languages
+ * which have troubles handling structures containing memory pointers.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs (
+ ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity, size_t* dstPos,
+ const void* src, size_t srcSize, size_t* srcPos,
+ ZSTD_EndDirective endOp);
+
+
+/* *************************************
+* Advanced decompression functions
+***************************************/
+
+/*! ZSTD_isFrame() :
+ * Tells if the content of `buffer` starts with a valid Frame Identifier.
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
+ * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
+ * Note 3 : Skippable Frame Identifiers are considered valid. */
+ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
+
+/*! ZSTD_createDDict_byReference() :
+ * Create a digested dictionary, ready to start decompression operation without startup delay.
+ * Dictionary content is referenced, and therefore stays in dictBuffer.
+ * It is important that dictBuffer outlives DDict,
+ * it must remain read accessible throughout the lifetime of DDict */
+ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
+
+/*! ZSTD_DCtx_loadDictionary_byReference() :
+ * Same as ZSTD_DCtx_loadDictionary(),
+ * but references `dict` content instead of copying it into `dctx`.
+ * This saves memory if `dict` remains around.,
+ * However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+
+/*! ZSTD_DCtx_loadDictionary_advanced() :
+ * Same as ZSTD_DCtx_loadDictionary(),
+ * but gives direct control over
+ * how to load the dictionary (by copy ? by reference ?)
+ * and how to interpret it (automatic ? force raw mode ? full mode only ?). */
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
+
+/*! ZSTD_DCtx_refPrefix_advanced() :
+ * Same as ZSTD_DCtx_refPrefix(), but gives finer control over
+ * how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
+
+/*! ZSTD_DCtx_setMaxWindowSize() :
+ * Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
+ * This protects a decoder context from reserving too much memory for itself (potential attack scenario).
+ * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.
+ * By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()).
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
+
+/*! ZSTD_DCtx_getParameter() :
+ * Get the requested decompression parameter value, selected by enum ZSTD_dParameter,
+ * and store it into int* value.
+ * @return : 0, or an error code (which can be tested with ZSTD_isError()).
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
+
+/* ZSTD_d_format
+ * experimental parameter,
+ * allowing selection between ZSTD_format_e input compression formats
+ */
+#define ZSTD_d_format ZSTD_d_experimentalParam1
+/* ZSTD_d_stableOutBuffer
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable.
+ *
+ * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same
+ * between calls, except for the modifications that zstd makes to pos (the
+ * caller must not modify pos). This is checked by the decompressor, and
+ * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer
+ * MUST be large enough to fit the entire decompressed frame. This will be
+ * checked when the frame content size is known. The data in the ZSTD_outBuffer
+ * in the range [dst, dst + pos) MUST not be modified during decompression
+ * or you will get data corruption.
+ *
+ * When this flags is enabled zstd won't allocate an output buffer, because
+ * it can write directly to the ZSTD_outBuffer, but it will still allocate
+ * an input buffer large enough to fit any compressed block. This will also
+ * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer.
+ * If you need to avoid the input buffer allocation use the buffer-less
+ * streaming API.
+ *
+ * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using
+ * this flag is ALWAYS memory safe, and will never access out-of-bounds
+ * memory. However, decompression WILL fail if you violate the preconditions.
+ *
+ * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST
+ * not be modified during decompression or you will get data corruption. This
+ * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate
+ * matches. Normally zstd maintains its own buffer for this purpose, but passing
+ * this flag tells zstd to use the user provided buffer.
+ */
+#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2
+
+/* ZSTD_d_forceIgnoreChecksum
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable
+ *
+ * Tells the decompressor to skip checksum validation during decompression, regardless
+ * of whether checksumming was specified during compression. This offers some
+ * slight performance benefits, and may be useful for debugging.
+ * Param has values of type ZSTD_forceIgnoreChecksum_e
+ */
+#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3
+
+/* ZSTD_d_refMultipleDDicts
+ * Experimental parameter.
+ * Default is 0 == disabled. Set to 1 to enable
+ *
+ * If enabled and dctx is allocated on the heap, then additional memory will be allocated
+ * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict()
+ * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead
+ * store all references. At decompression time, the appropriate dictID is selected
+ * from the set of DDicts based on the dictID in the frame.
+ *
+ * Usage is simply calling ZSTD_refDDict() on multiple dict buffers.
+ *
+ * Param has values of byte ZSTD_refMultipleDDicts_e
+ *
+ * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory
+ * allocation for the hash table. ZSTD_freeDCtx() also frees this memory.
+ * Memory is allocated as per ZSTD_DCtx::customMem.
+ *
+ * Although this function allocates memory for the table, the user is still responsible for
+ * memory management of the underlying ZSTD_DDict* themselves.
+ */
+#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4
+
+
+/*! ZSTD_DCtx_setFormat() :
+ * This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().
+ * Instruct the decoder context about what kind of data to decode next.
+ * This instruction is mandatory to decode data without a fully-formed header,
+ * such ZSTD_f_zstd1_magicless for example.
+ * @return : 0, or an error code (which can be tested using ZSTD_isError()). */
+ZSTD_DEPRECATED("use ZSTD_DCtx_setParameter() instead")
+size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
+
+/*! ZSTD_decompressStream_simpleArgs() :
+ * Same as ZSTD_decompressStream(),
+ * but using only integral types as arguments.
+ * This can be helpful for binders from dynamic languages
+ * which have troubles handling structures containing memory pointers.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs (
+ ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity, size_t* dstPos,
+ const void* src, size_t srcSize, size_t* srcPos);
+
+
+/* ******************************************************************
+* Advanced streaming functions
+* Warning : most of these functions are now redundant with the Advanced API.
+* Once Advanced API reaches "stable" status,
+* redundant functions will be deprecated, and then at some point removed.
+********************************************************************/
+
+/*===== Advanced Streaming compression functions =====*/
+
+/*! ZSTD_initCStream_srcSize() :
+ * This function is DEPRECATED, and equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)
+ * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ *
+ * pledgedSrcSize must be correct. If it is not known at init time, use
+ * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,
+ * "0" also disables frame content size field. It may be enabled in the future.
+ * This prototype will generate compilation warnings.
+ */
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,
+ int compressionLevel,
+ unsigned long long pledgedSrcSize);
+
+/*! ZSTD_initCStream_usingDict() :
+ * This function is DEPRECATED, and is equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);
+ * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
+ *
+ * Creates of an internal CDict (incompatible with static CCtx), except if
+ * dict == NULL or dictSize < 8, in which case no dict is used.
+ * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if
+ * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.
+ * This prototype will generate compilation warnings.
+ */
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,
+ const void* dict, size_t dictSize,
+ int compressionLevel);
+
+/*! ZSTD_initCStream_advanced() :
+ * This function is DEPRECATED, and is approximately equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * // Pseudocode: Set each zstd parameter and leave the rest as-is.
+ * for ((param, value) : params) {
+ * ZSTD_CCtx_setParameter(zcs, param, value);
+ * }
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ * ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);
+ *
+ * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.
+ * pledgedSrcSize must be correct.
+ * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.
+ * This prototype will generate compilation warnings.
+ */
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
+ const void* dict, size_t dictSize,
+ ZSTD_parameters params,
+ unsigned long long pledgedSrcSize);
+
+/*! ZSTD_initCStream_usingCDict() :
+ * This function is DEPRECATED, and equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_refCDict(zcs, cdict);
+ *
+ * note : cdict will just be referenced, and must outlive compression session
+ * This prototype will generate compilation warnings.
+ */
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);
+
+/*! ZSTD_initCStream_usingCDict_advanced() :
+ * This function is DEPRECATED, and is approximately equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * // Pseudocode: Set each zstd frame parameter and leave the rest as-is.
+ * for ((fParam, value) : fParams) {
+ * ZSTD_CCtx_setParameter(zcs, fParam, value);
+ * }
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ * ZSTD_CCtx_refCDict(zcs, cdict);
+ *
+ * same as ZSTD_initCStream_usingCDict(), with control over frame parameters.
+ * pledgedSrcSize must be correct. If srcSize is not known at init time, use
+ * value ZSTD_CONTENTSIZE_UNKNOWN.
+ * This prototype will generate compilation warnings.
+ */
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions")
+size_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,
+ const ZSTD_CDict* cdict,
+ ZSTD_frameParameters fParams,
+ unsigned long long pledgedSrcSize);
+
+/*! ZSTD_resetCStream() :
+ * This function is DEPRECATED, and is equivalent to:
+ * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
+ * ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);
+ * Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but
+ * ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be
+ * explicitly specified.
+ *
+ * start a new frame, using same parameters from previous frame.
+ * This is typically useful to skip dictionary loading stage, since it will re-use it in-place.
+ * Note that zcs must be init at least once before using ZSTD_resetCStream().
+ * If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.
+ * If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.
+ * For the time being, pledgedSrcSize==0 is interpreted as "srcSize unknown" for compatibility with older programs,
+ * but it will change to mean "empty" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.
+ * @return : 0, or an error code (which can be tested using ZSTD_isError())
+ * This prototype will generate compilation warnings.
+ */
+ZSTD_DEPRECATED("use ZSTD_CCtx_reset, see zstd.h for detailed instructions")
+size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);
+
+
+typedef struct {
+ unsigned long long ingested; /* nb input bytes read and buffered */
+ unsigned long long consumed; /* nb input bytes actually compressed */
+ unsigned long long produced; /* nb of compressed bytes generated and buffered */
+ unsigned long long flushed; /* nb of compressed bytes flushed : not provided; can be tracked from caller side */
+ unsigned currentJobID; /* MT only : latest started job nb */
+ unsigned nbActiveWorkers; /* MT only : nb of workers actively compressing at probe time */
+} ZSTD_frameProgression;
+
+/* ZSTD_getFrameProgression() :
+ * tells how much data has been ingested (read from input)
+ * consumed (input actually compressed) and produced (output) for current frame.
+ * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed.
+ * Aggregates progression inside active worker threads.
+ */
+ZSTDLIB_STATIC_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
+
+/*! ZSTD_toFlushNow() :
+ * Tell how many bytes are ready to be flushed immediately.
+ * Useful for multithreading scenarios (nbWorkers >= 1).
+ * Probe the oldest active job, defined as oldest job not yet entirely flushed,
+ * and check its output buffer.
+ * @return : amount of data stored in oldest job and ready to be flushed immediately.
+ * if @return == 0, it means either :
+ * + there is no active job (could be checked with ZSTD_frameProgression()), or
+ * + oldest job is still actively compressing data,
+ * but everything it has produced has also been flushed so far,
+ * therefore flush speed is limited by production speed of oldest job
+ * irrespective of the speed of concurrent (and newer) jobs.
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
+
+
+/*===== Advanced Streaming decompression functions =====*/
+
+/*!
+ * This function is deprecated, and is equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
+ * ZSTD_DCtx_loadDictionary(zds, dict, dictSize);
+ *
+ * note: no dictionary will be used if dict == NULL or dictSize < 8
+ * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
+
+/*!
+ * This function is deprecated, and is equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
+ * ZSTD_DCtx_refDDict(zds, ddict);
+ *
+ * note : ddict is referenced, it must outlive decompression session
+ * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
+
+/*!
+ * This function is deprecated, and is equivalent to:
+ *
+ * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);
+ *
+ * re-use decompression parameters from previous init; saves dictionary loading
+ * Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
+ */
+ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
+
+
+/* *******************************************************************
+* Buffer-less and synchronous inner streaming functions
+*
+* This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
+* But it's also a complex one, with several restrictions, documented below.
+* Prefer normal streaming API for an easier experience.
+********************************************************************* */
+
+/*
+ Buffer-less streaming compression (synchronous mode)
+
+ A ZSTD_CCtx object is required to track streaming operations.
+ Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
+ ZSTD_CCtx object can be re-used multiple times within successive compression operations.
+
+ Start by initializing a context.
+ Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.
+ It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx()
+
+ Then, consume your input using ZSTD_compressContinue().
+ There are some important considerations to keep in mind when using this advanced function :
+ - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only.
+ - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks.
+ - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario.
+ Worst case evaluation is provided by ZSTD_compressBound().
+ ZSTD_compressContinue() doesn't guarantee recover after a failed compression.
+ - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog).
+ It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks)
+ - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps.
+ In which case, it will "discard" the relevant memory section from its history.
+
+ Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.
+ It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.
+ Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.
+
+ `ZSTD_CCtx` object can be re-used (ZSTD_compressBegin()) to compress again.
+*/
+
+/*===== Buffer-less streaming compression functions =====*/
+ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /*< note: fails if cdict==NULL */
+ZSTDLIB_STATIC_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /*< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
+
+ZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+
+/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */
+ZSTD_DEPRECATED("use advanced API to access custom parameters")
+size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /*< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */
+ZSTD_DEPRECATED("use advanced API to access custom parameters")
+size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize); /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
+/*
+ Buffer-less streaming decompression (synchronous mode)
+
+ A ZSTD_DCtx object is required to track streaming operations.
+ Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
+ A ZSTD_DCtx object can be re-used multiple times.
+
+ First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().
+ Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.
+ Data fragment must be large enough to ensure successful decoding.
+ `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.
+ @result : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.
+ >0 : `srcSize` is too small, please provide at least @result bytes on next attempt.
+ errorCode, which can be tested using ZSTD_isError().
+
+ It fills a ZSTD_frameHeader structure with important information to correctly decode the frame,
+ such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`).
+ Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information.
+ As a consequence, check that values remain within valid application range.
+ For example, do not allocate memory blindly, check that `windowSize` is within expectation.
+ Each application can set its own limits, depending on local restrictions.
+ For extended interoperability, it is recommended to support `windowSize` of at least 8 MB.
+
+ ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes.
+ ZSTD_decompressContinue() is very sensitive to contiguity,
+ if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,
+ or that previous contiguous segment is large enough to properly handle maximum back-reference distance.
+ There are multiple ways to guarantee this condition.
+
+ The most memory efficient way is to use a round buffer of sufficient size.
+ Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(),
+ which can @return an error code if required value is too large for current system (in 32-bits mode).
+ In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one,
+ up to the moment there is not enough room left in the buffer to guarantee decoding another full block,
+ which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`.
+ At which point, decoding can resume from the beginning of the buffer.
+ Note that already decoded data stored in the buffer should be flushed before being overwritten.
+
+ There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory.
+
+ Finally, if you control the compression process, you can also ignore all buffer size rules,
+ as long as the encoder and decoder progress in "lock-step",
+ aka use exactly the same buffer sizes, break contiguity at the same place, etc.
+
+ Once buffers are setup, start decompression, with ZSTD_decompressBegin().
+ If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict().
+
+ Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.
+ ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().
+ ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.
+
+ @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
+ It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item.
+ It can also be an error code, which can be tested with ZSTD_isError().
+
+ A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.
+ Context can then be reset to start a new decompression.
+
+ Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType().
+ This information is not required to properly decode a frame.
+
+ == Special case : skippable frames ==
+
+ Skippable frames allow integration of user-defined data into a flow of concatenated frames.
+ Skippable frames will be ignored (skipped) by decompressor.
+ The format of skippable frames is as follows :
+ a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F
+ b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
+ c) Frame Content - any content (User Data) of length equal to Frame Size
+ For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame.
+ For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content.
+*/
+
+/*===== Buffer-less streaming decompression functions =====*/
+typedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_frameType_e;
+typedef struct {
+ unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means "empty" */
+ unsigned long long windowSize; /* can be very large, up to <= frameContentSize */
+ unsigned blockSizeMax;
+ ZSTD_frameType_e frameType; /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */
+ unsigned headerSize;
+ unsigned dictID;
+ unsigned checksumFlag;
+} ZSTD_frameHeader;
+
+/*! ZSTD_getFrameHeader() :
+ * decode Frame Header, or requires larger `srcSize`.
+ * @return : 0, `zfhPtr` is correctly filled,
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
+ * or an error code, which can be tested using ZSTD_isError() */
+ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /*< doesn't consume input */
+/*! ZSTD_getFrameHeader_advanced() :
+ * same as ZSTD_getFrameHeader(),
+ * with added capability to select a format (like ZSTD_f_zstd1_magicless) */
+ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
+ZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /*< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
+
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
+
+ZSTDLIB_STATIC_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+
+/* misc */
+ZSTDLIB_STATIC_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
+typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
+ZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
+
+
+
+
+/* ============================ */
+/* Block level API */
+/* ============================ */
+
+/*!
+ Block functions produce and decode raw zstd blocks, without frame metadata.
+ Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes).
+ But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes.
+
+ A few rules to respect :
+ - Compressing and decompressing require a context structure
+ + Use ZSTD_createCCtx() and ZSTD_createDCtx()
+ - It is necessary to init context before starting
+ + compression : any ZSTD_compressBegin*() variant, including with dictionary
+ + decompression : any ZSTD_decompressBegin*() variant, including with dictionary
+ + copyCCtx() and copyDCtx() can be used too
+ - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB
+ + If input is larger than a block size, it's necessary to split input data into multiple blocks
+ + For inputs larger than a single block, consider using regular ZSTD_compress() instead.
+ Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block.
+ - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) !
+ ===> In which case, nothing is produced into `dst` !
+ + User __must__ test for such outcome and deal directly with uncompressed data
+ + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0.
+ Doing so would mess up with statistics history, leading to potential data corruption.
+ + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !!
+ + In case of multiple successive blocks, should some of them be uncompressed,
+ decoder must be informed of their existence in order to follow proper history.
+ Use ZSTD_insertBlock() for such a case.
+*/
+
+/*===== Raw zstd block functions =====*/
+ZSTDLIB_STATIC_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
+ZSTDLIB_STATIC_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /*< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
+
+
+#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
+
diff --git a/include/menu.h b/include/menu.h
index 702aacb..1e88141 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -6,6 +6,7 @@
#ifndef __MENU_H__
#define __MENU_H__
+struct cli_ch_state;
struct menu;
struct menu *menu_create(char *title, int timeout, int prompt,
@@ -42,20 +43,72 @@
struct bootmenu_entry *first; /* first menu entry */
};
+/** enum bootmenu_key - keys that can be returned by the bootmenu */
enum bootmenu_key {
- KEY_NONE = 0,
- KEY_UP,
- KEY_DOWN,
- KEY_SELECT,
- KEY_QUIT,
- KEY_PLUS,
- KEY_MINUS,
- KEY_SPACE,
+ BKEY_NONE = 0,
+ BKEY_UP,
+ BKEY_DOWN,
+ BKEY_SELECT,
+ BKEY_QUIT,
+ BKEY_PLUS,
+ BKEY_MINUS,
+ BKEY_SPACE,
+
+ BKEY_COUNT,
};
-void bootmenu_autoboot_loop(struct bootmenu_data *menu,
- enum bootmenu_key *key, int *esc);
-void bootmenu_loop(struct bootmenu_data *menu,
- enum bootmenu_key *key, int *esc);
+/**
+ * bootmenu_autoboot_loop() - handle autobooting if no key is pressed
+ *
+ * This shows a prompt to allow the user to press a key to interrupt auto boot
+ * of the first menu option.
+ *
+ * It then waits for the required time (menu->delay in seconds) for a key to be
+ * pressed. If nothing is pressed in that time, @key returns KEY_SELECT
+ * indicating that the current option should be chosen.
+ *
+ * @menu: Menu being processed
+ * @esc: Set to 1 if the escape key is pressed, otherwise not updated
+ * Returns: code for the key the user pressed:
+ * enter: KEY_SELECT
+ * Ctrl-C: KEY_QUIT
+ * anything else: KEY_NONE
+ */
+enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu,
+ struct cli_ch_state *cch);
+
+/**
+ * bootmenu_loop() - handle waiting for a keypress when autoboot is disabled
+ *
+ * This is used when the menu delay is negative, indicating that the delay has
+ * elapsed, or there was no delay to begin with.
+ *
+ * It reads a character and processes it, returning a menu-key code if a
+ * character is recognised
+ *
+ * @menu: Menu being processed
+ * @esc: On input, a non-zero value indicates that an escape sequence has
+ * resulted in that many characters so far. On exit this is updated to the
+ * new number of characters
+ * Returns: code for the key the user pressed:
+ * enter: BKEY_SELECT
+ * Ctrl-C: BKEY_QUIT
+ * Up arrow: BKEY_UP
+ * Down arrow: BKEY_DOWN
+ * Escape (by itself): BKEY_QUIT
+ * Plus: BKEY_PLUS
+ * Minus: BKEY_MINUS
+ * Space: BKEY_SPACE
+ */
+enum bootmenu_key bootmenu_loop(struct bootmenu_data *menu,
+ struct cli_ch_state *cch);
+
+/**
+ * bootmenu_conv_key() - Convert a U-Boot keypress into a menu key
+ *
+ * @ichar: Keypress to convert (ASCII, including control characters)
+ * Returns: Menu key that corresponds to @ichar, or BKEY_NONE if none
+ */
+enum bootmenu_key bootmenu_conv_key(int ichar);
#endif /* __MENU_H__ */
diff --git a/include/net.h b/include/net.h
index ee08f33..399af5e 100644
--- a/include/net.h
+++ b/include/net.h
@@ -66,6 +66,21 @@
int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
/**
+ * dhcp_run() - Run DHCP on the current ethernet device
+ *
+ * This sets the autoload variable, then puts it back to similar to its original
+ * state (y, n or unset).
+ *
+ * @addr: Address to load the file into (0 if @autoload is false)
+ * @fname: Filename of file to load (NULL if @autoload is false or to use the
+ * default filename)
+ * @autoload: true to load the file, false to just get the network IP
+ * @return 0 if OK, -EINVAL if the environment failed, -ENOENT if ant file was
+ * not found
+ */
+int dhcp_run(ulong addr, const char *fname, bool autoload);
+
+/**
* An incoming packet handler.
* @param pkt pointer to the application packet
* @param dport destination UDP port
@@ -886,4 +901,20 @@
*/
void reset_phy(void);
+#if CONFIG_IS_ENABLED(NET)
+/**
+ * eth_set_enable_bootdevs() - Enable or disable binding of Ethernet bootdevs
+ *
+ * These get in the way of bootstd testing, so are normally disabled by tests.
+ * This provide control of this setting. It only affects binding of Ethernet
+ * devices, so if that has already happened, this flag does nothing.
+ *
+ * @enable: true to enable binding of bootdevs when binding new Ethernet
+ * devices, false to disable it
+ */
+void eth_set_enable_bootdevs(bool enable);
+#else
+static inline void eth_set_enable_bootdevs(bool enable) {}
+#endif
+
#endif /* __NET_H__ */
diff --git a/include/ns16550.h b/include/ns16550.h
index 243226f..e7e6866 100644
--- a/include/ns16550.h
+++ b/include/ns16550.h
@@ -26,15 +26,13 @@
#include <linux/types.h>
-#if CONFIG_IS_ENABLED(DM_SERIAL) && !defined(CONFIG_SYS_NS16550_REG_SIZE)
+#if CONFIG_IS_ENABLED(DM_SERIAL) || defined(CONFIG_NS16550_DYNAMIC) || \
+ defined(CONFIG_DEBUG_UART)
/*
* For driver model we always use one byte per register, and sort out the
- * differences in the driver
+ * differences in the driver. In the case of CONFIG_NS16550_DYNAMIC we do
+ * similar, and CONFIG_DEBUG_UART is responsible for shifts in its own manner.
*/
-#define CONFIG_SYS_NS16550_REG_SIZE (-1)
-#endif
-
-#if defined(CONFIG_NS16550_DYNAMIC) || defined(CONFIG_DEBUG_UART)
#define UART_REG(x) unsigned char x
#else
#if !defined(CONFIG_SYS_NS16550_REG_SIZE) || (CONFIG_SYS_NS16550_REG_SIZE == 0)
diff --git a/include/part.h b/include/part.h
index 807370d..be75c73 100644
--- a/include/part.h
+++ b/include/part.h
@@ -303,6 +303,14 @@
}
#endif
+/**
+ * part_get_bootable() - Find the first bootable partition
+ *
+ * @desc: Block-device descriptor
+ * @return first bootable partition, or 0 if there is none
+ */
+int part_get_bootable(struct blk_desc *desc);
+
struct udevice;
/**
* part_create_block_devices - Create block devices for disk partitions
diff --git a/include/rc4.h b/include/rc4.h
index c1ff134..d1257f2 100644
--- a/include/rc4.h
+++ b/include/rc4.h
@@ -15,6 +15,6 @@
* @len: Length of buffer in bytes
* @key: 16-byte key to use
*/
-void rc4_encode(unsigned char *buf, unsigned int len, unsigned char key[16]);
+void rc4_encode(unsigned char *buf, unsigned int len, const unsigned char key[16]);
#endif
diff --git a/include/test/suites.h b/include/test/suites.h
index a01000e..9ce49cb 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -38,6 +38,7 @@
char *const argv[]);
int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_exit(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
diff --git a/include/test/test.h b/include/test/test.h
index 4ad7461..838e3ce 100644
--- a/include/test/test.h
+++ b/include/test/test.h
@@ -71,6 +71,8 @@
* since it cannot access the flags.
*/
UT_TESTF_MANUAL = BIT(8),
+ UT_TESTF_ETH_BOOTDEV = BIT(9), /* enable Ethernet bootdevs */
+ UT_TESTF_SF_BOOTDEV = BIT(10), /* enable SPI flash bootdevs */
};
/**
@@ -169,4 +171,74 @@
return ret;
}
+/**
+ * Control skipping of time delays
+ *
+ * Some tests have unnecessay time delays (e.g. USB). Allow these to be
+ * skipped to speed up testing
+ *
+ * @param skip_delays true to skip delays from now on, false to honour delay
+ * requests
+ */
+static inline void test_set_skip_delays(bool skip_delays)
+{
+#ifdef CONFIG_SANDBOX
+ state_set_skip_delays(skip_delays);
+#endif
+}
+
+/**
+ * test_set_eth_enable() - Enable / disable Ethernet
+ *
+ * Allows control of whether Ethernet packets are actually send/received
+ *
+ * @enable: true to enable Ethernet, false to disable
+ */
+static inline void test_set_eth_enable(bool enable)
+{
+#ifdef CONFIG_SANDBOX
+ sandbox_set_eth_enable(enable);
+#endif
+}
+
+/* Allow ethernet to be disabled for testing purposes */
+static inline bool test_eth_enabled(void)
+{
+ bool enabled = true;
+
+#ifdef CONFIG_SANDBOX
+ enabled = sandbox_eth_enabled();
+#endif
+ return enabled;
+}
+
+/* Allow ethernet bootdev to be ignored for testing purposes */
+static inline bool test_eth_bootdev_enabled(void)
+{
+ bool enabled = true;
+
+#ifdef CONFIG_SANDBOX
+ enabled = sandbox_eth_enabled();
+#endif
+ return enabled;
+}
+
+/* Allow SPI flash bootdev to be ignored for testing purposes */
+static inline bool test_sf_bootdev_enabled(void)
+{
+ bool enabled = true;
+
+#ifdef CONFIG_SANDBOX
+ enabled = sandbox_sf_bootdev_enabled();
+#endif
+ return enabled;
+}
+
+static inline void test_sf_set_enable_bootdevs(bool enable)
+{
+#ifdef CONFIG_SANDBOX
+ sandbox_sf_set_enable_bootdevs(enable);
+#endif
+}
+
#endif /* __TEST_TEST_H */
diff --git a/include/usb/ulpi.h b/include/usb/ulpi.h
index 71642d2..126623c 100644
--- a/include/usb/ulpi.h
+++ b/include/usb/ulpi.h
@@ -20,8 +20,8 @@
#define ULPI_ERROR (1 << 8) /* overflow from any register value */
-#ifndef CONFIG_USB_ULPI_TIMEOUT
-#define CONFIG_USB_ULPI_TIMEOUT 1000 /* timeout in us */
+#ifndef CFG_USB_ULPI_TIMEOUT
+#define CFG_USB_ULPI_TIMEOUT 1000 /* timeout in us */
#endif
/*
diff --git a/include/video.h b/include/video.h
index 43f2e2c..3f67a93 100644
--- a/include/video.h
+++ b/include/video.h
@@ -248,7 +248,7 @@
* that direction
* - if a coordinate is -ve then it will be offset to the
* left/top of the centre by that many pixels
- * - if a coordinate is positive it will be used unchnaged.
+ * - if a coordinate is positive it will be used unchanged.
* Return: 0 if OK, -ve on error
*/
int video_bmp_display(struct udevice *dev, ulong bmp_image, int x, int y,
diff --git a/include/video_console.h b/include/video_console.h
index d755eb7..9d2c0f2 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -63,6 +63,15 @@
};
/**
+ * struct vidfont_info - information about a font
+ *
+ * @name: Font name, e.g. nimbus_sans_l_regular
+ */
+struct vidfont_info {
+ const char *name;
+};
+
+/**
* struct vidconsole_ops - Video console operations
*
* These operations work on either an absolute console position (measured
@@ -111,6 +120,9 @@
/**
* entry_start() - Indicate that text entry is starting afresh
*
+ * @dev: Device to adjust
+ * Returns: 0 on success, -ve on error
+ *
* Consoles which use proportional fonts need to track the position of
* each character output so that backspace will return to the correct
* place. This method signals to the console driver that a new entry
@@ -123,6 +135,9 @@
/**
* backspace() - Handle erasing the last character
*
+ * @dev: Device to adjust
+ * Returns: 0 on success, -ve on error
+ *
* With proportional fonts the vidconsole uclass cannot itself erase
* the previous character. This optional method will be called when
* a backspace is needed. The driver should erase the previous
@@ -133,12 +148,54 @@
* characters.
*/
int (*backspace)(struct udevice *dev);
+
+ /**
+ * get_font() - Obtain information about a font (optional)
+ *
+ * @dev: Device to check
+ * @seq: Font number to query (0=first, 1=second, etc.)
+ * @info: Returns font information on success
+ * Returns: 0 on success, -ENOENT if no such font
+ */
+ int (*get_font)(struct udevice *dev, int seq,
+ struct vidfont_info *info);
+
+ /**
+ * select_font() - Select a particular font by name / size
+ *
+ * @dev: Device to adjust
+ * @name: Font name to use (NULL to use default)
+ * @size: Font size to use (0 to use default)
+ * Returns: 0 on success, -ENOENT if no such font
+ */
+ int (*select_font)(struct udevice *dev, const char *name, uint size);
};
/* Get a pointer to the driver operations for a video console device */
#define vidconsole_get_ops(dev) ((struct vidconsole_ops *)(dev)->driver->ops)
/**
+ * vidconsole_get_font() - Obtain information about a font
+ *
+ * @dev: Device to check
+ * @seq: Font number to query (0=first, 1=second, etc.)
+ * @info: Returns font information on success
+ * Returns: 0 on success, -ENOENT if no such font, -ENOSYS if there is no such
+ * method
+ */
+int vidconsole_get_font(struct udevice *dev, int seq,
+ struct vidfont_info *info);
+
+/**
+ * vidconsole_select_font() - Select a particular font by name / size
+ *
+ * @dev: Device to adjust
+ * @name: Font name to use (NULL to use default)
+ * @size: Font size to use (0 to use default)
+ */
+int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
+
+/**
* vidconsole_putc_xy() - write a single character to a position
*
* @dev: Device to write to
@@ -234,27 +291,21 @@
/**
* vidconsole_list_fonts() - List the available fonts
*
- * This shows a list on the console
- */
-void vidconsole_list_fonts(void);
-
-/**
- * vidconsole_select_font() - Select a font to use
+ * @dev: vidconsole device to check
*
- * @dev: vidconsole device
- * @name: Font name
- * @size: Size of the font (norminal pixel height) or 0 for default
+ * This shows a list of fonts known by this vidconsole. The list is displayed on
+ * the console (not necessarily @dev but probably)
*/
-int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
+void vidconsole_list_fonts(struct udevice *dev);
/**
- * vidconsole_get_font() - get the current font name and size
+ * vidconsole_get_font_size() - get the current font name and size
*
* @dev: vidconsole device
* @sizep: Place to put the font size (nominal height in pixels)
* Returns: Current font name
*/
-const char *vidconsole_get_font(struct udevice *dev, uint *sizep);
+const char *vidconsole_get_font_size(struct udevice *dev, uint *sizep);
#ifdef CONFIG_VIDEO_COPY
/**
diff --git a/include/vsprintf.h b/include/vsprintf.h
index e006af2..ed8a060 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -329,6 +329,30 @@
void str_to_upper(const char *in, char *out, size_t len);
/**
+ * str_to_list() - Convert a string to a list of string pointers
+ *
+ * Splits a string containing space-delimited substrings into a number of
+ * separate strings, e.g. "this is" becomes {"this", "is", NULL}. If @instr is
+ * empty then this returns just {NULL}. The string should have only a single
+ * space between items, with no leading or trailing spaces.
+ *
+ * @instr: String to process (this is alloced by this function)
+ * Returns: List of string pointers, terminated by NULL. Each entry points to
+ * a string. If @instr is empty, the list consists just of a single NULL entry.
+ * Note that the first entry points to the alloced string.
+ * Returns NULL if out of memory
+ */
+const char **str_to_list(const char *instr);
+
+/**
+ * str_free_list() - Free a string list
+ *
+ * @ptr: String list to free, as created by str_to_list(). This can also be
+ * NULL, in which case the function does nothing
+ */
+void str_free_list(const char **ptr);
+
+/**
* vsscanf - Unformat a buffer into a list of arguments
* @inp: input buffer
* @fmt0: format of buffer
diff --git a/lib/Kconfig b/lib/Kconfig
index def36f2..549bd35 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -316,7 +316,7 @@
config TRACE
bool "Support for tracing of function calls and timing"
imply CMD_TRACE
- select TIMER_EARLY
+ imply TIMER_EARLY
help
Enables function tracing within U-Boot. This allows recording of call
traces including timing information. The command can write data to
@@ -422,6 +422,7 @@
config SPL_TPM
bool "Trusted Platform Module (TPM) Support in SPL"
depends on SPL_DM
+ imply SPL_CRC8
help
This enables support for TPMs which can be used to provide security
features for your board. The TPM can be connected via LPC or I2C
@@ -617,6 +618,23 @@
security applications, but it can be useful for providing a quick
checksum of a block of data.
+config CRC8
+ def_bool y
+ help
+ Enables CRC8 support in U-Boot. This is normally required. CRC8 is
+ a simple and fast checksumming algorithm which does a bytewise
+ checksum with feedback to produce an 8-bit result. The code is small
+ and it does not require a lookup table (unlike CRC32).
+
+config SPL_CRC8
+ bool "Support CRC8 in SPL"
+ depends on SPL
+ help
+ Enables CRC8 support in SPL. This is not normally required. CRC8 is
+ a simple and fast checksumming algorithm which does a bytewise
+ checksum with feedback to produce an 8-bit result. The code is small
+ and it does not require a lookup table (unlike CRC32).
+
config CRC32
def_bool y
help
@@ -694,6 +712,21 @@
help
This enables Zstandard decompression library.
+if ZSTD
+
+config ZSTD_LIB_MINIFY
+ bool "Minify Zstandard code"
+ default y
+ help
+ This disables various optional components and changes the
+ compilation flags to prioritize space-saving.
+
+ For detailed info, see zstd's lib/README.md
+
+ https://github.com/facebook/zstd/blob/dev/lib/README.md
+
+endif
+
config SPL_LZ4
bool "Enable LZ4 decompression support in SPL"
depends on SPL
@@ -1027,6 +1060,13 @@
Define the number of supported reserved regions in the library logical
memory blocks.
+config PHANDLE_CHECK_SEQ
+ bool "Enable phandle check while getting sequence number"
+ help
+ When there are multiple device tree nodes with same name,
+ enable this config option to distinguish them using
+ phandles in fdtdec_get_alias_seq() function.
+
endmenu
menu "FWU Multi Bank Updates"
diff --git a/lib/Makefile b/lib/Makefile
index d77b33e..a282e40 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -57,12 +57,13 @@
obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-common.o
ifeq ($(CONFIG_$(SPL_TPL_)TPM),y)
-obj-y += crc8.o
obj-$(CONFIG_TPM) += tpm_api.o
obj-$(CONFIG_TPM_V1) += tpm-v1.o
obj-$(CONFIG_TPM_V2) += tpm-v2.o
endif
+obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o
+
obj-y += crypto/
obj-$(CONFIG_$(SPL_TPL_)GENERATE_ACPI_TABLE) += acpi/
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index b498c72..c56904a 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -14,8 +14,8 @@
depends on !EFI_APP
default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8
select CHARSET
+ # We need to send DM events, dynamically, in the EFI block driver
select DM_EVENT
- select EVENT
select EVENT_DYNAMIC
select LIB_UUID
imply PARTITION_UUIDS
@@ -124,6 +124,15 @@
Provide the SetTime() runtime service at boottime. This service
can be used by an EFI application to adjust the real time clock.
+config EFI_SCROLL_ON_CLEAR_SCREEN
+ bool "Avoid overwriting previous output on clear screen"
+ help
+ Instead of erasing the screen content when the console screen should
+ be cleared, emit blank new lines so that previous output is scrolled
+ out of sight rather than overwritten. On serial consoles this allows
+ to capture complete boot logs (except for interactive menus etc.)
+ and can ease debugging related issues.
+
config EFI_HAVE_CAPSULE_SUPPORT
bool
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 4d08dd3..1ed8c7a 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -461,10 +461,21 @@
}
/**
- * efi_cout_clear_screen() - clear screen
+ * efi_clear_screen() - clear screen
*/
static void efi_clear_screen(void)
{
+ if (CONFIG_IS_ENABLED(EFI_SCROLL_ON_CLEAR_SCREEN)) {
+ unsigned int row, screen_rows, screen_columns;
+
+ /* Avoid overwriting previous outputs on streaming consoles */
+ screen_rows = efi_cout_modes[efi_con_mode.mode].rows;
+ screen_columns = efi_cout_modes[efi_con_mode.mode].columns;
+ printf(ESC "[%u;%uH", screen_rows, screen_columns);
+ for (row = 1; row < screen_rows; row++)
+ printf("\n");
+ }
+
/*
* The Linux console wants both a clear and a home command. The video
* uclass does not support <ESC>[H without coordinates, yet.
@@ -489,6 +500,12 @@
{
EFI_ENTRY("%p", this);
+ /* Set default colors if not done yet */
+ if (efi_con_mode.attribute == 0) {
+ efi_con_mode.attribute = 0x07;
+ printf(ESC "[0;37;40m");
+ }
+
efi_clear_screen();
return EFI_EXIT(EFI_SUCCESS);
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 7ea0334..d225671 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -13,6 +13,7 @@
#include <dm/device-internal.h>
#include <dm/tag.h>
#include <event.h>
+#include <efi_driver.h>
#include <efi_loader.h>
#include <fs.h>
#include <log.h>
@@ -386,6 +387,7 @@
* @part_info: partition info
* @part: partition
* @disk: pointer to receive the created handle
+ * @agent_handle: handle of the EFI block driver
* Return: disk object
*/
static efi_status_t efi_disk_add_dev(
@@ -395,7 +397,8 @@
int dev_index,
struct disk_partition *part_info,
unsigned int part,
- struct efi_disk_obj **disk)
+ struct efi_disk_obj **disk,
+ efi_handle_t agent_handle)
{
struct efi_disk_obj *diskobj;
struct efi_object *handle;
@@ -421,13 +424,16 @@
if (!node) {
ret = EFI_OUT_OF_RESOURCES;
+ log_debug("no node\n");
goto error;
}
/* Parent must expose EFI_BLOCK_IO_PROTOCOL */
ret = efi_search_protocol(parent, &efi_block_io_guid, &handler);
- if (ret != EFI_SUCCESS)
+ if (ret != EFI_SUCCESS) {
+ log_debug("search failed\n");
goto error;
+ }
/*
* Link the partition (child controller) to the block device
@@ -436,8 +442,10 @@
ret = efi_protocol_open(handler, &protocol_interface, NULL,
&diskobj->header,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
- if (ret != EFI_SUCCESS)
- goto error;
+ if (ret != EFI_SUCCESS) {
+ log_debug("prot open failed\n");
+ goto error;
+ }
diskobj->dp = efi_dp_append_node(dp_parent, node);
efi_free_pool(node);
@@ -468,8 +476,10 @@
*/
esp_guid, NULL,
NULL);
- if (ret != EFI_SUCCESS)
+ if (ret != EFI_SUCCESS) {
+ log_debug("install failed %lx\n", ret);
goto error;
+ }
/*
* On partitions or whole disks without partitions install the
@@ -482,8 +492,10 @@
ret = efi_add_protocol(&diskobj->header,
&efi_simple_file_system_protocol_guid,
diskobj->volume);
- if (ret != EFI_SUCCESS)
+ if (ret != EFI_SUCCESS) {
+ log_debug("simple FS failed\n");
return ret;
+ }
}
diskobj->ops = block_io_disk_template;
diskobj->dev_index = dev_index;
@@ -529,17 +541,18 @@
return ret;
}
-/*
- * Create a handle for a whole raw disk
+/**
+ * efi_disk_create_raw() - create a handle for a whole raw disk
*
- * @dev uclass device (UCLASS_BLK)
+ * @dev: udevice (UCLASS_BLK)
+ * @agent_handle: handle of the EFI block driver
*
* Create an efi_disk object which is associated with @dev.
* The type of @dev must be UCLASS_BLK.
*
- * @return 0 on success, -1 otherwise
+ * Return: 0 on success, -1 otherwise
*/
-static int efi_disk_create_raw(struct udevice *dev)
+static int efi_disk_create_raw(struct udevice *dev, efi_handle_t agent_handle)
{
struct efi_disk_obj *disk;
struct blk_desc *desc;
@@ -550,36 +563,40 @@
diskid = desc->devnum;
ret = efi_disk_add_dev(NULL, NULL, desc,
- diskid, NULL, 0, &disk);
+ diskid, NULL, 0, &disk, agent_handle);
if (ret != EFI_SUCCESS) {
- if (ret == EFI_NOT_READY)
+ if (ret == EFI_NOT_READY) {
log_notice("Disk %s not ready\n", dev->name);
- else
+ ret = -EBUSY;
+ } else {
log_err("Adding disk for %s failed (err=%ld/%#lx)\n", dev->name, ret, ret);
+ ret = -ENOENT;
+ }
- return -1;
+ return ret;
}
if (efi_link_dev(&disk->header, dev)) {
efi_free_pool(disk->dp);
efi_delete_handle(&disk->header);
- return -1;
+ return -EINVAL;
}
return 0;
}
-/*
- * Create a handle for a disk partition
+/**
+ * efi_disk_create_part() - create a handle for a disk partition
*
- * @dev uclass device (UCLASS_PARTITION)
+ * @dev: udevice (UCLASS_PARTITION)
+ * @agent_handle: handle of the EFI block driver
*
* Create an efi_disk object which is associated with @dev.
* The type of @dev must be UCLASS_PARTITION.
*
- * @return 0 on success, -1 otherwise
+ * Return: 0 on success, -1 otherwise
*/
-static int efi_disk_create_part(struct udevice *dev)
+static int efi_disk_create_part(struct udevice *dev, efi_handle_t agent_handle)
{
efi_handle_t parent;
struct blk_desc *desc;
@@ -608,7 +625,7 @@
dp_parent = (struct efi_device_path *)handler->protocol_interface;
ret = efi_disk_add_dev(parent, dp_parent, desc, diskid,
- info, part, &disk);
+ info, part, &disk, agent_handle);
if (ret != EFI_SUCCESS) {
log_err("Adding partition for %s failed\n", dev->name);
return -1;
@@ -623,17 +640,18 @@
return 0;
}
-/*
- * Create efi_disk objects for a block device
+/**
+ * efi_disk_probe() - create efi_disk objects for a block device
*
- * @dev uclass device (UCLASS_BLK)
+ * @ctx: event context - driver binding protocol
+ * @event: EV_PM_POST_PROBE event
*
* Create efi_disk objects for partitions as well as a raw disk
* which is associated with @dev.
* The type of @dev must be UCLASS_BLK.
* This function is expected to be called at EV_PM_POST_PROBE.
*
- * @return 0 on success, -1 otherwise
+ * Return: 0 on success, -1 otherwise
*/
int efi_disk_probe(void *ctx, struct event *event)
{
@@ -641,28 +659,30 @@
enum uclass_id id;
struct blk_desc *desc;
struct udevice *child;
+ struct efi_driver_binding_extended_protocol *db_prot = ctx;
+ efi_handle_t agent_handle = db_prot->bp.driver_binding_handle;
int ret;
dev = event->data.dm.dev;
id = device_get_uclass_id(dev);
- /* TODO: We won't support partitions in a partition */
+ /* We won't support partitions in a partition */
if (id != UCLASS_BLK)
return 0;
/*
- * avoid creating duplicated objects now that efi_driver
+ * Avoid creating duplicated objects now that efi_driver
* has already created an efi_disk at this moment.
*/
desc = dev_get_uclass_plat(dev);
if (desc->uclass_id != UCLASS_EFI_LOADER) {
- ret = efi_disk_create_raw(dev);
+ ret = efi_disk_create_raw(dev, agent_handle);
if (ret)
return -1;
}
device_foreach_child(child, dev) {
- ret = efi_disk_create_part(child);
+ ret = efi_disk_create_part(child, agent_handle);
if (ret)
return -1;
}
diff --git a/lib/efi_loader/efi_freestanding.c b/lib/efi_loader/efi_freestanding.c
index c85df02..4b65fc6 100644
--- a/lib/efi_loader/efi_freestanding.c
+++ b/lib/efi_loader/efi_freestanding.c
@@ -100,7 +100,7 @@
* func_ptr: Pointer to function being entered
* caller: Pointer to function which called this function
*/
-void __attribute__((no_instrument_function))
+void notrace
__cyg_profile_func_enter(void *func_ptr, void *caller)
{
}
@@ -116,7 +116,7 @@
* func_ptr: Pointer to function being entered
* caller: Pointer to function which called this function
*/
-void __attribute__((no_instrument_function))
+void notrace
__cyg_profile_func_exit(void *func_ptr, void *caller)
{
}
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 27db3be..3b54ecb1 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -758,6 +758,9 @@
{
EFI_ENTRY("%p, %pUs", this, key_guid);
+ if (!key_guid)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
return EFI_EXIT(EFI_NOT_FOUND);
}
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 32254d2..b7bee98 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -78,12 +78,19 @@
return ret;
}
-/*
+/**
+ * efi_mem_cmp() - comparator function for sorting memory map
+ *
* Sorts the memory list from highest address to lowest address
*
* When allocating memory we should always start from the highest
* address chunk, so sort the memory list such that the first list
* iterator gets the highest address and goes lower from there.
+ *
+ * @priv: unused
+ * @a: first memory area
+ * @b: second memory area
+ * Return: 1 if @a is before @b, -1 if @b is before @a, 0 if equal
*/
static int efi_mem_cmp(void *priv, struct list_head *a, struct list_head *b)
{
@@ -98,11 +105,22 @@
return -1;
}
+/**
+ * desc_get_end() - get end address of memory area
+ *
+ * @desc: memory descriptor
+ * Return: end address + 1
+ */
static uint64_t desc_get_end(struct efi_mem_desc *desc)
{
return desc->physical_start + (desc->num_pages << EFI_PAGE_SHIFT);
}
+/**
+ * efi_mem_sort() - sort memory map
+ *
+ * Sort the memory map and then try to merge adjacent memory areas.
+ */
static void efi_mem_sort(void)
{
struct list_head *lhandle;
@@ -148,12 +166,13 @@
}
}
-/** efi_mem_carve_out - unmap memory region
+/**
+ * efi_mem_carve_out() - unmap memory region
*
* @map: memory map
* @carve_desc: memory region to unmap
* @overlap_only_ram: the carved out region may only overlap RAM
- * Return Value: the number of overlapping pages which have been
+ * Return: the number of overlapping pages which have been
* removed from the map,
* EFI_CARVE_NO_OVERLAP, if the regions don't overlap,
* EFI_CARVE_OVERLAPS_NONRAM, if the carve and map overlap,
@@ -403,6 +422,13 @@
return EFI_NOT_FOUND;
}
+/**
+ * efi_find_free_memory() - find free memory pages
+ *
+ * @len: size of memory area needed
+ * @max_addr: highest address to allocate
+ * Return: pointer to free memory area or 0
+ */
static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr)
{
struct list_head *lhandle;
@@ -445,13 +471,13 @@
return 0;
}
-/*
- * Allocate memory pages.
+/**
+ * efi_allocate_pages - allocate memory pages
*
- * @type type of allocation to be performed
- * @memory_type usage type of the allocated memory
- * @pages number of pages to be allocated
- * @memory allocated memory
+ * @type: type of allocation to be performed
+ * @memory_type: usage type of the allocated memory
+ * @pages: number of pages to be allocated
+ * @memory: allocated memory
* Return: status code
*/
efi_status_t efi_allocate_pages(enum efi_allocate_type type,
@@ -507,6 +533,13 @@
return EFI_SUCCESS;
}
+/**
+ * efi_alloc() - allocate memory pages
+ *
+ * @len: size of the memory to be allocated
+ * @memory_type: usage type of the allocated memory
+ * Return: pointer to the allocated memory area or NULL
+ */
void *efi_alloc(uint64_t len, int memory_type)
{
uint64_t ret = 0;
@@ -552,7 +585,7 @@
}
/**
- * efi_alloc_aligned_pages - allocate
+ * efi_alloc_aligned_pages() - allocate aligned memory pages
*
* @len: len in bytes
* @memory_type: usage type of the allocated memory
@@ -673,15 +706,15 @@
return ret;
}
-/*
- * Get map describing memory usage.
+/**
+ * efi_get_memory_map() - get map describing memory usage.
*
- * @memory_map_size on entry the size, in bytes, of the memory map buffer,
+ * @memory_map_size: on entry the size, in bytes, of the memory map buffer,
* on exit the size of the copied memory map
- * @memory_map buffer to which the memory map is written
- * @map_key key for the memory map
- * @descriptor_size size of an individual memory descriptor
- * @descriptor_version version number of the memory descriptor structure
+ * @memory_map: buffer to which the memory map is written
+ * @map_key: key for the memory map
+ * @descriptor_size: size of an individual memory descriptor
+ * @descriptor_version: version number of the memory descriptor structure
* Return: status code
*/
efi_status_t efi_get_memory_map(efi_uintn_t *memory_map_size,
@@ -741,8 +774,8 @@
*
* The caller is responsible for calling FreePool() if the call succeeds.
*
- * @memory_map buffer to which the memory map is written
- * @map_size size of the memory map
+ * @map_size: size of the memory map
+ * @memory_map: buffer to which the memory map is written
* Return: status code
*/
efi_status_t efi_get_memory_map_alloc(efi_uintn_t *map_size,
@@ -818,6 +851,11 @@
return EFI_SUCCESS;
}
+/**
+ * efi_add_known_memory() - add memory banks to map
+ *
+ * This function may be overridden for specific architectures.
+ */
__weak void efi_add_known_memory(void)
{
u64 ram_top = board_get_usable_ram_top(0) & ~EFI_PAGE_MASK;
@@ -844,7 +882,11 @@
}
}
-/* Add memory regions for U-Boot's memory and for the runtime services code */
+/**
+ * add_u_boot_and_runtime() - add U-Boot code to memory map
+ *
+ * Add memory regions for U-Boot's memory and for the runtime services code.
+ */
static void add_u_boot_and_runtime(void)
{
unsigned long runtime_start, runtime_end, runtime_pages;
diff --git a/lib/efi_loader/efi_riscv.c b/lib/efi_loader/efi_riscv.c
index bccfefd..0641727 100644
--- a/lib/efi_loader/efi_riscv.c
+++ b/lib/efi_loader/efi_riscv.c
@@ -31,7 +31,7 @@
EFI_ENTRY("%p, %p", this, boot_hartid);
if (this != &riscv_efi_boot_prot || !boot_hartid)
- return EFI_INVALID_PARAMETER;
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
*boot_hartid = gd->arch.boot_hart;
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 5437641..f0f01d3 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -128,7 +128,7 @@
{
efi_status_t ret = EFI_SUCCESS;
- if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_UPDATE)) {
+ if (IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)) {
ret = efi_set_variable_int(u"CapsuleMax",
&efi_guid_capsule_report,
EFI_VARIABLE_READ_ONLY |
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index a525ebf..918e9a2 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -2417,7 +2417,7 @@
ret = platform_get_tpm2_device(&dev);
if (ret != EFI_SUCCESS) {
- log_warning("Unable to find TPMv2 device\n");
+ log_warning("Missing TPMv2 device for EFI_TCG_PROTOCOL\n");
return EFI_SUCCESS;
}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index 503a33e..7c32adf 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -334,9 +334,11 @@
else
ret = EFI_SUCCESS;
- /* Write non-volatile EFI variables to file */
- if (attributes & EFI_VARIABLE_NON_VOLATILE &&
- ret == EFI_SUCCESS && efi_obj_list_initialized == EFI_SUCCESS)
+ /*
+ * Write non-volatile EFI variables to file
+ * TODO: check if a value change has occured to avoid superfluous writes
+ */
+ if (attributes & EFI_VARIABLE_NON_VOLATILE)
efi_var_to_file();
return EFI_SUCCESS;
diff --git a/lib/efi_selftest/efi_selftest_hii.c b/lib/efi_selftest/efi_selftest_hii.c
index eaf3b09..f4b5588 100644
--- a/lib/efi_selftest/efi_selftest_hii.c
+++ b/lib/efi_selftest/efi_selftest_hii.c
@@ -564,7 +564,19 @@
*/
static int test_hii_database_set_keyboard_layout(void)
{
+ efi_status_t ret;
+
PRINT_TESTNAME;
+
+ /* Invalid key guid. */
+ ret = hii_database_protocol->set_keyboard_layout(
+ hii_database_protocol, NULL);
+ if (ret != EFI_INVALID_PARAMETER) {
+ efi_st_error("set_keyboard_layout returned %u not invalid\n",
+ (unsigned int)ret);
+ return EFI_ST_FAILURE;
+ }
+
/* set_keyboard_layout() not implemented yet */
return EFI_ST_SUCCESS;
}
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 64c5b3d..0827e16 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -13,6 +13,7 @@
#include <log.h>
#include <malloc.h>
#include <net.h>
+#include <spl.h>
#include <env.h>
#include <errno.h>
#include <fdtdec.h>
@@ -518,8 +519,11 @@
* Adding an extra check to distinguish DT nodes with
* same name
*/
- if (offset != fdt_path_offset(blob, prop))
- continue;
+ if (IS_ENABLED(CONFIG_PHANDLE_CHECK_SEQ)) {
+ if (fdt_get_phandle(blob, offset) !=
+ fdt_get_phandle(blob, fdt_path_offset(blob, prop)))
+ continue;
+ }
val = trailing_strtol(name);
if (val != -1) {
@@ -586,6 +590,34 @@
return fdt_path_offset(blob, prop);
}
+/**
+ * fdtdec_prepare_fdt() - Check we have a valid fdt available to control U-Boot
+ *
+ * @blob: Blob to check
+ *
+ * If not, a message is printed to the console if the console is ready.
+ *
+ * Return: 0 if all ok, -ENOENT if not
+ */
+static int fdtdec_prepare_fdt(const void *blob)
+{
+ if (!blob || ((uintptr_t)blob & 3) || fdt_check_header(blob)) {
+ if (spl_phase() <= PHASE_SPL) {
+ puts("Missing DTB\n");
+ } else {
+ printf("No valid device tree binary found at %p\n",
+ blob);
+ if (_DEBUG && blob) {
+ printf("fdt_blob=%p\n", blob);
+ print_buffer((ulong)blob, blob, 4, 32, 0);
+ }
+ }
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
int fdtdec_check_fdt(void)
{
/*
@@ -594,34 +626,7 @@
* FDT (prior to console ready) will need to make their own
* arrangements and do their own checks.
*/
- assert(!fdtdec_prepare_fdt());
- return 0;
-}
-
-/*
- * This function is a little odd in that it accesses global data. At some
- * point if the architecture board.c files merge this will make more sense.
- * Even now, it is common code.
- */
-int fdtdec_prepare_fdt(void)
-{
- if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
- fdt_check_header(gd->fdt_blob)) {
-#ifdef CONFIG_SPL_BUILD
- puts("Missing DTB\n");
-#else
- printf("No valid device tree binary found at %p\n",
- gd->fdt_blob);
-# ifdef DEBUG
- if (gd->fdt_blob) {
- printf("fdt_blob=%p\n", gd->fdt_blob);
- print_buffer((ulong)gd->fdt_blob, gd->fdt_blob, 4,
- 32, 0);
- }
-# endif
-#endif
- return -1;
- }
+ assert(!fdtdec_prepare_fdt(gd->fdt_blob));
return 0;
}
@@ -1229,6 +1234,29 @@
#else
/* FDT is at end of image */
fdt_blob = (ulong *)&_end;
+
+ if (_DEBUG && !fdtdec_prepare_fdt(fdt_blob)) {
+ int stack_ptr;
+ const void *top = fdt_blob + fdt_totalsize(fdt_blob);
+
+ /*
+ * Perform a sanity check on the memory layout. If this fails,
+ * it indicates that the device tree is positioned above the
+ * global data pointer or the stack pointer. This should not
+ * happen.
+ *
+ * If this fails, check that SYS_INIT_SP_ADDR has enough space
+ * below it for SYS_MALLOC_F_LEN and global_data, as well as the
+ * stack, without overwriting the device tree or U-Boot itself.
+ * Since the device tree is sitting at _end (the start of the
+ * BSS region), we need the top of the device tree to be below
+ * any memory allocated by board_init_f_alloc_reserve().
+ */
+ if (top > (void *)gd || top > (void *)&stack_ptr) {
+ printf("FDT %p gd %p\n", fdt_blob, gd);
+ panic("FDT overlap");
+ }
+ }
#endif
return fdt_blob;
@@ -1666,7 +1694,7 @@
if (CONFIG_IS_ENABLED(MULTI_DTB_FIT))
setup_multi_dtb_fit();
- ret = fdtdec_prepare_fdt();
+ ret = fdtdec_prepare_fdt(gd->fdt_blob);
if (!ret)
ret = fdtdec_board_setup(gd->fdt_blob);
oftree_reset();
@@ -1698,7 +1726,7 @@
*rescan = 1;
gd->fdt_blob = fdt_blob;
- return fdtdec_prepare_fdt();
+ return fdtdec_prepare_fdt(fdt_blob);
}
/*
diff --git a/lib/gzip.c b/lib/gzip.c
index c6c0ec8..2595b2d 100644
--- a/lib/gzip.c
+++ b/lib/gzip.c
@@ -14,8 +14,8 @@
#include <u-boot/zlib.h>
#include "zlib/zutil.h"
-#ifndef CONFIG_GZIP_COMPRESS_DEF_SZ
-#define CONFIG_GZIP_COMPRESS_DEF_SZ 0x200
+#ifndef CFG_GZIP_COMPRESS_DEF_SZ
+#define CFG_GZIP_COMPRESS_DEF_SZ 0x200
#endif
#define ZALLOC_ALIGNMENT 16
@@ -75,17 +75,17 @@
}
while (srclen > 0) {
- comp_len = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
- CONFIG_GZIP_COMPRESS_DEF_SZ : srclen;
+ comp_len = (srclen > CFG_GZIP_COMPRESS_DEF_SZ) ?
+ CFG_GZIP_COMPRESS_DEF_SZ : srclen;
s.next_in = src;
s.avail_in = comp_len;
- flush = (srclen > CONFIG_GZIP_COMPRESS_DEF_SZ)?
+ flush = (srclen > CFG_GZIP_COMPRESS_DEF_SZ)?
Z_NO_FLUSH : Z_FINISH;
do {
- left_len = (*lenp > CONFIG_GZIP_COMPRESS_DEF_SZ) ?
- CONFIG_GZIP_COMPRESS_DEF_SZ : *lenp;
+ left_len = (*lenp > CFG_GZIP_COMPRESS_DEF_SZ) ?
+ CFG_GZIP_COMPRESS_DEF_SZ : *lenp;
s.next_out = dst;
s.avail_out = left_len;
r = deflate(&s, flush);
diff --git a/lib/rc4.c b/lib/rc4.c
index 0c00439..720112d 100644
--- a/lib/rc4.c
+++ b/lib/rc4.c
@@ -12,7 +12,7 @@
#endif
#include <rc4.h>
-void rc4_encode(unsigned char *buf, unsigned int len, unsigned char key[16])
+void rc4_encode(unsigned char *buf, unsigned int len, const unsigned char key[16])
{
unsigned char s[256], k[256], temp;
unsigned short i, j, t;
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
index b2a2119..d20bdb5 100644
--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -608,7 +608,7 @@
BIGNUM *modulus, *r_squared;
uint64_t exponent;
uint32_t n0_inv;
- int parent, node;
+ int parent, node = -FDT_ERR_NOTFOUND;
char name[100];
int ret;
int bits;
diff --git a/lib/strto.c b/lib/strto.c
index 6462d4f..1549211 100644
--- a/lib/strto.c
+++ b/lib/strto.c
@@ -11,6 +11,7 @@
#include <common.h>
#include <errno.h>
+#include <malloc.h>
#include <linux/ctype.h>
/* from lib/kstrtox.c */
@@ -222,3 +223,43 @@
if (len)
*out = '\0';
}
+
+const char **str_to_list(const char *instr)
+{
+ const char **ptr;
+ char *str, *p;
+ int count, i;
+
+ /* don't allocate if the string is empty */
+ str = *instr ? strdup(instr) : (char *)instr;
+ if (!str)
+ return NULL;
+
+ /* count the number of space-separated strings */
+ for (count = *str != '\0', p = str; *p; p++) {
+ if (*p == ' ') {
+ count++;
+ *p = '\0';
+ }
+ }
+
+ /* allocate the pointer array, allowing for a NULL terminator */
+ ptr = calloc(count + 1, sizeof(char *));
+ if (!ptr) {
+ if (*str)
+ free(str);
+ return NULL;
+ }
+
+ for (i = 0, p = str; i < count; p += strlen(p) + 1, i++)
+ ptr[i] = p;
+
+ return ptr;
+}
+
+void str_free_list(const char **ptr)
+{
+ if (ptr)
+ free((char *)ptr[0]);
+ free(ptr);
+}
diff --git a/lib/time.c b/lib/time.c
index 8235026..5252190 100644
--- a/lib/time.c
+++ b/lib/time.c
@@ -19,8 +19,8 @@
#include <asm/io.h>
#include <linux/delay.h>
-#ifndef CONFIG_WD_PERIOD
-# define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */
+#ifndef CFG_WD_PERIOD
+# define CFG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */
#endif
DECLARE_GLOBAL_DATA_PTR;
@@ -63,7 +63,7 @@
}
#else
-extern unsigned long __weak timer_read_counter(void);
+extern unsigned long timer_read_counter(void);
#endif
#if CONFIG_IS_ENABLED(TIMER)
@@ -199,7 +199,7 @@
do {
schedule();
- kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
+ kv = usec > CFG_WD_PERIOD ? CFG_WD_PERIOD : usec;
__udelay(kv);
usec -= kv;
} while(usec);
diff --git a/lib/trace.c b/lib/trace.c
index 54f0bf2..b9dc6d2 100644
--- a/lib/trace.c
+++ b/lib/trace.c
@@ -40,7 +40,8 @@
int max_depth;
};
-static struct trace_hdr *hdr; /* Pointer to start of trace buffer */
+/* Pointer to start of trace buffer */
+static struct trace_hdr *hdr __section(".data");
static inline uintptr_t __attribute__((no_instrument_function))
func_ptr_to_num(void *func_ptr)
@@ -68,7 +69,7 @@
/**
* trace_save_gd() - save the value of the gd register
*/
-static void __attribute__((no_instrument_function)) trace_save_gd(void)
+static void notrace trace_save_gd(void)
{
trace_gd = gd;
}
@@ -81,7 +82,7 @@
* have to set the gd register to the U-Boot value when entering a trace
* point and set it back to the application value when exiting the trace point.
*/
-static void __attribute__((no_instrument_function)) trace_swap_gd(void)
+static void notrace trace_swap_gd(void)
{
volatile gd_t *temp_gd = trace_gd;
@@ -91,18 +92,17 @@
#else
-static void __attribute__((no_instrument_function)) trace_save_gd(void)
+static void notrace trace_save_gd(void)
{
}
-static void __attribute__((no_instrument_function)) trace_swap_gd(void)
+static void notrace trace_swap_gd(void)
{
}
#endif
-static void __attribute__((no_instrument_function)) add_ftrace(void *func_ptr,
- void *caller, ulong flags)
+static void notrace add_ftrace(void *func_ptr, void *caller, ulong flags)
{
if (hdr->depth > hdr->depth_limit) {
hdr->ftrace_too_deep_count++;
@@ -118,7 +118,7 @@
hdr->ftrace_count++;
}
-static void __attribute__((no_instrument_function)) add_textbase(void)
+static void notrace add_textbase(void)
{
if (hdr->ftrace_count < hdr->ftrace_size) {
struct trace_call *rec = &hdr->ftrace[hdr->ftrace_count];
@@ -139,8 +139,7 @@
* @func_ptr: pointer to function being entered
* @caller: pointer to function which called this function
*/
-void __attribute__((no_instrument_function)) __cyg_profile_func_enter(
- void *func_ptr, void *caller)
+void notrace __cyg_profile_func_enter(void *func_ptr, void *caller)
{
if (trace_enabled) {
int func;
@@ -167,8 +166,7 @@
* @func_ptr: pointer to function being entered
* @caller: pointer to function which called this function
*/
-void __attribute__((no_instrument_function)) __cyg_profile_func_exit(
- void *func_ptr, void *caller)
+void notrace __cyg_profile_func_exit(void *func_ptr, void *caller)
{
if (trace_enabled) {
trace_swap_gd();
@@ -327,7 +325,7 @@
puts(" calls not traced due to depth\n");
}
-void __attribute__((no_instrument_function)) trace_set_enabled(int enabled)
+void notrace trace_set_enabled(int enabled)
{
trace_enabled = enabled != 0;
}
@@ -339,8 +337,7 @@
* @buff_size: Size of trace buffer
* Return: 0 if ok
*/
-int __attribute__((no_instrument_function)) trace_init(void *buff,
- size_t buff_size)
+int notrace trace_init(void *buff, size_t buff_size)
{
ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
size_t needed;
@@ -404,7 +401,7 @@
*
* Return: 0 if ok, -ENOSPC if not enough memory is available
*/
-int __attribute__((no_instrument_function)) trace_early_init(void)
+int notrace trace_early_init(void)
{
ulong func_count = gd->mon_len / FUNC_SITE_SIZE;
size_t buff_size = CONFIG_TRACE_EARLY_SIZE;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 530d808..8de3882 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -145,6 +145,7 @@
#define LEFT 16 /* left justified */
#define SMALL 32 /* Must be 32 == 0x20 */
#define SPECIAL 64 /* 0x */
+#define ERRSTR 128 /* %dE showing error string if enabled */
/*
* Macro to add a new character to our output string, but only if it will
@@ -678,6 +679,8 @@
break;
case 'd':
+ if (fmt[1] == 'E')
+ flags |= ERRSTR;
case 'i':
flags |= SIGN;
case 'u':
@@ -712,6 +715,15 @@
}
str = number(str, end, num, base, field_width, precision,
flags);
+ if (IS_ENABLED(CONFIG_ERRNO_STR) && (flags & ERRSTR)) {
+ const char *p;
+
+ ADDCH(str, ':');
+ ADDCH(str, ' ');
+ for (p = errno_str(num); *p; p++)
+ ADDCH(str, *p);
+ fmt++;
+ }
}
if (size > 0) {
diff --git a/lib/zstd/Makefile b/lib/zstd/Makefile
index 1217089..2003e18 100644
--- a/lib/zstd/Makefile
+++ b/lib/zstd/Makefile
@@ -1,4 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+# ################################################################
+# Copyright (c) Facebook, Inc.
+# All rights reserved.
+#
+# This source code is licensed under both the BSD-style license (found in the
+# LICENSE file in the root directory of this source tree) and the GPLv2 (found
+# in the COPYING file in the root directory of this source tree).
+# You may select, at your option, one of the above-listed licenses.
+# ################################################################
obj-y += zstd_decompress.o
+obj-y += zstd_common.o
-zstd_decompress-y := huf_decompress.o decompress.o \
- entropy_common.o fse_decompress.o zstd_common.o zstd.o
+ifeq ($(CONFIG_ZSTD_LIB_MINIFY),y)
+ccflags-y += -DHUF_FORCE_DECOMPRESS_X1
+ccflags-y += -DZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+ccflags-y += -DZSTD_NO_INLINE
+ccflags-y += -DZSTD_STRIP_ERROR_STRINGS
+ccflags-y += -DDYNAMIC_BMI2=0
+endif
+
+zstd_decompress-y := \
+ zstd_decompress_module.o \
+ decompress/huf_decompress.o \
+ decompress/zstd_ddict.o \
+ decompress/zstd_decompress.o \
+ decompress/zstd_decompress_block.o \
+ zstd.o \
+
+zstd_common-y := \
+ zstd_common_module.o \
+ common/debug.o \
+ common/entropy_common.o \
+ common/error_private.o \
+ common/fse_decompress.o \
+ common/zstd_common.o \
diff --git a/lib/zstd/bitstream.h b/lib/zstd/bitstream.h
deleted file mode 100644
index 44abfd5..0000000
--- a/lib/zstd/bitstream.h
+++ /dev/null
@@ -1,344 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause) */
-/*
- * bitstream
- * Part of FSE library
- * header file (to include)
- * Copyright (C) 2013-2016, Yann Collet.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- */
-#ifndef BITSTREAM_H_MODULE
-#define BITSTREAM_H_MODULE
-
-/*
-* This API consists of small unitary functions, which must be inlined for best performance.
-* Since link-time-optimization is not available for all compilers,
-* these functions are defined into a .h to be included.
-*/
-
-/*-****************************************
-* Dependencies
-******************************************/
-#include "error_private.h" /* error codes and messages */
-#include "mem.h" /* unaligned access routines */
-
-/*=========================================
-* Target specific
-=========================================*/
-#define STREAM_ACCUMULATOR_MIN_32 25
-#define STREAM_ACCUMULATOR_MIN_64 57
-#define STREAM_ACCUMULATOR_MIN ((U32)(ZSTD_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
-
-/*-******************************************
-* bitStream encoding API (write forward)
-********************************************/
-/* bitStream can mix input from multiple sources.
-* A critical property of these streams is that they encode and decode in **reverse** direction.
-* So the first bit sequence you add will be the last to be read, like a LIFO stack.
-*/
-typedef struct {
- size_t bitContainer;
- int bitPos;
- char *startPtr;
- char *ptr;
- char *endPtr;
-} BIT_CStream_t;
-
-ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *dstBuffer, size_t dstCapacity);
-ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
-ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC);
-ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC);
-
-/* Start with initCStream, providing the size of buffer to write into.
-* bitStream will never write outside of this buffer.
-* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
-*
-* bits are first added to a local register.
-* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
-* Writing data into memory is an explicit operation, performed by the flushBits function.
-* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
-* After a flushBits, a maximum of 7 bits might still be stored into local register.
-*
-* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
-*
-* Last operation is to close the bitStream.
-* The function returns the final size of CStream in bytes.
-* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
-*/
-
-/*-********************************************
-* bitStream decoding API (read backward)
-**********************************************/
-typedef struct {
- size_t bitContainer;
- unsigned bitsConsumed;
- const char *ptr;
- const char *start;
-} BIT_DStream_t;
-
-typedef enum {
- BIT_DStream_unfinished = 0,
- BIT_DStream_endOfBuffer = 1,
- BIT_DStream_completed = 2,
- BIT_DStream_overflow = 3
-} BIT_DStream_status; /* result of BIT_reloadDStream() */
-/* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
-
-ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, size_t srcSize);
-ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, unsigned nbBits);
-ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD);
-ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *bitD);
-
-/* Start by invoking BIT_initDStream().
-* A chunk of the bitStream is then stored into a local register.
-* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
-* You can then retrieve bitFields stored into the local register, **in reverse order**.
-* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
-* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
-* Otherwise, it can be less than that, so proceed accordingly.
-* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
-*/
-
-/*-****************************************
-* unsafe API
-******************************************/
-ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits);
-/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
-
-ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC);
-/* unsafe version; does not check buffer overflow */
-
-ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, unsigned nbBits);
-/* faster, but works only if nbBits >= 1 */
-
-/*-**************************************************************
-* Internal functions
-****************************************************************/
-ZSTD_STATIC unsigned BIT_highbit32(register U32 val) { return 31 - __builtin_clz(val); }
-
-/*===== Local Constants =====*/
-static const unsigned BIT_mask[] = {0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF,
- 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
- 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF}; /* up to 26 bits */
-
-/*-**************************************************************
-* bitStream encoding
-****************************************************************/
-/*! BIT_initCStream() :
- * `dstCapacity` must be > sizeof(void*)
- * Return: 0 if success,
- otherwise an error code (can be tested using ERR_isError() ) */
-ZSTD_STATIC size_t BIT_initCStream(BIT_CStream_t *bitC, void *startPtr, size_t dstCapacity)
-{
- bitC->bitContainer = 0;
- bitC->bitPos = 0;
- bitC->startPtr = (char *)startPtr;
- bitC->ptr = bitC->startPtr;
- bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->ptr);
- if (dstCapacity <= sizeof(bitC->ptr))
- return ERROR(dstSize_tooSmall);
- return 0;
-}
-
-/*! BIT_addBits() :
- can add up to 26 bits into `bitC`.
- Does not check for register overflow ! */
-ZSTD_STATIC void BIT_addBits(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
-{
- bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
- bitC->bitPos += nbBits;
-}
-
-/*! BIT_addBitsFast() :
- * works only if `value` is _clean_, meaning all high bits above nbBits are 0 */
-ZSTD_STATIC void BIT_addBitsFast(BIT_CStream_t *bitC, size_t value, unsigned nbBits)
-{
- bitC->bitContainer |= value << bitC->bitPos;
- bitC->bitPos += nbBits;
-}
-
-/*! BIT_flushBitsFast() :
- * unsafe version; does not check buffer overflow */
-ZSTD_STATIC void BIT_flushBitsFast(BIT_CStream_t *bitC)
-{
- size_t const nbBytes = bitC->bitPos >> 3;
- ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
- bitC->ptr += nbBytes;
- bitC->bitPos &= 7;
- bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
-}
-
-/*! BIT_flushBits() :
- * safe version; check for buffer overflow, and prevents it.
- * note : does not signal buffer overflow. This will be revealed later on using BIT_closeCStream() */
-ZSTD_STATIC void BIT_flushBits(BIT_CStream_t *bitC)
-{
- size_t const nbBytes = bitC->bitPos >> 3;
- ZSTD_writeLEST(bitC->ptr, bitC->bitContainer);
- bitC->ptr += nbBytes;
- if (bitC->ptr > bitC->endPtr)
- bitC->ptr = bitC->endPtr;
- bitC->bitPos &= 7;
- bitC->bitContainer >>= nbBytes * 8; /* if bitPos >= sizeof(bitContainer)*8 --> undefined behavior */
-}
-
-/*! BIT_closeCStream() :
- * Return: size of CStream, in bytes,
- or 0 if it could not fit into dstBuffer */
-ZSTD_STATIC size_t BIT_closeCStream(BIT_CStream_t *bitC)
-{
- BIT_addBitsFast(bitC, 1, 1); /* endMark */
- BIT_flushBits(bitC);
-
- if (bitC->ptr >= bitC->endPtr)
- return 0; /* doesn't fit within authorized budget : cancel */
-
- return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
-}
-
-/*-********************************************************
-* bitStream decoding
-**********************************************************/
-/*! BIT_initDStream() :
-* Initialize a BIT_DStream_t.
-* `bitD` : a pointer to an already allocated BIT_DStream_t structure.
-* `srcSize` must be the *exact* size of the bitStream, in bytes.
-* @return : size of stream (== srcSize) or an errorCode if a problem is detected
-*/
-ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, size_t srcSize)
-{
- if (srcSize < 1) {
- memset(bitD, 0, sizeof(*bitD));
- return ERROR(srcSize_wrong);
- }
-
- if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
- bitD->start = (const char *)srcBuffer;
- bitD->ptr = (const char *)srcBuffer + srcSize - sizeof(bitD->bitContainer);
- bitD->bitContainer = ZSTD_readLEST(bitD->ptr);
- {
- BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
- bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
- if (lastByte == 0)
- return ERROR(GENERIC); /* endMark not present */
- }
- } else {
- bitD->start = (const char *)srcBuffer;
- bitD->ptr = bitD->start;
- bitD->bitContainer = *(const BYTE *)(bitD->start);
- switch (srcSize) {
- case 7: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[6]) << (sizeof(bitD->bitContainer) * 8 - 16);
- case 6: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[5]) << (sizeof(bitD->bitContainer) * 8 - 24);
- case 5: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[4]) << (sizeof(bitD->bitContainer) * 8 - 32);
- case 4: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[3]) << 24;
- case 3: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[2]) << 16;
- case 2: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[1]) << 8;
- default:;
- }
- {
- BYTE const lastByte = ((const BYTE *)srcBuffer)[srcSize - 1];
- bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
- if (lastByte == 0)
- return ERROR(GENERIC); /* endMark not present */
- }
- bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize) * 8;
- }
-
- return srcSize;
-}
-
-ZSTD_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) { return bitContainer >> start; }
-
-ZSTD_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) { return (bitContainer >> start) & BIT_mask[nbBits]; }
-
-ZSTD_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { return bitContainer & BIT_mask[nbBits]; }
-
-/*! BIT_lookBits() :
- * Provides next n bits from local register.
- * local register is not modified.
- * On 32-bits, maxNbBits==24.
- * On 64-bits, maxNbBits==56.
- * Return: value extracted
- */
-ZSTD_STATIC size_t BIT_lookBits(const BIT_DStream_t *bitD, U32 nbBits)
-{
- U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
- return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask - nbBits) & bitMask);
-}
-
-/*! BIT_lookBitsFast() :
-* unsafe version; only works only if nbBits >= 1 */
-ZSTD_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t *bitD, U32 nbBits)
-{
- U32 const bitMask = sizeof(bitD->bitContainer) * 8 - 1;
- return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask + 1) - nbBits) & bitMask);
-}
-
-ZSTD_STATIC void BIT_skipBits(BIT_DStream_t *bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; }
-
-/*! BIT_readBits() :
- * Read (consume) next n bits from local register and update.
- * Pay attention to not read more than nbBits contained into local register.
- * Return: extracted value.
- */
-ZSTD_STATIC size_t BIT_readBits(BIT_DStream_t *bitD, U32 nbBits)
-{
- size_t const value = BIT_lookBits(bitD, nbBits);
- BIT_skipBits(bitD, nbBits);
- return value;
-}
-
-/*! BIT_readBitsFast() :
-* unsafe version; only works only if nbBits >= 1 */
-ZSTD_STATIC size_t BIT_readBitsFast(BIT_DStream_t *bitD, U32 nbBits)
-{
- size_t const value = BIT_lookBitsFast(bitD, nbBits);
- BIT_skipBits(bitD, nbBits);
- return value;
-}
-
-/*! BIT_reloadDStream() :
-* Refill `bitD` from buffer previously set in BIT_initDStream() .
-* This function is safe, it guarantees it will not read beyond src buffer.
-* @return : status of `BIT_DStream_t` internal register.
- if status == BIT_DStream_unfinished, internal register is filled with >= (sizeof(bitD->bitContainer)*8 - 7) bits */
-ZSTD_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t *bitD)
-{
- if (bitD->bitsConsumed > (sizeof(bitD->bitContainer) * 8)) /* should not happen => corruption detected */
- return BIT_DStream_overflow;
-
- if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {
- bitD->ptr -= bitD->bitsConsumed >> 3;
- bitD->bitsConsumed &= 7;
- bitD->bitContainer = ZSTD_readLEST(bitD->ptr);
- return BIT_DStream_unfinished;
- }
- if (bitD->ptr == bitD->start) {
- if (bitD->bitsConsumed < sizeof(bitD->bitContainer) * 8)
- return BIT_DStream_endOfBuffer;
- return BIT_DStream_completed;
- }
- {
- U32 nbBytes = bitD->bitsConsumed >> 3;
- BIT_DStream_status result = BIT_DStream_unfinished;
- if (bitD->ptr - nbBytes < bitD->start) {
- nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
- result = BIT_DStream_endOfBuffer;
- }
- bitD->ptr -= nbBytes;
- bitD->bitsConsumed -= nbBytes * 8;
- bitD->bitContainer = ZSTD_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD) */
- return result;
- }
-}
-
-/*! BIT_endOfDStream() :
-* @return Tells if DStream has exactly reached its end (all bits consumed).
-*/
-ZSTD_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t *DStream)
-{
- return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer) * 8));
-}
-
-#endif /* BITSTREAM_H_MODULE */
diff --git a/lib/zstd/common/bitstream.h b/lib/zstd/common/bitstream.h
new file mode 100644
index 0000000..feef3a1
--- /dev/null
+++ b/lib/zstd/common/bitstream.h
@@ -0,0 +1,446 @@
+/* ******************************************************************
+ * bitstream
+ * Part of FSE library
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+#ifndef BITSTREAM_H_MODULE
+#define BITSTREAM_H_MODULE
+
+/*
+* This API consists of small unitary functions, which must be inlined for best performance.
+* Since link-time-optimization is not available for all compilers,
+* these functions are defined into a .h to be included.
+*/
+
+/*-****************************************
+* Dependencies
+******************************************/
+#include "mem.h" /* unaligned access routines */
+#include "compiler.h" /* UNLIKELY() */
+#include "debug.h" /* assert(), DEBUGLOG(), RAWLOG() */
+#include "error_private.h" /* error codes and messages */
+
+
+/*=========================================
+* Target specific
+=========================================*/
+
+#define STREAM_ACCUMULATOR_MIN_32 25
+#define STREAM_ACCUMULATOR_MIN_64 57
+#define STREAM_ACCUMULATOR_MIN ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))
+
+
+/*-******************************************
+* bitStream encoding API (write forward)
+********************************************/
+/* bitStream can mix input from multiple sources.
+ * A critical property of these streams is that they encode and decode in **reverse** direction.
+ * So the first bit sequence you add will be the last to be read, like a LIFO stack.
+ */
+typedef struct {
+ size_t bitContainer;
+ unsigned bitPos;
+ char* startPtr;
+ char* ptr;
+ char* endPtr;
+} BIT_CStream_t;
+
+MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);
+MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
+MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC);
+MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);
+
+/* Start with initCStream, providing the size of buffer to write into.
+* bitStream will never write outside of this buffer.
+* `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.
+*
+* bits are first added to a local register.
+* Local register is size_t, hence 64-bits on 64-bits systems, or 32-bits on 32-bits systems.
+* Writing data into memory is an explicit operation, performed by the flushBits function.
+* Hence keep track how many bits are potentially stored into local register to avoid register overflow.
+* After a flushBits, a maximum of 7 bits might still be stored into local register.
+*
+* Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.
+*
+* Last operation is to close the bitStream.
+* The function returns the final size of CStream in bytes.
+* If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)
+*/
+
+
+/*-********************************************
+* bitStream decoding API (read backward)
+**********************************************/
+typedef struct {
+ size_t bitContainer;
+ unsigned bitsConsumed;
+ const char* ptr;
+ const char* start;
+ const char* limitPtr;
+} BIT_DStream_t;
+
+typedef enum { BIT_DStream_unfinished = 0,
+ BIT_DStream_endOfBuffer = 1,
+ BIT_DStream_completed = 2,
+ BIT_DStream_overflow = 3 } BIT_DStream_status; /* result of BIT_reloadDStream() */
+ /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */
+
+MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);
+MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);
+MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);
+MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);
+
+
+/* Start by invoking BIT_initDStream().
+* A chunk of the bitStream is then stored into a local register.
+* Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
+* You can then retrieve bitFields stored into the local register, **in reverse order**.
+* Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.
+* A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.
+* Otherwise, it can be less than that, so proceed accordingly.
+* Checking if DStream has reached its end can be performed with BIT_endOfDStream().
+*/
+
+
+/*-****************************************
+* unsafe API
+******************************************/
+MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, size_t value, unsigned nbBits);
+/* faster, but works only if value is "clean", meaning all high bits above nbBits are 0 */
+
+MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);
+/* unsafe version; does not check buffer overflow */
+
+MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);
+/* faster, but works only if nbBits >= 1 */
+
+
+
+/*-**************************************************************
+* Internal functions
+****************************************************************/
+MEM_STATIC unsigned BIT_highbit32 (U32 val)
+{
+ assert(val != 0);
+ {
+# if (__GNUC__ >= 3) /* Use GCC Intrinsic */
+ return __builtin_clz (val) ^ 31;
+# else /* Software version */
+ static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29,
+ 11, 14, 16, 18, 22, 25, 3, 30,
+ 8, 12, 20, 28, 15, 17, 24, 7,
+ 19, 27, 23, 6, 26, 5, 4, 31 };
+ U32 v = val;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];
+# endif
+ }
+}
+
+/*===== Local Constants =====*/
+static const unsigned BIT_mask[] = {
+ 0, 1, 3, 7, 0xF, 0x1F,
+ 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
+ 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF,
+ 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,
+ 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,
+ 0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */
+#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))
+
+/*-**************************************************************
+* bitStream encoding
+****************************************************************/
+/*! BIT_initCStream() :
+ * `dstCapacity` must be > sizeof(size_t)
+ * @return : 0 if success,
+ * otherwise an error code (can be tested using ERR_isError()) */
+MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,
+ void* startPtr, size_t dstCapacity)
+{
+ bitC->bitContainer = 0;
+ bitC->bitPos = 0;
+ bitC->startPtr = (char*)startPtr;
+ bitC->ptr = bitC->startPtr;
+ bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);
+ if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);
+ return 0;
+}
+
+/*! BIT_addBits() :
+ * can add up to 31 bits into `bitC`.
+ * Note : does not check for register overflow ! */
+MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,
+ size_t value, unsigned nbBits)
+{
+ DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32);
+ assert(nbBits < BIT_MASK_SIZE);
+ assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
+ bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos;
+ bitC->bitPos += nbBits;
+}
+
+/*! BIT_addBitsFast() :
+ * works only if `value` is _clean_,
+ * meaning all high bits above nbBits are 0 */
+MEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,
+ size_t value, unsigned nbBits)
+{
+ assert((value>>nbBits) == 0);
+ assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);
+ bitC->bitContainer |= value << bitC->bitPos;
+ bitC->bitPos += nbBits;
+}
+
+/*! BIT_flushBitsFast() :
+ * assumption : bitContainer has not overflowed
+ * unsafe version; does not check buffer overflow */
+MEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)
+{
+ size_t const nbBytes = bitC->bitPos >> 3;
+ assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
+ assert(bitC->ptr <= bitC->endPtr);
+ MEM_writeLEST(bitC->ptr, bitC->bitContainer);
+ bitC->ptr += nbBytes;
+ bitC->bitPos &= 7;
+ bitC->bitContainer >>= nbBytes*8;
+}
+
+/*! BIT_flushBits() :
+ * assumption : bitContainer has not overflowed
+ * safe version; check for buffer overflow, and prevents it.
+ * note : does not signal buffer overflow.
+ * overflow will be revealed later on using BIT_closeCStream() */
+MEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)
+{
+ size_t const nbBytes = bitC->bitPos >> 3;
+ assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);
+ assert(bitC->ptr <= bitC->endPtr);
+ MEM_writeLEST(bitC->ptr, bitC->bitContainer);
+ bitC->ptr += nbBytes;
+ if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
+ bitC->bitPos &= 7;
+ bitC->bitContainer >>= nbBytes*8;
+}
+
+/*! BIT_closeCStream() :
+ * @return : size of CStream, in bytes,
+ * or 0 if it could not fit into dstBuffer */
+MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)
+{
+ BIT_addBitsFast(bitC, 1, 1); /* endMark */
+ BIT_flushBits(bitC);
+ if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
+ return (bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);
+}
+
+
+/*-********************************************************
+* bitStream decoding
+**********************************************************/
+/*! BIT_initDStream() :
+ * Initialize a BIT_DStream_t.
+ * `bitD` : a pointer to an already allocated BIT_DStream_t structure.
+ * `srcSize` must be the *exact* size of the bitStream, in bytes.
+ * @return : size of stream (== srcSize), or an errorCode if a problem is detected
+ */
+MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)
+{
+ if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }
+
+ bitD->start = (const char*)srcBuffer;
+ bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);
+
+ if (srcSize >= sizeof(bitD->bitContainer)) { /* normal case */
+ bitD->ptr = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);
+ bitD->bitContainer = MEM_readLEST(bitD->ptr);
+ { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
+ bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0; /* ensures bitsConsumed is always set */
+ if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }
+ } else {
+ bitD->ptr = bitD->start;
+ bitD->bitContainer = *(const BYTE*)(bitD->start);
+ switch(srcSize)
+ {
+ case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
+ ZSTD_FALLTHROUGH;
+
+ case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
+ ZSTD_FALLTHROUGH;
+
+ case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
+ ZSTD_FALLTHROUGH;
+
+ case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
+ ZSTD_FALLTHROUGH;
+
+ case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
+ ZSTD_FALLTHROUGH;
+
+ case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
+ ZSTD_FALLTHROUGH;
+
+ default: break;
+ }
+ { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];
+ bitD->bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
+ if (lastByte == 0) return ERROR(corruption_detected); /* endMark not present */
+ }
+ bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;
+ }
+
+ return srcSize;
+}
+
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start)
+{
+ return bitContainer >> start;
+}
+
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits)
+{
+ U32 const regMask = sizeof(bitContainer)*8 - 1;
+ /* if start > regMask, bitstream is corrupted, and result is undefined */
+ assert(nbBits < BIT_MASK_SIZE);
+ /* x86 transform & ((1 << nbBits) - 1) to bzhi instruction, it is better
+ * than accessing memory. When bmi2 instruction is not present, we consider
+ * such cpus old (pre-Haswell, 2013) and their performance is not of that
+ * importance.
+ */
+#if defined(__x86_64__) || defined(_M_X86)
+ return (bitContainer >> (start & regMask)) & ((((U64)1) << nbBits) - 1);
+#else
+ return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
+#endif
+}
+
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
+{
+ assert(nbBits < BIT_MASK_SIZE);
+ return bitContainer & BIT_mask[nbBits];
+}
+
+/*! BIT_lookBits() :
+ * Provides next n bits from local register.
+ * local register is not modified.
+ * On 32-bits, maxNbBits==24.
+ * On 64-bits, maxNbBits==56.
+ * @return : value extracted */
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits)
+{
+ /* arbitrate between double-shift and shift+mask */
+#if 1
+ /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,
+ * bitstream is likely corrupted, and result is undefined */
+ return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);
+#else
+ /* this code path is slower on my os-x laptop */
+ U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
+ return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);
+#endif
+}
+
+/*! BIT_lookBitsFast() :
+ * unsafe version; only works if nbBits >= 1 */
+MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)
+{
+ U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;
+ assert(nbBits >= 1);
+ return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);
+}
+
+MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)
+{
+ bitD->bitsConsumed += nbBits;
+}
+
+/*! BIT_readBits() :
+ * Read (consume) next n bits from local register and update.
+ * Pay attention to not read more than nbBits contained into local register.
+ * @return : extracted value. */
+MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)
+{
+ size_t const value = BIT_lookBits(bitD, nbBits);
+ BIT_skipBits(bitD, nbBits);
+ return value;
+}
+
+/*! BIT_readBitsFast() :
+ * unsafe version; only works only if nbBits >= 1 */
+MEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)
+{
+ size_t const value = BIT_lookBitsFast(bitD, nbBits);
+ assert(nbBits >= 1);
+ BIT_skipBits(bitD, nbBits);
+ return value;
+}
+
+/*! BIT_reloadDStreamFast() :
+ * Similar to BIT_reloadDStream(), but with two differences:
+ * 1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!
+ * 2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this
+ * point you must use BIT_reloadDStream() to reload.
+ */
+MEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)
+{
+ if (UNLIKELY(bitD->ptr < bitD->limitPtr))
+ return BIT_DStream_overflow;
+ assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);
+ bitD->ptr -= bitD->bitsConsumed >> 3;
+ bitD->bitsConsumed &= 7;
+ bitD->bitContainer = MEM_readLEST(bitD->ptr);
+ return BIT_DStream_unfinished;
+}
+
+/*! BIT_reloadDStream() :
+ * Refill `bitD` from buffer previously set in BIT_initDStream() .
+ * This function is safe, it guarantees it will not read beyond src buffer.
+ * @return : status of `BIT_DStream_t` internal register.
+ * when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */
+MEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)
+{
+ if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8)) /* overflow detected, like end of stream */
+ return BIT_DStream_overflow;
+
+ if (bitD->ptr >= bitD->limitPtr) {
+ return BIT_reloadDStreamFast(bitD);
+ }
+ if (bitD->ptr == bitD->start) {
+ if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;
+ return BIT_DStream_completed;
+ }
+ /* start < ptr < limitPtr */
+ { U32 nbBytes = bitD->bitsConsumed >> 3;
+ BIT_DStream_status result = BIT_DStream_unfinished;
+ if (bitD->ptr - nbBytes < bitD->start) {
+ nbBytes = (U32)(bitD->ptr - bitD->start); /* ptr > start */
+ result = BIT_DStream_endOfBuffer;
+ }
+ bitD->ptr -= nbBytes;
+ bitD->bitsConsumed -= nbBytes*8;
+ bitD->bitContainer = MEM_readLEST(bitD->ptr); /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */
+ return result;
+ }
+}
+
+/*! BIT_endOfDStream() :
+ * @return : 1 if DStream has _exactly_ reached its end (all bits consumed).
+ */
+MEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)
+{
+ return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));
+}
+
+
+#endif /* BITSTREAM_H_MODULE */
diff --git a/lib/zstd/common/compiler.h b/lib/zstd/common/compiler.h
new file mode 100644
index 0000000..c42d39f
--- /dev/null
+++ b/lib/zstd/common/compiler.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_COMPILER_H
+#define ZSTD_COMPILER_H
+
+#include "portability_macros.h"
+
+/*-*******************************************************
+* Compiler specifics
+*********************************************************/
+/* force inlining */
+
+#if !defined(ZSTD_NO_INLINE)
+#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
+# define INLINE_KEYWORD inline
+#else
+# define INLINE_KEYWORD
+#endif
+
+#define FORCE_INLINE_ATTR __attribute__((always_inline))
+
+#else
+
+#define INLINE_KEYWORD
+#define FORCE_INLINE_ATTR
+
+#endif
+
+/*
+ On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
+ This explicitly marks such functions as __cdecl so that the code will still compile
+ if a CC other than __cdecl has been made the default.
+*/
+#define WIN_CDECL
+
+/*
+ * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant
+ * parameters. They must be inlined for the compiler to eliminate the constant
+ * branches.
+ */
+#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
+/*
+ * HINT_INLINE is used to help the compiler generate better code. It is *not*
+ * used for "templates", so it can be tweaked based on the compilers
+ * performance.
+ *
+ * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the
+ * always_inline attribute.
+ *
+ * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline
+ * attribute.
+ */
+#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5
+# define HINT_INLINE static INLINE_KEYWORD
+#else
+# define HINT_INLINE static INLINE_KEYWORD FORCE_INLINE_ATTR
+#endif
+
+/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */
+#define UNUSED_ATTR __attribute__((unused))
+
+/* force no inlining */
+#define FORCE_NOINLINE static __attribute__((__noinline__))
+
+
+/* target attribute */
+#define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
+
+/* Target attribute for BMI2 dynamic dispatch.
+ * Enable lzcnt, bmi, and bmi2.
+ * We test for bmi1 & bmi2. lzcnt is included in bmi1.
+ */
+#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2")
+
+/* prefetch
+ * can be disabled, by declaring NO_PREFETCH build macro */
+#if ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
+# define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
+# define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)
+#elif defined(__aarch64__)
+# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr)))
+# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr)))
+#else
+# define PREFETCH_L1(ptr) (void)(ptr) /* disabled */
+# define PREFETCH_L2(ptr) (void)(ptr) /* disabled */
+#endif /* NO_PREFETCH */
+
+#define CACHELINE_SIZE 64
+
+#define PREFETCH_AREA(p, s) { \
+ const char* const _ptr = (const char*)(p); \
+ size_t const _size = (size_t)(s); \
+ size_t _pos; \
+ for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \
+ PREFETCH_L2(_ptr + _pos); \
+ } \
+}
+
+/* vectorization
+ * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,
+ * and some compilers, like Intel ICC and MCST LCC, do not support it at all. */
+#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)
+# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
+# else
+# define DONT_VECTORIZE _Pragma("GCC optimize(\"no-tree-vectorize\")")
+# endif
+#else
+# define DONT_VECTORIZE
+#endif
+
+/* Tell the compiler that a branch is likely or unlikely.
+ * Only use these macros if it causes the compiler to generate better code.
+ * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc
+ * and clang, please do.
+ */
+#define LIKELY(x) (__builtin_expect((x), 1))
+#define UNLIKELY(x) (__builtin_expect((x), 0))
+
+#if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))
+# define ZSTD_UNREACHABLE { assert(0), __builtin_unreachable(); }
+#else
+# define ZSTD_UNREACHABLE { assert(0); }
+#endif
+
+/* disable warnings */
+
+/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/
+
+
+/* compile time determination of SIMD support */
+
+/* C-language Attributes are added in C23. */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
+# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
+#else
+# define ZSTD_HAS_C_ATTRIBUTE(x) 0
+#endif
+
+/* Only use C++ attributes in C++. Some compilers report support for C++
+ * attributes when compiling with C.
+ */
+#define ZSTD_HAS_CPP_ATTRIBUTE(x) 0
+
+/* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute.
+ * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough
+ * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough
+ * - Else: __attribute__((__fallthrough__))
+ */
+#define ZSTD_FALLTHROUGH fallthrough
+
+/*-**************************************************************
+* Alignment check
+*****************************************************************/
+
+/* this test was initially positioned in mem.h,
+ * but this file is removed (or replaced) for linux kernel
+ * so it's now hosted in compiler.h,
+ * which remains valid for both user & kernel spaces.
+ */
+
+#ifndef ZSTD_ALIGNOF
+/* covers gcc, clang & MSVC */
+/* note : this section must come first, before C11,
+ * due to a limitation in the kernel source generator */
+# define ZSTD_ALIGNOF(T) __alignof(T)
+
+#endif /* ZSTD_ALIGNOF */
+
+/*-**************************************************************
+* Sanitizer
+*****************************************************************/
+
+
+
+#endif /* ZSTD_COMPILER_H */
diff --git a/lib/zstd/common/cpu.h b/lib/zstd/common/cpu.h
new file mode 100644
index 0000000..0db7b42
--- /dev/null
+++ b/lib/zstd/common/cpu.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_COMMON_CPU_H
+#define ZSTD_COMMON_CPU_H
+
+/*
+ * Implementation taken from folly/CpuId.h
+ * https://github.com/facebook/folly/blob/master/folly/CpuId.h
+ */
+
+#include "mem.h"
+
+
+typedef struct {
+ U32 f1c;
+ U32 f1d;
+ U32 f7b;
+ U32 f7c;
+} ZSTD_cpuid_t;
+
+MEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {
+ U32 f1c = 0;
+ U32 f1d = 0;
+ U32 f7b = 0;
+ U32 f7c = 0;
+#if defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)
+ /* The following block like the normal cpuid branch below, but gcc
+ * reserves ebx for use of its pic register so we must specially
+ * handle the save and restore to avoid clobbering the register
+ */
+ U32 n;
+ __asm__(
+ "pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "popl %%ebx\n\t"
+ : "=a"(n)
+ : "a"(0)
+ : "ecx", "edx");
+ if (n >= 1) {
+ U32 f1a;
+ __asm__(
+ "pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "popl %%ebx\n\t"
+ : "=a"(f1a), "=c"(f1c), "=d"(f1d)
+ : "a"(1));
+ }
+ if (n >= 7) {
+ __asm__(
+ "pushl %%ebx\n\t"
+ "cpuid\n\t"
+ "movl %%ebx, %%eax\n\t"
+ "popl %%ebx"
+ : "=a"(f7b), "=c"(f7c)
+ : "a"(7), "c"(0)
+ : "edx");
+ }
+#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)
+ U32 n;
+ __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
+ if (n >= 1) {
+ U32 f1a;
+ __asm__("cpuid" : "=a"(f1a), "=c"(f1c), "=d"(f1d) : "a"(1) : "ebx");
+ }
+ if (n >= 7) {
+ U32 f7a;
+ __asm__("cpuid"
+ : "=a"(f7a), "=b"(f7b), "=c"(f7c)
+ : "a"(7), "c"(0)
+ : "edx");
+ }
+#endif
+ {
+ ZSTD_cpuid_t cpuid;
+ cpuid.f1c = f1c;
+ cpuid.f1d = f1d;
+ cpuid.f7b = f7b;
+ cpuid.f7c = f7c;
+ return cpuid;
+ }
+}
+
+#define X(name, r, bit) \
+ MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) { \
+ return ((cpuid.r) & (1U << bit)) != 0; \
+ }
+
+/* cpuid(1): Processor Info and Feature Bits. */
+#define C(name, bit) X(name, f1c, bit)
+ C(sse3, 0)
+ C(pclmuldq, 1)
+ C(dtes64, 2)
+ C(monitor, 3)
+ C(dscpl, 4)
+ C(vmx, 5)
+ C(smx, 6)
+ C(eist, 7)
+ C(tm2, 8)
+ C(ssse3, 9)
+ C(cnxtid, 10)
+ C(fma, 12)
+ C(cx16, 13)
+ C(xtpr, 14)
+ C(pdcm, 15)
+ C(pcid, 17)
+ C(dca, 18)
+ C(sse41, 19)
+ C(sse42, 20)
+ C(x2apic, 21)
+ C(movbe, 22)
+ C(popcnt, 23)
+ C(tscdeadline, 24)
+ C(aes, 25)
+ C(xsave, 26)
+ C(osxsave, 27)
+ C(avx, 28)
+ C(f16c, 29)
+ C(rdrand, 30)
+#undef C
+#define D(name, bit) X(name, f1d, bit)
+ D(fpu, 0)
+ D(vme, 1)
+ D(de, 2)
+ D(pse, 3)
+ D(tsc, 4)
+ D(msr, 5)
+ D(pae, 6)
+ D(mce, 7)
+ D(cx8, 8)
+ D(apic, 9)
+ D(sep, 11)
+ D(mtrr, 12)
+ D(pge, 13)
+ D(mca, 14)
+ D(cmov, 15)
+ D(pat, 16)
+ D(pse36, 17)
+ D(psn, 18)
+ D(clfsh, 19)
+ D(ds, 21)
+ D(acpi, 22)
+ D(mmx, 23)
+ D(fxsr, 24)
+ D(sse, 25)
+ D(sse2, 26)
+ D(ss, 27)
+ D(htt, 28)
+ D(tm, 29)
+ D(pbe, 31)
+#undef D
+
+/* cpuid(7): Extended Features. */
+#define B(name, bit) X(name, f7b, bit)
+ B(bmi1, 3)
+ B(hle, 4)
+ B(avx2, 5)
+ B(smep, 7)
+ B(bmi2, 8)
+ B(erms, 9)
+ B(invpcid, 10)
+ B(rtm, 11)
+ B(mpx, 14)
+ B(avx512f, 16)
+ B(avx512dq, 17)
+ B(rdseed, 18)
+ B(adx, 19)
+ B(smap, 20)
+ B(avx512ifma, 21)
+ B(pcommit, 22)
+ B(clflushopt, 23)
+ B(clwb, 24)
+ B(avx512pf, 26)
+ B(avx512er, 27)
+ B(avx512cd, 28)
+ B(sha, 29)
+ B(avx512bw, 30)
+ B(avx512vl, 31)
+#undef B
+#define C(name, bit) X(name, f7c, bit)
+ C(prefetchwt1, 0)
+ C(avx512vbmi, 1)
+#undef C
+
+#undef X
+
+#endif /* ZSTD_COMMON_CPU_H */
diff --git a/lib/zstd/common/debug.c b/lib/zstd/common/debug.c
new file mode 100644
index 0000000..bb863c9
--- /dev/null
+++ b/lib/zstd/common/debug.c
@@ -0,0 +1,24 @@
+/* ******************************************************************
+ * debug
+ * Part of FSE library
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+
+
+/*
+ * This module only hosts one global variable
+ * which can be used to dynamically influence the verbosity of traces,
+ * such as DEBUGLOG and RAWLOG
+ */
+
+#include "debug.h"
+
+int g_debuglevel = DEBUGLEVEL;
diff --git a/lib/zstd/common/debug.h b/lib/zstd/common/debug.h
new file mode 100644
index 0000000..7f43dd3
--- /dev/null
+++ b/lib/zstd/common/debug.h
@@ -0,0 +1,92 @@
+/* ******************************************************************
+ * debug
+ * Part of FSE library
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+
+
+/*
+ * The purpose of this header is to enable debug functions.
+ * They regroup assert(), DEBUGLOG() and RAWLOG() for run-time,
+ * and DEBUG_STATIC_ASSERT() for compile-time.
+ *
+ * By default, DEBUGLEVEL==0, which means run-time debug is disabled.
+ *
+ * Level 1 enables assert() only.
+ * Starting level 2, traces can be generated and pushed to stderr.
+ * The higher the level, the more verbose the traces.
+ *
+ * It's possible to dynamically adjust level using variable g_debug_level,
+ * which is only declared if DEBUGLEVEL>=2,
+ * and is a global variable, not multi-thread protected (use with care)
+ */
+
+#ifndef DEBUG_H_12987983217
+#define DEBUG_H_12987983217
+
+
+
+/* static assert is triggered at compile time, leaving no runtime artefact.
+ * static assert only works with compile-time constants.
+ * Also, this variant can only be used inside a function. */
+#define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1])
+
+
+/* DEBUGLEVEL is expected to be defined externally,
+ * typically through compiler command line.
+ * Value must be a number. */
+#ifndef DEBUGLEVEL
+# define DEBUGLEVEL 0
+#endif
+
+
+/* recommended values for DEBUGLEVEL :
+ * 0 : release mode, no debug, all run-time checks disabled
+ * 1 : enables assert() only, no display
+ * 2 : reserved, for currently active debug path
+ * 3 : events once per object lifetime (CCtx, CDict, etc.)
+ * 4 : events once per frame
+ * 5 : events once per block
+ * 6 : events once per sequence (verbose)
+ * 7+: events at every position (*very* verbose)
+ *
+ * It's generally inconvenient to output traces > 5.
+ * In which case, it's possible to selectively trigger high verbosity levels
+ * by modifying g_debug_level.
+ */
+
+#if (DEBUGLEVEL>=2)
+# define ZSTD_DEPS_NEED_IO
+# include "zstd_deps.h"
+extern int g_debuglevel; /* the variable is only declared,
+ it actually lives in debug.c,
+ and is shared by the whole process.
+ It's not thread-safe.
+ It's useful when enabling very verbose levels
+ on selective conditions (such as position in src) */
+
+# define RAWLOG(l, ...) { \
+ if (l<=g_debuglevel) { \
+ ZSTD_DEBUG_PRINT(__VA_ARGS__); \
+ } }
+# define DEBUGLOG(l, ...) { \
+ if (l<=g_debuglevel) { \
+ ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \
+ ZSTD_DEBUG_PRINT(" \n"); \
+ } }
+#else
+# define RAWLOG(l, ...) {} /* disabled */
+# define DEBUGLOG(l, ...) {} /* disabled */
+#endif
+
+
+
+#endif /* DEBUG_H_12987983217 */
diff --git a/lib/zstd/common/entropy_common.c b/lib/zstd/common/entropy_common.c
new file mode 100644
index 0000000..fef6705
--- /dev/null
+++ b/lib/zstd/common/entropy_common.c
@@ -0,0 +1,357 @@
+/* ******************************************************************
+ * Common functions of New Generation Entropy library
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum : https://groups.google.com/forum/#!forum/lz4c
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+
+/* *************************************
+* Dependencies
+***************************************/
+#include "mem.h"
+#include "error_private.h" /* ERR_*, ERROR */
+#define FSE_STATIC_LINKING_ONLY /* FSE_MIN_TABLELOG */
+#include "fse.h"
+#define HUF_STATIC_LINKING_ONLY /* HUF_TABLELOG_ABSOLUTEMAX */
+#include "huf.h"
+
+
+/*=== Version ===*/
+unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
+
+
+/*=== Error Management ===*/
+unsigned FSE_isError(size_t code) { return ERR_isError(code); }
+const char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }
+
+unsigned HUF_isError(size_t code) { return ERR_isError(code); }
+const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }
+
+
+/*-**************************************************************
+* FSE NCount encoding-decoding
+****************************************************************/
+static U32 FSE_ctz(U32 val)
+{
+ assert(val != 0);
+ {
+# if (__GNUC__ >= 3) /* GCC Intrinsic */
+ return __builtin_ctz(val);
+# else /* Software version */
+ U32 count = 0;
+ while ((val & 1) == 0) {
+ val >>= 1;
+ ++count;
+ }
+ return count;
+# endif
+ }
+}
+
+FORCE_INLINE_TEMPLATE
+size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
+{
+ const BYTE* const istart = (const BYTE*) headerBuffer;
+ const BYTE* const iend = istart + hbSize;
+ const BYTE* ip = istart;
+ int nbBits;
+ int remaining;
+ int threshold;
+ U32 bitStream;
+ int bitCount;
+ unsigned charnum = 0;
+ unsigned const maxSV1 = *maxSVPtr + 1;
+ int previous0 = 0;
+
+ if (hbSize < 8) {
+ /* This function only works when hbSize >= 8 */
+ char buffer[8] = {0};
+ ZSTD_memcpy(buffer, headerBuffer, hbSize);
+ { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,
+ buffer, sizeof(buffer));
+ if (FSE_isError(countSize)) return countSize;
+ if (countSize > hbSize) return ERROR(corruption_detected);
+ return countSize;
+ } }
+ assert(hbSize >= 8);
+
+ /* init */
+ ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */
+ bitStream = MEM_readLE32(ip);
+ nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
+ if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);
+ bitStream >>= 4;
+ bitCount = 4;
+ *tableLogPtr = nbBits;
+ remaining = (1<<nbBits)+1;
+ threshold = 1<<nbBits;
+ nbBits++;
+
+ for (;;) {
+ if (previous0) {
+ /* Count the number of repeats. Each time the
+ * 2-bit repeat code is 0b11 there is another
+ * repeat.
+ * Avoid UB by setting the high bit to 1.
+ */
+ int repeats = FSE_ctz(~bitStream | 0x80000000) >> 1;
+ while (repeats >= 12) {
+ charnum += 3 * 12;
+ if (LIKELY(ip <= iend-7)) {
+ ip += 3;
+ } else {
+ bitCount -= (int)(8 * (iend - 7 - ip));
+ bitCount &= 31;
+ ip = iend - 4;
+ }
+ bitStream = MEM_readLE32(ip) >> bitCount;
+ repeats = FSE_ctz(~bitStream | 0x80000000) >> 1;
+ }
+ charnum += 3 * repeats;
+ bitStream >>= 2 * repeats;
+ bitCount += 2 * repeats;
+
+ /* Add the final repeat which isn't 0b11. */
+ assert((bitStream & 3) < 3);
+ charnum += bitStream & 3;
+ bitCount += 2;
+
+ /* This is an error, but break and return an error
+ * at the end, because returning out of a loop makes
+ * it harder for the compiler to optimize.
+ */
+ if (charnum >= maxSV1) break;
+
+ /* We don't need to set the normalized count to 0
+ * because we already memset the whole buffer to 0.
+ */
+
+ if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
+ assert((bitCount >> 3) <= 3); /* For first condition to work */
+ ip += bitCount>>3;
+ bitCount &= 7;
+ } else {
+ bitCount -= (int)(8 * (iend - 4 - ip));
+ bitCount &= 31;
+ ip = iend - 4;
+ }
+ bitStream = MEM_readLE32(ip) >> bitCount;
+ }
+ {
+ int const max = (2*threshold-1) - remaining;
+ int count;
+
+ if ((bitStream & (threshold-1)) < (U32)max) {
+ count = bitStream & (threshold-1);
+ bitCount += nbBits-1;
+ } else {
+ count = bitStream & (2*threshold-1);
+ if (count >= threshold) count -= max;
+ bitCount += nbBits;
+ }
+
+ count--; /* extra accuracy */
+ /* When it matters (small blocks), this is a
+ * predictable branch, because we don't use -1.
+ */
+ if (count >= 0) {
+ remaining -= count;
+ } else {
+ assert(count == -1);
+ remaining += count;
+ }
+ normalizedCounter[charnum++] = (short)count;
+ previous0 = !count;
+
+ assert(threshold > 1);
+ if (remaining < threshold) {
+ /* This branch can be folded into the
+ * threshold update condition because we
+ * know that threshold > 1.
+ */
+ if (remaining <= 1) break;
+ nbBits = BIT_highbit32(remaining) + 1;
+ threshold = 1 << (nbBits - 1);
+ }
+ if (charnum >= maxSV1) break;
+
+ if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {
+ ip += bitCount>>3;
+ bitCount &= 7;
+ } else {
+ bitCount -= (int)(8 * (iend - 4 - ip));
+ bitCount &= 31;
+ ip = iend - 4;
+ }
+ bitStream = MEM_readLE32(ip) >> bitCount;
+ } }
+ if (remaining != 1) return ERROR(corruption_detected);
+ /* Only possible when there are too many zeros. */
+ if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall);
+ if (bitCount > 32) return ERROR(corruption_detected);
+ *maxSVPtr = charnum-1;
+
+ ip += (bitCount+7)>>3;
+ return ip-istart;
+}
+
+/* Avoids the FORCE_INLINE of the _body() function. */
+static size_t FSE_readNCount_body_default(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
+{
+ return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+}
+
+#if DYNAMIC_BMI2
+BMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
+{
+ return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+}
+#endif
+
+size_t FSE_readNCount_bmi2(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+ }
+#endif
+ (void)bmi2;
+ return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);
+}
+
+size_t FSE_readNCount(
+ short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
+ const void* headerBuffer, size_t hbSize)
+{
+ return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0);
+}
+
+
+/*! HUF_readStats() :
+ Read compact Huffman tree, saved by HUF_writeCTable().
+ `huffWeight` is destination buffer.
+ `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
+ @return : size read from `src` , or an error Code .
+ Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
+*/
+size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize)
+{
+ U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
+ return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0);
+}
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize,
+ int bmi2)
+{
+ U32 weightTotal;
+ const BYTE* ip = (const BYTE*) src;
+ size_t iSize;
+ size_t oSize;
+
+ if (!srcSize) return ERROR(srcSize_wrong);
+ iSize = ip[0];
+ /* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */
+
+ if (iSize >= 128) { /* special header */
+ oSize = iSize - 127;
+ iSize = ((oSize+1)/2);
+ if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
+ if (oSize >= hwSize) return ERROR(corruption_detected);
+ ip += 1;
+ { U32 n;
+ for (n=0; n<oSize; n+=2) {
+ huffWeight[n] = ip[n/2] >> 4;
+ huffWeight[n+1] = ip[n/2] & 15;
+ } } }
+ else { /* header compressed with FSE (normal case) */
+ if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
+ /* max (hwSize-1) values decoded, as last one is implied */
+ oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2);
+ if (FSE_isError(oSize)) return oSize;
+ }
+
+ /* collect weight stats */
+ ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
+ weightTotal = 0;
+ { U32 n; for (n=0; n<oSize; n++) {
+ if (huffWeight[n] > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
+ rankStats[huffWeight[n]]++;
+ weightTotal += (1 << huffWeight[n]) >> 1;
+ } }
+ if (weightTotal == 0) return ERROR(corruption_detected);
+
+ /* get last non-null symbol weight (implied, total must be 2^n) */
+ { U32 const tableLog = BIT_highbit32(weightTotal) + 1;
+ if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
+ *tableLogPtr = tableLog;
+ /* determine last weight */
+ { U32 const total = 1 << tableLog;
+ U32 const rest = total - weightTotal;
+ U32 const verif = 1 << BIT_highbit32(rest);
+ U32 const lastWeight = BIT_highbit32(rest) + 1;
+ if (verif != rest) return ERROR(corruption_detected); /* last value must be a clean power of 2 */
+ huffWeight[oSize] = (BYTE)lastWeight;
+ rankStats[lastWeight]++;
+ } }
+
+ /* check tree construction validity */
+ if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
+
+ /* results */
+ *nbSymbolsPtr = (U32)(oSize+1);
+ return iSize+1;
+}
+
+/* Avoids the FORCE_INLINE of the _body() function. */
+static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0);
+}
+
+#if DYNAMIC_BMI2
+static BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1);
+}
+#endif
+
+size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+ U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize,
+ int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
+ }
+#endif
+ (void)bmi2;
+ return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);
+}
diff --git a/lib/zstd/common/error_private.c b/lib/zstd/common/error_private.c
new file mode 100644
index 0000000..6d1135f
--- /dev/null
+++ b/lib/zstd/common/error_private.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/* The purpose of this file is to have a single list of error strings embedded in binary */
+
+#include "error_private.h"
+
+const char* ERR_getErrorString(ERR_enum code)
+{
+#ifdef ZSTD_STRIP_ERROR_STRINGS
+ (void)code;
+ return "Error strings stripped";
+#else
+ static const char* const notErrorCode = "Unspecified error code";
+ switch( code )
+ {
+ case PREFIX(no_error): return "No error detected";
+ case PREFIX(GENERIC): return "Error (generic)";
+ case PREFIX(prefix_unknown): return "Unknown frame descriptor";
+ case PREFIX(version_unsupported): return "Version not supported";
+ case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
+ case PREFIX(frameParameter_windowTooLarge): return "Frame requires too much memory for decoding";
+ case PREFIX(corruption_detected): return "Corrupted block detected";
+ case PREFIX(checksum_wrong): return "Restored data doesn't match checksum";
+ case PREFIX(parameter_unsupported): return "Unsupported parameter";
+ case PREFIX(parameter_outOfBound): return "Parameter is out of bound";
+ case PREFIX(init_missing): return "Context should be init first";
+ case PREFIX(memory_allocation): return "Allocation error : not enough memory";
+ case PREFIX(workSpace_tooSmall): return "workSpace buffer is not large enough";
+ case PREFIX(stage_wrong): return "Operation not authorized at current processing stage";
+ case PREFIX(tableLog_tooLarge): return "tableLog requires too much memory : unsupported";
+ case PREFIX(maxSymbolValue_tooLarge): return "Unsupported max Symbol Value : too large";
+ case PREFIX(maxSymbolValue_tooSmall): return "Specified maxSymbolValue is too small";
+ case PREFIX(dictionary_corrupted): return "Dictionary is corrupted";
+ case PREFIX(dictionary_wrong): return "Dictionary mismatch";
+ case PREFIX(dictionaryCreation_failed): return "Cannot create Dictionary from provided samples";
+ case PREFIX(dstSize_tooSmall): return "Destination buffer is too small";
+ case PREFIX(srcSize_wrong): return "Src size is incorrect";
+ case PREFIX(dstBuffer_null): return "Operation on NULL destination buffer";
+ /* following error codes are not stable and may be removed or changed in a future version */
+ case PREFIX(frameIndex_tooLarge): return "Frame index is too large";
+ case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking";
+ case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong";
+ case PREFIX(srcBuffer_wrong): return "Source buffer is wrong";
+ case PREFIX(maxCode):
+ default: return notErrorCode;
+ }
+#endif
+}
diff --git a/lib/zstd/common/error_private.h b/lib/zstd/common/error_private.h
new file mode 100644
index 0000000..ca5101e
--- /dev/null
+++ b/lib/zstd/common/error_private.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/* Note : this module is expected to remain private, do not expose it */
+
+#ifndef ERROR_H_MODULE
+#define ERROR_H_MODULE
+
+
+
+/* ****************************************
+* Dependencies
+******************************************/
+#include <linux/zstd_errors.h> /* enum list */
+#include "compiler.h"
+#include "debug.h"
+#include "zstd_deps.h" /* size_t */
+
+
+/* ****************************************
+* Compiler-specific
+******************************************/
+#define ERR_STATIC static __attribute__((unused))
+
+
+/*-****************************************
+* Customization (error_public.h)
+******************************************/
+typedef ZSTD_ErrorCode ERR_enum;
+#define PREFIX(name) ZSTD_error_##name
+
+
+/*-****************************************
+* Error codes handling
+******************************************/
+#undef ERROR /* already defined on Visual Studio */
+#define ERROR(name) ZSTD_ERROR(name)
+#define ZSTD_ERROR(name) ((size_t)-PREFIX(name))
+
+ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
+
+ERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }
+
+/* check and forward error code */
+#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e
+#define CHECK_F(f) { CHECK_V_F(_var_err__, f); }
+
+
+/*-****************************************
+* Error Strings
+******************************************/
+
+const char* ERR_getErrorString(ERR_enum code); /* error_private.c */
+
+ERR_STATIC const char* ERR_getErrorName(size_t code)
+{
+ return ERR_getErrorString(ERR_getErrorCode(code));
+}
+
+/*
+ * Ignore: this is an internal helper.
+ *
+ * This is a helper function to help force C99-correctness during compilation.
+ * Under strict compilation modes, variadic macro arguments can't be empty.
+ * However, variadic function arguments can be. Using a function therefore lets
+ * us statically check that at least one (string) argument was passed,
+ * independent of the compilation flags.
+ */
+static INLINE_KEYWORD UNUSED_ATTR
+void _force_has_format_string(const char *format, ...) {
+ (void)format;
+}
+
+/*
+ * Ignore: this is an internal helper.
+ *
+ * We want to force this function invocation to be syntactically correct, but
+ * we don't want to force runtime evaluation of its arguments.
+ */
+#define _FORCE_HAS_FORMAT_STRING(...) \
+ if (0) { \
+ _force_has_format_string(__VA_ARGS__); \
+ }
+
+#define ERR_QUOTE(str) #str
+
+/*
+ * Return the specified error if the condition evaluates to true.
+ *
+ * In debug modes, prints additional information.
+ * In order to do that (particularly, printing the conditional that failed),
+ * this can't just wrap RETURN_ERROR().
+ */
+#define RETURN_ERROR_IF(cond, err, ...) \
+ if (cond) { \
+ RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
+ __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return ERROR(err); \
+ }
+
+/*
+ * Unconditionally return the specified error.
+ *
+ * In debug modes, prints additional information.
+ */
+#define RETURN_ERROR(err, ...) \
+ do { \
+ RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
+ __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return ERROR(err); \
+ } while(0);
+
+/*
+ * If the provided expression evaluates to an error code, returns that error code.
+ *
+ * In debug modes, prints additional information.
+ */
+#define FORWARD_IF_ERROR(err, ...) \
+ do { \
+ size_t const err_code = (err); \
+ if (ERR_isError(err_code)) { \
+ RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
+ __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return err_code; \
+ } \
+ } while(0);
+
+
+#endif /* ERROR_H_MODULE */
diff --git a/lib/zstd/common/fse.h b/lib/zstd/common/fse.h
new file mode 100644
index 0000000..4507043
--- /dev/null
+++ b/lib/zstd/common/fse.h
@@ -0,0 +1,711 @@
+/* ******************************************************************
+ * FSE : Finite State Entropy codec
+ * Public Prototypes declaration
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+
+
+#ifndef FSE_H
+#define FSE_H
+
+
+/*-*****************************************
+* Dependencies
+******************************************/
+#include "zstd_deps.h" /* size_t, ptrdiff_t */
+
+
+/*-*****************************************
+* FSE_PUBLIC_API : control library symbols visibility
+******************************************/
+#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
+# define FSE_PUBLIC_API __attribute__ ((visibility ("default")))
+#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
+# define FSE_PUBLIC_API __declspec(dllexport)
+#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
+# define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
+#else
+# define FSE_PUBLIC_API
+#endif
+
+/*------ Version ------*/
+#define FSE_VERSION_MAJOR 0
+#define FSE_VERSION_MINOR 9
+#define FSE_VERSION_RELEASE 0
+
+#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
+#define FSE_QUOTE(str) #str
+#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
+#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
+
+#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)
+FSE_PUBLIC_API unsigned FSE_versionNumber(void); /*< library version number; to be used when checking dll version */
+
+
+/*-****************************************
+* FSE simple functions
+******************************************/
+/*! FSE_compress() :
+ Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.
+ 'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize).
+ @return : size of compressed data (<= dstCapacity).
+ Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
+ if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.
+ if FSE_isError(return), compression failed (more details using FSE_getErrorName())
+*/
+FSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize);
+
+/*! FSE_decompress():
+ Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',
+ into already allocated destination buffer 'dst', of size 'dstCapacity'.
+ @return : size of regenerated data (<= maxDstSize),
+ or an error code, which can be tested using FSE_isError() .
+
+ ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!!
+ Why ? : making this distinction requires a header.
+ Header management is intentionally delegated to the user layer, which can better manage special cases.
+*/
+FSE_PUBLIC_API size_t FSE_decompress(void* dst, size_t dstCapacity,
+ const void* cSrc, size_t cSrcSize);
+
+
+/*-*****************************************
+* Tool functions
+******************************************/
+FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
+
+/* Error Management */
+FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
+FSE_PUBLIC_API const char* FSE_getErrorName(size_t code); /* provides error code string (useful for debugging) */
+
+
+/*-*****************************************
+* FSE advanced functions
+******************************************/
+/*! FSE_compress2() :
+ Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'
+ Both parameters can be defined as '0' to mean : use default value
+ @return : size of compressed data
+ Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!
+ if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.
+ if FSE_isError(return), it's an error code.
+*/
+FSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
+
+
+/*-*****************************************
+* FSE detailed API
+******************************************/
+/*!
+FSE_compress() does the following:
+1. count symbol occurrence from source[] into table count[] (see hist.h)
+2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
+3. save normalized counters to memory buffer using writeNCount()
+4. build encoding table 'CTable' from normalized counters
+5. encode the data stream using encoding table 'CTable'
+
+FSE_decompress() does the following:
+1. read normalized counters with readNCount()
+2. build decoding table 'DTable' from normalized counters
+3. decode the data stream using decoding table 'DTable'
+
+The following API allows targeting specific sub-functions for advanced tasks.
+For example, it's possible to compress several blocks using the same 'CTable',
+or to save and provide normalized distribution using external method.
+*/
+
+/* *** COMPRESSION *** */
+
+/*! FSE_optimalTableLog():
+ dynamically downsize 'tableLog' when conditions are met.
+ It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
+ @return : recommended tableLog (necessarily <= 'maxTableLog') */
+FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
+
+/*! FSE_normalizeCount():
+ normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
+ 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
+ useLowProbCount is a boolean parameter which trades off compressed size for
+ faster header decoding. When it is set to 1, the compressed data will be slightly
+ smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be
+ faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0
+ is a good default, since header deserialization makes a big speed difference.
+ Otherwise, useLowProbCount=1 is a good default, since the speed difference is small.
+ @return : tableLog,
+ or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,
+ const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);
+
+/*! FSE_NCountWriteBound():
+ Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
+ Typically useful for allocation purpose. */
+FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
+
+/*! FSE_writeNCount():
+ Compactly save 'normalizedCounter' into 'buffer'.
+ @return : size of the compressed table,
+ or an errorCode, which can be tested using FSE_isError(). */
+FSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,
+ const short* normalizedCounter,
+ unsigned maxSymbolValue, unsigned tableLog);
+
+/*! Constructor and Destructor of FSE_CTable.
+ Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
+typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
+FSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog);
+FSE_PUBLIC_API void FSE_freeCTable (FSE_CTable* ct);
+
+/*! FSE_buildCTable():
+ Builds `ct`, which must be already allocated, using FSE_createCTable().
+ @return : 0, or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
+
+/*! FSE_compress_usingCTable():
+ Compress `src` using `ct` into `dst` which must be already allocated.
+ @return : size of compressed data (<= `dstCapacity`),
+ or 0 if compressed data could not fit into `dst`,
+ or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);
+
+/*!
+Tutorial :
+----------
+The first step is to count all symbols. FSE_count() does this job very fast.
+Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
+'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
+maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
+FSE_count() will return the number of occurrence of the most frequent symbol.
+This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
+
+The next step is to normalize the frequencies.
+FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
+It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
+You can use 'tableLog'==0 to mean "use default tableLog value".
+If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
+which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
+
+The result of FSE_normalizeCount() will be saved into a table,
+called 'normalizedCounter', which is a table of signed short.
+'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
+The return value is tableLog if everything proceeded as expected.
+It is 0 if there is a single symbol within distribution.
+If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
+
+'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
+'buffer' must be already allocated.
+For guaranteed success, buffer size must be at least FSE_headerBound().
+The result of the function is the number of bytes written into 'buffer'.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
+
+'normalizedCounter' can then be used to create the compression table 'CTable'.
+The space required by 'CTable' must be already allocated, using FSE_createCTable().
+You can then use FSE_buildCTable() to fill 'CTable'.
+If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
+
+'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
+Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
+The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
+If it returns '0', compressed data could not fit into 'dst'.
+If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
+*/
+
+
+/* *** DECOMPRESSION *** */
+
+/*! FSE_readNCount():
+ Read compactly saved 'normalizedCounter' from 'rBuffer'.
+ @return : size read from 'rBuffer',
+ or an errorCode, which can be tested using FSE_isError().
+ maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
+FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,
+ unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
+ const void* rBuffer, size_t rBuffSize);
+
+/*! FSE_readNCount_bmi2():
+ * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise.
+ */
+FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,
+ unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,
+ const void* rBuffer, size_t rBuffSize, int bmi2);
+
+/*! Constructor and Destructor of FSE_DTable.
+ Note that its size depends on 'tableLog' */
+typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
+FSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog);
+FSE_PUBLIC_API void FSE_freeDTable(FSE_DTable* dt);
+
+/*! FSE_buildDTable():
+ Builds 'dt', which must be already allocated, using FSE_createDTable().
+ return : 0, or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
+
+/*! FSE_decompress_usingDTable():
+ Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
+ into `dst` which must be already allocated.
+ @return : size of regenerated data (necessarily <= `dstCapacity`),
+ or an errorCode, which can be tested using FSE_isError() */
+FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);
+
+/*!
+Tutorial :
+----------
+(Note : these functions only decompress FSE-compressed blocks.
+ If block is uncompressed, use memcpy() instead
+ If block is a single repeated byte, use memset() instead )
+
+The first step is to obtain the normalized frequencies of symbols.
+This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
+'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
+In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
+or size the table to handle worst case situations (typically 256).
+FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
+The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
+Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
+If there is an error, the function will return an error code, which can be tested using FSE_isError().
+
+The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
+This is performed by the function FSE_buildDTable().
+The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
+If there is an error, the function will return an error code, which can be tested using FSE_isError().
+
+`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().
+`cSrcSize` must be strictly correct, otherwise decompression will fail.
+FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
+If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
+*/
+
+#endif /* FSE_H */
+
+#if !defined(FSE_H_FSE_STATIC_LINKING_ONLY)
+#define FSE_H_FSE_STATIC_LINKING_ONLY
+
+/* *** Dependency *** */
+#include "bitstream.h"
+
+
+/* *****************************************
+* Static allocation
+*******************************************/
+/* FSE buffer bounds */
+#define FSE_NCOUNTBOUND 512
+#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)
+#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
+
+/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
+#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))
+#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog)))
+
+/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */
+#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))
+#define FSE_DTABLE_SIZE(maxTableLog) (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))
+
+
+/* *****************************************
+ * FSE advanced API
+ ***************************************** */
+
+unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
+/*< same as FSE_optimalTableLog(), which used `minus==2` */
+
+/* FSE_compress_wksp() :
+ * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).
+ * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.
+ */
+#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )
+size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
+
+size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);
+/*< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
+
+size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
+/*< build a fake FSE_CTable, designed to compress always the same symbolValue */
+
+/* FSE_buildCTable_wksp() :
+ * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
+ * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.
+ * See FSE_buildCTable_wksp() for breakdown of workspace usage.
+ */
+#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */)
+#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))
+size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
+
+#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)
+#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))
+FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
+/*< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */
+
+size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);
+/*< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
+
+size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);
+/*< build a fake FSE_DTable, designed to always generate the same symbolValue */
+
+#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)
+#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))
+size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize);
+/*< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */
+
+size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);
+/*< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */
+
+typedef enum {
+ FSE_repeat_none, /*< Cannot use the previous table */
+ FSE_repeat_check, /*< Can use the previous table but it must be checked */
+ FSE_repeat_valid /*< Can use the previous table and it is assumed to be valid */
+ } FSE_repeat;
+
+/* *****************************************
+* FSE symbol compression API
+*******************************************/
+/*!
+ This API consists of small unitary functions, which highly benefit from being inlined.
+ Hence their body are included in next section.
+*/
+typedef struct {
+ ptrdiff_t value;
+ const void* stateTable;
+ const void* symbolTT;
+ unsigned stateLog;
+} FSE_CState_t;
+
+static void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);
+
+static void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);
+
+static void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);
+
+/*<
+These functions are inner components of FSE_compress_usingCTable().
+They allow the creation of custom streams, mixing multiple tables and bit sources.
+
+A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
+So the first symbol you will encode is the last you will decode, like a LIFO stack.
+
+You will need a few variables to track your CStream. They are :
+
+FSE_CTable ct; // Provided by FSE_buildCTable()
+BIT_CStream_t bitStream; // bitStream tracking structure
+FSE_CState_t state; // State tracking structure (can have several)
+
+
+The first thing to do is to init bitStream and state.
+ size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
+ FSE_initCState(&state, ct);
+
+Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
+You can then encode your input data, byte after byte.
+FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
+Remember decoding will be done in reverse direction.
+ FSE_encodeByte(&bitStream, &state, symbol);
+
+At any time, you can also add any bit sequence.
+Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
+ BIT_addBits(&bitStream, bitField, nbBits);
+
+The above methods don't commit data to memory, they just store it into local register, for speed.
+Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
+Writing data to memory is a manual operation, performed by the flushBits function.
+ BIT_flushBits(&bitStream);
+
+Your last FSE encoding operation shall be to flush your last state value(s).
+ FSE_flushState(&bitStream, &state);
+
+Finally, you must close the bitStream.
+The function returns the size of CStream in bytes.
+If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
+If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
+ size_t size = BIT_closeCStream(&bitStream);
+*/
+
+
+/* *****************************************
+* FSE symbol decompression API
+*******************************************/
+typedef struct {
+ size_t state;
+ const void* table; /* precise table may vary, depending on U16 */
+} FSE_DState_t;
+
+
+static void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);
+
+static unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
+
+static unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);
+
+/*<
+Let's now decompose FSE_decompress_usingDTable() into its unitary components.
+You will decode FSE-encoded symbols from the bitStream,
+and also any other bitFields you put in, **in reverse order**.
+
+You will need a few variables to track your bitStream. They are :
+
+BIT_DStream_t DStream; // Stream context
+FSE_DState_t DState; // State context. Multiple ones are possible
+FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable()
+
+The first thing to do is to init the bitStream.
+ errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
+
+You should then retrieve your initial state(s)
+(in reverse flushing order if you have several ones) :
+ errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
+
+You can then decode your data, symbol after symbol.
+For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
+Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
+ unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
+
+You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
+Note : maximum allowed nbBits is 25, for 32-bits compatibility
+ size_t bitField = BIT_readBits(&DStream, nbBits);
+
+All above operations only read from local register (which size depends on size_t).
+Refueling the register from memory is manually performed by the reload method.
+ endSignal = FSE_reloadDStream(&DStream);
+
+BIT_reloadDStream() result tells if there is still some more data to read from DStream.
+BIT_DStream_unfinished : there is still some data left into the DStream.
+BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
+BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
+BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
+
+When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
+to properly detect the exact end of stream.
+After each decoded symbol, check if DStream is fully consumed using this simple test :
+ BIT_reloadDStream(&DStream) >= BIT_DStream_completed
+
+When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
+Checking if DStream has reached its end is performed by :
+ BIT_endOfDStream(&DStream);
+Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
+ FSE_endOfDState(&DState);
+*/
+
+
+/* *****************************************
+* FSE unsafe API
+*******************************************/
+static unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);
+/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
+
+
+/* *****************************************
+* Implementation of inlined functions
+*******************************************/
+typedef struct {
+ int deltaFindState;
+ U32 deltaNbBits;
+} FSE_symbolCompressionTransform; /* total 8 bytes */
+
+MEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)
+{
+ const void* ptr = ct;
+ const U16* u16ptr = (const U16*) ptr;
+ const U32 tableLog = MEM_read16(ptr);
+ statePtr->value = (ptrdiff_t)1<<tableLog;
+ statePtr->stateTable = u16ptr+2;
+ statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);
+ statePtr->stateLog = tableLog;
+}
+
+
+/*! FSE_initCState2() :
+* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
+* uses the smallest state value possible, saving the cost of this symbol */
+MEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)
+{
+ FSE_initCState(statePtr, ct);
+ { const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
+ const U16* stateTable = (const U16*)(statePtr->stateTable);
+ U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);
+ statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
+ statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
+ }
+}
+
+MEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)
+{
+ FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];
+ const U16* const stateTable = (const U16*)(statePtr->stateTable);
+ U32 const nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
+ BIT_addBits(bitC, statePtr->value, nbBitsOut);
+ statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
+}
+
+MEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)
+{
+ BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
+ BIT_flushBits(bitC);
+}
+
+
+/* FSE_getMaxNbBits() :
+ * Approximate maximum cost of a symbol, in bits.
+ * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)
+ * note 1 : assume symbolValue is valid (<= maxSymbolValue)
+ * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
+MEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)
+{
+ const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
+ return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;
+}
+
+/* FSE_bitCost() :
+ * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)
+ * note 1 : assume symbolValue is valid (<= maxSymbolValue)
+ * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */
+MEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)
+{
+ const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;
+ U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;
+ U32 const threshold = (minNbBits+1) << 16;
+ assert(tableLog < 16);
+ assert(accuracyLog < 31-tableLog); /* ensure enough room for renormalization double shift */
+ { U32 const tableSize = 1 << tableLog;
+ U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);
+ U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog; /* linear interpolation (very approximate) */
+ U32 const bitMultiplier = 1 << accuracyLog;
+ assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);
+ assert(normalizedDeltaFromThreshold <= bitMultiplier);
+ return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;
+ }
+}
+
+
+/* ====== Decompression ====== */
+
+typedef struct {
+ U16 tableLog;
+ U16 fastMode;
+} FSE_DTableHeader; /* sizeof U32 */
+
+typedef struct
+{
+ unsigned short newState;
+ unsigned char symbol;
+ unsigned char nbBits;
+} FSE_decode_t; /* size == U32 */
+
+MEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)
+{
+ const void* ptr = dt;
+ const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;
+ DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
+ BIT_reloadDStream(bitD);
+ DStatePtr->table = dt + 1;
+}
+
+MEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
+ return DInfo.symbol;
+}
+
+MEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ size_t const lowBits = BIT_readBits(bitD, nbBits);
+ DStatePtr->state = DInfo.newState + lowBits;
+}
+
+MEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ BYTE const symbol = DInfo.symbol;
+ size_t const lowBits = BIT_readBits(bitD, nbBits);
+
+ DStatePtr->state = DInfo.newState + lowBits;
+ return symbol;
+}
+
+/*! FSE_decodeSymbolFast() :
+ unsafe, only works if no symbol has a probability > 50% */
+MEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)
+{
+ FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];
+ U32 const nbBits = DInfo.nbBits;
+ BYTE const symbol = DInfo.symbol;
+ size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
+
+ DStatePtr->state = DInfo.newState + lowBits;
+ return symbol;
+}
+
+MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)
+{
+ return DStatePtr->state == 0;
+}
+
+
+
+#ifndef FSE_COMMONDEFS_ONLY
+
+/* **************************************************************
+* Tuning parameters
+****************************************************************/
+/*!MEMORY_USAGE :
+* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
+* Increasing memory usage improves compression ratio
+* Reduced memory usage can improve speed, due to cache effect
+* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
+#ifndef FSE_MAX_MEMORY_USAGE
+# define FSE_MAX_MEMORY_USAGE 14
+#endif
+#ifndef FSE_DEFAULT_MEMORY_USAGE
+# define FSE_DEFAULT_MEMORY_USAGE 13
+#endif
+#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)
+# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE"
+#endif
+
+/*!FSE_MAX_SYMBOL_VALUE :
+* Maximum symbol value authorized.
+* Required for proper stack allocation */
+#ifndef FSE_MAX_SYMBOL_VALUE
+# define FSE_MAX_SYMBOL_VALUE 255
+#endif
+
+/* **************************************************************
+* template functions type & suffix
+****************************************************************/
+#define FSE_FUNCTION_TYPE BYTE
+#define FSE_FUNCTION_EXTENSION
+#define FSE_DECODE_TYPE FSE_decode_t
+
+
+#endif /* !FSE_COMMONDEFS_ONLY */
+
+
+/* ***************************************************************
+* Constants
+*****************************************************************/
+#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE-2)
+#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)
+#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)
+#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)
+#define FSE_MIN_TABLELOG 5
+
+#define FSE_TABLELOG_ABSOLUTE_MAX 15
+#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
+# error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
+#endif
+
+#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)
+
+
+#endif /* FSE_STATIC_LINKING_ONLY */
+
+
diff --git a/lib/zstd/common/fse_decompress.c b/lib/zstd/common/fse_decompress.c
new file mode 100644
index 0000000..a0d0609
--- /dev/null
+++ b/lib/zstd/common/fse_decompress.c
@@ -0,0 +1,390 @@
+/* ******************************************************************
+ * FSE : Finite State Entropy decoder
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ * - Public forum : https://groups.google.com/forum/#!forum/lz4c
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+
+
+/* **************************************************************
+* Includes
+****************************************************************/
+#include "debug.h" /* assert */
+#include "bitstream.h"
+#include "compiler.h"
+#define FSE_STATIC_LINKING_ONLY
+#include "fse.h"
+#include "error_private.h"
+#define ZSTD_DEPS_NEED_MALLOC
+#include "zstd_deps.h"
+
+
+/* **************************************************************
+* Error Management
+****************************************************************/
+#define FSE_isError ERR_isError
+#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c) /* use only *after* variable declarations */
+
+
+/* **************************************************************
+* Templates
+****************************************************************/
+/*
+ designed to be included
+ for type-specific functions (template emulation in C)
+ Objective is to write these functions only once, for improved maintenance
+*/
+
+/* safety checks */
+#ifndef FSE_FUNCTION_EXTENSION
+# error "FSE_FUNCTION_EXTENSION must be defined"
+#endif
+#ifndef FSE_FUNCTION_TYPE
+# error "FSE_FUNCTION_TYPE must be defined"
+#endif
+
+/* Function names */
+#define FSE_CAT(X,Y) X##Y
+#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)
+#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)
+
+
+/* Function templates */
+FSE_DTable* FSE_createDTable (unsigned tableLog)
+{
+ if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;
+ return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );
+}
+
+void FSE_freeDTable (FSE_DTable* dt)
+{
+ ZSTD_free(dt);
+}
+
+static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
+{
+ void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
+ FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);
+ U16* symbolNext = (U16*)workSpace;
+ BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1);
+
+ U32 const maxSV1 = maxSymbolValue + 1;
+ U32 const tableSize = 1 << tableLog;
+ U32 highThreshold = tableSize-1;
+
+ /* Sanity Checks */
+ if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge);
+ if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);
+ if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);
+
+ /* Init, lay down lowprob symbols */
+ { FSE_DTableHeader DTableH;
+ DTableH.tableLog = (U16)tableLog;
+ DTableH.fastMode = 1;
+ { S16 const largeLimit= (S16)(1 << (tableLog-1));
+ U32 s;
+ for (s=0; s<maxSV1; s++) {
+ if (normalizedCounter[s]==-1) {
+ tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
+ symbolNext[s] = 1;
+ } else {
+ if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
+ symbolNext[s] = normalizedCounter[s];
+ } } }
+ ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
+ }
+
+ /* Spread symbols */
+ if (highThreshold == tableSize - 1) {
+ size_t const tableMask = tableSize-1;
+ size_t const step = FSE_TABLESTEP(tableSize);
+ /* First lay down the symbols in order.
+ * We use a uint64_t to lay down 8 bytes at a time. This reduces branch
+ * misses since small blocks generally have small table logs, so nearly
+ * all symbols have counts <= 8. We ensure we have 8 bytes at the end of
+ * our buffer to handle the over-write.
+ */
+ {
+ U64 const add = 0x0101010101010101ull;
+ size_t pos = 0;
+ U64 sv = 0;
+ U32 s;
+ for (s=0; s<maxSV1; ++s, sv += add) {
+ int i;
+ int const n = normalizedCounter[s];
+ MEM_write64(spread + pos, sv);
+ for (i = 8; i < n; i += 8) {
+ MEM_write64(spread + pos + i, sv);
+ }
+ pos += n;
+ }
+ }
+ /* Now we spread those positions across the table.
+ * The benefit of doing it in two stages is that we avoid the the
+ * variable size inner loop, which caused lots of branch misses.
+ * Now we can run through all the positions without any branch misses.
+ * We unroll the loop twice, since that is what emperically worked best.
+ */
+ {
+ size_t position = 0;
+ size_t s;
+ size_t const unroll = 2;
+ assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
+ for (s = 0; s < (size_t)tableSize; s += unroll) {
+ size_t u;
+ for (u = 0; u < unroll; ++u) {
+ size_t const uPosition = (position + (u * step)) & tableMask;
+ tableDecode[uPosition].symbol = spread[s + u];
+ }
+ position = (position + (unroll * step)) & tableMask;
+ }
+ assert(position == 0);
+ }
+ } else {
+ U32 const tableMask = tableSize-1;
+ U32 const step = FSE_TABLESTEP(tableSize);
+ U32 s, position = 0;
+ for (s=0; s<maxSV1; s++) {
+ int i;
+ for (i=0; i<normalizedCounter[s]; i++) {
+ tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
+ position = (position + step) & tableMask;
+ while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
+ } }
+ if (position!=0) return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
+ }
+
+ /* Build Decoding table */
+ { U32 u;
+ for (u=0; u<tableSize; u++) {
+ FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
+ U32 const nextState = symbolNext[symbol]++;
+ tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
+ tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
+ } }
+
+ return 0;
+}
+
+size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize);
+}
+
+
+#ifndef FSE_COMMONDEFS_ONLY
+
+/*-*******************************************************
+* Decompression (Byte symbols)
+*********************************************************/
+size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)
+{
+ void* ptr = dt;
+ FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
+ void* dPtr = dt + 1;
+ FSE_decode_t* const cell = (FSE_decode_t*)dPtr;
+
+ DTableH->tableLog = 0;
+ DTableH->fastMode = 0;
+
+ cell->newState = 0;
+ cell->symbol = symbolValue;
+ cell->nbBits = 0;
+
+ return 0;
+}
+
+
+size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)
+{
+ void* ptr = dt;
+ FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;
+ void* dPtr = dt + 1;
+ FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;
+ const unsigned tableSize = 1 << nbBits;
+ const unsigned tableMask = tableSize - 1;
+ const unsigned maxSV1 = tableMask+1;
+ unsigned s;
+
+ /* Sanity checks */
+ if (nbBits < 1) return ERROR(GENERIC); /* min size */
+
+ /* Build Decoding Table */
+ DTableH->tableLog = (U16)nbBits;
+ DTableH->fastMode = 1;
+ for (s=0; s<maxSV1; s++) {
+ dinfo[s].newState = 0;
+ dinfo[s].symbol = (BYTE)s;
+ dinfo[s].nbBits = (BYTE)nbBits;
+ }
+
+ return 0;
+}
+
+FORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(
+ void* dst, size_t maxDstSize,
+ const void* cSrc, size_t cSrcSize,
+ const FSE_DTable* dt, const unsigned fast)
+{
+ BYTE* const ostart = (BYTE*) dst;
+ BYTE* op = ostart;
+ BYTE* const omax = op + maxDstSize;
+ BYTE* const olimit = omax-3;
+
+ BIT_DStream_t bitD;
+ FSE_DState_t state1;
+ FSE_DState_t state2;
+
+ /* Init */
+ CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));
+
+ FSE_initDState(&state1, &bitD, dt);
+ FSE_initDState(&state2, &bitD, dt);
+
+#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
+
+ /* 4 symbols per loop */
+ for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) {
+ op[0] = FSE_GETSYMBOL(&state1);
+
+ if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
+ BIT_reloadDStream(&bitD);
+
+ op[1] = FSE_GETSYMBOL(&state2);
+
+ if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
+ { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }
+
+ op[2] = FSE_GETSYMBOL(&state1);
+
+ if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8) /* This test must be static */
+ BIT_reloadDStream(&bitD);
+
+ op[3] = FSE_GETSYMBOL(&state2);
+ }
+
+ /* tail */
+ /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
+ while (1) {
+ if (op>(omax-2)) return ERROR(dstSize_tooSmall);
+ *op++ = FSE_GETSYMBOL(&state1);
+ if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
+ *op++ = FSE_GETSYMBOL(&state2);
+ break;
+ }
+
+ if (op>(omax-2)) return ERROR(dstSize_tooSmall);
+ *op++ = FSE_GETSYMBOL(&state2);
+ if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {
+ *op++ = FSE_GETSYMBOL(&state1);
+ break;
+ } }
+
+ return op-ostart;
+}
+
+
+size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,
+ const void* cSrc, size_t cSrcSize,
+ const FSE_DTable* dt)
+{
+ const void* ptr = dt;
+ const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
+ const U32 fastMode = DTableH->fastMode;
+
+ /* select fast mode (static) */
+ if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
+ return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
+}
+
+
+size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0);
+}
+
+typedef struct {
+ short ncount[FSE_MAX_SYMBOL_VALUE + 1];
+ FSE_DTable dtable[1]; /* Dynamically sized */
+} FSE_DecompressWksp;
+
+
+FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(
+ void* dst, size_t dstCapacity,
+ const void* cSrc, size_t cSrcSize,
+ unsigned maxLog, void* workSpace, size_t wkspSize,
+ int bmi2)
+{
+ const BYTE* const istart = (const BYTE*)cSrc;
+ const BYTE* ip = istart;
+ unsigned tableLog;
+ unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
+ FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;
+
+ DEBUG_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);
+ if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);
+
+ /* normal FSE decoding mode */
+ {
+ size_t const NCountLength = FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);
+ if (FSE_isError(NCountLength)) return NCountLength;
+ if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
+ assert(NCountLength <= cSrcSize);
+ ip += NCountLength;
+ cSrcSize -= NCountLength;
+ }
+
+ if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);
+ workSpace = wksp->dtable + FSE_DTABLE_SIZE_U32(tableLog);
+ wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);
+
+ CHECK_F( FSE_buildDTable_internal(wksp->dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );
+
+ {
+ const void* ptr = wksp->dtable;
+ const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;
+ const U32 fastMode = DTableH->fastMode;
+
+ /* select fast mode (static) */
+ if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 1);
+ return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, wksp->dtable, 0);
+ }
+}
+
+/* Avoids the FORCE_INLINE of the _body() function. */
+static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0);
+}
+
+#if DYNAMIC_BMI2
+BMI2_TARGET_ATTRIBUTE static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
+{
+ return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);
+}
+#endif
+
+size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
+ }
+#endif
+ (void)bmi2;
+ return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);
+}
+
+
+typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];
+
+
+
+#endif /* FSE_COMMONDEFS_ONLY */
diff --git a/lib/zstd/common/huf.h b/lib/zstd/common/huf.h
new file mode 100644
index 0000000..5042ff8
--- /dev/null
+++ b/lib/zstd/common/huf.h
@@ -0,0 +1,358 @@
+/* ******************************************************************
+ * huff0 huffman codec,
+ * part of Finite State Entropy library
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+
+
+#ifndef HUF_H_298734234
+#define HUF_H_298734234
+
+/* *** Dependencies *** */
+#include "zstd_deps.h" /* size_t */
+
+
+/* *** library symbols visibility *** */
+/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual,
+ * HUF symbols remain "private" (internal symbols for library only).
+ * Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */
+#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)
+# define HUF_PUBLIC_API __attribute__ ((visibility ("default")))
+#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) /* Visual expected */
+# define HUF_PUBLIC_API __declspec(dllexport)
+#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)
+# define HUF_PUBLIC_API __declspec(dllimport) /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */
+#else
+# define HUF_PUBLIC_API
+#endif
+
+
+/* ========================== */
+/* *** simple functions *** */
+/* ========================== */
+
+/* HUF_compress() :
+ * Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.
+ * 'dst' buffer must be already allocated.
+ * Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize).
+ * `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB.
+ * @return : size of compressed data (<= `dstCapacity`).
+ * Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!
+ * if HUF_isError(return), compression failed (more details using HUF_getErrorName())
+ */
+HUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize);
+
+/* HUF_decompress() :
+ * Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',
+ * into already allocated buffer 'dst', of minimum size 'dstSize'.
+ * `originalSize` : **must** be the ***exact*** size of original (uncompressed) data.
+ * Note : in contrast with FSE, HUF_decompress can regenerate
+ * RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,
+ * because it knows size to regenerate (originalSize).
+ * @return : size of regenerated data (== originalSize),
+ * or an error code, which can be tested using HUF_isError()
+ */
+HUF_PUBLIC_API size_t HUF_decompress(void* dst, size_t originalSize,
+ const void* cSrc, size_t cSrcSize);
+
+
+/* *** Tool functions *** */
+#define HUF_BLOCKSIZE_MAX (128 * 1024) /*< maximum input size for a single block compressed with HUF_compress */
+HUF_PUBLIC_API size_t HUF_compressBound(size_t size); /*< maximum compressed size (worst case) */
+
+/* Error Management */
+HUF_PUBLIC_API unsigned HUF_isError(size_t code); /*< tells if a return value is an error code */
+HUF_PUBLIC_API const char* HUF_getErrorName(size_t code); /*< provides error code string (useful for debugging) */
+
+
+/* *** Advanced function *** */
+
+/* HUF_compress2() :
+ * Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`.
+ * `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX .
+ * `tableLog` must be `<= HUF_TABLELOG_MAX` . */
+HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog);
+
+/* HUF_compress4X_wksp() :
+ * Same as HUF_compress2(), but uses externally allocated `workSpace`.
+ * `workspace` must be at least as large as HUF_WORKSPACE_SIZE */
+#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */)
+#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64))
+HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog,
+ void* workSpace, size_t wkspSize);
+
+#endif /* HUF_H_298734234 */
+
+/* ******************************************************************
+ * WARNING !!
+ * The following section contains advanced and experimental definitions
+ * which shall never be used in the context of a dynamic library,
+ * because they are not guaranteed to remain stable in the future.
+ * Only consider them in association with static linking.
+ * *****************************************************************/
+#if !defined(HUF_H_HUF_STATIC_LINKING_ONLY)
+#define HUF_H_HUF_STATIC_LINKING_ONLY
+
+/* *** Dependencies *** */
+#include "mem.h" /* U32 */
+#define FSE_STATIC_LINKING_ONLY
+#include "fse.h"
+
+
+/* *** Constants *** */
+#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_TABLELOG_ABSOLUTEMAX */
+#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */
+#define HUF_SYMBOLVALUE_MAX 255
+
+#define HUF_TABLELOG_ABSOLUTEMAX 12 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
+#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
+# error "HUF_TABLELOG_MAX is too large !"
+#endif
+
+
+/* ****************************************
+* Static allocation
+******************************************/
+/* HUF buffer bounds */
+#define HUF_CTABLEBOUND 129
+#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8) /* only true when incompressible is pre-filtered with fast heuristic */
+#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
+
+/* static allocation of HUF's Compression Table */
+/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */
+typedef size_t HUF_CElt; /* consider it an incomplete type */
+#define HUF_CTABLE_SIZE_ST(maxSymbolValue) ((maxSymbolValue)+2) /* Use tables of size_t, for proper alignment */
+#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_ST(maxSymbolValue) * sizeof(size_t))
+#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
+ HUF_CElt name[HUF_CTABLE_SIZE_ST(maxSymbolValue)] /* no final ; */
+
+/* static allocation of HUF's DTable */
+typedef U32 HUF_DTable;
+#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1<<(maxTableLog)))
+#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \
+ HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) }
+#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \
+ HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }
+
+
+/* ****************************************
+* Advanced decompression functions
+******************************************/
+size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< single-symbol decoder */
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< double-symbols decoder */
+#endif
+
+size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< decodes RLE and uncompressed */
+size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< considers RLE and uncompressed as errors */
+size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /*< considers RLE and uncompressed as errors */
+size_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< single-symbol decoder */
+size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /*< single-symbol decoder */
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< double-symbols decoder */
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /*< double-symbols decoder */
+#endif
+
+
+/* ****************************************
+ * HUF detailed API
+ * ****************************************/
+
+/*! HUF_compress() does the following:
+ * 1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within "fse.h")
+ * 2. (optional) refine tableLog using HUF_optimalTableLog()
+ * 3. build Huffman table from count using HUF_buildCTable()
+ * 4. save Huffman table to memory buffer using HUF_writeCTable()
+ * 5. encode the data stream using HUF_compress4X_usingCTable()
+ *
+ * The following API allows targeting specific sub-functions for advanced tasks.
+ * For example, it's possible to compress several blocks using the same 'CTable',
+ * or to save and regenerate 'CTable' using external methods.
+ */
+unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
+size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */
+size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
+size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);
+size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
+size_t HUF_compress4X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
+size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
+int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
+
+typedef enum {
+ HUF_repeat_none, /*< Cannot use the previous table */
+ HUF_repeat_check, /*< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */
+ HUF_repeat_valid /*< Can use the previous table and it is assumed to be valid */
+ } HUF_repeat;
+/* HUF_compress4X_repeat() :
+ * Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+ * If it uses hufTable it does not modify hufTable or repeat.
+ * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+ * If preferRepeat then the old table will always be used if valid.
+ * If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
+size_t HUF_compress4X_repeat(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog,
+ void* workSpace, size_t wkspSize, /*< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2, unsigned suspectUncompressible);
+
+/* HUF_buildCTable_wksp() :
+ * Same as HUF_buildCTable(), but using externally allocated scratch buffer.
+ * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.
+ */
+#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1)
+#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))
+size_t HUF_buildCTable_wksp (HUF_CElt* tree,
+ const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,
+ void* workSpace, size_t wkspSize);
+
+/*! HUF_readStats() :
+ * Read compact Huffman tree, saved by HUF_writeCTable().
+ * `huffWeight` is destination buffer.
+ * @return : size read from `src` , or an error Code .
+ * Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
+size_t HUF_readStats(BYTE* huffWeight, size_t hwSize,
+ U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize);
+
+/*! HUF_readStats_wksp() :
+ * Same as HUF_readStats() but takes an external workspace which must be
+ * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE.
+ * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
+ */
+#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1)
+#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned))
+size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,
+ U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,
+ const void* src, size_t srcSize,
+ void* workspace, size_t wkspSize,
+ int bmi2);
+
+/* HUF_readCTable() :
+ * Loading a CTable saved with HUF_writeCTable() */
+size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);
+
+/* HUF_getNbBitsFromCTable() :
+ * Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX
+ * Note 1 : is not inlined, as HUF_CElt definition is private */
+U32 HUF_getNbBitsFromCTable(const HUF_CElt* symbolTable, U32 symbolValue);
+
+/*
+ * HUF_decompress() does the following:
+ * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics
+ * 2. build Huffman table from save, using HUF_readDTableX?()
+ * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()
+ */
+
+/* HUF_selectDecoder() :
+ * Tells which decoder is likely to decode faster,
+ * based on a set of pre-computed metrics.
+ * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
+ * Assumption : 0 < dstSize <= 128 KB */
+U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);
+
+/*
+ * The minimum workspace size for the `workSpace` used in
+ * HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp().
+ *
+ * The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when
+ * HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.
+ * Buffer overflow errors may potentially occur if code modifications result in
+ * a required workspace size greater than that specified in the following
+ * macro.
+ */
+#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))
+#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
+
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize);
+size_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize);
+size_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);
+#endif
+
+size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
+
+
+/* ====================== */
+/* single stream variants */
+/* ====================== */
+
+size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
+size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /*< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U64 U64 */
+size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
+size_t HUF_compress1X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
+/* HUF_compress1X_repeat() :
+ * Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
+ * If it uses hufTable it does not modify hufTable or repeat.
+ * If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
+ * If preferRepeat then the old table will always be used if valid.
+ * If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
+size_t HUF_compress1X_repeat(void* dst, size_t dstSize,
+ const void* src, size_t srcSize,
+ unsigned maxSymbolValue, unsigned tableLog,
+ void* workSpace, size_t wkspSize, /*< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2, unsigned suspectUncompressible);
+
+size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* double-symbol decoder */
+#endif
+
+size_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);
+size_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< single-symbol decoder */
+size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /*< single-symbol decoder */
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /*< double-symbols decoder */
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /*< double-symbols decoder */
+#endif
+
+size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable); /*< automatic selection of sing or double symbol decoder, based on DTable */
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);
+#endif
+
+/* BMI2 variants.
+ * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.
+ */
+size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
+#endif
+size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);
+size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
+#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
+#endif
+
+#endif /* HUF_STATIC_LINKING_ONLY */
+
diff --git a/lib/zstd/common/mem.h b/lib/zstd/common/mem.h
new file mode 100644
index 0000000..9794296
--- /dev/null
+++ b/lib/zstd/common/mem.h
@@ -0,0 +1,262 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef MEM_H_MODULE
+#define MEM_H_MODULE
+
+/*-****************************************
+* Dependencies
+******************************************/
+#include <asm/unaligned.h> /* get_unaligned, put_unaligned* */
+#include <linux/compiler.h> /* inline */
+#include <asm/byteorder.h> /* swab32, swab64 */
+#include <linux/types.h> /* size_t, ptrdiff_t */
+#include "debug.h" /* DEBUG_STATIC_ASSERT */
+#include "compiler.h" /* INLINE_KEYWORD, UNUSED_ATTR */
+
+/*-****************************************
+* Compiler specifics
+******************************************/
+#define MEM_STATIC static INLINE_KEYWORD UNUSED_ATTR
+
+/*-**************************************************************
+* Basic Types
+*****************************************************************/
+typedef uint8_t BYTE;
+typedef uint8_t U8;
+typedef int8_t S8;
+typedef uint16_t U16;
+typedef int16_t S16;
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint64_t U64;
+typedef int64_t S64;
+
+/*-**************************************************************
+* Memory I/O API
+*****************************************************************/
+/*=== Static platform detection ===*/
+MEM_STATIC unsigned MEM_32bits(void);
+MEM_STATIC unsigned MEM_64bits(void);
+MEM_STATIC unsigned MEM_isLittleEndian(void);
+
+/*=== Native unaligned read/write ===*/
+MEM_STATIC U16 MEM_read16(const void* memPtr);
+MEM_STATIC U32 MEM_read32(const void* memPtr);
+MEM_STATIC U64 MEM_read64(const void* memPtr);
+MEM_STATIC size_t MEM_readST(const void* memPtr);
+
+MEM_STATIC void MEM_write16(void* memPtr, U16 value);
+MEM_STATIC void MEM_write32(void* memPtr, U32 value);
+MEM_STATIC void MEM_write64(void* memPtr, U64 value);
+
+/*=== Little endian unaligned read/write ===*/
+MEM_STATIC U16 MEM_readLE16(const void* memPtr);
+MEM_STATIC U32 MEM_readLE24(const void* memPtr);
+MEM_STATIC U32 MEM_readLE32(const void* memPtr);
+MEM_STATIC U64 MEM_readLE64(const void* memPtr);
+MEM_STATIC size_t MEM_readLEST(const void* memPtr);
+
+MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);
+MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);
+MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);
+MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);
+MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);
+
+/*=== Big endian unaligned read/write ===*/
+MEM_STATIC U32 MEM_readBE32(const void* memPtr);
+MEM_STATIC U64 MEM_readBE64(const void* memPtr);
+MEM_STATIC size_t MEM_readBEST(const void* memPtr);
+
+MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);
+MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);
+MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);
+
+/*=== Byteswap ===*/
+MEM_STATIC U32 MEM_swap32(U32 in);
+MEM_STATIC U64 MEM_swap64(U64 in);
+MEM_STATIC size_t MEM_swapST(size_t in);
+
+/*-**************************************************************
+* Memory I/O Implementation
+*****************************************************************/
+MEM_STATIC unsigned MEM_32bits(void)
+{
+ return sizeof(size_t) == 4;
+}
+
+MEM_STATIC unsigned MEM_64bits(void)
+{
+ return sizeof(size_t) == 8;
+}
+
+#if defined(__LITTLE_ENDIAN)
+#define MEM_LITTLE_ENDIAN 1
+#else
+#define MEM_LITTLE_ENDIAN 0
+#endif
+
+MEM_STATIC unsigned MEM_isLittleEndian(void)
+{
+ return MEM_LITTLE_ENDIAN;
+}
+
+MEM_STATIC U16 MEM_read16(const void *memPtr)
+{
+ return get_unaligned((const U16 *)memPtr);
+}
+
+MEM_STATIC U32 MEM_read32(const void *memPtr)
+{
+ return get_unaligned((const U32 *)memPtr);
+}
+
+MEM_STATIC U64 MEM_read64(const void *memPtr)
+{
+ return get_unaligned((const U64 *)memPtr);
+}
+
+MEM_STATIC size_t MEM_readST(const void *memPtr)
+{
+ return get_unaligned((const size_t *)memPtr);
+}
+
+MEM_STATIC void MEM_write16(void *memPtr, U16 value)
+{
+ put_unaligned(value, (U16 *)memPtr);
+}
+
+MEM_STATIC void MEM_write32(void *memPtr, U32 value)
+{
+ put_unaligned(value, (U32 *)memPtr);
+}
+
+MEM_STATIC void MEM_write64(void *memPtr, U64 value)
+{
+ put_unaligned(value, (U64 *)memPtr);
+}
+
+/*=== Little endian r/w ===*/
+
+MEM_STATIC U16 MEM_readLE16(const void *memPtr)
+{
+ return get_unaligned_le16(memPtr);
+}
+
+MEM_STATIC void MEM_writeLE16(void *memPtr, U16 val)
+{
+ put_unaligned_le16(val, memPtr);
+}
+
+MEM_STATIC U32 MEM_readLE24(const void *memPtr)
+{
+ return MEM_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16);
+}
+
+MEM_STATIC void MEM_writeLE24(void *memPtr, U32 val)
+{
+ MEM_writeLE16(memPtr, (U16)val);
+ ((BYTE *)memPtr)[2] = (BYTE)(val >> 16);
+}
+
+MEM_STATIC U32 MEM_readLE32(const void *memPtr)
+{
+ return get_unaligned_le32(memPtr);
+}
+
+MEM_STATIC void MEM_writeLE32(void *memPtr, U32 val32)
+{
+ put_unaligned_le32(val32, memPtr);
+}
+
+MEM_STATIC U64 MEM_readLE64(const void *memPtr)
+{
+ return get_unaligned_le64(memPtr);
+}
+
+MEM_STATIC void MEM_writeLE64(void *memPtr, U64 val64)
+{
+ put_unaligned_le64(val64, memPtr);
+}
+
+MEM_STATIC size_t MEM_readLEST(const void *memPtr)
+{
+ if (MEM_32bits())
+ return (size_t)MEM_readLE32(memPtr);
+ else
+ return (size_t)MEM_readLE64(memPtr);
+}
+
+MEM_STATIC void MEM_writeLEST(void *memPtr, size_t val)
+{
+ if (MEM_32bits())
+ MEM_writeLE32(memPtr, (U32)val);
+ else
+ MEM_writeLE64(memPtr, (U64)val);
+}
+
+/*=== Big endian r/w ===*/
+
+MEM_STATIC U32 MEM_readBE32(const void *memPtr)
+{
+ return get_unaligned_be32(memPtr);
+}
+
+MEM_STATIC void MEM_writeBE32(void *memPtr, U32 val32)
+{
+ put_unaligned_be32(val32, memPtr);
+}
+
+MEM_STATIC U64 MEM_readBE64(const void *memPtr)
+{
+ return get_unaligned_be64(memPtr);
+}
+
+MEM_STATIC void MEM_writeBE64(void *memPtr, U64 val64)
+{
+ put_unaligned_be64(val64, memPtr);
+}
+
+MEM_STATIC size_t MEM_readBEST(const void *memPtr)
+{
+ if (MEM_32bits())
+ return (size_t)MEM_readBE32(memPtr);
+ else
+ return (size_t)MEM_readBE64(memPtr);
+}
+
+MEM_STATIC void MEM_writeBEST(void *memPtr, size_t val)
+{
+ if (MEM_32bits())
+ MEM_writeBE32(memPtr, (U32)val);
+ else
+ MEM_writeBE64(memPtr, (U64)val);
+}
+
+MEM_STATIC U32 MEM_swap32(U32 in)
+{
+ return swab32(in);
+}
+
+MEM_STATIC U64 MEM_swap64(U64 in)
+{
+ return swab64(in);
+}
+
+MEM_STATIC size_t MEM_swapST(size_t in)
+{
+ if (MEM_32bits())
+ return (size_t)MEM_swap32((U32)in);
+ else
+ return (size_t)MEM_swap64((U64)in);
+}
+
+#endif /* MEM_H_MODULE */
diff --git a/lib/zstd/common/portability_macros.h b/lib/zstd/common/portability_macros.h
new file mode 100644
index 0000000..0e3b2c0
--- /dev/null
+++ b/lib/zstd/common/portability_macros.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_PORTABILITY_MACROS_H
+#define ZSTD_PORTABILITY_MACROS_H
+
+/*
+ * This header file contains macro defintions to support portability.
+ * This header is shared between C and ASM code, so it MUST only
+ * contain macro definitions. It MUST not contain any C code.
+ *
+ * This header ONLY defines macros to detect platforms/feature support.
+ *
+ */
+
+
+/* compat. with non-clang compilers */
+#ifndef __has_attribute
+ #define __has_attribute(x) 0
+#endif
+
+/* compat. with non-clang compilers */
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/* compat. with non-clang compilers */
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+/* detects whether we are being compiled under msan */
+
+/* detects whether we are being compiled under asan */
+
+/* detects whether we are being compiled under dfsan */
+
+/* Mark the internal assembly functions as hidden */
+#ifdef __ELF__
+# define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func
+#else
+# define ZSTD_HIDE_ASM_FUNCTION(func)
+#endif
+
+/* Enable runtime BMI2 dispatch based on the CPU.
+ * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
+ */
+#ifndef DYNAMIC_BMI2
+ #if ((defined(__clang__) && __has_attribute(__target__)) \
+ || (defined(__GNUC__) \
+ && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
+ && (defined(__x86_64__) || defined(_M_X64)) \
+ && !defined(__BMI2__)
+ # define DYNAMIC_BMI2 1
+ #else
+ # define DYNAMIC_BMI2 0
+ #endif
+#endif
+
+/*
+ * Only enable assembly for GNUC comptabile compilers,
+ * because other platforms may not support GAS assembly syntax.
+ *
+ * Only enable assembly for Linux / MacOS, other platforms may
+ * work, but they haven't been tested. This could likely be
+ * extended to BSD systems.
+ *
+ * Disable assembly when MSAN is enabled, because MSAN requires
+ * 100% of code to be instrumented to work.
+ */
+#define ZSTD_ASM_SUPPORTED 1
+
+/*
+ * Determines whether we should enable assembly for x86-64
+ * with BMI2.
+ *
+ * Enable if all of the following conditions hold:
+ * - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM
+ * - Assembly is supported
+ * - We are compiling for x86-64 and either:
+ * - DYNAMIC_BMI2 is enabled
+ * - BMI2 is supported at compile time
+ */
+#define ZSTD_ENABLE_ASM_X86_64_BMI2 0
+
+#endif /* ZSTD_PORTABILITY_MACROS_H */
diff --git a/lib/zstd/common/zstd_common.c b/lib/zstd/common/zstd_common.c
new file mode 100644
index 0000000..3d7e35b
--- /dev/null
+++ b/lib/zstd/common/zstd_common.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+
+/*-*************************************
+* Dependencies
+***************************************/
+#define ZSTD_DEPS_NEED_MALLOC
+#include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */
+#include "error_private.h"
+#include "zstd_internal.h"
+
+
+/*-****************************************
+* Version
+******************************************/
+unsigned ZSTD_versionNumber(void) { return ZSTD_VERSION_NUMBER; }
+
+const char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; }
+
+
+/*-****************************************
+* ZSTD Error Management
+******************************************/
+#undef ZSTD_isError /* defined within zstd_internal.h */
+/*! ZSTD_isError() :
+ * tells if a return value is an error code
+ * symbol is required for external callers */
+unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }
+
+/*! ZSTD_getErrorName() :
+ * provides error code string from function result (useful for debugging) */
+const char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }
+
+/*! ZSTD_getError() :
+ * convert a `size_t` function result into a proper ZSTD_errorCode enum */
+ZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }
+
+/*! ZSTD_getErrorString() :
+ * provides error code string from enum */
+const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); }
+
+
+
+/*=**************************************************************
+* Custom allocator
+****************************************************************/
+void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem)
+{
+ if (customMem.customAlloc)
+ return customMem.customAlloc(customMem.opaque, size);
+ return ZSTD_malloc(size);
+}
+
+void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem)
+{
+ if (customMem.customAlloc) {
+ /* calloc implemented as malloc+memset;
+ * not as efficient as calloc, but next best guess for custom malloc */
+ void* const ptr = customMem.customAlloc(customMem.opaque, size);
+ ZSTD_memset(ptr, 0, size);
+ return ptr;
+ }
+ return ZSTD_calloc(1, size);
+}
+
+void ZSTD_customFree(void* ptr, ZSTD_customMem customMem)
+{
+ if (ptr!=NULL) {
+ if (customMem.customFree)
+ customMem.customFree(customMem.opaque, ptr);
+ else
+ ZSTD_free(ptr);
+ }
+}
diff --git a/lib/zstd/common/zstd_deps.h b/lib/zstd/common/zstd_deps.h
new file mode 100644
index 0000000..e45ec56
--- /dev/null
+++ b/lib/zstd/common/zstd_deps.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/*
+ * This file provides common libc dependencies that zstd requires.
+ * The purpose is to allow replacing this file with a custom implementation
+ * to compile zstd without libc support.
+ */
+
+/* Need:
+ * NULL
+ * INT_MAX
+ * UINT_MAX
+ * ZSTD_memcpy()
+ * ZSTD_memset()
+ * ZSTD_memmove()
+ */
+#ifndef ZSTD_DEPS_COMMON
+#define ZSTD_DEPS_COMMON
+
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+
+#define ZSTD_memcpy(d,s,n) __builtin_memcpy((d),(s),(n))
+#define ZSTD_memmove(d,s,n) __builtin_memmove((d),(s),(n))
+#define ZSTD_memset(d,s,n) __builtin_memset((d),(s),(n))
+
+#endif /* ZSTD_DEPS_COMMON */
+
+/*
+ * Define malloc as always failing. That means the user must
+ * either use ZSTD_customMem or statically allocate memory.
+ * Need:
+ * ZSTD_malloc()
+ * ZSTD_free()
+ * ZSTD_calloc()
+ */
+#ifdef ZSTD_DEPS_NEED_MALLOC
+#ifndef ZSTD_DEPS_MALLOC
+#define ZSTD_DEPS_MALLOC
+
+#define ZSTD_malloc(s) ({ (void)(s); NULL; })
+#define ZSTD_free(p) ((void)(p))
+#define ZSTD_calloc(n,s) ({ (void)(n); (void)(s); NULL; })
+
+#endif /* ZSTD_DEPS_MALLOC */
+#endif /* ZSTD_DEPS_NEED_MALLOC */
+
+/*
+ * Provides 64-bit math support.
+ * Need:
+ * U64 ZSTD_div64(U64 dividend, U32 divisor)
+ */
+#ifdef ZSTD_DEPS_NEED_MATH64
+#ifndef ZSTD_DEPS_MATH64
+#define ZSTD_DEPS_MATH64
+
+#include <linux/math64.h>
+
+static uint64_t ZSTD_div64(uint64_t dividend, uint32_t divisor) {
+ return div_u64(dividend, divisor);
+}
+
+#endif /* ZSTD_DEPS_MATH64 */
+#endif /* ZSTD_DEPS_NEED_MATH64 */
+
+/*
+ * This is only requested when DEBUGLEVEL >= 1, meaning
+ * it is disabled in production.
+ * Need:
+ * assert()
+ */
+#ifdef ZSTD_DEPS_NEED_ASSERT
+#ifndef ZSTD_DEPS_ASSERT
+#define ZSTD_DEPS_ASSERT
+
+#include <linux/kernel.h>
+
+#define assert(x) WARN_ON((x))
+
+#endif /* ZSTD_DEPS_ASSERT */
+#endif /* ZSTD_DEPS_NEED_ASSERT */
+
+/*
+ * This is only requested when DEBUGLEVEL >= 2, meaning
+ * it is disabled in production.
+ * Need:
+ * ZSTD_DEBUG_PRINT()
+ */
+#ifdef ZSTD_DEPS_NEED_IO
+#ifndef ZSTD_DEPS_IO
+#define ZSTD_DEPS_IO
+
+#include <linux/printk.h>
+
+#define ZSTD_DEBUG_PRINT(...) pr_debug(__VA_ARGS__)
+
+#endif /* ZSTD_DEPS_IO */
+#endif /* ZSTD_DEPS_NEED_IO */
+
+/*
+ * Only requested when MSAN is enabled.
+ * Need:
+ * intptr_t
+ */
+#ifdef ZSTD_DEPS_NEED_STDINT
+#ifndef ZSTD_DEPS_STDINT
+#define ZSTD_DEPS_STDINT
+
+/*
+ * The Linux Kernel doesn't provide intptr_t, only uintptr_t, which
+ * is an unsigned long.
+ */
+typedef long intptr_t;
+
+#endif /* ZSTD_DEPS_STDINT */
+#endif /* ZSTD_DEPS_NEED_STDINT */
diff --git a/lib/zstd/common/zstd_internal.h b/lib/zstd/common/zstd_internal.h
new file mode 100644
index 0000000..93305d9
--- /dev/null
+++ b/lib/zstd/common/zstd_internal.h
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_CCOMMON_H_MODULE
+#define ZSTD_CCOMMON_H_MODULE
+
+/* this module contains definitions which must be identical
+ * across compression, decompression and dictBuilder.
+ * It also contains a few functions useful to at least 2 of them
+ * and which benefit from being inlined */
+
+/*-*************************************
+* Dependencies
+***************************************/
+#include "compiler.h"
+#include "cpu.h"
+#include "mem.h"
+#include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */
+#include "error_private.h"
+#define ZSTD_STATIC_LINKING_ONLY
+#include <linux/zstd.h>
+#define FSE_STATIC_LINKING_ONLY
+#include "fse.h"
+#define HUF_STATIC_LINKING_ONLY
+#include "huf.h"
+#include <linux/xxhash.h> /* XXH_reset, update, digest */
+#define ZSTD_TRACE 0
+
+
+/* ---- static assert (debug) --- */
+#define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)
+#define ZSTD_isError ERR_isError /* for inlining */
+#define FSE_isError ERR_isError
+#define HUF_isError ERR_isError
+
+
+/*-*************************************
+* shared macros
+***************************************/
+#undef MIN
+#undef MAX
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#define BOUNDED(min,val,max) (MAX(min,MIN(val,max)))
+
+
+/*-*************************************
+* Common constants
+***************************************/
+#define ZSTD_OPT_NUM (1<<12)
+
+#define ZSTD_REP_NUM 3 /* number of repcodes */
+static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
+
+#define KB *(1 <<10)
+#define MB *(1 <<20)
+#define GB *(1U<<30)
+
+#define BIT7 128
+#define BIT6 64
+#define BIT5 32
+#define BIT4 16
+#define BIT1 2
+#define BIT0 1
+
+#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
+static UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
+static UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
+
+#define ZSTD_FRAMEIDSIZE 4 /* magic number size */
+
+#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
+static UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
+typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
+
+#define ZSTD_FRAMECHECKSUMSIZE 4
+
+#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
+#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
+
+#define HufLog 12
+typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e;
+
+#define LONGNBSEQ 0x7F00
+
+#define MINMATCH 3
+
+#define Litbits 8
+#define MaxLit ((1<<Litbits) - 1)
+#define MaxML 52
+#define MaxLL 35
+#define DefaultMaxOff 28
+#define MaxOff 31
+#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
+#define MLFSELog 9
+#define LLFSELog 9
+#define OffFSELog 8
+#define MaxFSELog MAX(MAX(MLFSELog, LLFSELog), OffFSELog)
+
+#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */
+/* Each table cannot take more than #symbols * FSELog bits */
+#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)
+
+static UNUSED_ATTR const U8 LL_bits[MaxLL+1] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 2, 2, 3, 3,
+ 4, 6, 7, 8, 9,10,11,12,
+ 13,14,15,16
+};
+static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {
+ 4, 3, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 2, 1, 1, 1, 1, 1,
+ -1,-1,-1,-1
+};
+#define LL_DEFAULTNORMLOG 6 /* for static allocation */
+static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
+
+static UNUSED_ATTR const U8 ML_bits[MaxML+1] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 2, 2, 3, 3,
+ 4, 4, 5, 7, 8, 9,10,11,
+ 12,13,14,15,16
+};
+static UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = {
+ 1, 4, 3, 2, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1,-1,-1,
+ -1,-1,-1,-1,-1
+};
+#define ML_DEFAULTNORMLOG 6 /* for static allocation */
+static UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
+
+static UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = {
+ 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ -1,-1,-1,-1,-1
+};
+#define OF_DEFAULTNORMLOG 5 /* for static allocation */
+static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
+
+
+/*-*******************************************
+* Shared functions to include for inlining
+*********************************************/
+static void ZSTD_copy8(void* dst, const void* src) {
+#if defined(ZSTD_ARCH_ARM_NEON)
+ vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src));
+#else
+ ZSTD_memcpy(dst, src, 8);
+#endif
+}
+#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
+
+/* Need to use memmove here since the literal buffer can now be located within
+ the dst buffer. In circumstances where the op "catches up" to where the
+ literal buffer is, there can be partial overlaps in this call on the final
+ copy if the literal is being shifted by less than 16 bytes. */
+static void ZSTD_copy16(void* dst, const void* src) {
+#if defined(ZSTD_ARCH_ARM_NEON)
+ vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));
+#elif defined(ZSTD_ARCH_X86_SSE2)
+ _mm_storeu_si128((__m128i*)dst, _mm_loadu_si128((const __m128i*)src));
+#elif defined(__clang__)
+ ZSTD_memmove(dst, src, 16);
+#else
+ /* ZSTD_memmove is not inlined properly by gcc */
+ BYTE copy16_buf[16];
+ ZSTD_memcpy(copy16_buf, src, 16);
+ ZSTD_memcpy(dst, copy16_buf, 16);
+#endif
+}
+#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; }
+
+#define WILDCOPY_OVERLENGTH 32
+#define WILDCOPY_VECLEN 16
+
+typedef enum {
+ ZSTD_no_overlap,
+ ZSTD_overlap_src_before_dst
+ /* ZSTD_overlap_dst_before_src, */
+} ZSTD_overlap_e;
+
+/*! ZSTD_wildcopy() :
+ * Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0)
+ * @param ovtype controls the overlap detection
+ * - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.
+ * - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart.
+ * The src buffer must be before the dst buffer.
+ */
+MEM_STATIC FORCE_INLINE_ATTR
+void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype)
+{
+ ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;
+ const BYTE* ip = (const BYTE*)src;
+ BYTE* op = (BYTE*)dst;
+ BYTE* const oend = op + length;
+
+ if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {
+ /* Handle short offset copies. */
+ do {
+ COPY8(op, ip)
+ } while (op < oend);
+ } else {
+ assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN);
+ /* Separate out the first COPY16() call because the copy length is
+ * almost certain to be short, so the branches have different
+ * probabilities. Since it is almost certain to be short, only do
+ * one COPY16() in the first call. Then, do two calls per loop since
+ * at that point it is more likely to have a high trip count.
+ */
+#ifdef __aarch64__
+ do {
+ COPY16(op, ip);
+ }
+ while (op < oend);
+#else
+ ZSTD_copy16(op, ip);
+ if (16 >= length) return;
+ op += 16;
+ ip += 16;
+ do {
+ COPY16(op, ip);
+ COPY16(op, ip);
+ }
+ while (op < oend);
+#endif
+ }
+}
+
+MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
+{
+ size_t const length = MIN(dstCapacity, srcSize);
+ if (length > 0) {
+ ZSTD_memcpy(dst, src, length);
+ }
+ return length;
+}
+
+/* define "workspace is too large" as this number of times larger than needed */
+#define ZSTD_WORKSPACETOOLARGE_FACTOR 3
+
+/* when workspace is continuously too large
+ * during at least this number of times,
+ * context's memory usage is considered wasteful,
+ * because it's sized to handle a worst case scenario which rarely happens.
+ * In which case, resize it down to free some memory */
+#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128
+
+/* Controls whether the input/output buffer is buffered or stable. */
+typedef enum {
+ ZSTD_bm_buffered = 0, /* Buffer the input/output */
+ ZSTD_bm_stable = 1 /* ZSTD_inBuffer/ZSTD_outBuffer is stable */
+} ZSTD_bufferMode_e;
+
+
+/*-*******************************************
+* Private declarations
+*********************************************/
+typedef struct seqDef_s {
+ U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */
+ U16 litLength;
+ U16 mlBase; /* mlBase == matchLength - MINMATCH */
+} seqDef;
+
+/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */
+typedef enum {
+ ZSTD_llt_none = 0, /* no longLengthType */
+ ZSTD_llt_literalLength = 1, /* represents a long literal */
+ ZSTD_llt_matchLength = 2 /* represents a long match */
+} ZSTD_longLengthType_e;
+
+typedef struct {
+ seqDef* sequencesStart;
+ seqDef* sequences; /* ptr to end of sequences */
+ BYTE* litStart;
+ BYTE* lit; /* ptr to end of literals */
+ BYTE* llCode;
+ BYTE* mlCode;
+ BYTE* ofCode;
+ size_t maxNbSeq;
+ size_t maxNbLit;
+
+ /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength
+ * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment
+ * the existing value of the litLength or matchLength by 0x10000.
+ */
+ ZSTD_longLengthType_e longLengthType;
+ U32 longLengthPos; /* Index of the sequence to apply long length modification to */
+} seqStore_t;
+
+typedef struct {
+ U32 litLength;
+ U32 matchLength;
+} ZSTD_sequenceLength;
+
+/*
+ * Returns the ZSTD_sequenceLength for the given sequences. It handles the decoding of long sequences
+ * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength.
+ */
+MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore, seqDef const* seq)
+{
+ ZSTD_sequenceLength seqLen;
+ seqLen.litLength = seq->litLength;
+ seqLen.matchLength = seq->mlBase + MINMATCH;
+ if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {
+ if (seqStore->longLengthType == ZSTD_llt_literalLength) {
+ seqLen.litLength += 0xFFFF;
+ }
+ if (seqStore->longLengthType == ZSTD_llt_matchLength) {
+ seqLen.matchLength += 0xFFFF;
+ }
+ }
+ return seqLen;
+}
+
+/*
+ * Contains the compressed frame size and an upper-bound for the decompressed frame size.
+ * Note: before using `compressedSize`, check for errors using ZSTD_isError().
+ * similarly, before using `decompressedBound`, check for errors using:
+ * `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
+ */
+typedef struct {
+ size_t compressedSize;
+ unsigned long long decompressedBound;
+} ZSTD_frameSizeInfo; /* decompress & legacy */
+
+const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBuilder */
+void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */
+
+/* custom memory allocation functions */
+void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem);
+void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem);
+void ZSTD_customFree(void* ptr, ZSTD_customMem customMem);
+
+
+MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */
+{
+ assert(val != 0);
+ {
+# if (__GNUC__ >= 3) /* GCC Intrinsic */
+ return __builtin_clz (val) ^ 31;
+# else /* Software version */
+ static const U32 DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
+ U32 v = val;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ return DeBruijnClz[(v * 0x07C4ACDDU) >> 27];
+# endif
+ }
+}
+
+/*
+ * Counts the number of trailing zeros of a `size_t`.
+ * Most compilers should support CTZ as a builtin. A backup
+ * implementation is provided if the builtin isn't supported, but
+ * it may not be terribly efficient.
+ */
+MEM_STATIC unsigned ZSTD_countTrailingZeros(size_t val)
+{
+ if (MEM_64bits()) {
+# if (__GNUC__ >= 4)
+ return __builtin_ctzll((U64)val);
+# else
+ static const int DeBruijnBytePos[64] = { 0, 1, 2, 7, 3, 13, 8, 19,
+ 4, 25, 14, 28, 9, 34, 20, 56,
+ 5, 17, 26, 54, 15, 41, 29, 43,
+ 10, 31, 38, 35, 21, 45, 49, 57,
+ 63, 6, 12, 18, 24, 27, 33, 55,
+ 16, 53, 40, 42, 30, 37, 44, 48,
+ 62, 11, 23, 32, 52, 39, 36, 47,
+ 61, 22, 51, 46, 60, 50, 59, 58 };
+ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
+# endif
+ } else { /* 32 bits */
+# if (__GNUC__ >= 3)
+ return __builtin_ctz((U32)val);
+# else
+ static const int DeBruijnBytePos[32] = { 0, 1, 28, 2, 29, 14, 24, 3,
+ 30, 22, 20, 15, 25, 17, 4, 8,
+ 31, 27, 13, 23, 21, 19, 16, 7,
+ 26, 12, 18, 6, 11, 5, 10, 9 };
+ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
+# endif
+ }
+}
+
+
+/* ZSTD_invalidateRepCodes() :
+ * ensures next compression will not use repcodes from previous block.
+ * Note : only works with regular variant;
+ * do not use with extDict variant ! */
+void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx); /* zstdmt, adaptive_compression (shouldn't get this definition from here) */
+
+
+typedef struct {
+ blockType_e blockType;
+ U32 lastBlock;
+ U32 origSize;
+} blockProperties_t; /* declared here for decompress and fullbench */
+
+/*! ZSTD_getcBlockSize() :
+ * Provides the size of compressed block from block header `src` */
+/* Used by: decompress, fullbench (does not get its definition from here) */
+size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
+ blockProperties_t* bpPtr);
+
+/*! ZSTD_decodeSeqHeaders() :
+ * decode sequence header from src */
+/* Used by: decompress, fullbench (does not get its definition from here) */
+size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
+ const void* src, size_t srcSize);
+
+/*
+ * @returns true iff the CPU supports dynamic BMI2 dispatch.
+ */
+MEM_STATIC int ZSTD_cpuSupportsBmi2(void)
+{
+ ZSTD_cpuid_t cpuid = ZSTD_cpuid();
+ return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);
+}
+
+
+#endif /* ZSTD_CCOMMON_H_MODULE */
diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c
deleted file mode 100644
index edfddd8..0000000
--- a/lib/zstd/decompress.c
+++ /dev/null
@@ -1,2516 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear)
-/**
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
- * All rights reserved.
- */
-
-/* ***************************************************************
-* Tuning parameters
-*****************************************************************/
-/*!
-* MAXWINDOWSIZE_DEFAULT :
-* maximum window size accepted by DStream, by default.
-* Frames requiring more memory will be rejected.
-*/
-#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
-#define ZSTD_MAXWINDOWSIZE_DEFAULT ((1 << ZSTD_WINDOWLOG_MAX) + 1) /* defined within zstd.h */
-#endif
-
-/*-*******************************************************
-* Dependencies
-*********************************************************/
-#include "fse.h"
-#include "huf.h"
-#include "mem.h" /* low level memory routines */
-#include "zstd_internal.h"
-#include <malloc.h>
-#include <linux/kernel.h>
-#include <linux/compat.h>
-#include <linux/string.h> /* memcpy, memmove, memset */
-
-#define ZSTD_PREFETCH(ptr) __builtin_prefetch(ptr, 0, 0)
-
-/*-*************************************
-* Macros
-***************************************/
-#define ZSTD_isError ERR_isError /* for inlining */
-#define FSE_isError ERR_isError
-#define HUF_isError ERR_isError
-
-/*_*******************************************************
-* Memory operations
-**********************************************************/
-static void ZSTD_copy4(void *dst, const void *src) { memcpy(dst, src, 4); }
-
-/*-*************************************************************
-* Context management
-***************************************************************/
-typedef enum {
- ZSTDds_getFrameHeaderSize,
- ZSTDds_decodeFrameHeader,
- ZSTDds_decodeBlockHeader,
- ZSTDds_decompressBlock,
- ZSTDds_decompressLastBlock,
- ZSTDds_checkChecksum,
- ZSTDds_decodeSkippableHeader,
- ZSTDds_skipFrame
-} ZSTD_dStage;
-
-typedef struct {
- FSE_DTable LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];
- FSE_DTable OFTable[FSE_DTABLE_SIZE_U32(OffFSELog)];
- FSE_DTable MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];
- HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
- U64 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32 / 2];
- U32 rep[ZSTD_REP_NUM];
-} ZSTD_entropyTables_t;
-
-struct ZSTD_DCtx_s {
- const FSE_DTable *LLTptr;
- const FSE_DTable *MLTptr;
- const FSE_DTable *OFTptr;
- const HUF_DTable *HUFptr;
- ZSTD_entropyTables_t entropy;
- const void *previousDstEnd; /* detect continuity */
- const void *base; /* start of curr segment */
- const void *vBase; /* virtual start of previous segment if it was just before curr one */
- const void *dictEnd; /* end of previous segment */
- size_t expected;
- ZSTD_frameParams fParams;
- blockType_e bType; /* used in ZSTD_decompressContinue(), to transfer blockType between header decoding and block decoding stages */
- ZSTD_dStage stage;
- U32 litEntropy;
- U32 fseEntropy;
- struct xxh64_state xxhState;
- size_t headerSize;
- U32 dictID;
- const BYTE *litPtr;
- ZSTD_customMem customMem;
- size_t litSize;
- size_t rleSize;
- BYTE litBuffer[ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];
- BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
-}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
-
-size_t ZSTD_DCtxWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DCtx)); }
-
-size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx)
-{
- dctx->expected = ZSTD_frameHeaderSize_prefix;
- dctx->stage = ZSTDds_getFrameHeaderSize;
- dctx->previousDstEnd = NULL;
- dctx->base = NULL;
- dctx->vBase = NULL;
- dctx->dictEnd = NULL;
- dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
- dctx->litEntropy = dctx->fseEntropy = 0;
- dctx->dictID = 0;
- ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
- memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
- dctx->LLTptr = dctx->entropy.LLTable;
- dctx->MLTptr = dctx->entropy.MLTable;
- dctx->OFTptr = dctx->entropy.OFTable;
- dctx->HUFptr = dctx->entropy.hufTable;
- return 0;
-}
-
-ZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
-{
- ZSTD_DCtx *dctx;
-
- if (!customMem.customAlloc || !customMem.customFree)
- return NULL;
-
- dctx = (ZSTD_DCtx *)ZSTD_malloc(sizeof(ZSTD_DCtx), customMem);
- if (!dctx)
- return NULL;
- memcpy(&dctx->customMem, &customMem, sizeof(customMem));
- ZSTD_decompressBegin(dctx);
- return dctx;
-}
-
-ZSTD_DCtx *ZSTD_initDCtx(void *workspace, size_t workspaceSize)
-{
- ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
- return ZSTD_createDCtx_advanced(stackMem);
-}
-
-size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx)
-{
- if (dctx == NULL)
- return 0; /* support free on NULL */
- ZSTD_free(dctx, dctx->customMem);
- return 0; /* reserved as a potential error code in the future */
-}
-
-void ZSTD_copyDCtx(ZSTD_DCtx *dstDCtx, const ZSTD_DCtx *srcDCtx)
-{
- size_t const workSpaceSize = (ZSTD_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH) + ZSTD_frameHeaderSize_max;
- memcpy(dstDCtx, srcDCtx, sizeof(ZSTD_DCtx) - workSpaceSize); /* no need to copy workspace */
-}
-
-static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict);
-
-/*-*************************************************************
-* Decompression section
-***************************************************************/
-
-/*! ZSTD_isFrame() :
- * Tells if the content of `buffer` starts with a valid Frame Identifier.
- * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
- * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
- * Note 3 : Skippable Frame Identifiers are considered valid. */
-unsigned ZSTD_isFrame(const void *buffer, size_t size)
-{
- if (size < 4)
- return 0;
- {
- U32 const magic = ZSTD_readLE32(buffer);
- if (magic == ZSTD_MAGICNUMBER)
- return 1;
- if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START)
- return 1;
- }
- return 0;
-}
-
-/** ZSTD_frameHeaderSize() :
-* srcSize must be >= ZSTD_frameHeaderSize_prefix.
-* @return : size of the Frame Header */
-static size_t ZSTD_frameHeaderSize(const void *src, size_t srcSize)
-{
- if (srcSize < ZSTD_frameHeaderSize_prefix)
- return ERROR(srcSize_wrong);
- {
- BYTE const fhd = ((const BYTE *)src)[4];
- U32 const dictID = fhd & 3;
- U32 const singleSegment = (fhd >> 5) & 1;
- U32 const fcsId = fhd >> 6;
- return ZSTD_frameHeaderSize_prefix + !singleSegment + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId] + (singleSegment && !fcsId);
- }
-}
-
-/** ZSTD_getFrameParams() :
-* decode Frame Header, or require larger `srcSize`.
-* @return : 0, `fparamsPtr` is correctly filled,
-* >0, `srcSize` is too small, result is expected `srcSize`,
-* or an error code, which can be tested using ZSTD_isError() */
-size_t ZSTD_getFrameParams(ZSTD_frameParams *fparamsPtr, const void *src, size_t srcSize)
-{
- const BYTE *ip = (const BYTE *)src;
-
- if (srcSize < ZSTD_frameHeaderSize_prefix)
- return ZSTD_frameHeaderSize_prefix;
- if (ZSTD_readLE32(src) != ZSTD_MAGICNUMBER) {
- if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
- if (srcSize < ZSTD_skippableHeaderSize)
- return ZSTD_skippableHeaderSize; /* magic number + skippable frame length */
- memset(fparamsPtr, 0, sizeof(*fparamsPtr));
- fparamsPtr->frameContentSize = ZSTD_readLE32((const char *)src + 4);
- fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */
- return 0;
- }
- return ERROR(prefix_unknown);
- }
-
- /* ensure there is enough `srcSize` to fully read/decode frame header */
- {
- size_t const fhsize = ZSTD_frameHeaderSize(src, srcSize);
- if (srcSize < fhsize)
- return fhsize;
- }
-
- {
- BYTE const fhdByte = ip[4];
- size_t pos = 5;
- U32 const dictIDSizeCode = fhdByte & 3;
- U32 const checksumFlag = (fhdByte >> 2) & 1;
- U32 const singleSegment = (fhdByte >> 5) & 1;
- U32 const fcsID = fhdByte >> 6;
- U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;
- U32 windowSize = 0;
- U32 dictID = 0;
- U64 frameContentSize = 0;
- if ((fhdByte & 0x08) != 0)
- return ERROR(frameParameter_unsupported); /* reserved bits, which must be zero */
- if (!singleSegment) {
- BYTE const wlByte = ip[pos++];
- U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
- if (windowLog > ZSTD_WINDOWLOG_MAX)
- return ERROR(frameParameter_windowTooLarge); /* avoids issue with 1 << windowLog */
- windowSize = (1U << windowLog);
- windowSize += (windowSize >> 3) * (wlByte & 7);
- }
-
- switch (dictIDSizeCode) {
- default: /* impossible */
- case 0: break;
- case 1:
- dictID = ip[pos];
- pos++;
- break;
- case 2:
- dictID = ZSTD_readLE16(ip + pos);
- pos += 2;
- break;
- case 3:
- dictID = ZSTD_readLE32(ip + pos);
- pos += 4;
- break;
- }
- switch (fcsID) {
- default: /* impossible */
- case 0:
- if (singleSegment)
- frameContentSize = ip[pos];
- break;
- case 1: frameContentSize = ZSTD_readLE16(ip + pos) + 256; break;
- case 2: frameContentSize = ZSTD_readLE32(ip + pos); break;
- case 3: frameContentSize = ZSTD_readLE64(ip + pos); break;
- }
- if (!windowSize)
- windowSize = (U32)frameContentSize;
- if (windowSize > windowSizeMax)
- return ERROR(frameParameter_windowTooLarge);
- fparamsPtr->frameContentSize = frameContentSize;
- fparamsPtr->windowSize = windowSize;
- fparamsPtr->dictID = dictID;
- fparamsPtr->checksumFlag = checksumFlag;
- }
- return 0;
-}
-
-/** ZSTD_getFrameContentSize() :
-* compatible with legacy mode
-* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
-* - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
-* - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
-unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
-{
- {
- ZSTD_frameParams fParams;
- if (ZSTD_getFrameParams(&fParams, src, srcSize) != 0)
- return ZSTD_CONTENTSIZE_ERROR;
- if (fParams.windowSize == 0) {
- /* Either skippable or empty frame, size == 0 either way */
- return 0;
- } else if (fParams.frameContentSize != 0) {
- return fParams.frameContentSize;
- } else {
- return ZSTD_CONTENTSIZE_UNKNOWN;
- }
- }
-}
-
-/** ZSTD_findDecompressedSize() :
- * compatible with legacy mode
- * `srcSize` must be the exact length of some number of ZSTD compressed and/or
- * skippable frames
- * Return: decompressed size of the frames contained */
-unsigned long long ZSTD_findDecompressedSize(const void *src, size_t srcSize)
-{
- {
- unsigned long long totalDstSize = 0;
- while (srcSize >= ZSTD_frameHeaderSize_prefix) {
- const U32 magicNumber = ZSTD_readLE32(src);
-
- if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
- size_t skippableSize;
- if (srcSize < ZSTD_skippableHeaderSize)
- return ERROR(srcSize_wrong);
- skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize;
- if (srcSize < skippableSize) {
- return ZSTD_CONTENTSIZE_ERROR;
- }
-
- src = (const BYTE *)src + skippableSize;
- srcSize -= skippableSize;
- continue;
- }
-
- {
- unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
- if (ret >= ZSTD_CONTENTSIZE_ERROR)
- return ret;
-
- /* check for overflow */
- if (totalDstSize + ret < totalDstSize)
- return ZSTD_CONTENTSIZE_ERROR;
- totalDstSize += ret;
- }
- {
- size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
- if (ZSTD_isError(frameSrcSize)) {
- return ZSTD_CONTENTSIZE_ERROR;
- }
-
- src = (const BYTE *)src + frameSrcSize;
- srcSize -= frameSrcSize;
- }
- }
-
- if (srcSize) {
- return ZSTD_CONTENTSIZE_ERROR;
- }
-
- return totalDstSize;
- }
-}
-
-/** ZSTD_decodeFrameHeader() :
-* `headerSize` must be the size provided by ZSTD_frameHeaderSize().
-* @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
-static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx *dctx, const void *src, size_t headerSize)
-{
- size_t const result = ZSTD_getFrameParams(&(dctx->fParams), src, headerSize);
- if (ZSTD_isError(result))
- return result; /* invalid header */
- if (result > 0)
- return ERROR(srcSize_wrong); /* headerSize too small */
- if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID))
- return ERROR(dictionary_wrong);
- if (dctx->fParams.checksumFlag)
- xxh64_reset(&dctx->xxhState, 0);
- return 0;
-}
-
-typedef struct {
- blockType_e blockType;
- U32 lastBlock;
- U32 origSize;
-} blockProperties_t;
-
-/*! ZSTD_getcBlockSize() :
-* Provides the size of compressed block from block header `src` */
-size_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr)
-{
- if (srcSize < ZSTD_blockHeaderSize)
- return ERROR(srcSize_wrong);
- {
- U32 const cBlockHeader = ZSTD_readLE24(src);
- U32 const cSize = cBlockHeader >> 3;
- bpPtr->lastBlock = cBlockHeader & 1;
- bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
- bpPtr->origSize = cSize; /* only useful for RLE */
- if (bpPtr->blockType == bt_rle)
- return 1;
- if (bpPtr->blockType == bt_reserved)
- return ERROR(corruption_detected);
- return cSize;
- }
-}
-
-static size_t ZSTD_copyRawBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
-{
- if (srcSize > dstCapacity)
- return ERROR(dstSize_tooSmall);
- memcpy(dst, src, srcSize);
- return srcSize;
-}
-
-static size_t ZSTD_setRleBlock(void *dst, size_t dstCapacity, const void *src, size_t srcSize, size_t regenSize)
-{
- if (srcSize != 1)
- return ERROR(srcSize_wrong);
- if (regenSize > dstCapacity)
- return ERROR(dstSize_tooSmall);
- memset(dst, *(const BYTE *)src, regenSize);
- return regenSize;
-}
-
-/*! ZSTD_decodeLiteralsBlock() :
- @return : nb of bytes read from src (< srcSize ) */
-size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
-{
- if (srcSize < MIN_CBLOCK_SIZE)
- return ERROR(corruption_detected);
-
- {
- const BYTE *const istart = (const BYTE *)src;
- symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
-
- switch (litEncType) {
- case set_repeat:
- if (dctx->litEntropy == 0)
- return ERROR(dictionary_corrupted);
- /* fall-through */
- case set_compressed:
- if (srcSize < 5)
- return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */
- {
- size_t lhSize, litSize, litCSize;
- U32 singleStream = 0;
- U32 const lhlCode = (istart[0] >> 2) & 3;
- U32 const lhc = ZSTD_readLE32(istart);
- switch (lhlCode) {
- case 0:
- case 1:
- default: /* note : default is impossible, since lhlCode into [0..3] */
- /* 2 - 2 - 10 - 10 */
- singleStream = !lhlCode;
- lhSize = 3;
- litSize = (lhc >> 4) & 0x3FF;
- litCSize = (lhc >> 14) & 0x3FF;
- break;
- case 2:
- /* 2 - 2 - 14 - 14 */
- lhSize = 4;
- litSize = (lhc >> 4) & 0x3FFF;
- litCSize = lhc >> 18;
- break;
- case 3:
- /* 2 - 2 - 18 - 18 */
- lhSize = 5;
- litSize = (lhc >> 4) & 0x3FFFF;
- litCSize = (lhc >> 22) + (istart[4] << 10);
- break;
- }
- if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX)
- return ERROR(corruption_detected);
- if (litCSize + lhSize > srcSize)
- return ERROR(corruption_detected);
-
- if (HUF_isError(
- (litEncType == set_repeat)
- ? (singleStream ? HUF_decompress1X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr)
- : HUF_decompress4X_usingDTable(dctx->litBuffer, litSize, istart + lhSize, litCSize, dctx->HUFptr))
- : (singleStream
- ? HUF_decompress1X2_DCtx_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize,
- dctx->entropy.workspace, sizeof(dctx->entropy.workspace))
- : HUF_decompress4X_hufOnly_wksp(dctx->entropy.hufTable, dctx->litBuffer, litSize, istart + lhSize, litCSize,
- dctx->entropy.workspace, sizeof(dctx->entropy.workspace)))))
- return ERROR(corruption_detected);
-
- dctx->litPtr = dctx->litBuffer;
- dctx->litSize = litSize;
- dctx->litEntropy = 1;
- if (litEncType == set_compressed)
- dctx->HUFptr = dctx->entropy.hufTable;
- memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
- return litCSize + lhSize;
- }
-
- case set_basic: {
- size_t litSize, lhSize;
- U32 const lhlCode = ((istart[0]) >> 2) & 3;
- switch (lhlCode) {
- case 0:
- case 2:
- default: /* note : default is impossible, since lhlCode into [0..3] */
- lhSize = 1;
- litSize = istart[0] >> 3;
- break;
- case 1:
- lhSize = 2;
- litSize = ZSTD_readLE16(istart) >> 4;
- break;
- case 3:
- lhSize = 3;
- litSize = ZSTD_readLE24(istart) >> 4;
- break;
- }
-
- if (lhSize + litSize + WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
- if (litSize + lhSize > srcSize)
- return ERROR(corruption_detected);
- memcpy(dctx->litBuffer, istart + lhSize, litSize);
- dctx->litPtr = dctx->litBuffer;
- dctx->litSize = litSize;
- memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
- return lhSize + litSize;
- }
- /* direct reference into compressed stream */
- dctx->litPtr = istart + lhSize;
- dctx->litSize = litSize;
- return lhSize + litSize;
- }
-
- case set_rle: {
- U32 const lhlCode = ((istart[0]) >> 2) & 3;
- size_t litSize, lhSize;
- switch (lhlCode) {
- case 0:
- case 2:
- default: /* note : default is impossible, since lhlCode into [0..3] */
- lhSize = 1;
- litSize = istart[0] >> 3;
- break;
- case 1:
- lhSize = 2;
- litSize = ZSTD_readLE16(istart) >> 4;
- break;
- case 3:
- lhSize = 3;
- litSize = ZSTD_readLE24(istart) >> 4;
- if (srcSize < 4)
- return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */
- break;
- }
- if (litSize > ZSTD_BLOCKSIZE_ABSOLUTEMAX)
- return ERROR(corruption_detected);
- memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
- dctx->litPtr = dctx->litBuffer;
- dctx->litSize = litSize;
- return lhSize + 1;
- }
- default:
- return ERROR(corruption_detected); /* impossible */
- }
- }
-}
-
-typedef union {
- FSE_decode_t realData;
- U32 alignedBy4;
-} FSE_decode_t4;
-
-static const FSE_decode_t4 LL_defaultDTable[(1 << LL_DEFAULTNORMLOG) + 1] = {
- {{LL_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
- {{0, 0, 4}}, /* 0 : base, symbol, bits */
- {{16, 0, 4}},
- {{32, 1, 5}},
- {{0, 3, 5}},
- {{0, 4, 5}},
- {{0, 6, 5}},
- {{0, 7, 5}},
- {{0, 9, 5}},
- {{0, 10, 5}},
- {{0, 12, 5}},
- {{0, 14, 6}},
- {{0, 16, 5}},
- {{0, 18, 5}},
- {{0, 19, 5}},
- {{0, 21, 5}},
- {{0, 22, 5}},
- {{0, 24, 5}},
- {{32, 25, 5}},
- {{0, 26, 5}},
- {{0, 27, 6}},
- {{0, 29, 6}},
- {{0, 31, 6}},
- {{32, 0, 4}},
- {{0, 1, 4}},
- {{0, 2, 5}},
- {{32, 4, 5}},
- {{0, 5, 5}},
- {{32, 7, 5}},
- {{0, 8, 5}},
- {{32, 10, 5}},
- {{0, 11, 5}},
- {{0, 13, 6}},
- {{32, 16, 5}},
- {{0, 17, 5}},
- {{32, 19, 5}},
- {{0, 20, 5}},
- {{32, 22, 5}},
- {{0, 23, 5}},
- {{0, 25, 4}},
- {{16, 25, 4}},
- {{32, 26, 5}},
- {{0, 28, 6}},
- {{0, 30, 6}},
- {{48, 0, 4}},
- {{16, 1, 4}},
- {{32, 2, 5}},
- {{32, 3, 5}},
- {{32, 5, 5}},
- {{32, 6, 5}},
- {{32, 8, 5}},
- {{32, 9, 5}},
- {{32, 11, 5}},
- {{32, 12, 5}},
- {{0, 15, 6}},
- {{32, 17, 5}},
- {{32, 18, 5}},
- {{32, 20, 5}},
- {{32, 21, 5}},
- {{32, 23, 5}},
- {{32, 24, 5}},
- {{0, 35, 6}},
- {{0, 34, 6}},
- {{0, 33, 6}},
- {{0, 32, 6}},
-}; /* LL_defaultDTable */
-
-static const FSE_decode_t4 ML_defaultDTable[(1 << ML_DEFAULTNORMLOG) + 1] = {
- {{ML_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
- {{0, 0, 6}}, /* 0 : base, symbol, bits */
- {{0, 1, 4}},
- {{32, 2, 5}},
- {{0, 3, 5}},
- {{0, 5, 5}},
- {{0, 6, 5}},
- {{0, 8, 5}},
- {{0, 10, 6}},
- {{0, 13, 6}},
- {{0, 16, 6}},
- {{0, 19, 6}},
- {{0, 22, 6}},
- {{0, 25, 6}},
- {{0, 28, 6}},
- {{0, 31, 6}},
- {{0, 33, 6}},
- {{0, 35, 6}},
- {{0, 37, 6}},
- {{0, 39, 6}},
- {{0, 41, 6}},
- {{0, 43, 6}},
- {{0, 45, 6}},
- {{16, 1, 4}},
- {{0, 2, 4}},
- {{32, 3, 5}},
- {{0, 4, 5}},
- {{32, 6, 5}},
- {{0, 7, 5}},
- {{0, 9, 6}},
- {{0, 12, 6}},
- {{0, 15, 6}},
- {{0, 18, 6}},
- {{0, 21, 6}},
- {{0, 24, 6}},
- {{0, 27, 6}},
- {{0, 30, 6}},
- {{0, 32, 6}},
- {{0, 34, 6}},
- {{0, 36, 6}},
- {{0, 38, 6}},
- {{0, 40, 6}},
- {{0, 42, 6}},
- {{0, 44, 6}},
- {{32, 1, 4}},
- {{48, 1, 4}},
- {{16, 2, 4}},
- {{32, 4, 5}},
- {{32, 5, 5}},
- {{32, 7, 5}},
- {{32, 8, 5}},
- {{0, 11, 6}},
- {{0, 14, 6}},
- {{0, 17, 6}},
- {{0, 20, 6}},
- {{0, 23, 6}},
- {{0, 26, 6}},
- {{0, 29, 6}},
- {{0, 52, 6}},
- {{0, 51, 6}},
- {{0, 50, 6}},
- {{0, 49, 6}},
- {{0, 48, 6}},
- {{0, 47, 6}},
- {{0, 46, 6}},
-}; /* ML_defaultDTable */
-
-static const FSE_decode_t4 OF_defaultDTable[(1 << OF_DEFAULTNORMLOG) + 1] = {
- {{OF_DEFAULTNORMLOG, 1, 1}}, /* header : tableLog, fastMode, fastMode */
- {{0, 0, 5}}, /* 0 : base, symbol, bits */
- {{0, 6, 4}},
- {{0, 9, 5}},
- {{0, 15, 5}},
- {{0, 21, 5}},
- {{0, 3, 5}},
- {{0, 7, 4}},
- {{0, 12, 5}},
- {{0, 18, 5}},
- {{0, 23, 5}},
- {{0, 5, 5}},
- {{0, 8, 4}},
- {{0, 14, 5}},
- {{0, 20, 5}},
- {{0, 2, 5}},
- {{16, 7, 4}},
- {{0, 11, 5}},
- {{0, 17, 5}},
- {{0, 22, 5}},
- {{0, 4, 5}},
- {{16, 8, 4}},
- {{0, 13, 5}},
- {{0, 19, 5}},
- {{0, 1, 5}},
- {{16, 6, 4}},
- {{0, 10, 5}},
- {{0, 16, 5}},
- {{0, 28, 5}},
- {{0, 27, 5}},
- {{0, 26, 5}},
- {{0, 25, 5}},
- {{0, 24, 5}},
-}; /* OF_defaultDTable */
-
-/*! ZSTD_buildSeqTable() :
- @return : nb bytes read from src,
- or an error code if it fails, testable with ZSTD_isError()
-*/
-static size_t ZSTD_buildSeqTable(FSE_DTable *DTableSpace, const FSE_DTable **DTablePtr, symbolEncodingType_e type, U32 max, U32 maxLog, const void *src,
- size_t srcSize, const FSE_decode_t4 *defaultTable, U32 flagRepeatTable, void *workspace, size_t workspaceSize)
-{
- const void *const tmpPtr = defaultTable; /* bypass strict aliasing */
- switch (type) {
- case set_rle:
- if (!srcSize)
- return ERROR(srcSize_wrong);
- if ((*(const BYTE *)src) > max)
- return ERROR(corruption_detected);
- FSE_buildDTable_rle(DTableSpace, *(const BYTE *)src);
- *DTablePtr = DTableSpace;
- return 1;
- case set_basic: *DTablePtr = (const FSE_DTable *)tmpPtr; return 0;
- case set_repeat:
- if (!flagRepeatTable)
- return ERROR(corruption_detected);
- return 0;
- default: /* impossible */
- case set_compressed: {
- U32 tableLog;
- S16 *norm = (S16 *)workspace;
- size_t const spaceUsed32 = ALIGN(sizeof(S16) * (MaxSeq + 1), sizeof(U32)) >> 2;
-
- if ((spaceUsed32 << 2) > workspaceSize)
- return ERROR(GENERIC);
- workspace = (U32 *)workspace + spaceUsed32;
- workspaceSize -= (spaceUsed32 << 2);
- {
- size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
- if (FSE_isError(headerSize))
- return ERROR(corruption_detected);
- if (tableLog > maxLog)
- return ERROR(corruption_detected);
- FSE_buildDTable_wksp(DTableSpace, norm, max, tableLog, workspace, workspaceSize);
- *DTablePtr = DTableSpace;
- return headerSize;
- }
- }
- }
-}
-
-size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx *dctx, int *nbSeqPtr, const void *src, size_t srcSize)
-{
- const BYTE *const istart = (const BYTE *const)src;
- const BYTE *const iend = istart + srcSize;
- const BYTE *ip = istart;
-
- /* check */
- if (srcSize < MIN_SEQUENCES_SIZE)
- return ERROR(srcSize_wrong);
-
- /* SeqHead */
- {
- int nbSeq = *ip++;
- if (!nbSeq) {
- *nbSeqPtr = 0;
- return 1;
- }
- if (nbSeq > 0x7F) {
- if (nbSeq == 0xFF) {
- if (ip + 2 > iend)
- return ERROR(srcSize_wrong);
- nbSeq = ZSTD_readLE16(ip) + LONGNBSEQ, ip += 2;
- } else {
- if (ip >= iend)
- return ERROR(srcSize_wrong);
- nbSeq = ((nbSeq - 0x80) << 8) + *ip++;
- }
- }
- *nbSeqPtr = nbSeq;
- }
-
- /* FSE table descriptors */
- if (ip + 4 > iend)
- return ERROR(srcSize_wrong); /* minimum possible size */
- {
- symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
- symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
- symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
- ip++;
-
- /* Build DTables */
- {
- size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr, LLtype, MaxLL, LLFSELog, ip, iend - ip,
- LL_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
- if (ZSTD_isError(llhSize))
- return ERROR(corruption_detected);
- ip += llhSize;
- }
- {
- size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr, OFtype, MaxOff, OffFSELog, ip, iend - ip,
- OF_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
- if (ZSTD_isError(ofhSize))
- return ERROR(corruption_detected);
- ip += ofhSize;
- }
- {
- size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr, MLtype, MaxML, MLFSELog, ip, iend - ip,
- ML_defaultDTable, dctx->fseEntropy, dctx->entropy.workspace, sizeof(dctx->entropy.workspace));
- if (ZSTD_isError(mlhSize))
- return ERROR(corruption_detected);
- ip += mlhSize;
- }
- }
-
- return ip - istart;
-}
-
-typedef struct {
- size_t litLength;
- size_t matchLength;
- size_t offset;
- const BYTE *match;
-} seq_t;
-
-typedef struct {
- BIT_DStream_t DStream;
- FSE_DState_t stateLL;
- FSE_DState_t stateOffb;
- FSE_DState_t stateML;
- size_t prevOffset[ZSTD_REP_NUM];
- const BYTE *base;
- size_t pos;
- uPtrDiff gotoDict;
-} seqState_t;
-
-FORCE_NOINLINE
-size_t ZSTD_execSequenceLast7(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
- const BYTE *const vBase, const BYTE *const dictEnd)
-{
- BYTE *const oLitEnd = op + sequence.litLength;
- size_t const sequenceLength = sequence.litLength + sequence.matchLength;
- BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
- BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
- const BYTE *const iLitEnd = *litPtr + sequence.litLength;
- const BYTE *match = oLitEnd - sequence.offset;
-
- /* check */
- if (oMatchEnd > oend)
- return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
- if (iLitEnd > litLimit)
- return ERROR(corruption_detected); /* over-read beyond lit buffer */
- if (oLitEnd <= oend_w)
- return ERROR(GENERIC); /* Precondition */
-
- /* copy literals */
- if (op < oend_w) {
- ZSTD_wildcopy(op, *litPtr, oend_w - op);
- *litPtr += oend_w - op;
- op = oend_w;
- }
- while (op < oLitEnd)
- *op++ = *(*litPtr)++;
-
- /* copy Match */
- if (sequence.offset > (size_t)(oLitEnd - base)) {
- /* offset beyond prefix */
- if (sequence.offset > (size_t)(oLitEnd - vBase))
- return ERROR(corruption_detected);
- match = dictEnd - (base - match);
- if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
- return sequenceLength;
- }
- /* span extDict & currPrefixSegment */
- {
- size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = base;
- }
- }
- while (op < oMatchEnd)
- *op++ = *match++;
- return sequenceLength;
-}
-
-static seq_t ZSTD_decodeSequence(seqState_t *seqState)
-{
- seq_t seq;
-
- U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
- U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
-
- U32 const llBits = LL_bits[llCode];
- U32 const mlBits = ML_bits[mlCode];
- U32 const ofBits = ofCode;
- U32 const totalBits = llBits + mlBits + ofBits;
-
- static const U32 LL_base[MaxLL + 1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18,
- 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000};
-
- static const U32 ML_base[MaxML + 1] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41,
- 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003};
-
- static const U32 OF_base[MaxOff + 1] = {0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD,
- 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD,
- 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD};
-
- /* sequence */
- {
- size_t offset;
- if (!ofCode)
- offset = 0;
- else {
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
- if (ZSTD_32bits())
- BIT_reloadDStream(&seqState->DStream);
- }
-
- if (ofCode <= 1) {
- offset += (llCode == 0);
- if (offset) {
- size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
- temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
- if (offset != 1)
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset = temp;
- } else {
- offset = seqState->prevOffset[0];
- }
- } else {
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset;
- }
- seq.offset = offset;
- }
-
- seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
- if (ZSTD_32bits() && (mlBits + llBits > 24))
- BIT_reloadDStream(&seqState->DStream);
-
- seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
- if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog)))
- BIT_reloadDStream(&seqState->DStream);
-
- /* ANS state update */
- FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
- FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
- if (ZSTD_32bits())
- BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
-
- seq.match = NULL;
-
- return seq;
-}
-
-FORCE_INLINE
-size_t ZSTD_execSequence(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
- const BYTE *const vBase, const BYTE *const dictEnd)
-{
- BYTE *const oLitEnd = op + sequence.litLength;
- size_t const sequenceLength = sequence.litLength + sequence.matchLength;
- BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
- BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
- const BYTE *const iLitEnd = *litPtr + sequence.litLength;
- const BYTE *match = oLitEnd - sequence.offset;
-
- /* check */
- if (oMatchEnd > oend)
- return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
- if (iLitEnd > litLimit)
- return ERROR(corruption_detected); /* over-read beyond lit buffer */
- if (oLitEnd > oend_w)
- return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
-
- /* copy Literals */
- ZSTD_copy8(op, *litPtr);
- if (sequence.litLength > 8)
- ZSTD_wildcopy(op + 8, (*litPtr) + 8,
- sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
- op = oLitEnd;
- *litPtr = iLitEnd; /* update for next sequence */
-
- /* copy Match */
- if (sequence.offset > (size_t)(oLitEnd - base)) {
- /* offset beyond prefix */
- if (sequence.offset > (size_t)(oLitEnd - vBase))
- return ERROR(corruption_detected);
- match = dictEnd + (match - base);
- if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
- return sequenceLength;
- }
- /* span extDict & currPrefixSegment */
- {
- size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = base;
- if (op > oend_w || sequence.matchLength < MINMATCH) {
- U32 i;
- for (i = 0; i < sequence.matchLength; ++i)
- op[i] = match[i];
- return sequenceLength;
- }
- }
- }
- /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
-
- /* match within prefix */
- if (sequence.offset < 8) {
- /* close range match, overlap */
- static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
- static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */
- int const sub2 = dec64table[sequence.offset];
- op[0] = match[0];
- op[1] = match[1];
- op[2] = match[2];
- op[3] = match[3];
- match += dec32table[sequence.offset];
- ZSTD_copy4(op + 4, match);
- match -= sub2;
- } else {
- ZSTD_copy8(op, match);
- }
- op += 8;
- match += 8;
-
- if (oMatchEnd > oend - (16 - MINMATCH)) {
- if (op < oend_w) {
- ZSTD_wildcopy(op, match, oend_w - op);
- match += oend_w - op;
- op = oend_w;
- }
- while (op < oMatchEnd)
- *op++ = *match++;
- } else {
- ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */
- }
- return sequenceLength;
-}
-
-static size_t ZSTD_decompressSequences(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize)
-{
- const BYTE *ip = (const BYTE *)seqStart;
- const BYTE *const iend = ip + seqSize;
- BYTE *const ostart = (BYTE * const)dst;
- BYTE *const oend = ostart + maxDstSize;
- BYTE *op = ostart;
- const BYTE *litPtr = dctx->litPtr;
- const BYTE *const litEnd = litPtr + dctx->litSize;
- const BYTE *const base = (const BYTE *)(dctx->base);
- const BYTE *const vBase = (const BYTE *)(dctx->vBase);
- const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd);
- int nbSeq;
-
- /* Build Decoding Tables */
- {
- size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
- if (ZSTD_isError(seqHSize))
- return seqHSize;
- ip += seqHSize;
- }
-
- /* Regen sequences */
- if (nbSeq) {
- seqState_t seqState;
- dctx->fseEntropy = 1;
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqState.prevOffset[i] = dctx->entropy.rep[i];
- }
- CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected);
- FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
- FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
- FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
-
- for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq;) {
- nbSeq--;
- {
- seq_t const sequence = ZSTD_decodeSequence(&seqState);
- size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);
- if (ZSTD_isError(oneSeqSize))
- return oneSeqSize;
- op += oneSeqSize;
- }
- }
-
- /* check if reached exact end */
- if (nbSeq)
- return ERROR(corruption_detected);
- /* save reps for next block */
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]);
- }
- }
-
- /* last literal segment */
- {
- size_t const lastLLSize = litEnd - litPtr;
- if (lastLLSize > (size_t)(oend - op))
- return ERROR(dstSize_tooSmall);
- memcpy(op, litPtr, lastLLSize);
- op += lastLLSize;
- }
-
- return op - ostart;
-}
-
-FORCE_INLINE seq_t ZSTD_decodeSequenceLong_generic(seqState_t *seqState, int const longOffsets)
-{
- seq_t seq;
-
- U32 const llCode = FSE_peekSymbol(&seqState->stateLL);
- U32 const mlCode = FSE_peekSymbol(&seqState->stateML);
- U32 const ofCode = FSE_peekSymbol(&seqState->stateOffb); /* <= maxOff, by table construction */
-
- U32 const llBits = LL_bits[llCode];
- U32 const mlBits = ML_bits[mlCode];
- U32 const ofBits = ofCode;
- U32 const totalBits = llBits + mlBits + ofBits;
-
- static const U32 LL_base[MaxLL + 1] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18,
- 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000};
-
- static const U32 ML_base[MaxML + 1] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 39, 41,
- 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803, 0x1003, 0x2003, 0x4003, 0x8003, 0x10003};
-
- static const U32 OF_base[MaxOff + 1] = {0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD,
- 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD,
- 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD};
-
- /* sequence */
- {
- size_t offset;
- if (!ofCode)
- offset = 0;
- else {
- if (longOffsets) {
- int const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN);
- offset = OF_base[ofCode] + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
- if (ZSTD_32bits() || extraBits)
- BIT_reloadDStream(&seqState->DStream);
- if (extraBits)
- offset += BIT_readBitsFast(&seqState->DStream, extraBits);
- } else {
- offset = OF_base[ofCode] + BIT_readBitsFast(&seqState->DStream, ofBits); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
- if (ZSTD_32bits())
- BIT_reloadDStream(&seqState->DStream);
- }
- }
-
- if (ofCode <= 1) {
- offset += (llCode == 0);
- if (offset) {
- size_t temp = (offset == 3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
- temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
- if (offset != 1)
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset = temp;
- } else {
- offset = seqState->prevOffset[0];
- }
- } else {
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset;
- }
- seq.offset = offset;
- }
-
- seq.matchLength = ML_base[mlCode] + ((mlCode > 31) ? BIT_readBitsFast(&seqState->DStream, mlBits) : 0); /* <= 16 bits */
- if (ZSTD_32bits() && (mlBits + llBits > 24))
- BIT_reloadDStream(&seqState->DStream);
-
- seq.litLength = LL_base[llCode] + ((llCode > 15) ? BIT_readBitsFast(&seqState->DStream, llBits) : 0); /* <= 16 bits */
- if (ZSTD_32bits() || (totalBits > 64 - 7 - (LLFSELog + MLFSELog + OffFSELog)))
- BIT_reloadDStream(&seqState->DStream);
-
- {
- size_t const pos = seqState->pos + seq.litLength;
- seq.match = seqState->base + pos - seq.offset; /* single memory segment */
- if (seq.offset > pos)
- seq.match += seqState->gotoDict; /* separate memory segment */
- seqState->pos = pos + seq.matchLength;
- }
-
- /* ANS state update */
- FSE_updateState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
- FSE_updateState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
- if (ZSTD_32bits())
- BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- FSE_updateState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
-
- return seq;
-}
-
-static seq_t ZSTD_decodeSequenceLong(seqState_t *seqState, unsigned const windowSize)
-{
- if (ZSTD_highbit32(windowSize) > STREAM_ACCUMULATOR_MIN) {
- return ZSTD_decodeSequenceLong_generic(seqState, 1);
- } else {
- return ZSTD_decodeSequenceLong_generic(seqState, 0);
- }
-}
-
-FORCE_INLINE
-size_t ZSTD_execSequenceLong(BYTE *op, BYTE *const oend, seq_t sequence, const BYTE **litPtr, const BYTE *const litLimit, const BYTE *const base,
- const BYTE *const vBase, const BYTE *const dictEnd)
-{
- BYTE *const oLitEnd = op + sequence.litLength;
- size_t const sequenceLength = sequence.litLength + sequence.matchLength;
- BYTE *const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
- BYTE *const oend_w = oend - WILDCOPY_OVERLENGTH;
- const BYTE *const iLitEnd = *litPtr + sequence.litLength;
- const BYTE *match = sequence.match;
-
- /* check */
- if (oMatchEnd > oend)
- return ERROR(dstSize_tooSmall); /* last match must start at a minimum distance of WILDCOPY_OVERLENGTH from oend */
- if (iLitEnd > litLimit)
- return ERROR(corruption_detected); /* over-read beyond lit buffer */
- if (oLitEnd > oend_w)
- return ZSTD_execSequenceLast7(op, oend, sequence, litPtr, litLimit, base, vBase, dictEnd);
-
- /* copy Literals */
- ZSTD_copy8(op, *litPtr);
- if (sequence.litLength > 8)
- ZSTD_wildcopy(op + 8, (*litPtr) + 8,
- sequence.litLength - 8); /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */
- op = oLitEnd;
- *litPtr = iLitEnd; /* update for next sequence */
-
- /* copy Match */
- if (sequence.offset > (size_t)(oLitEnd - base)) {
- /* offset beyond prefix */
- if (sequence.offset > (size_t)(oLitEnd - vBase))
- return ERROR(corruption_detected);
- if (match + sequence.matchLength <= dictEnd) {
- memmove(oLitEnd, match, sequence.matchLength);
- return sequenceLength;
- }
- /* span extDict & currPrefixSegment */
- {
- size_t const length1 = dictEnd - match;
- memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = base;
- if (op > oend_w || sequence.matchLength < MINMATCH) {
- U32 i;
- for (i = 0; i < sequence.matchLength; ++i)
- op[i] = match[i];
- return sequenceLength;
- }
- }
- }
- /* Requirement: op <= oend_w && sequence.matchLength >= MINMATCH */
-
- /* match within prefix */
- if (sequence.offset < 8) {
- /* close range match, overlap */
- static const U32 dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; /* added */
- static const int dec64table[] = {8, 8, 8, 7, 8, 9, 10, 11}; /* subtracted */
- int const sub2 = dec64table[sequence.offset];
- op[0] = match[0];
- op[1] = match[1];
- op[2] = match[2];
- op[3] = match[3];
- match += dec32table[sequence.offset];
- ZSTD_copy4(op + 4, match);
- match -= sub2;
- } else {
- ZSTD_copy8(op, match);
- }
- op += 8;
- match += 8;
-
- if (oMatchEnd > oend - (16 - MINMATCH)) {
- if (op < oend_w) {
- ZSTD_wildcopy(op, match, oend_w - op);
- match += oend_w - op;
- op = oend_w;
- }
- while (op < oMatchEnd)
- *op++ = *match++;
- } else {
- ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8); /* works even if matchLength < 8 */
- }
- return sequenceLength;
-}
-
-static size_t ZSTD_decompressSequencesLong(ZSTD_DCtx *dctx, void *dst, size_t maxDstSize, const void *seqStart, size_t seqSize)
-{
- const BYTE *ip = (const BYTE *)seqStart;
- const BYTE *const iend = ip + seqSize;
- BYTE *const ostart = (BYTE * const)dst;
- BYTE *const oend = ostart + maxDstSize;
- BYTE *op = ostart;
- const BYTE *litPtr = dctx->litPtr;
- const BYTE *const litEnd = litPtr + dctx->litSize;
- const BYTE *const base = (const BYTE *)(dctx->base);
- const BYTE *const vBase = (const BYTE *)(dctx->vBase);
- const BYTE *const dictEnd = (const BYTE *)(dctx->dictEnd);
- unsigned const windowSize = dctx->fParams.windowSize;
- int nbSeq;
-
- /* Build Decoding Tables */
- {
- size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, seqSize);
- if (ZSTD_isError(seqHSize))
- return seqHSize;
- ip += seqHSize;
- }
-
- /* Regen sequences */
- if (nbSeq) {
-#define STORED_SEQS 4
-#define STOSEQ_MASK (STORED_SEQS - 1)
-#define ADVANCED_SEQS 4
- seq_t *sequences = (seq_t *)dctx->entropy.workspace;
- int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
- seqState_t seqState;
- int seqNb;
- ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.workspace) >= sizeof(seq_t) * STORED_SEQS);
- dctx->fseEntropy = 1;
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- seqState.prevOffset[i] = dctx->entropy.rep[i];
- }
- seqState.base = base;
- seqState.pos = (size_t)(op - base);
- seqState.gotoDict = (uPtrDiff)dictEnd - (uPtrDiff)base; /* cast to avoid undefined behaviour */
- CHECK_E(BIT_initDStream(&seqState.DStream, ip, iend - ip), corruption_detected);
- FSE_initDState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
- FSE_initDState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
- FSE_initDState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
-
- /* prepare in advance */
- for (seqNb = 0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && seqNb < seqAdvance; seqNb++) {
- sequences[seqNb] = ZSTD_decodeSequenceLong(&seqState, windowSize);
- }
- if (seqNb < seqAdvance)
- return ERROR(corruption_detected);
-
- /* decode and decompress */
- for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && seqNb < nbSeq; seqNb++) {
- seq_t const sequence = ZSTD_decodeSequenceLong(&seqState, windowSize);
- size_t const oneSeqSize =
- ZSTD_execSequenceLong(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
- if (ZSTD_isError(oneSeqSize))
- return oneSeqSize;
- ZSTD_PREFETCH(sequence.match);
- sequences[seqNb & STOSEQ_MASK] = sequence;
- op += oneSeqSize;
- }
- if (seqNb < nbSeq)
- return ERROR(corruption_detected);
-
- /* finish queue */
- seqNb -= seqAdvance;
- for (; seqNb < nbSeq; seqNb++) {
- size_t const oneSeqSize = ZSTD_execSequenceLong(op, oend, sequences[seqNb & STOSEQ_MASK], &litPtr, litEnd, base, vBase, dictEnd);
- if (ZSTD_isError(oneSeqSize))
- return oneSeqSize;
- op += oneSeqSize;
- }
-
- /* save reps for next block */
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]);
- }
- }
-
- /* last literal segment */
- {
- size_t const lastLLSize = litEnd - litPtr;
- if (lastLLSize > (size_t)(oend - op))
- return ERROR(dstSize_tooSmall);
- memcpy(op, litPtr, lastLLSize);
- op += lastLLSize;
- }
-
- return op - ostart;
-}
-
-static size_t ZSTD_decompressBlock_internal(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
-{ /* blockType == blockCompressed */
- const BYTE *ip = (const BYTE *)src;
-
- if (srcSize >= ZSTD_BLOCKSIZE_ABSOLUTEMAX)
- return ERROR(srcSize_wrong);
-
- /* Decode literals section */
- {
- size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
- if (ZSTD_isError(litCSize))
- return litCSize;
- ip += litCSize;
- srcSize -= litCSize;
- }
- if (sizeof(size_t) > 4) /* do not enable prefetching on 32-bits x86, as it's performance detrimental */
- /* likely because of register pressure */
- /* if that's the correct cause, then 32-bits ARM should be affected differently */
- /* it would be good to test this on ARM real hardware, to see if prefetch version improves speed */
- if (dctx->fParams.windowSize > (1 << 23))
- return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize);
- return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);
-}
-
-static void ZSTD_checkContinuity(ZSTD_DCtx *dctx, const void *dst)
-{
- if (dst != dctx->previousDstEnd) { /* not contiguous */
- dctx->dictEnd = dctx->previousDstEnd;
- dctx->vBase = (const char *)dst - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base));
- dctx->base = dst;
- dctx->previousDstEnd = dst;
- }
-}
-
-size_t ZSTD_decompressBlock(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
-{
- size_t dSize;
- ZSTD_checkContinuity(dctx, dst);
- dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);
- dctx->previousDstEnd = (char *)dst + dSize;
- return dSize;
-}
-
-/** ZSTD_insertBlock() :
- insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
-size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSize)
-{
- ZSTD_checkContinuity(dctx, blockStart);
- dctx->previousDstEnd = (const char *)blockStart + blockSize;
- return blockSize;
-}
-
-size_t ZSTD_generateNxBytes(void *dst, size_t dstCapacity, BYTE byte, size_t length)
-{
- if (length > dstCapacity)
- return ERROR(dstSize_tooSmall);
- memset(dst, byte, length);
- return length;
-}
-
-/** ZSTD_findFrameCompressedSize() :
- * compatible with legacy mode
- * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
- * `srcSize` must be at least as large as the frame contained
- * Return: the compressed size of the frame starting at `src` */
-size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
-{
- if (srcSize >= ZSTD_skippableHeaderSize && (ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
- return ZSTD_skippableHeaderSize + ZSTD_readLE32((const BYTE *)src + 4);
- } else {
- const BYTE *ip = (const BYTE *)src;
- const BYTE *const ipstart = ip;
- size_t remainingSize = srcSize;
- ZSTD_frameParams fParams;
-
- size_t const headerSize = ZSTD_frameHeaderSize(ip, remainingSize);
- if (ZSTD_isError(headerSize))
- return headerSize;
-
- /* Frame Header */
- {
- size_t const ret = ZSTD_getFrameParams(&fParams, ip, remainingSize);
- if (ZSTD_isError(ret))
- return ret;
- if (ret > 0)
- return ERROR(srcSize_wrong);
- }
-
- ip += headerSize;
- remainingSize -= headerSize;
-
- /* Loop on each block */
- while (1) {
- blockProperties_t blockProperties;
- size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
- if (ZSTD_isError(cBlockSize))
- return cBlockSize;
-
- if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
- return ERROR(srcSize_wrong);
-
- ip += ZSTD_blockHeaderSize + cBlockSize;
- remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
-
- if (blockProperties.lastBlock)
- break;
- }
-
- if (fParams.checksumFlag) { /* Frame content checksum */
- if (remainingSize < 4)
- return ERROR(srcSize_wrong);
- ip += 4;
- remainingSize -= 4;
- }
-
- return ip - ipstart;
- }
-}
-
-/*! ZSTD_decompressFrame() :
-* @dctx must be properly initialized */
-static size_t ZSTD_decompressFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void **srcPtr, size_t *srcSizePtr)
-{
- const BYTE *ip = (const BYTE *)(*srcPtr);
- BYTE *const ostart = (BYTE * const)dst;
- BYTE *const oend = ostart + dstCapacity;
- BYTE *op = ostart;
- size_t remainingSize = *srcSizePtr;
-
- /* check */
- if (remainingSize < ZSTD_frameHeaderSize_min + ZSTD_blockHeaderSize)
- return ERROR(srcSize_wrong);
-
- /* Frame Header */
- {
- size_t const frameHeaderSize = ZSTD_frameHeaderSize(ip, ZSTD_frameHeaderSize_prefix);
- if (ZSTD_isError(frameHeaderSize))
- return frameHeaderSize;
- if (remainingSize < frameHeaderSize + ZSTD_blockHeaderSize)
- return ERROR(srcSize_wrong);
- CHECK_F(ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize));
- ip += frameHeaderSize;
- remainingSize -= frameHeaderSize;
- }
-
- /* Loop on each block */
- while (1) {
- size_t decodedSize;
- blockProperties_t blockProperties;
- size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
- if (ZSTD_isError(cBlockSize))
- return cBlockSize;
-
- ip += ZSTD_blockHeaderSize;
- remainingSize -= ZSTD_blockHeaderSize;
- if (cBlockSize > remainingSize)
- return ERROR(srcSize_wrong);
-
- switch (blockProperties.blockType) {
- case bt_compressed: decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend - op, ip, cBlockSize); break;
- case bt_raw: decodedSize = ZSTD_copyRawBlock(op, oend - op, ip, cBlockSize); break;
- case bt_rle: decodedSize = ZSTD_generateNxBytes(op, oend - op, *ip, blockProperties.origSize); break;
- case bt_reserved:
- default: return ERROR(corruption_detected);
- }
-
- if (ZSTD_isError(decodedSize))
- return decodedSize;
- if (dctx->fParams.checksumFlag)
- xxh64_update(&dctx->xxhState, op, decodedSize);
- op += decodedSize;
- ip += cBlockSize;
- remainingSize -= cBlockSize;
- if (blockProperties.lastBlock)
- break;
- }
-
- if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
- U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState);
- U32 checkRead;
- if (remainingSize < 4)
- return ERROR(checksum_wrong);
- checkRead = ZSTD_readLE32(ip);
- if (checkRead != checkCalc)
- return ERROR(checksum_wrong);
- ip += 4;
- remainingSize -= 4;
- }
-
- /* Allow caller to get size read */
- *srcPtr = ip;
- *srcSizePtr = remainingSize;
- return op - ostart;
-}
-
-static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict);
-static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict);
-
-static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize,
- const ZSTD_DDict *ddict)
-{
- void *const dststart = dst;
-
- if (ddict) {
- if (dict) {
- /* programmer error, these two cases should be mutually exclusive */
- return ERROR(GENERIC);
- }
-
- dict = ZSTD_DDictDictContent(ddict);
- dictSize = ZSTD_DDictDictSize(ddict);
- }
-
- while (srcSize >= ZSTD_frameHeaderSize_prefix) {
- U32 magicNumber;
-
- magicNumber = ZSTD_readLE32(src);
- if (magicNumber != ZSTD_MAGICNUMBER) {
- if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) {
- size_t skippableSize;
- if (srcSize < ZSTD_skippableHeaderSize)
- return ERROR(srcSize_wrong);
- skippableSize = ZSTD_readLE32((const BYTE *)src + 4) + ZSTD_skippableHeaderSize;
- if (srcSize < skippableSize) {
- return ERROR(srcSize_wrong);
- }
-
- src = (const BYTE *)src + skippableSize;
- srcSize -= skippableSize;
- continue;
- } else {
- return ERROR(prefix_unknown);
- }
- }
-
- if (ddict) {
- /* we were called from ZSTD_decompress_usingDDict */
- ZSTD_refDDict(dctx, ddict);
- } else {
- /* this will initialize correctly with no dict if dict == NULL, so
- * use this in all cases but ddict */
- CHECK_F(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize));
- }
- ZSTD_checkContinuity(dctx, dst);
-
- {
- const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity, &src, &srcSize);
- if (ZSTD_isError(res))
- return res;
- /* don't need to bounds check this, ZSTD_decompressFrame will have
- * already */
- dst = (BYTE *)dst + res;
- dstCapacity -= res;
- }
- }
-
- if (srcSize)
- return ERROR(srcSize_wrong); /* input not entirely consumed */
-
- return (BYTE *)dst - (BYTE *)dststart;
-}
-
-size_t ZSTD_decompress_usingDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const void *dict, size_t dictSize)
-{
- return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
-}
-
-size_t ZSTD_decompressDCtx(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
-{
- return ZSTD_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);
-}
-
-/*-**************************************
-* Advanced Streaming Decompression API
-* Bufferless and synchronous
-****************************************/
-size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx *dctx) { return dctx->expected; }
-
-ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx *dctx)
-{
- switch (dctx->stage) {
- default: /* should not happen */
- case ZSTDds_getFrameHeaderSize:
- case ZSTDds_decodeFrameHeader: return ZSTDnit_frameHeader;
- case ZSTDds_decodeBlockHeader: return ZSTDnit_blockHeader;
- case ZSTDds_decompressBlock: return ZSTDnit_block;
- case ZSTDds_decompressLastBlock: return ZSTDnit_lastBlock;
- case ZSTDds_checkChecksum: return ZSTDnit_checksum;
- case ZSTDds_decodeSkippableHeader:
- case ZSTDds_skipFrame: return ZSTDnit_skippableFrame;
- }
-}
-
-int ZSTD_isSkipFrame(ZSTD_DCtx *dctx) { return dctx->stage == ZSTDds_skipFrame; } /* for zbuff */
-
-/** ZSTD_decompressContinue() :
-* @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
-* or an error code, which can be tested using ZSTD_isError() */
-size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize)
-{
- /* Sanity check */
- if (srcSize != dctx->expected)
- return ERROR(srcSize_wrong);
- if (dstCapacity)
- ZSTD_checkContinuity(dctx, dst);
-
- switch (dctx->stage) {
- case ZSTDds_getFrameHeaderSize:
- if (srcSize != ZSTD_frameHeaderSize_prefix)
- return ERROR(srcSize_wrong); /* impossible */
- if ((ZSTD_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
- dctx->expected = ZSTD_skippableHeaderSize - ZSTD_frameHeaderSize_prefix; /* magic number + skippable frame length */
- dctx->stage = ZSTDds_decodeSkippableHeader;
- return 0;
- }
- dctx->headerSize = ZSTD_frameHeaderSize(src, ZSTD_frameHeaderSize_prefix);
- if (ZSTD_isError(dctx->headerSize))
- return dctx->headerSize;
- memcpy(dctx->headerBuffer, src, ZSTD_frameHeaderSize_prefix);
- if (dctx->headerSize > ZSTD_frameHeaderSize_prefix) {
- dctx->expected = dctx->headerSize - ZSTD_frameHeaderSize_prefix;
- dctx->stage = ZSTDds_decodeFrameHeader;
- return 0;
- }
- dctx->expected = 0; /* not necessary to copy more */
-
- case ZSTDds_decodeFrameHeader:
- memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
- CHECK_F(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize));
- dctx->expected = ZSTD_blockHeaderSize;
- dctx->stage = ZSTDds_decodeBlockHeader;
- return 0;
-
- case ZSTDds_decodeBlockHeader: {
- blockProperties_t bp;
- size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
- if (ZSTD_isError(cBlockSize))
- return cBlockSize;
- dctx->expected = cBlockSize;
- dctx->bType = bp.blockType;
- dctx->rleSize = bp.origSize;
- if (cBlockSize) {
- dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;
- return 0;
- }
- /* empty block */
- if (bp.lastBlock) {
- if (dctx->fParams.checksumFlag) {
- dctx->expected = 4;
- dctx->stage = ZSTDds_checkChecksum;
- } else {
- dctx->expected = 0; /* end of frame */
- dctx->stage = ZSTDds_getFrameHeaderSize;
- }
- } else {
- dctx->expected = 3; /* go directly to next header */
- dctx->stage = ZSTDds_decodeBlockHeader;
- }
- return 0;
- }
- case ZSTDds_decompressLastBlock:
- case ZSTDds_decompressBlock: {
- size_t rSize;
- switch (dctx->bType) {
- case bt_compressed: rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize); break;
- case bt_raw: rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize); break;
- case bt_rle: rSize = ZSTD_setRleBlock(dst, dstCapacity, src, srcSize, dctx->rleSize); break;
- case bt_reserved: /* should never happen */
- default: return ERROR(corruption_detected);
- }
- if (ZSTD_isError(rSize))
- return rSize;
- if (dctx->fParams.checksumFlag)
- xxh64_update(&dctx->xxhState, dst, rSize);
-
- if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
- if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
- dctx->expected = 4;
- dctx->stage = ZSTDds_checkChecksum;
- } else {
- dctx->expected = 0; /* ends here */
- dctx->stage = ZSTDds_getFrameHeaderSize;
- }
- } else {
- dctx->stage = ZSTDds_decodeBlockHeader;
- dctx->expected = ZSTD_blockHeaderSize;
- dctx->previousDstEnd = (char *)dst + rSize;
- }
- return rSize;
- }
- case ZSTDds_checkChecksum: {
- U32 const h32 = (U32)xxh64_digest(&dctx->xxhState);
- U32 const check32 = ZSTD_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */
- if (check32 != h32)
- return ERROR(checksum_wrong);
- dctx->expected = 0;
- dctx->stage = ZSTDds_getFrameHeaderSize;
- return 0;
- }
- case ZSTDds_decodeSkippableHeader: {
- memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected);
- dctx->expected = ZSTD_readLE32(dctx->headerBuffer + 4);
- dctx->stage = ZSTDds_skipFrame;
- return 0;
- }
- case ZSTDds_skipFrame: {
- dctx->expected = 0;
- dctx->stage = ZSTDds_getFrameHeaderSize;
- return 0;
- }
- default:
- return ERROR(GENERIC); /* impossible */
- }
-}
-
-static size_t ZSTD_refDictContent(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
-{
- dctx->dictEnd = dctx->previousDstEnd;
- dctx->vBase = (const char *)dict - ((const char *)(dctx->previousDstEnd) - (const char *)(dctx->base));
- dctx->base = dict;
- dctx->previousDstEnd = (const char *)dict + dictSize;
- return 0;
-}
-
-/* ZSTD_loadEntropy() :
- * dict : must point at beginning of a valid zstd dictionary
- * Return: size of entropy tables read */
-static size_t ZSTD_loadEntropy(ZSTD_entropyTables_t *entropy, const void *const dict, size_t const dictSize)
-{
- const BYTE *dictPtr = (const BYTE *)dict;
- const BYTE *const dictEnd = dictPtr + dictSize;
-
- if (dictSize <= 8)
- return ERROR(dictionary_corrupted);
- dictPtr += 8; /* skip header = magic + dictID */
-
- {
- size_t const hSize = HUF_readDTableX4_wksp(entropy->hufTable, dictPtr, dictEnd - dictPtr, entropy->workspace, sizeof(entropy->workspace));
- if (HUF_isError(hSize))
- return ERROR(dictionary_corrupted);
- dictPtr += hSize;
- }
-
- {
- short offcodeNCount[MaxOff + 1];
- U32 offcodeMaxValue = MaxOff, offcodeLog;
- size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd - dictPtr);
- if (FSE_isError(offcodeHeaderSize))
- return ERROR(dictionary_corrupted);
- if (offcodeLog > OffFSELog)
- return ERROR(dictionary_corrupted);
- CHECK_E(FSE_buildDTable_wksp(entropy->OFTable, offcodeNCount, offcodeMaxValue, offcodeLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
- dictPtr += offcodeHeaderSize;
- }
-
- {
- short matchlengthNCount[MaxML + 1];
- unsigned matchlengthMaxValue = MaxML, matchlengthLog;
- size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd - dictPtr);
- if (FSE_isError(matchlengthHeaderSize))
- return ERROR(dictionary_corrupted);
- if (matchlengthLog > MLFSELog)
- return ERROR(dictionary_corrupted);
- CHECK_E(FSE_buildDTable_wksp(entropy->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
- dictPtr += matchlengthHeaderSize;
- }
-
- {
- short litlengthNCount[MaxLL + 1];
- unsigned litlengthMaxValue = MaxLL, litlengthLog;
- size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd - dictPtr);
- if (FSE_isError(litlengthHeaderSize))
- return ERROR(dictionary_corrupted);
- if (litlengthLog > LLFSELog)
- return ERROR(dictionary_corrupted);
- CHECK_E(FSE_buildDTable_wksp(entropy->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog, entropy->workspace, sizeof(entropy->workspace)), dictionary_corrupted);
- dictPtr += litlengthHeaderSize;
- }
-
- if (dictPtr + 12 > dictEnd)
- return ERROR(dictionary_corrupted);
- {
- int i;
- size_t const dictContentSize = (size_t)(dictEnd - (dictPtr + 12));
- for (i = 0; i < 3; i++) {
- U32 const rep = ZSTD_readLE32(dictPtr);
- dictPtr += 4;
- if (rep == 0 || rep >= dictContentSize)
- return ERROR(dictionary_corrupted);
- entropy->rep[i] = rep;
- }
- }
-
- return dictPtr - (const BYTE *)dict;
-}
-
-static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
-{
- if (dictSize < 8)
- return ZSTD_refDictContent(dctx, dict, dictSize);
- {
- U32 const magic = ZSTD_readLE32(dict);
- if (magic != ZSTD_DICT_MAGIC) {
- return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
- }
- }
- dctx->dictID = ZSTD_readLE32((const char *)dict + 4);
-
- /* load entropy tables */
- {
- size_t const eSize = ZSTD_loadEntropy(&dctx->entropy, dict, dictSize);
- if (ZSTD_isError(eSize))
- return ERROR(dictionary_corrupted);
- dict = (const char *)dict + eSize;
- dictSize -= eSize;
- }
- dctx->litEntropy = dctx->fseEntropy = 1;
-
- /* reference dictionary content */
- return ZSTD_refDictContent(dctx, dict, dictSize);
-}
-
-size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx *dctx, const void *dict, size_t dictSize)
-{
- CHECK_F(ZSTD_decompressBegin(dctx));
- if (dict && dictSize)
- CHECK_E(ZSTD_decompress_insertDictionary(dctx, dict, dictSize), dictionary_corrupted);
- return 0;
-}
-
-/* ====== ZSTD_DDict ====== */
-
-struct ZSTD_DDict_s {
- void *dictBuffer;
- const void *dictContent;
- size_t dictSize;
- ZSTD_entropyTables_t entropy;
- U32 dictID;
- U32 entropyPresent;
- ZSTD_customMem cMem;
-}; /* typedef'd to ZSTD_DDict within "zstd.h" */
-
-size_t ZSTD_DDictWorkspaceBound(void) { return ZSTD_ALIGN(sizeof(ZSTD_stack)) + ZSTD_ALIGN(sizeof(ZSTD_DDict)); }
-
-static const void *ZSTD_DDictDictContent(const ZSTD_DDict *ddict) { return ddict->dictContent; }
-
-static size_t ZSTD_DDictDictSize(const ZSTD_DDict *ddict) { return ddict->dictSize; }
-
-static void ZSTD_refDDict(ZSTD_DCtx *dstDCtx, const ZSTD_DDict *ddict)
-{
- ZSTD_decompressBegin(dstDCtx); /* init */
- if (ddict) { /* support refDDict on NULL */
- dstDCtx->dictID = ddict->dictID;
- dstDCtx->base = ddict->dictContent;
- dstDCtx->vBase = ddict->dictContent;
- dstDCtx->dictEnd = (const BYTE *)ddict->dictContent + ddict->dictSize;
- dstDCtx->previousDstEnd = dstDCtx->dictEnd;
- if (ddict->entropyPresent) {
- dstDCtx->litEntropy = 1;
- dstDCtx->fseEntropy = 1;
- dstDCtx->LLTptr = ddict->entropy.LLTable;
- dstDCtx->MLTptr = ddict->entropy.MLTable;
- dstDCtx->OFTptr = ddict->entropy.OFTable;
- dstDCtx->HUFptr = ddict->entropy.hufTable;
- dstDCtx->entropy.rep[0] = ddict->entropy.rep[0];
- dstDCtx->entropy.rep[1] = ddict->entropy.rep[1];
- dstDCtx->entropy.rep[2] = ddict->entropy.rep[2];
- } else {
- dstDCtx->litEntropy = 0;
- dstDCtx->fseEntropy = 0;
- }
- }
-}
-
-static size_t ZSTD_loadEntropy_inDDict(ZSTD_DDict *ddict)
-{
- ddict->dictID = 0;
- ddict->entropyPresent = 0;
- if (ddict->dictSize < 8)
- return 0;
- {
- U32 const magic = ZSTD_readLE32(ddict->dictContent);
- if (magic != ZSTD_DICT_MAGIC)
- return 0; /* pure content mode */
- }
- ddict->dictID = ZSTD_readLE32((const char *)ddict->dictContent + 4);
-
- /* load entropy tables */
- CHECK_E(ZSTD_loadEntropy(&ddict->entropy, ddict->dictContent, ddict->dictSize), dictionary_corrupted);
- ddict->entropyPresent = 1;
- return 0;
-}
-
-static ZSTD_DDict *ZSTD_createDDict_advanced(const void *dict, size_t dictSize, unsigned byReference, ZSTD_customMem customMem)
-{
- if (!customMem.customAlloc || !customMem.customFree)
- return NULL;
-
- {
- ZSTD_DDict *const ddict = (ZSTD_DDict *)ZSTD_malloc(sizeof(ZSTD_DDict), customMem);
- if (!ddict)
- return NULL;
- ddict->cMem = customMem;
-
- if ((byReference) || (!dict) || (!dictSize)) {
- ddict->dictBuffer = NULL;
- ddict->dictContent = dict;
- } else {
- void *const internalBuffer = ZSTD_malloc(dictSize, customMem);
- if (!internalBuffer) {
- ZSTD_freeDDict(ddict);
- return NULL;
- }
- memcpy(internalBuffer, dict, dictSize);
- ddict->dictBuffer = internalBuffer;
- ddict->dictContent = internalBuffer;
- }
- ddict->dictSize = dictSize;
- ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
- /* parse dictionary content */
- {
- size_t const errorCode = ZSTD_loadEntropy_inDDict(ddict);
- if (ZSTD_isError(errorCode)) {
- ZSTD_freeDDict(ddict);
- return NULL;
- }
- }
-
- return ddict;
- }
-}
-
-/*! ZSTD_initDDict() :
-* Create a digested dictionary, to start decompression without startup delay.
-* `dict` content is copied inside DDict.
-* Consequently, `dict` can be released after `ZSTD_DDict` creation */
-ZSTD_DDict *ZSTD_initDDict(const void *dict, size_t dictSize, void *workspace, size_t workspaceSize)
-{
- ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
- return ZSTD_createDDict_advanced(dict, dictSize, 1, stackMem);
-}
-
-size_t ZSTD_freeDDict(ZSTD_DDict *ddict)
-{
- if (ddict == NULL)
- return 0; /* support free on NULL */
- {
- ZSTD_customMem const cMem = ddict->cMem;
- ZSTD_free(ddict->dictBuffer, cMem);
- ZSTD_free(ddict, cMem);
- return 0;
- }
-}
-
-/*! ZSTD_getDictID_fromDict() :
- * Provides the dictID stored within dictionary.
- * if @return == 0, the dictionary is not conformant with Zstandard specification.
- * It can still be loaded, but as a content-only dictionary. */
-unsigned ZSTD_getDictID_fromDict(const void *dict, size_t dictSize)
-{
- if (dictSize < 8)
- return 0;
- if (ZSTD_readLE32(dict) != ZSTD_DICT_MAGIC)
- return 0;
- return ZSTD_readLE32((const char *)dict + 4);
-}
-
-/*! ZSTD_getDictID_fromDDict() :
- * Provides the dictID of the dictionary loaded into `ddict`.
- * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
- * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
-unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict *ddict)
-{
- if (ddict == NULL)
- return 0;
- return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
-}
-
-/*! ZSTD_getDictID_fromFrame() :
- * Provides the dictID required to decompressed the frame stored within `src`.
- * If @return == 0, the dictID could not be decoded.
- * This could for one of the following reasons :
- * - The frame does not require a dictionary to be decoded (most common case).
- * - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
- * Note : this use case also happens when using a non-conformant dictionary.
- * - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
- * - This is not a Zstandard frame.
- * When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
-unsigned ZSTD_getDictID_fromFrame(const void *src, size_t srcSize)
-{
- ZSTD_frameParams zfp = {0, 0, 0, 0};
- size_t const hError = ZSTD_getFrameParams(&zfp, src, srcSize);
- if (ZSTD_isError(hError))
- return 0;
- return zfp.dictID;
-}
-
-/*! ZSTD_decompress_usingDDict() :
-* Decompression using a pre-digested Dictionary
-* Use dictionary without significant overhead. */
-size_t ZSTD_decompress_usingDDict(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, const void *src, size_t srcSize, const ZSTD_DDict *ddict)
-{
- /* pass content and size in case legacy frames are encountered */
- return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, NULL, 0, ddict);
-}
-
-/*=====================================
-* Streaming decompression
-*====================================*/
-
-typedef enum { zdss_init, zdss_loadHeader, zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
-
-/* *** Resource management *** */
-struct ZSTD_DStream_s {
- ZSTD_DCtx *dctx;
- ZSTD_DDict *ddictLocal;
- const ZSTD_DDict *ddict;
- ZSTD_frameParams fParams;
- ZSTD_dStreamStage stage;
- char *inBuff;
- size_t inBuffSize;
- size_t inPos;
- size_t maxWindowSize;
- char *outBuff;
- size_t outBuffSize;
- size_t outStart;
- size_t outEnd;
- size_t blockSize;
- BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX]; /* tmp buffer to store frame header */
- size_t lhSize;
- ZSTD_customMem customMem;
- void *legacyContext;
- U32 previousLegacyVersion;
- U32 legacyVersion;
- U32 hostageByte;
-}; /* typedef'd to ZSTD_DStream within "zstd.h" */
-
-size_t ZSTD_DStreamWorkspaceBound(size_t maxWindowSize)
-{
- size_t const blockSize = MIN(maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
- size_t const inBuffSize = blockSize;
- size_t const outBuffSize = maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
- return ZSTD_DCtxWorkspaceBound() + ZSTD_ALIGN(sizeof(ZSTD_DStream)) + ZSTD_ALIGN(inBuffSize) + ZSTD_ALIGN(outBuffSize);
-}
-
-static ZSTD_DStream *ZSTD_createDStream_advanced(ZSTD_customMem customMem)
-{
- ZSTD_DStream *zds;
-
- if (!customMem.customAlloc || !customMem.customFree)
- return NULL;
-
- zds = (ZSTD_DStream *)ZSTD_malloc(sizeof(ZSTD_DStream), customMem);
- if (zds == NULL)
- return NULL;
- memset(zds, 0, sizeof(ZSTD_DStream));
- memcpy(&zds->customMem, &customMem, sizeof(ZSTD_customMem));
- zds->dctx = ZSTD_createDCtx_advanced(customMem);
- if (zds->dctx == NULL) {
- ZSTD_freeDStream(zds);
- return NULL;
- }
- zds->stage = zdss_init;
- zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
- return zds;
-}
-
-ZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace, size_t workspaceSize)
-{
- ZSTD_customMem const stackMem = ZSTD_initStack(workspace, workspaceSize);
- ZSTD_DStream *zds = ZSTD_createDStream_advanced(stackMem);
- if (!zds) {
- return NULL;
- }
-
- zds->maxWindowSize = maxWindowSize;
- zds->stage = zdss_loadHeader;
- zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
- ZSTD_freeDDict(zds->ddictLocal);
- zds->ddictLocal = NULL;
- zds->ddict = zds->ddictLocal;
- zds->legacyVersion = 0;
- zds->hostageByte = 0;
-
- {
- size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
- size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
-
- zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
- zds->inBuffSize = blockSize;
- zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
- zds->outBuffSize = neededOutSize;
- if (zds->inBuff == NULL || zds->outBuff == NULL) {
- ZSTD_freeDStream(zds);
- return NULL;
- }
- }
- return zds;
-}
-
-ZSTD_DStream *ZSTD_initDStream_usingDDict(size_t maxWindowSize, const ZSTD_DDict *ddict, void *workspace, size_t workspaceSize)
-{
- ZSTD_DStream *zds = ZSTD_initDStream(maxWindowSize, workspace, workspaceSize);
- if (zds) {
- zds->ddict = ddict;
- }
- return zds;
-}
-
-size_t ZSTD_freeDStream(ZSTD_DStream *zds)
-{
- if (zds == NULL)
- return 0; /* support free on null */
- {
- ZSTD_customMem const cMem = zds->customMem;
- ZSTD_freeDCtx(zds->dctx);
- zds->dctx = NULL;
- ZSTD_freeDDict(zds->ddictLocal);
- zds->ddictLocal = NULL;
- ZSTD_free(zds->inBuff, cMem);
- zds->inBuff = NULL;
- ZSTD_free(zds->outBuff, cMem);
- zds->outBuff = NULL;
- ZSTD_free(zds, cMem);
- return 0;
- }
-}
-
-/* *** Initialization *** */
-
-size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize; }
-size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }
-
-size_t ZSTD_resetDStream(ZSTD_DStream *zds)
-{
- zds->stage = zdss_loadHeader;
- zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
- zds->legacyVersion = 0;
- zds->hostageByte = 0;
- return ZSTD_frameHeaderSize_prefix;
-}
-
-/* ***** Decompression ***** */
-
-ZSTD_STATIC size_t ZSTD_limitCopy(void *dst, size_t dstCapacity, const void *src, size_t srcSize)
-{
- size_t const length = MIN(dstCapacity, srcSize);
- memcpy(dst, src, length);
- return length;
-}
-
-size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inBuffer *input)
-{
- const char *const istart = (const char *)(input->src) + input->pos;
- const char *const iend = (const char *)(input->src) + input->size;
- const char *ip = istart;
- char *const ostart = (char *)(output->dst) + output->pos;
- char *const oend = (char *)(output->dst) + output->size;
- char *op = ostart;
- U32 someMoreWork = 1;
-
- while (someMoreWork) {
- switch (zds->stage) {
- case zdss_init:
- ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */
- /* fall-through */
-
- case zdss_loadHeader: {
- size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize);
- if (ZSTD_isError(hSize))
- return hSize;
- if (hSize != 0) { /* need more input */
- size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
- if (toLoad > (size_t)(iend - ip)) { /* not enough input to load full header */
- memcpy(zds->headerBuffer + zds->lhSize, ip, iend - ip);
- zds->lhSize += iend - ip;
- input->pos = input->size;
- return (MAX(ZSTD_frameHeaderSize_min, hSize) - zds->lhSize) +
- ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
- }
- memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad);
- zds->lhSize = hSize;
- ip += toLoad;
- break;
- }
-
- /* check for single-pass mode opportunity */
- if (zds->fParams.frameContentSize && zds->fParams.windowSize /* skippable frame if == 0 */
- && (U64)(size_t)(oend - op) >= zds->fParams.frameContentSize) {
- size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend - istart);
- if (cSize <= (size_t)(iend - istart)) {
- size_t const decompressedSize = ZSTD_decompress_usingDDict(zds->dctx, op, oend - op, istart, cSize, zds->ddict);
- if (ZSTD_isError(decompressedSize))
- return decompressedSize;
- ip = istart + cSize;
- op += decompressedSize;
- zds->dctx->expected = 0;
- zds->stage = zdss_init;
- someMoreWork = 0;
- break;
- }
- }
-
- /* Consume header */
- ZSTD_refDDict(zds->dctx, zds->ddict);
- {
- size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zds->dctx); /* == ZSTD_frameHeaderSize_prefix */
- CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer, h1Size));
- {
- size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zds->dctx);
- CHECK_F(ZSTD_decompressContinue(zds->dctx, NULL, 0, zds->headerBuffer + h1Size, h2Size));
- }
- }
-
- zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
- if (zds->fParams.windowSize > zds->maxWindowSize)
- return ERROR(frameParameter_windowTooLarge);
-
- /* Buffers are preallocated, but double check */
- {
- size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
- size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
- if (zds->inBuffSize < blockSize) {
- return ERROR(GENERIC);
- }
- if (zds->outBuffSize < neededOutSize) {
- return ERROR(GENERIC);
- }
- zds->blockSize = blockSize;
- }
- zds->stage = zdss_read;
- }
- /* pass-through */
-
- case zdss_read: {
- size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
- if (neededInSize == 0) { /* end of frame */
- zds->stage = zdss_init;
- someMoreWork = 0;
- break;
- }
- if ((size_t)(iend - ip) >= neededInSize) { /* decode directly from src */
- const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
- size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart,
- (isSkipFrame ? 0 : zds->outBuffSize - zds->outStart), ip, neededInSize);
- if (ZSTD_isError(decodedSize))
- return decodedSize;
- ip += neededInSize;
- if (!decodedSize && !isSkipFrame)
- break; /* this was just a header */
- zds->outEnd = zds->outStart + decodedSize;
- zds->stage = zdss_flush;
- break;
- }
- if (ip == iend) {
- someMoreWork = 0;
- break;
- } /* no more input */
- zds->stage = zdss_load;
- /* pass-through */
- }
-
- case zdss_load: {
- size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx);
- size_t const toLoad = neededInSize - zds->inPos; /* should always be <= remaining space within inBuff */
- size_t loadedSize;
- if (toLoad > zds->inBuffSize - zds->inPos)
- return ERROR(corruption_detected); /* should never happen */
- loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend - ip);
- ip += loadedSize;
- zds->inPos += loadedSize;
- if (loadedSize < toLoad) {
- someMoreWork = 0;
- break;
- } /* not enough input, wait for more */
-
- /* decode loaded input */
- {
- const int isSkipFrame = ZSTD_isSkipFrame(zds->dctx);
- size_t const decodedSize = ZSTD_decompressContinue(zds->dctx, zds->outBuff + zds->outStart, zds->outBuffSize - zds->outStart,
- zds->inBuff, neededInSize);
- if (ZSTD_isError(decodedSize))
- return decodedSize;
- zds->inPos = 0; /* input is consumed */
- if (!decodedSize && !isSkipFrame) {
- zds->stage = zdss_read;
- break;
- } /* this was just a header */
- zds->outEnd = zds->outStart + decodedSize;
- zds->stage = zdss_flush;
- /* pass-through */
- }
- }
-
- case zdss_flush: {
- size_t const toFlushSize = zds->outEnd - zds->outStart;
- size_t const flushedSize = ZSTD_limitCopy(op, oend - op, zds->outBuff + zds->outStart, toFlushSize);
- op += flushedSize;
- zds->outStart += flushedSize;
- if (flushedSize == toFlushSize) { /* flush completed */
- zds->stage = zdss_read;
- if (zds->outStart + zds->blockSize > zds->outBuffSize)
- zds->outStart = zds->outEnd = 0;
- break;
- }
- /* cannot complete flush */
- someMoreWork = 0;
- break;
- }
- default:
- return ERROR(GENERIC); /* impossible */
- }
- }
-
- /* result */
- input->pos += (size_t)(ip - istart);
- output->pos += (size_t)(op - ostart);
- {
- size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds->dctx);
- if (!nextSrcSizeHint) { /* frame fully decoded */
- if (zds->outEnd == zds->outStart) { /* output fully flushed */
- if (zds->hostageByte) {
- if (input->pos >= input->size) {
- zds->stage = zdss_read;
- return 1;
- } /* can't release hostage (not present) */
- input->pos++; /* release hostage */
- }
- return 0;
- }
- if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
- input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
- zds->hostageByte = 1;
- }
- return 1;
- }
- nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds->dctx) == ZSTDnit_block); /* preload header of next block */
- if (zds->inPos > nextSrcSizeHint)
- return ERROR(GENERIC); /* should never happen */
- nextSrcSizeHint -= zds->inPos; /* already loaded*/
- return nextSrcSizeHint;
- }
-}
-
-EXPORT_SYMBOL(ZSTD_DCtxWorkspaceBound);
-EXPORT_SYMBOL(ZSTD_initDCtx);
-EXPORT_SYMBOL(ZSTD_decompressDCtx);
-EXPORT_SYMBOL(ZSTD_decompress_usingDict);
-
-EXPORT_SYMBOL(ZSTD_DDictWorkspaceBound);
-EXPORT_SYMBOL(ZSTD_initDDict);
-EXPORT_SYMBOL(ZSTD_decompress_usingDDict);
-
-EXPORT_SYMBOL(ZSTD_DStreamWorkspaceBound);
-EXPORT_SYMBOL(ZSTD_initDStream);
-EXPORT_SYMBOL(ZSTD_initDStream_usingDDict);
-EXPORT_SYMBOL(ZSTD_resetDStream);
-EXPORT_SYMBOL(ZSTD_decompressStream);
-EXPORT_SYMBOL(ZSTD_DStreamInSize);
-EXPORT_SYMBOL(ZSTD_DStreamOutSize);
-
-EXPORT_SYMBOL(ZSTD_findFrameCompressedSize);
-EXPORT_SYMBOL(ZSTD_getFrameContentSize);
-EXPORT_SYMBOL(ZSTD_findDecompressedSize);
-
-EXPORT_SYMBOL(ZSTD_isFrame);
-EXPORT_SYMBOL(ZSTD_getDictID_fromDict);
-EXPORT_SYMBOL(ZSTD_getDictID_fromDDict);
-EXPORT_SYMBOL(ZSTD_getDictID_fromFrame);
-
-EXPORT_SYMBOL(ZSTD_getFrameParams);
-EXPORT_SYMBOL(ZSTD_decompressBegin);
-EXPORT_SYMBOL(ZSTD_decompressBegin_usingDict);
-EXPORT_SYMBOL(ZSTD_copyDCtx);
-EXPORT_SYMBOL(ZSTD_nextSrcSizeToDecompress);
-EXPORT_SYMBOL(ZSTD_decompressContinue);
-EXPORT_SYMBOL(ZSTD_nextInputType);
-
-EXPORT_SYMBOL(ZSTD_decompressBlock);
-EXPORT_SYMBOL(ZSTD_insertBlock);
diff --git a/lib/zstd/decompress/huf_decompress.c b/lib/zstd/decompress/huf_decompress.c
new file mode 100644
index 0000000..89b269a
--- /dev/null
+++ b/lib/zstd/decompress/huf_decompress.c
@@ -0,0 +1,1740 @@
+/* ******************************************************************
+ * huff0 huffman decoder,
+ * part of Finite State Entropy library
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+****************************************************************** */
+
+/* **************************************************************
+* Dependencies
+****************************************************************/
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */
+#include "../common/compiler.h"
+#include "../common/bitstream.h" /* BIT_* */
+#include "../common/fse.h" /* to compress headers */
+#define HUF_STATIC_LINKING_ONLY
+#include "../common/huf.h"
+#include "../common/error_private.h"
+#include "../common/zstd_internal.h"
+
+/* **************************************************************
+* Constants
+****************************************************************/
+
+#define HUF_DECODER_FAST_TABLELOG 11
+
+/* **************************************************************
+* Macros
+****************************************************************/
+
+/* These two optional macros force the use one way or another of the two
+ * Huffman decompression implementations. You can't force in both directions
+ * at the same time.
+ */
+#if defined(HUF_FORCE_DECOMPRESS_X1) && \
+ defined(HUF_FORCE_DECOMPRESS_X2)
+#error "Cannot force the use of the X1 and X2 decoders at the same time!"
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2 && DYNAMIC_BMI2
+# define HUF_ASM_X86_64_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE
+#else
+# define HUF_ASM_X86_64_BMI2_ATTRS
+#endif
+
+#define HUF_EXTERN_C
+#define HUF_ASM_DECL HUF_EXTERN_C
+
+#if DYNAMIC_BMI2 || (ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
+# define HUF_NEED_BMI2_FUNCTION 1
+#else
+# define HUF_NEED_BMI2_FUNCTION 0
+#endif
+
+#if !(ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
+# define HUF_NEED_DEFAULT_FUNCTION 1
+#else
+# define HUF_NEED_DEFAULT_FUNCTION 0
+#endif
+
+/* **************************************************************
+* Error Management
+****************************************************************/
+#define HUF_isError ERR_isError
+
+
+/* **************************************************************
+* Byte alignment for workSpace management
+****************************************************************/
+#define HUF_ALIGN(x, a) HUF_ALIGN_MASK((x), (a) - 1)
+#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+
+
+/* **************************************************************
+* BMI2 Variant Wrappers
+****************************************************************/
+#if DYNAMIC_BMI2
+
+#define HUF_DGEN(fn) \
+ \
+ static size_t fn##_default( \
+ void* dst, size_t dstSize, \
+ const void* cSrc, size_t cSrcSize, \
+ const HUF_DTable* DTable) \
+ { \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ \
+ static BMI2_TARGET_ATTRIBUTE size_t fn##_bmi2( \
+ void* dst, size_t dstSize, \
+ const void* cSrc, size_t cSrcSize, \
+ const HUF_DTable* DTable) \
+ { \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ \
+ static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
+ { \
+ if (bmi2) { \
+ return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable); \
+ } \
+ return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable); \
+ }
+
+#else
+
+#define HUF_DGEN(fn) \
+ static size_t fn(void* dst, size_t dstSize, void const* cSrc, \
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2) \
+ { \
+ (void)bmi2; \
+ return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
+ }
+
+#endif
+
+
+/*-***************************/
+/* generic DTableDesc */
+/*-***************************/
+typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;
+
+static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
+{
+ DTableDesc dtd;
+ ZSTD_memcpy(&dtd, table, sizeof(dtd));
+ return dtd;
+}
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2
+
+static size_t HUF_initDStream(BYTE const* ip) {
+ BYTE const lastByte = ip[7];
+ size_t const bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
+ size_t const value = MEM_readLEST(ip) | 1;
+ assert(bitsConsumed <= 8);
+ return value << bitsConsumed;
+}
+typedef struct {
+ BYTE const* ip[4];
+ BYTE* op[4];
+ U64 bits[4];
+ void const* dt;
+ BYTE const* ilimit;
+ BYTE* oend;
+ BYTE const* iend[4];
+} HUF_DecompressAsmArgs;
+
+/*
+ * Initializes args for the asm decoding loop.
+ * @returns 0 on success
+ * 1 if the fallback implementation should be used.
+ * Or an error code on failure.
+ */
+static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable)
+{
+ void const* dt = DTable + 1;
+ U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;
+
+ const BYTE* const ilimit = (const BYTE*)src + 6 + 8;
+
+ BYTE* const oend = (BYTE*)dst + dstSize;
+
+ /* The following condition is false on x32 platform,
+ * but HUF_asm is not compatible with this ABI */
+ if (!(MEM_isLittleEndian() && !MEM_32bits())) return 1;
+
+ /* strict minimum : jump table + 1 byte per stream */
+ if (srcSize < 10)
+ return ERROR(corruption_detected);
+
+ /* Must have at least 8 bytes per stream because we don't handle initializing smaller bit containers.
+ * If table log is not correct at this point, fallback to the old decoder.
+ * On small inputs we don't have enough data to trigger the fast loop, so use the old decoder.
+ */
+ if (dtLog != HUF_DECODER_FAST_TABLELOG)
+ return 1;
+
+ /* Read the jump table. */
+ {
+ const BYTE* const istart = (const BYTE*)src;
+ size_t const length1 = MEM_readLE16(istart);
+ size_t const length2 = MEM_readLE16(istart+2);
+ size_t const length3 = MEM_readLE16(istart+4);
+ size_t const length4 = srcSize - (length1 + length2 + length3 + 6);
+ args->iend[0] = istart + 6; /* jumpTable */
+ args->iend[1] = args->iend[0] + length1;
+ args->iend[2] = args->iend[1] + length2;
+ args->iend[3] = args->iend[2] + length3;
+
+ /* HUF_initDStream() requires this, and this small of an input
+ * won't benefit from the ASM loop anyways.
+ * length1 must be >= 16 so that ip[0] >= ilimit before the loop
+ * starts.
+ */
+ if (length1 < 16 || length2 < 8 || length3 < 8 || length4 < 8)
+ return 1;
+ if (length4 > srcSize) return ERROR(corruption_detected); /* overflow */
+ }
+ /* ip[] contains the position that is currently loaded into bits[]. */
+ args->ip[0] = args->iend[1] - sizeof(U64);
+ args->ip[1] = args->iend[2] - sizeof(U64);
+ args->ip[2] = args->iend[3] - sizeof(U64);
+ args->ip[3] = (BYTE const*)src + srcSize - sizeof(U64);
+
+ /* op[] contains the output pointers. */
+ args->op[0] = (BYTE*)dst;
+ args->op[1] = args->op[0] + (dstSize+3)/4;
+ args->op[2] = args->op[1] + (dstSize+3)/4;
+ args->op[3] = args->op[2] + (dstSize+3)/4;
+
+ /* No point to call the ASM loop for tiny outputs. */
+ if (args->op[3] >= oend)
+ return 1;
+
+ /* bits[] is the bit container.
+ * It is read from the MSB down to the LSB.
+ * It is shifted left as it is read, and zeros are
+ * shifted in. After the lowest valid bit a 1 is
+ * set, so that CountTrailingZeros(bits[]) can be used
+ * to count how many bits we've consumed.
+ */
+ args->bits[0] = HUF_initDStream(args->ip[0]);
+ args->bits[1] = HUF_initDStream(args->ip[1]);
+ args->bits[2] = HUF_initDStream(args->ip[2]);
+ args->bits[3] = HUF_initDStream(args->ip[3]);
+
+ /* If ip[] >= ilimit, it is guaranteed to be safe to
+ * reload bits[]. It may be beyond its section, but is
+ * guaranteed to be valid (>= istart).
+ */
+ args->ilimit = ilimit;
+
+ args->oend = oend;
+ args->dt = dt;
+
+ return 0;
+}
+
+static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressAsmArgs const* args, int stream, BYTE* segmentEnd)
+{
+ /* Validate that we haven't overwritten. */
+ if (args->op[stream] > segmentEnd)
+ return ERROR(corruption_detected);
+ /* Validate that we haven't read beyond iend[].
+ * Note that ip[] may be < iend[] because the MSB is
+ * the next bit to read, and we may have consumed 100%
+ * of the stream, so down to iend[i] - 8 is valid.
+ */
+ if (args->ip[stream] < args->iend[stream] - 8)
+ return ERROR(corruption_detected);
+
+ /* Construct the BIT_DStream_t. */
+ bit->bitContainer = MEM_readLE64(args->ip[stream]);
+ bit->bitsConsumed = ZSTD_countTrailingZeros((size_t)args->bits[stream]);
+ bit->start = (const char*)args->iend[0];
+ bit->limitPtr = bit->start + sizeof(size_t);
+ bit->ptr = (const char*)args->ip[stream];
+
+ return 0;
+}
+#endif
+
+
+#ifndef HUF_FORCE_DECOMPRESS_X2
+
+/*-***************************/
+/* single-symbol decoding */
+/*-***************************/
+typedef struct { BYTE nbBits; BYTE byte; } HUF_DEltX1; /* single-symbol decoding */
+
+/*
+ * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at
+ * a time.
+ */
+static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {
+ U64 D4;
+ if (MEM_isLittleEndian()) {
+ D4 = (symbol << 8) + nbBits;
+ } else {
+ D4 = symbol + (nbBits << 8);
+ }
+ D4 *= 0x0001000100010001ULL;
+ return D4;
+}
+
+/*
+ * Increase the tableLog to targetTableLog and rescales the stats.
+ * If tableLog > targetTableLog this is a no-op.
+ * @returns New tableLog
+ */
+static U32 HUF_rescaleStats(BYTE* huffWeight, U32* rankVal, U32 nbSymbols, U32 tableLog, U32 targetTableLog)
+{
+ if (tableLog > targetTableLog)
+ return tableLog;
+ if (tableLog < targetTableLog) {
+ U32 const scale = targetTableLog - tableLog;
+ U32 s;
+ /* Increase the weight for all non-zero probability symbols by scale. */
+ for (s = 0; s < nbSymbols; ++s) {
+ huffWeight[s] += (BYTE)((huffWeight[s] == 0) ? 0 : scale);
+ }
+ /* Update rankVal to reflect the new weights.
+ * All weights except 0 get moved to weight + scale.
+ * Weights [1, scale] are empty.
+ */
+ for (s = targetTableLog; s > scale; --s) {
+ rankVal[s] = rankVal[s - scale];
+ }
+ for (s = scale; s > 0; --s) {
+ rankVal[s] = 0;
+ }
+ }
+ return targetTableLog;
+}
+
+typedef struct {
+ U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];
+ U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1];
+ U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
+ BYTE symbols[HUF_SYMBOLVALUE_MAX + 1];
+ BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
+} HUF_ReadDTableX1_Workspace;
+
+
+size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)
+{
+ return HUF_readDTableX1_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0);
+}
+
+size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2)
+{
+ U32 tableLog = 0;
+ U32 nbSymbols = 0;
+ size_t iSize;
+ void* const dtPtr = DTable + 1;
+ HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;
+ HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace;
+
+ DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp));
+ if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge);
+
+ DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
+ /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
+
+ iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), bmi2);
+ if (HUF_isError(iSize)) return iSize;
+
+
+ /* Table header */
+ { DTableDesc dtd = HUF_getDTableDesc(DTable);
+ U32 const maxTableLog = dtd.maxTableLog + 1;
+ U32 const targetTableLog = MIN(maxTableLog, HUF_DECODER_FAST_TABLELOG);
+ tableLog = HUF_rescaleStats(wksp->huffWeight, wksp->rankVal, nbSymbols, tableLog, targetTableLog);
+ if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */
+ dtd.tableType = 0;
+ dtd.tableLog = (BYTE)tableLog;
+ ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
+ }
+
+ /* Compute symbols and rankStart given rankVal:
+ *
+ * rankVal already contains the number of values of each weight.
+ *
+ * symbols contains the symbols ordered by weight. First are the rankVal[0]
+ * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on.
+ * symbols[0] is filled (but unused) to avoid a branch.
+ *
+ * rankStart contains the offset where each rank belongs in the DTable.
+ * rankStart[0] is not filled because there are no entries in the table for
+ * weight 0.
+ */
+ {
+ int n;
+ int nextRankStart = 0;
+ int const unroll = 4;
+ int const nLimit = (int)nbSymbols - unroll + 1;
+ for (n=0; n<(int)tableLog+1; n++) {
+ U32 const curr = nextRankStart;
+ nextRankStart += wksp->rankVal[n];
+ wksp->rankStart[n] = curr;
+ }
+ for (n=0; n < nLimit; n += unroll) {
+ int u;
+ for (u=0; u < unroll; ++u) {
+ size_t const w = wksp->huffWeight[n+u];
+ wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u);
+ }
+ }
+ for (; n < (int)nbSymbols; ++n) {
+ size_t const w = wksp->huffWeight[n];
+ wksp->symbols[wksp->rankStart[w]++] = (BYTE)n;
+ }
+ }
+
+ /* fill DTable
+ * We fill all entries of each weight in order.
+ * That way length is a constant for each iteration of the outer loop.
+ * We can switch based on the length to a different inner loop which is
+ * optimized for that particular case.
+ */
+ {
+ U32 w;
+ int symbol=wksp->rankVal[0];
+ int rankStart=0;
+ for (w=1; w<tableLog+1; ++w) {
+ int const symbolCount = wksp->rankVal[w];
+ int const length = (1 << w) >> 1;
+ int uStart = rankStart;
+ BYTE const nbBits = (BYTE)(tableLog + 1 - w);
+ int s;
+ int u;
+ switch (length) {
+ case 1:
+ for (s=0; s<symbolCount; ++s) {
+ HUF_DEltX1 D;
+ D.byte = wksp->symbols[symbol + s];
+ D.nbBits = nbBits;
+ dt[uStart] = D;
+ uStart += 1;
+ }
+ break;
+ case 2:
+ for (s=0; s<symbolCount; ++s) {
+ HUF_DEltX1 D;
+ D.byte = wksp->symbols[symbol + s];
+ D.nbBits = nbBits;
+ dt[uStart+0] = D;
+ dt[uStart+1] = D;
+ uStart += 2;
+ }
+ break;
+ case 4:
+ for (s=0; s<symbolCount; ++s) {
+ U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
+ MEM_write64(dt + uStart, D4);
+ uStart += 4;
+ }
+ break;
+ case 8:
+ for (s=0; s<symbolCount; ++s) {
+ U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
+ MEM_write64(dt + uStart, D4);
+ MEM_write64(dt + uStart + 4, D4);
+ uStart += 8;
+ }
+ break;
+ default:
+ for (s=0; s<symbolCount; ++s) {
+ U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);
+ for (u=0; u < length; u += 16) {
+ MEM_write64(dt + uStart + u + 0, D4);
+ MEM_write64(dt + uStart + u + 4, D4);
+ MEM_write64(dt + uStart + u + 8, D4);
+ MEM_write64(dt + uStart + u + 12, D4);
+ }
+ assert(u == length);
+ uStart += length;
+ }
+ break;
+ }
+ symbol += symbolCount;
+ rankStart += symbolCount * length;
+ }
+ }
+ return iSize;
+}
+
+FORCE_INLINE_TEMPLATE BYTE
+HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
+ BYTE const c = dt[val].byte;
+ BIT_skipBits(Dstream, dt[val].nbBits);
+ return c;
+}
+
+#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \
+ *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr) \
+ if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
+ HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
+
+#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \
+ if (MEM_64bits()) \
+ HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)
+
+HINT_INLINE size_t
+HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)
+{
+ BYTE* const pStart = p;
+
+ /* up to 4 symbols at a time */
+ if ((pEnd - p) > 3) {
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
+ HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
+ }
+ } else {
+ BIT_reloadDStream(bitDPtr);
+ }
+
+ /* [0-3] symbols remaining */
+ if (MEM_32bits())
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))
+ HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
+
+ /* no more data to retrieve from bitstream, no need to reload */
+ while (p < pEnd)
+ HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
+
+ return pEnd-pStart;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress1X1_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ BYTE* op = (BYTE*)dst;
+ BYTE* const oend = op + dstSize;
+ const void* dtPtr = DTable + 1;
+ const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
+ BIT_DStream_t bitD;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+
+ CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
+
+ HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);
+
+ if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
+
+ return dstSize;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress4X1_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ /* Check */
+ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+ { const BYTE* const istart = (const BYTE*) cSrc;
+ BYTE* const ostart = (BYTE*) dst;
+ BYTE* const oend = ostart + dstSize;
+ BYTE* const olimit = oend - 3;
+ const void* const dtPtr = DTable + 1;
+ const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;
+
+ /* Init */
+ BIT_DStream_t bitD1;
+ BIT_DStream_t bitD2;
+ BIT_DStream_t bitD3;
+ BIT_DStream_t bitD4;
+ size_t const length1 = MEM_readLE16(istart);
+ size_t const length2 = MEM_readLE16(istart+2);
+ size_t const length3 = MEM_readLE16(istart+4);
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+ const BYTE* const istart1 = istart + 6; /* jumpTable */
+ const BYTE* const istart2 = istart1 + length1;
+ const BYTE* const istart3 = istart2 + length2;
+ const BYTE* const istart4 = istart3 + length3;
+ const size_t segmentSize = (dstSize+3) / 4;
+ BYTE* const opStart2 = ostart + segmentSize;
+ BYTE* const opStart3 = opStart2 + segmentSize;
+ BYTE* const opStart4 = opStart3 + segmentSize;
+ BYTE* op1 = ostart;
+ BYTE* op2 = opStart2;
+ BYTE* op3 = opStart3;
+ BYTE* op4 = opStart4;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+ U32 endSignal = 1;
+
+ if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
+ if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
+ CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
+ CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
+ CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
+ CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
+
+ /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
+ if ((size_t)(oend - op4) >= sizeof(size_t)) {
+ for ( ; (endSignal) & (op4 < olimit) ; ) {
+ HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
+ endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
+ }
+ }
+
+ /* check corruption */
+ /* note : should not be necessary : op# advance in lock step, and we control op4.
+ * but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */
+ if (op1 > opStart2) return ERROR(corruption_detected);
+ if (op2 > opStart3) return ERROR(corruption_detected);
+ if (op3 > opStart4) return ERROR(corruption_detected);
+ /* note : op4 supposed already verified within main loop */
+
+ /* finish bitStreams one by one */
+ HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);
+ HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);
+ HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);
+ HUF_decodeStreamX1(op4, &bitD4, oend, dt, dtLog);
+
+ /* check */
+ { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+ if (!endCheck) return ERROR(corruption_detected); }
+
+ /* decoded size */
+ return dstSize;
+ }
+}
+
+#if HUF_NEED_BMI2_FUNCTION
+static BMI2_TARGET_ATTRIBUTE
+size_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if HUF_NEED_DEFAULT_FUNCTION
+static
+size_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2
+
+HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
+
+static HUF_ASM_X86_64_BMI2_ATTRS
+size_t
+HUF_decompress4X1_usingDTable_internal_bmi2_asm(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ void const* dt = DTable + 1;
+ const BYTE* const iend = (const BYTE*)cSrc + 6;
+ BYTE* const oend = (BYTE*)dst + dstSize;
+ HUF_DecompressAsmArgs args;
+ {
+ size_t const ret = HUF_DecompressAsmArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
+ FORWARD_IF_ERROR(ret, "Failed to init asm args");
+ if (ret != 0)
+ return HUF_decompress4X1_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+ }
+
+ assert(args.ip[0] >= args.ilimit);
+ HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(&args);
+
+ /* Our loop guarantees that ip[] >= ilimit and that we haven't
+ * overwritten any op[].
+ */
+ assert(args.ip[0] >= iend);
+ assert(args.ip[1] >= iend);
+ assert(args.ip[2] >= iend);
+ assert(args.ip[3] >= iend);
+ assert(args.op[3] <= oend);
+ (void)iend;
+
+ /* finish bit streams one by one. */
+ {
+ size_t const segmentSize = (dstSize+3) / 4;
+ BYTE* segmentEnd = (BYTE*)dst;
+ int i;
+ for (i = 0; i < 4; ++i) {
+ BIT_DStream_t bit;
+ if (segmentSize <= (size_t)(oend - segmentEnd))
+ segmentEnd += segmentSize;
+ else
+ segmentEnd = oend;
+ FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
+ /* Decompress and validate that we've produced exactly the expected length. */
+ args.op[i] += HUF_decodeStreamX1(args.op[i], &bit, segmentEnd, (HUF_DEltX1 const*)dt, HUF_DECODER_FAST_TABLELOG);
+ if (args.op[i] != segmentEnd) return ERROR(corruption_detected);
+ }
+ }
+
+ /* decoded size */
+ return dstSize;
+}
+#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
+
+typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
+ const void *cSrc,
+ size_t cSrcSize,
+ const HUF_DTable *DTable);
+
+HUF_DGEN(HUF_decompress1X1_usingDTable_internal)
+
+static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+# if ZSTD_ENABLE_ASM_X86_64_BMI2
+ return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+# else
+ return HUF_decompress4X1_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+# endif
+ }
+#else
+ (void)bmi2;
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
+ return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+#else
+ return HUF_decompress4X1_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
+#endif
+}
+
+
+size_t HUF_decompress1X1_usingDTable(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 0) return ERROR(GENERIC);
+ return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+}
+
+size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize)
+{
+ const BYTE* ip = (const BYTE*) cSrc;
+
+ size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);
+ if (HUF_isError(hSize)) return hSize;
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
+ ip += hSize; cSrcSize -= hSize;
+
+ return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
+}
+
+
+size_t HUF_decompress4X1_usingDTable(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 0) return ERROR(GENERIC);
+ return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+}
+
+static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize, int bmi2)
+{
+ const BYTE* ip = (const BYTE*) cSrc;
+
+ size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+ if (HUF_isError(hSize)) return hSize;
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
+ ip += hSize; cSrcSize -= hSize;
+
+ return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+}
+
+size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);
+}
+
+
+#endif /* HUF_FORCE_DECOMPRESS_X2 */
+
+
+#ifndef HUF_FORCE_DECOMPRESS_X1
+
+/* *************************/
+/* double-symbols decoding */
+/* *************************/
+
+typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2; /* double-symbols decoding */
+typedef struct { BYTE symbol; } sortedSymbol_t;
+typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
+typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
+
+/*
+ * Constructs a HUF_DEltX2 in a U32.
+ */
+static U32 HUF_buildDEltX2U32(U32 symbol, U32 nbBits, U32 baseSeq, int level)
+{
+ U32 seq;
+ DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, sequence) == 0);
+ DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, nbBits) == 2);
+ DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, length) == 3);
+ DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U32));
+ if (MEM_isLittleEndian()) {
+ seq = level == 1 ? symbol : (baseSeq + (symbol << 8));
+ return seq + (nbBits << 16) + ((U32)level << 24);
+ } else {
+ seq = level == 1 ? (symbol << 8) : ((baseSeq << 8) + symbol);
+ return (seq << 16) + (nbBits << 8) + (U32)level;
+ }
+}
+
+/*
+ * Constructs a HUF_DEltX2.
+ */
+static HUF_DEltX2 HUF_buildDEltX2(U32 symbol, U32 nbBits, U32 baseSeq, int level)
+{
+ HUF_DEltX2 DElt;
+ U32 const val = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
+ DEBUG_STATIC_ASSERT(sizeof(DElt) == sizeof(val));
+ ZSTD_memcpy(&DElt, &val, sizeof(val));
+ return DElt;
+}
+
+/*
+ * Constructs 2 HUF_DEltX2s and packs them into a U64.
+ */
+static U64 HUF_buildDEltX2U64(U32 symbol, U32 nbBits, U16 baseSeq, int level)
+{
+ U32 DElt = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
+ return (U64)DElt + ((U64)DElt << 32);
+}
+
+/*
+ * Fills the DTable rank with all the symbols from [begin, end) that are each
+ * nbBits long.
+ *
+ * @param DTableRank The start of the rank in the DTable.
+ * @param begin The first symbol to fill (inclusive).
+ * @param end The last symbol to fill (exclusive).
+ * @param nbBits Each symbol is nbBits long.
+ * @param tableLog The table log.
+ * @param baseSeq If level == 1 { 0 } else { the first level symbol }
+ * @param level The level in the table. Must be 1 or 2.
+ */
+static void HUF_fillDTableX2ForWeight(
+ HUF_DEltX2* DTableRank,
+ sortedSymbol_t const* begin, sortedSymbol_t const* end,
+ U32 nbBits, U32 tableLog,
+ U16 baseSeq, int const level)
+{
+ U32 const length = 1U << ((tableLog - nbBits) & 0x1F /* quiet static-analyzer */);
+ const sortedSymbol_t* ptr;
+ assert(level >= 1 && level <= 2);
+ switch (length) {
+ case 1:
+ for (ptr = begin; ptr != end; ++ptr) {
+ HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
+ *DTableRank++ = DElt;
+ }
+ break;
+ case 2:
+ for (ptr = begin; ptr != end; ++ptr) {
+ HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
+ DTableRank[0] = DElt;
+ DTableRank[1] = DElt;
+ DTableRank += 2;
+ }
+ break;
+ case 4:
+ for (ptr = begin; ptr != end; ++ptr) {
+ U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
+ ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
+ DTableRank += 4;
+ }
+ break;
+ case 8:
+ for (ptr = begin; ptr != end; ++ptr) {
+ U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
+ ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
+ DTableRank += 8;
+ }
+ break;
+ default:
+ for (ptr = begin; ptr != end; ++ptr) {
+ U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
+ HUF_DEltX2* const DTableRankEnd = DTableRank + length;
+ for (; DTableRank != DTableRankEnd; DTableRank += 8) {
+ ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
+ }
+ }
+ break;
+ }
+}
+
+/* HUF_fillDTableX2Level2() :
+ * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
+static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32 consumedBits,
+ const U32* rankVal, const int minWeight, const int maxWeight1,
+ const sortedSymbol_t* sortedSymbols, U32 const* rankStart,
+ U32 nbBitsBaseline, U16 baseSeq)
+{
+ /* Fill skipped values (all positions up to rankVal[minWeight]).
+ * These are positions only get a single symbol because the combined weight
+ * is too large.
+ */
+ if (minWeight>1) {
+ U32 const length = 1U << ((targetLog - consumedBits) & 0x1F /* quiet static-analyzer */);
+ U64 const DEltX2 = HUF_buildDEltX2U64(baseSeq, consumedBits, /* baseSeq */ 0, /* level */ 1);
+ int const skipSize = rankVal[minWeight];
+ assert(length > 1);
+ assert((U32)skipSize < length);
+ switch (length) {
+ case 2:
+ assert(skipSize == 1);
+ ZSTD_memcpy(DTable, &DEltX2, sizeof(DEltX2));
+ break;
+ case 4:
+ assert(skipSize <= 4);
+ ZSTD_memcpy(DTable + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + 2, &DEltX2, sizeof(DEltX2));
+ break;
+ default:
+ {
+ int i;
+ for (i = 0; i < skipSize; i += 8) {
+ ZSTD_memcpy(DTable + i + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + i + 2, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + i + 4, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + i + 6, &DEltX2, sizeof(DEltX2));
+ }
+ }
+ }
+ }
+
+ /* Fill each of the second level symbols by weight. */
+ {
+ int w;
+ for (w = minWeight; w < maxWeight1; ++w) {
+ int const begin = rankStart[w];
+ int const end = rankStart[w+1];
+ U32 const nbBits = nbBitsBaseline - w;
+ U32 const totalBits = nbBits + consumedBits;
+ HUF_fillDTableX2ForWeight(
+ DTable + rankVal[w],
+ sortedSymbols + begin, sortedSymbols + end,
+ totalBits, targetLog,
+ baseSeq, /* level */ 2);
+ }
+ }
+}
+
+static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
+ const sortedSymbol_t* sortedList,
+ const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
+ const U32 nbBitsBaseline)
+{
+ U32* const rankVal = rankValOrigin[0];
+ const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
+ const U32 minBits = nbBitsBaseline - maxWeight;
+ int w;
+ int const wEnd = (int)maxWeight + 1;
+
+ /* Fill DTable in order of weight. */
+ for (w = 1; w < wEnd; ++w) {
+ int const begin = (int)rankStart[w];
+ int const end = (int)rankStart[w+1];
+ U32 const nbBits = nbBitsBaseline - w;
+
+ if (targetLog-nbBits >= minBits) {
+ /* Enough room for a second symbol. */
+ int start = rankVal[w];
+ U32 const length = 1U << ((targetLog - nbBits) & 0x1F /* quiet static-analyzer */);
+ int minWeight = nbBits + scaleLog;
+ int s;
+ if (minWeight < 1) minWeight = 1;
+ /* Fill the DTable for every symbol of weight w.
+ * These symbols get at least 1 second symbol.
+ */
+ for (s = begin; s != end; ++s) {
+ HUF_fillDTableX2Level2(
+ DTable + start, targetLog, nbBits,
+ rankValOrigin[nbBits], minWeight, wEnd,
+ sortedList, rankStart,
+ nbBitsBaseline, sortedList[s].symbol);
+ start += length;
+ }
+ } else {
+ /* Only a single symbol. */
+ HUF_fillDTableX2ForWeight(
+ DTable + rankVal[w],
+ sortedList + begin, sortedList + end,
+ nbBits, targetLog,
+ /* baseSeq */ 0, /* level */ 1);
+ }
+ }
+}
+
+typedef struct {
+ rankValCol_t rankVal[HUF_TABLELOG_MAX];
+ U32 rankStats[HUF_TABLELOG_MAX + 1];
+ U32 rankStart0[HUF_TABLELOG_MAX + 3];
+ sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];
+ BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];
+ U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
+} HUF_ReadDTableX2_Workspace;
+
+size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_readDTableX2_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0);
+}
+
+size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize, int bmi2)
+{
+ U32 tableLog, maxW, nbSymbols;
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ U32 maxTableLog = dtd.maxTableLog;
+ size_t iSize;
+ void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */
+ HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
+ U32 *rankStart;
+
+ HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;
+
+ if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);
+
+ rankStart = wksp->rankStart0 + 1;
+ ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));
+ ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));
+
+ DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
+ if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
+ /* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
+
+ iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), bmi2);
+ if (HUF_isError(iSize)) return iSize;
+
+ /* check result */
+ if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
+ if (tableLog <= HUF_DECODER_FAST_TABLELOG && maxTableLog > HUF_DECODER_FAST_TABLELOG) maxTableLog = HUF_DECODER_FAST_TABLELOG;
+
+ /* find maxWeight */
+ for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
+
+ /* Get start index of each weight */
+ { U32 w, nextRankStart = 0;
+ for (w=1; w<maxW+1; w++) {
+ U32 curr = nextRankStart;
+ nextRankStart += wksp->rankStats[w];
+ rankStart[w] = curr;
+ }
+ rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
+ rankStart[maxW+1] = nextRankStart;
+ }
+
+ /* sort symbols by weight */
+ { U32 s;
+ for (s=0; s<nbSymbols; s++) {
+ U32 const w = wksp->weightList[s];
+ U32 const r = rankStart[w]++;
+ wksp->sortedSymbol[r].symbol = (BYTE)s;
+ }
+ rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
+ }
+
+ /* Build rankVal */
+ { U32* const rankVal0 = wksp->rankVal[0];
+ { int const rescale = (maxTableLog-tableLog) - 1; /* tableLog <= maxTableLog */
+ U32 nextRankVal = 0;
+ U32 w;
+ for (w=1; w<maxW+1; w++) {
+ U32 curr = nextRankVal;
+ nextRankVal += wksp->rankStats[w] << (w+rescale);
+ rankVal0[w] = curr;
+ } }
+ { U32 const minBits = tableLog+1 - maxW;
+ U32 consumed;
+ for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
+ U32* const rankValPtr = wksp->rankVal[consumed];
+ U32 w;
+ for (w = 1; w < maxW+1; w++) {
+ rankValPtr[w] = rankVal0[w] >> consumed;
+ } } } }
+
+ HUF_fillDTableX2(dt, maxTableLog,
+ wksp->sortedSymbol,
+ wksp->rankStart0, wksp->rankVal, maxW,
+ tableLog+1);
+
+ dtd.tableLog = (BYTE)maxTableLog;
+ dtd.tableType = 1;
+ ZSTD_memcpy(DTable, &dtd, sizeof(dtd));
+ return iSize;
+}
+
+
+FORCE_INLINE_TEMPLATE U32
+HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ ZSTD_memcpy(op, &dt[val].sequence, 2);
+ BIT_skipBits(DStream, dt[val].nbBits);
+ return dt[val].length;
+}
+
+FORCE_INLINE_TEMPLATE U32
+HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
+{
+ size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
+ ZSTD_memcpy(op, &dt[val].sequence, 1);
+ if (dt[val].length==1) {
+ BIT_skipBits(DStream, dt[val].nbBits);
+ } else {
+ if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
+ BIT_skipBits(DStream, dt[val].nbBits);
+ if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
+ /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
+ DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
+ }
+ }
+ return 1;
+}
+
+#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \
+ ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
+ if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \
+ ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
+
+#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
+ if (MEM_64bits()) \
+ ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)
+
+HINT_INLINE size_t
+HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
+ const HUF_DEltX2* const dt, const U32 dtLog)
+{
+ BYTE* const pStart = p;
+
+ /* up to 8 symbols at a time */
+ if ((size_t)(pEnd - p) >= sizeof(bitDPtr->bitContainer)) {
+ if (dtLog <= 11 && MEM_64bits()) {
+ /* up to 10 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-9)) {
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ }
+ } else {
+ /* up to 8 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ }
+ }
+ } else {
+ BIT_reloadDStream(bitDPtr);
+ }
+
+ /* closer to end : up to 2 symbols at a time */
+ if ((size_t)(pEnd - p) >= 2) {
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+
+ while (p <= pEnd-2)
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
+ }
+
+ if (p < pEnd)
+ p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);
+
+ return p-pStart;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress1X2_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ BIT_DStream_t bitD;
+
+ /* Init */
+ CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );
+
+ /* decode */
+ { BYTE* const ostart = (BYTE*) dst;
+ BYTE* const oend = ostart + dstSize;
+ const void* const dtPtr = DTable+1; /* force compiler to not use strict-aliasing */
+ const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);
+ }
+
+ /* check */
+ if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);
+
+ /* decoded size */
+ return dstSize;
+}
+FORCE_INLINE_TEMPLATE size_t
+HUF_decompress4X2_usingDTable_internal_body(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ if (cSrcSize < 10) return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
+
+ { const BYTE* const istart = (const BYTE*) cSrc;
+ BYTE* const ostart = (BYTE*) dst;
+ BYTE* const oend = ostart + dstSize;
+ BYTE* const olimit = oend - (sizeof(size_t)-1);
+ const void* const dtPtr = DTable+1;
+ const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;
+
+ /* Init */
+ BIT_DStream_t bitD1;
+ BIT_DStream_t bitD2;
+ BIT_DStream_t bitD3;
+ BIT_DStream_t bitD4;
+ size_t const length1 = MEM_readLE16(istart);
+ size_t const length2 = MEM_readLE16(istart+2);
+ size_t const length3 = MEM_readLE16(istart+4);
+ size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
+ const BYTE* const istart1 = istart + 6; /* jumpTable */
+ const BYTE* const istart2 = istart1 + length1;
+ const BYTE* const istart3 = istart2 + length2;
+ const BYTE* const istart4 = istart3 + length3;
+ size_t const segmentSize = (dstSize+3) / 4;
+ BYTE* const opStart2 = ostart + segmentSize;
+ BYTE* const opStart3 = opStart2 + segmentSize;
+ BYTE* const opStart4 = opStart3 + segmentSize;
+ BYTE* op1 = ostart;
+ BYTE* op2 = opStart2;
+ BYTE* op3 = opStart3;
+ BYTE* op4 = opStart4;
+ U32 endSignal = 1;
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+ U32 const dtLog = dtd.tableLog;
+
+ if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
+ if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
+ CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
+ CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
+ CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
+ CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
+
+ /* 16-32 symbols per loop (4-8 symbols per stream) */
+ if ((size_t)(oend - op4) >= sizeof(size_t)) {
+ for ( ; (endSignal) & (op4 < olimit); ) {
+#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
+ endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+ endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
+#else
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+ endSignal = (U32)LIKELY((U32)
+ (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
+ & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
+ & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
+ & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));
+#endif
+ }
+ }
+
+ /* check corruption */
+ if (op1 > opStart2) return ERROR(corruption_detected);
+ if (op2 > opStart3) return ERROR(corruption_detected);
+ if (op3 > opStart4) return ERROR(corruption_detected);
+ /* note : op4 already verified within main loop */
+
+ /* finish bitStreams one by one */
+ HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
+ HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
+ HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
+ HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
+
+ /* check */
+ { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
+ if (!endCheck) return ERROR(corruption_detected); }
+
+ /* decoded size */
+ return dstSize;
+ }
+}
+
+#if HUF_NEED_BMI2_FUNCTION
+static BMI2_TARGET_ATTRIBUTE
+size_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if HUF_NEED_DEFAULT_FUNCTION
+static
+size_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2
+
+HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
+
+static HUF_ASM_X86_64_BMI2_ATTRS size_t
+HUF_decompress4X2_usingDTable_internal_bmi2_asm(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable) {
+ void const* dt = DTable + 1;
+ const BYTE* const iend = (const BYTE*)cSrc + 6;
+ BYTE* const oend = (BYTE*)dst + dstSize;
+ HUF_DecompressAsmArgs args;
+ {
+ size_t const ret = HUF_DecompressAsmArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
+ FORWARD_IF_ERROR(ret, "Failed to init asm args");
+ if (ret != 0)
+ return HUF_decompress4X2_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+ }
+
+ assert(args.ip[0] >= args.ilimit);
+ HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(&args);
+
+ /* note : op4 already verified within main loop */
+ assert(args.ip[0] >= iend);
+ assert(args.ip[1] >= iend);
+ assert(args.ip[2] >= iend);
+ assert(args.ip[3] >= iend);
+ assert(args.op[3] <= oend);
+ (void)iend;
+
+ /* finish bitStreams one by one */
+ {
+ size_t const segmentSize = (dstSize+3) / 4;
+ BYTE* segmentEnd = (BYTE*)dst;
+ int i;
+ for (i = 0; i < 4; ++i) {
+ BIT_DStream_t bit;
+ if (segmentSize <= (size_t)(oend - segmentEnd))
+ segmentEnd += segmentSize;
+ else
+ segmentEnd = oend;
+ FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
+ args.op[i] += HUF_decodeStreamX2(args.op[i], &bit, segmentEnd, (HUF_DEltX2 const*)dt, HUF_DECODER_FAST_TABLELOG);
+ if (args.op[i] != segmentEnd)
+ return ERROR(corruption_detected);
+ }
+ }
+
+ /* decoded size */
+ return dstSize;
+}
+#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
+
+static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+# if ZSTD_ENABLE_ASM_X86_64_BMI2
+ return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+# else
+ return HUF_decompress4X2_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+# endif
+ }
+#else
+ (void)bmi2;
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
+ return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+#else
+ return HUF_decompress4X2_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
+#endif
+}
+
+HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
+
+size_t HUF_decompress1X2_usingDTable(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 1) return ERROR(GENERIC);
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+}
+
+size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize)
+{
+ const BYTE* ip = (const BYTE*) cSrc;
+
+ size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,
+ workSpace, wkspSize);
+ if (HUF_isError(hSize)) return hSize;
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
+ ip += hSize; cSrcSize -= hSize;
+
+ return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);
+}
+
+
+size_t HUF_decompress4X2_usingDTable(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ if (dtd.tableType != 1) return ERROR(GENERIC);
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+}
+
+static size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize, int bmi2)
+{
+ const BYTE* ip = (const BYTE*) cSrc;
+
+ size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,
+ workSpace, wkspSize);
+ if (HUF_isError(hSize)) return hSize;
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
+ ip += hSize; cSrcSize -= hSize;
+
+ return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+}
+
+size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize)
+{
+ return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);
+}
+
+
+#endif /* HUF_FORCE_DECOMPRESS_X1 */
+
+
+/* ***********************************/
+/* Universal decompression selectors */
+/* ***********************************/
+
+size_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#else
+ return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
+ HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#endif
+}
+
+size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#else
+ return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :
+ HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);
+#endif
+}
+
+
+#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
+typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
+static const algo_time_t algoTime[16 /* Quantization */][2 /* single, double */] =
+{
+ /* single, double, quad */
+ {{0,0}, {1,1}}, /* Q==0 : impossible */
+ {{0,0}, {1,1}}, /* Q==1 : impossible */
+ {{ 150,216}, { 381,119}}, /* Q == 2 : 12-18% */
+ {{ 170,205}, { 514,112}}, /* Q == 3 : 18-25% */
+ {{ 177,199}, { 539,110}}, /* Q == 4 : 25-32% */
+ {{ 197,194}, { 644,107}}, /* Q == 5 : 32-38% */
+ {{ 221,192}, { 735,107}}, /* Q == 6 : 38-44% */
+ {{ 256,189}, { 881,106}}, /* Q == 7 : 44-50% */
+ {{ 359,188}, {1167,109}}, /* Q == 8 : 50-56% */
+ {{ 582,187}, {1570,114}}, /* Q == 9 : 56-62% */
+ {{ 688,187}, {1712,122}}, /* Q ==10 : 62-69% */
+ {{ 825,186}, {1965,136}}, /* Q ==11 : 69-75% */
+ {{ 976,185}, {2131,150}}, /* Q ==12 : 75-81% */
+ {{1180,186}, {2070,175}}, /* Q ==13 : 81-87% */
+ {{1377,185}, {1731,202}}, /* Q ==14 : 87-93% */
+ {{1412,185}, {1695,202}}, /* Q ==15 : 93-99% */
+};
+#endif
+
+/* HUF_selectDecoder() :
+ * Tells which decoder is likely to decode faster,
+ * based on a set of pre-computed metrics.
+ * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .
+ * Assumption : 0 < dstSize <= 128 KB */
+U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
+{
+ assert(dstSize > 0);
+ assert(dstSize <= 128*1024);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dstSize;
+ (void)cSrcSize;
+ return 0;
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dstSize;
+ (void)cSrcSize;
+ return 1;
+#else
+ /* decoder timing evaluation */
+ { U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize); /* Q < 16 */
+ U32 const D256 = (U32)(dstSize >> 8);
+ U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
+ U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
+ DTime1 += DTime1 >> 5; /* small advantage to algorithm using less memory, to reduce cache eviction */
+ return DTime1 < DTime0;
+ }
+#endif
+}
+
+
+size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst,
+ size_t dstSize, const void* cSrc,
+ size_t cSrcSize, void* workSpace,
+ size_t wkspSize)
+{
+ /* validation checks */
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
+ if (cSrcSize == 0) return ERROR(corruption_detected);
+
+ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
+#else
+ return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize):
+ HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);
+#endif
+ }
+}
+
+size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ void* workSpace, size_t wkspSize)
+{
+ /* validation checks */
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
+ if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */
+ if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */
+ if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */
+
+ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize);
+#else
+ return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize):
+ HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,
+ cSrcSize, workSpace, wkspSize);
+#endif
+ }
+}
+
+
+size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#else
+ return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
+ HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#endif
+}
+
+#ifndef HUF_FORCE_DECOMPRESS_X2
+size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
+{
+ const BYTE* ip = (const BYTE*) cSrc;
+
+ size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+ if (HUF_isError(hSize)) return hSize;
+ if (hSize >= cSrcSize) return ERROR(srcSize_wrong);
+ ip += hSize; cSrcSize -= hSize;
+
+ return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);
+}
+#endif
+
+size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)
+{
+ DTableDesc const dtd = HUF_getDTableDesc(DTable);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)dtd;
+ assert(dtd.tableType == 0);
+ return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)dtd;
+ assert(dtd.tableType == 1);
+ return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#else
+ return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :
+ HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);
+#endif
+}
+
+size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)
+{
+ /* validation checks */
+ if (dstSize == 0) return ERROR(dstSize_tooSmall);
+ if (cSrcSize == 0) return ERROR(corruption_detected);
+
+ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
+#if defined(HUF_FORCE_DECOMPRESS_X1)
+ (void)algoNb;
+ assert(algoNb == 0);
+ return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+#elif defined(HUF_FORCE_DECOMPRESS_X2)
+ (void)algoNb;
+ assert(algoNb == 1);
+ return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+#else
+ return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :
+ HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);
+#endif
+ }
+}
+
diff --git a/lib/zstd/decompress/zstd_ddict.c b/lib/zstd/decompress/zstd_ddict.c
new file mode 100644
index 0000000..dbbc791
--- /dev/null
+++ b/lib/zstd/decompress/zstd_ddict.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/* zstd_ddict.c :
+ * concentrates all logic that needs to know the internals of ZSTD_DDict object */
+
+/*-*******************************************************
+* Dependencies
+*********************************************************/
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
+#include "../common/cpu.h" /* bmi2 */
+#include "../common/mem.h" /* low level memory routines */
+#define FSE_STATIC_LINKING_ONLY
+#include "../common/fse.h"
+#define HUF_STATIC_LINKING_ONLY
+#include "../common/huf.h"
+#include "zstd_decompress_internal.h"
+#include "zstd_ddict.h"
+
+
+
+
+/*-*******************************************************
+* Types
+*********************************************************/
+struct ZSTD_DDict_s {
+ void* dictBuffer;
+ const void* dictContent;
+ size_t dictSize;
+ ZSTD_entropyDTables_t entropy;
+ U32 dictID;
+ U32 entropyPresent;
+ ZSTD_customMem cMem;
+}; /* typedef'd to ZSTD_DDict within "zstd.h" */
+
+const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict)
+{
+ assert(ddict != NULL);
+ return ddict->dictContent;
+}
+
+size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict)
+{
+ assert(ddict != NULL);
+ return ddict->dictSize;
+}
+
+void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
+{
+ DEBUGLOG(4, "ZSTD_copyDDictParameters");
+ assert(dctx != NULL);
+ assert(ddict != NULL);
+ dctx->dictID = ddict->dictID;
+ dctx->prefixStart = ddict->dictContent;
+ dctx->virtualStart = ddict->dictContent;
+ dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;
+ dctx->previousDstEnd = dctx->dictEnd;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
+#endif
+ if (ddict->entropyPresent) {
+ dctx->litEntropy = 1;
+ dctx->fseEntropy = 1;
+ dctx->LLTptr = ddict->entropy.LLTable;
+ dctx->MLTptr = ddict->entropy.MLTable;
+ dctx->OFTptr = ddict->entropy.OFTable;
+ dctx->HUFptr = ddict->entropy.hufTable;
+ dctx->entropy.rep[0] = ddict->entropy.rep[0];
+ dctx->entropy.rep[1] = ddict->entropy.rep[1];
+ dctx->entropy.rep[2] = ddict->entropy.rep[2];
+ } else {
+ dctx->litEntropy = 0;
+ dctx->fseEntropy = 0;
+ }
+}
+
+
+static size_t
+ZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,
+ ZSTD_dictContentType_e dictContentType)
+{
+ ddict->dictID = 0;
+ ddict->entropyPresent = 0;
+ if (dictContentType == ZSTD_dct_rawContent) return 0;
+
+ if (ddict->dictSize < 8) {
+ if (dictContentType == ZSTD_dct_fullDict)
+ return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
+ return 0; /* pure content mode */
+ }
+ { U32 const magic = MEM_readLE32(ddict->dictContent);
+ if (magic != ZSTD_MAGIC_DICTIONARY) {
+ if (dictContentType == ZSTD_dct_fullDict)
+ return ERROR(dictionary_corrupted); /* only accept specified dictionaries */
+ return 0; /* pure content mode */
+ }
+ }
+ ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);
+
+ /* load entropy tables */
+ RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(
+ &ddict->entropy, ddict->dictContent, ddict->dictSize)),
+ dictionary_corrupted, "");
+ ddict->entropyPresent = 1;
+ return 0;
+}
+
+
+static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
+{
+ if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {
+ ddict->dictBuffer = NULL;
+ ddict->dictContent = dict;
+ if (!dict) dictSize = 0;
+ } else {
+ void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);
+ ddict->dictBuffer = internalBuffer;
+ ddict->dictContent = internalBuffer;
+ if (!internalBuffer) return ERROR(memory_allocation);
+ ZSTD_memcpy(internalBuffer, dict, dictSize);
+ }
+ ddict->dictSize = dictSize;
+ ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+
+ /* parse dictionary content */
+ FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , "");
+
+ return 0;
+}
+
+ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType,
+ ZSTD_customMem customMem)
+{
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
+
+ { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);
+ if (ddict == NULL) return NULL;
+ ddict->cMem = customMem;
+ { size_t const initResult = ZSTD_initDDict_internal(ddict,
+ dict, dictSize,
+ dictLoadMethod, dictContentType);
+ if (ZSTD_isError(initResult)) {
+ ZSTD_freeDDict(ddict);
+ return NULL;
+ } }
+ return ddict;
+ }
+}
+
+/*! ZSTD_createDDict() :
+* Create a digested dictionary, to start decompression without startup delay.
+* `dict` content is copied inside DDict.
+* Consequently, `dict` can be released after `ZSTD_DDict` creation */
+ZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)
+{
+ ZSTD_customMem const allocator = { NULL, NULL, NULL };
+ return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);
+}
+
+/*! ZSTD_createDDict_byReference() :
+ * Create a digested dictionary, to start decompression without startup delay.
+ * Dictionary content is simply referenced, it will be accessed during decompression.
+ * Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */
+ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)
+{
+ ZSTD_customMem const allocator = { NULL, NULL, NULL };
+ return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);
+}
+
+
+const ZSTD_DDict* ZSTD_initStaticDDict(
+ void* sBuffer, size_t sBufferSize,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
+{
+ size_t const neededSpace = sizeof(ZSTD_DDict)
+ + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
+ ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer;
+ assert(sBuffer != NULL);
+ assert(dict != NULL);
+ if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */
+ if (sBufferSize < neededSpace) return NULL;
+ if (dictLoadMethod == ZSTD_dlm_byCopy) {
+ ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */
+ dict = ddict+1;
+ }
+ if (ZSTD_isError( ZSTD_initDDict_internal(ddict,
+ dict, dictSize,
+ ZSTD_dlm_byRef, dictContentType) ))
+ return NULL;
+ return ddict;
+}
+
+
+size_t ZSTD_freeDDict(ZSTD_DDict* ddict)
+{
+ if (ddict==NULL) return 0; /* support free on NULL */
+ { ZSTD_customMem const cMem = ddict->cMem;
+ ZSTD_customFree(ddict->dictBuffer, cMem);
+ ZSTD_customFree(ddict, cMem);
+ return 0;
+ }
+}
+
+/*! ZSTD_estimateDDictSize() :
+ * Estimate amount of memory that will be needed to create a dictionary for decompression.
+ * Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */
+size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)
+{
+ return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);
+}
+
+size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)
+{
+ if (ddict==NULL) return 0; /* support sizeof on NULL */
+ return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;
+}
+
+/*! ZSTD_getDictID_fromDDict() :
+ * Provides the dictID of the dictionary loaded into `ddict`.
+ * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
+ * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
+unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)
+{
+ if (ddict==NULL) return 0;
+ return ZSTD_getDictID_fromDict(ddict->dictContent, ddict->dictSize);
+}
diff --git a/lib/zstd/decompress/zstd_ddict.h b/lib/zstd/decompress/zstd_ddict.h
new file mode 100644
index 0000000..8c1a79d
--- /dev/null
+++ b/lib/zstd/decompress/zstd_ddict.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+#ifndef ZSTD_DDICT_H
+#define ZSTD_DDICT_H
+
+/*-*******************************************************
+ * Dependencies
+ *********************************************************/
+#include "../common/zstd_deps.h" /* size_t */
+#include <linux/zstd.h> /* ZSTD_DDict, and several public functions */
+
+
+/*-*******************************************************
+ * Interface
+ *********************************************************/
+
+/* note: several prototypes are already published in `zstd.h` :
+ * ZSTD_createDDict()
+ * ZSTD_createDDict_byReference()
+ * ZSTD_createDDict_advanced()
+ * ZSTD_freeDDict()
+ * ZSTD_initStaticDDict()
+ * ZSTD_sizeof_DDict()
+ * ZSTD_estimateDDictSize()
+ * ZSTD_getDictID_fromDict()
+ */
+
+const void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict);
+size_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict);
+
+void ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
+
+
+
+#endif /* ZSTD_DDICT_H */
diff --git a/lib/zstd/decompress/zstd_decompress.c b/lib/zstd/decompress/zstd_decompress.c
new file mode 100644
index 0000000..b9b935a
--- /dev/null
+++ b/lib/zstd/decompress/zstd_decompress.c
@@ -0,0 +1,2131 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+/* ***************************************************************
+* Tuning parameters
+*****************************************************************/
+/*!
+ * HEAPMODE :
+ * Select how default decompression function ZSTD_decompress() allocates its context,
+ * on stack (0), or into heap (1, default; requires malloc()).
+ * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.
+ */
+#ifndef ZSTD_HEAPMODE
+# define ZSTD_HEAPMODE 1
+#endif
+
+/*!
+* LEGACY_SUPPORT :
+* if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)
+*/
+
+/*!
+ * MAXWINDOWSIZE_DEFAULT :
+ * maximum window size accepted by DStream __by default__.
+ * Frames requiring more memory will be rejected.
+ * It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().
+ */
+#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
+# define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)
+#endif
+
+/*!
+ * NO_FORWARD_PROGRESS_MAX :
+ * maximum allowed nb of calls to ZSTD_decompressStream()
+ * without any forward progress
+ * (defined as: no byte read from input, and no byte flushed to output)
+ * before triggering an error.
+ */
+#ifndef ZSTD_NO_FORWARD_PROGRESS_MAX
+# define ZSTD_NO_FORWARD_PROGRESS_MAX 16
+#endif
+
+
+/*-*******************************************************
+* Dependencies
+*********************************************************/
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
+#include "../common/mem.h" /* low level memory routines */
+#define FSE_STATIC_LINKING_ONLY
+#include "../common/fse.h"
+#define HUF_STATIC_LINKING_ONLY
+#include "../common/huf.h"
+#include <linux/xxhash.h> /* xxh64_reset, xxh64_update, xxh64_digest, XXH64 */
+#include "../common/zstd_internal.h" /* blockProperties_t */
+#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
+#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
+#include "zstd_decompress_block.h" /* ZSTD_decompressBlock_internal */
+
+
+
+
+/* ***********************************
+ * Multiple DDicts Hashset internals *
+ *************************************/
+
+#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4
+#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3 /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.
+ * Currently, that means a 0.75 load factor.
+ * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded
+ * the load factor of the ddict hash set.
+ */
+
+#define DDICT_HASHSET_TABLE_BASE_SIZE 64
+#define DDICT_HASHSET_RESIZE_FACTOR 2
+
+/* Hash function to determine starting position of dict insertion within the table
+ * Returns an index between [0, hashSet->ddictPtrTableSize]
+ */
+static size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {
+ const U64 hash = xxh64(&dictID, sizeof(U32), 0);
+ /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */
+ return hash & (hashSet->ddictPtrTableSize - 1);
+}
+
+/* Adds DDict to a hashset without resizing it.
+ * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.
+ * Returns 0 if successful, or a zstd error code if something went wrong.
+ */
+static size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {
+ const U32 dictID = ZSTD_getDictID_fromDDict(ddict);
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
+ RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, "Hash set is full!");
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
+ while (hashSet->ddictPtrTable[idx] != NULL) {
+ /* Replace existing ddict if inserting ddict with same dictID */
+ if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {
+ DEBUGLOG(4, "DictID already exists, replacing rather than adding");
+ hashSet->ddictPtrTable[idx] = ddict;
+ return 0;
+ }
+ idx &= idxRangeMask;
+ idx++;
+ }
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
+ hashSet->ddictPtrTable[idx] = ddict;
+ hashSet->ddictPtrCount++;
+ return 0;
+}
+
+/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and
+ * rehashes all values, allocates new table, frees old table.
+ * Returns 0 on success, otherwise a zstd error code.
+ */
+static size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
+ size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;
+ const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);
+ const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;
+ size_t oldTableSize = hashSet->ddictPtrTableSize;
+ size_t i;
+
+ DEBUGLOG(4, "Expanding DDict hash table! Old size: %zu new size: %zu", oldTableSize, newTableSize);
+ RETURN_ERROR_IF(!newTable, memory_allocation, "Expanded hashset allocation failed!");
+ hashSet->ddictPtrTable = newTable;
+ hashSet->ddictPtrTableSize = newTableSize;
+ hashSet->ddictPtrCount = 0;
+ for (i = 0; i < oldTableSize; ++i) {
+ if (oldTable[i] != NULL) {
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), "");
+ }
+ }
+ ZSTD_customFree((void*)oldTable, customMem);
+ DEBUGLOG(4, "Finished re-hash");
+ return 0;
+}
+
+/* Fetches a DDict with the given dictID
+ * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.
+ */
+static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {
+ size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);
+ const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;
+ DEBUGLOG(4, "Hashed index: for dictID: %u is %zu", dictID, idx);
+ for (;;) {
+ size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);
+ if (currDictID == dictID || currDictID == 0) {
+ /* currDictID == 0 implies a NULL ddict entry */
+ break;
+ } else {
+ idx &= idxRangeMask; /* Goes to start of table when we reach the end */
+ idx++;
+ }
+ }
+ DEBUGLOG(4, "Final idx after probing for dictID %u is: %zu", dictID, idx);
+ return hashSet->ddictPtrTable[idx];
+}
+
+/* Allocates space for and returns a ddict hash set
+ * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.
+ * Returns NULL if allocation failed.
+ */
+static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
+ ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
+ DEBUGLOG(4, "Allocating new hash set");
+ if (!ret)
+ return NULL;
+ ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
+ if (!ret->ddictPtrTable) {
+ ZSTD_customFree(ret, customMem);
+ return NULL;
+ }
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
+ ret->ddictPtrCount = 0;
+ return ret;
+}
+
+/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.
+ * Note: The ZSTD_DDict* within the table are NOT freed.
+ */
+static void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {
+ DEBUGLOG(4, "Freeing ddict hash set");
+ if (hashSet && hashSet->ddictPtrTable) {
+ ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);
+ }
+ if (hashSet) {
+ ZSTD_customFree(hashSet, customMem);
+ }
+}
+
+/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.
+ * Returns 0 on success, or a ZSTD error.
+ */
+static size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {
+ DEBUGLOG(4, "Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);
+ if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), "");
+ }
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), "");
+ return 0;
+}
+
+/*-*************************************************************
+* Context management
+***************************************************************/
+size_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)
+{
+ if (dctx==NULL) return 0; /* support sizeof NULL */
+ return sizeof(*dctx)
+ + ZSTD_sizeof_DDict(dctx->ddictLocal)
+ + dctx->inBuffSize + dctx->outBuffSize;
+}
+
+size_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }
+
+
+static size_t ZSTD_startingInputLength(ZSTD_format_e format)
+{
+ size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);
+ /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */
+ assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );
+ return startingInputLength;
+}
+
+static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
+{
+ assert(dctx->streamStage == zdss_init);
+ dctx->format = ZSTD_f_zstd1;
+ dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
+ dctx->outBufferMode = ZSTD_bm_buffered;
+ dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
+ dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
+}
+
+static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
+{
+ dctx->staticSize = 0;
+ dctx->ddict = NULL;
+ dctx->ddictLocal = NULL;
+ dctx->dictEnd = NULL;
+ dctx->ddictIsCold = 0;
+ dctx->dictUses = ZSTD_dont_use;
+ dctx->inBuff = NULL;
+ dctx->inBuffSize = 0;
+ dctx->outBuffSize = 0;
+ dctx->streamStage = zdss_init;
+ dctx->noForwardProgress = 0;
+ dctx->oversizedDuration = 0;
+#if DYNAMIC_BMI2
+ dctx->bmi2 = ZSTD_cpuSupportsBmi2();
+#endif
+ dctx->ddictSet = NULL;
+ ZSTD_DCtx_resetParameters(dctx);
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ dctx->dictContentEndForFuzzing = NULL;
+#endif
+}
+
+ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
+{
+ ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;
+
+ if ((size_t)workspace & 7) return NULL; /* 8-aligned */
+ if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL; /* minimum size */
+
+ ZSTD_initDCtx_internal(dctx);
+ dctx->staticSize = workspaceSize;
+ dctx->inBuff = (char*)(dctx+1);
+ return dctx;
+}
+
+static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
+ if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
+
+ { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
+ if (!dctx) return NULL;
+ dctx->customMem = customMem;
+ ZSTD_initDCtx_internal(dctx);
+ return dctx;
+ }
+}
+
+ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
+{
+ return ZSTD_createDCtx_internal(customMem);
+}
+
+ZSTD_DCtx* ZSTD_createDCtx(void)
+{
+ DEBUGLOG(3, "ZSTD_createDCtx");
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
+}
+
+static void ZSTD_clearDict(ZSTD_DCtx* dctx)
+{
+ ZSTD_freeDDict(dctx->ddictLocal);
+ dctx->ddictLocal = NULL;
+ dctx->ddict = NULL;
+ dctx->dictUses = ZSTD_dont_use;
+}
+
+size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)
+{
+ if (dctx==NULL) return 0; /* support free on NULL */
+ RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx");
+ { ZSTD_customMem const cMem = dctx->customMem;
+ ZSTD_clearDict(dctx);
+ ZSTD_customFree(dctx->inBuff, cMem);
+ dctx->inBuff = NULL;
+ if (dctx->ddictSet) {
+ ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);
+ dctx->ddictSet = NULL;
+ }
+ ZSTD_customFree(dctx, cMem);
+ return 0;
+ }
+}
+
+/* no longer useful */
+void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)
+{
+ size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);
+ ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */
+}
+
+/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on
+ * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then
+ * accordingly sets the ddict to be used to decompress the frame.
+ *
+ * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.
+ *
+ * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.
+ */
+static void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {
+ assert(dctx->refMultipleDDicts && dctx->ddictSet);
+ DEBUGLOG(4, "Adjusting DDict based on requested dict ID from frame");
+ if (dctx->ddict) {
+ const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);
+ if (frameDDict) {
+ DEBUGLOG(4, "DDict found!");
+ ZSTD_clearDict(dctx);
+ dctx->dictID = dctx->fParams.dictID;
+ dctx->ddict = frameDDict;
+ dctx->dictUses = ZSTD_use_indefinitely;
+ }
+ }
+}
+
+
+/*-*************************************************************
+ * Frame header decoding
+ ***************************************************************/
+
+/*! ZSTD_isFrame() :
+ * Tells if the content of `buffer` starts with a valid Frame Identifier.
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
+ * Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
+ * Note 3 : Skippable Frame Identifiers are considered valid. */
+unsigned ZSTD_isFrame(const void* buffer, size_t size)
+{
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
+ { U32 const magic = MEM_readLE32(buffer);
+ if (magic == ZSTD_MAGICNUMBER) return 1;
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
+ }
+ return 0;
+}
+
+/*! ZSTD_isSkippableFrame() :
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
+ */
+unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
+{
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
+ { U32 const magic = MEM_readLE32(buffer);
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
+ }
+ return 0;
+}
+
+/* ZSTD_frameHeaderSize_internal() :
+ * srcSize must be large enough to reach header size fields.
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
+ * @return : size of the Frame Header
+ * or an error code, which can be tested with ZSTD_isError() */
+static size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)
+{
+ size_t const minInputSize = ZSTD_startingInputLength(format);
+ RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, "");
+
+ { BYTE const fhd = ((const BYTE*)src)[minInputSize-1];
+ U32 const dictID= fhd & 3;
+ U32 const singleSegment = (fhd >> 5) & 1;
+ U32 const fcsId = fhd >> 6;
+ return minInputSize + !singleSegment
+ + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]
+ + (singleSegment && !fcsId);
+ }
+}
+
+/* ZSTD_frameHeaderSize() :
+ * srcSize must be >= ZSTD_frameHeaderSize_prefix.
+ * @return : size of the Frame Header,
+ * or an error code (if srcSize is too small) */
+size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)
+{
+ return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);
+}
+
+
+/* ZSTD_getFrameHeader_advanced() :
+ * decode Frame Header, or require larger `srcSize`.
+ * note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless
+ * @return : 0, `zfhPtr` is correctly filled,
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
+ * or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)
+{
+ const BYTE* ip = (const BYTE*)src;
+ size_t const minInputSize = ZSTD_startingInputLength(format);
+
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */
+ if (srcSize < minInputSize) return minInputSize;
+ RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter");
+
+ if ( (format != ZSTD_f_zstd1_magicless)
+ && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {
+ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ /* skippable frame */
+ if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)
+ return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */
+ ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));
+ zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);
+ zfhPtr->frameType = ZSTD_skippableFrame;
+ return 0;
+ }
+ RETURN_ERROR(prefix_unknown, "");
+ }
+
+ /* ensure there is enough `srcSize` to fully read/decode frame header */
+ { size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);
+ if (srcSize < fhsize) return fhsize;
+ zfhPtr->headerSize = (U32)fhsize;
+ }
+
+ { BYTE const fhdByte = ip[minInputSize-1];
+ size_t pos = minInputSize;
+ U32 const dictIDSizeCode = fhdByte&3;
+ U32 const checksumFlag = (fhdByte>>2)&1;
+ U32 const singleSegment = (fhdByte>>5)&1;
+ U32 const fcsID = fhdByte>>6;
+ U64 windowSize = 0;
+ U32 dictID = 0;
+ U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;
+ RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,
+ "reserved bits, must be zero");
+
+ if (!singleSegment) {
+ BYTE const wlByte = ip[pos++];
+ U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;
+ RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, "");
+ windowSize = (1ULL << windowLog);
+ windowSize += (windowSize >> 3) * (wlByte&7);
+ }
+ switch(dictIDSizeCode)
+ {
+ default:
+ assert(0); /* impossible */
+ ZSTD_FALLTHROUGH;
+ case 0 : break;
+ case 1 : dictID = ip[pos]; pos++; break;
+ case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
+ case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;
+ }
+ switch(fcsID)
+ {
+ default:
+ assert(0); /* impossible */
+ ZSTD_FALLTHROUGH;
+ case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
+ case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
+ case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
+ case 3 : frameContentSize = MEM_readLE64(ip+pos); break;
+ }
+ if (singleSegment) windowSize = frameContentSize;
+
+ zfhPtr->frameType = ZSTD_frame;
+ zfhPtr->frameContentSize = frameContentSize;
+ zfhPtr->windowSize = windowSize;
+ zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
+ zfhPtr->dictID = dictID;
+ zfhPtr->checksumFlag = checksumFlag;
+ }
+ return 0;
+}
+
+/* ZSTD_getFrameHeader() :
+ * decode Frame Header, or require larger `srcSize`.
+ * note : this function does not consume input, it only reads it.
+ * @return : 0, `zfhPtr` is correctly filled,
+ * >0, `srcSize` is too small, value is wanted `srcSize` amount,
+ * or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize)
+{
+ return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
+}
+
+/* ZSTD_getFrameContentSize() :
+ * compatible with legacy mode
+ * @return : decompressed size of the single frame pointed to be `src` if known, otherwise
+ * - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined
+ * - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */
+unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)
+{
+ { ZSTD_frameHeader zfh;
+ if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)
+ return ZSTD_CONTENTSIZE_ERROR;
+ if (zfh.frameType == ZSTD_skippableFrame) {
+ return 0;
+ } else {
+ return zfh.frameContentSize;
+ } }
+}
+
+static size_t readSkippableFrameSize(void const* src, size_t srcSize)
+{
+ size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;
+ U32 sizeU32;
+
+ RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, "");
+
+ sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);
+ RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,
+ frameParameter_unsupported, "");
+ {
+ size_t const skippableSize = skippableHeaderSize + sizeU32;
+ RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, "");
+ return skippableSize;
+ }
+}
+
+/*! ZSTD_readSkippableFrame() :
+ * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
+ *
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
+ * in the magicVariant.
+ *
+ * Returns an error if destination buffer is not large enough, or if the frame is not skippable.
+ *
+ * @return : number of bytes written or a ZSTD error.
+ */
+ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
+ const void* src, size_t srcSize)
+{
+ U32 const magicNumber = MEM_readLE32(src);
+ size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
+
+ /* check input validity */
+ RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
+ RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
+ RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
+
+ /* deliver payload */
+ if (skippableContentSize > 0 && dst != NULL)
+ ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
+ if (magicVariant != NULL)
+ *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
+ return skippableContentSize;
+}
+
+/* ZSTD_findDecompressedSize() :
+ * compatible with legacy mode
+ * `srcSize` must be the exact length of some number of ZSTD compressed and/or
+ * skippable frames
+ * @return : decompressed size of the frames contained */
+unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)
+{
+ unsigned long long totalDstSize = 0;
+
+ while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {
+ U32 const magicNumber = MEM_readLE32(src);
+
+ if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ size_t const skippableSize = readSkippableFrameSize(src, srcSize);
+ if (ZSTD_isError(skippableSize)) {
+ return ZSTD_CONTENTSIZE_ERROR;
+ }
+ assert(skippableSize <= srcSize);
+
+ src = (const BYTE *)src + skippableSize;
+ srcSize -= skippableSize;
+ continue;
+ }
+
+ { unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
+ if (ret >= ZSTD_CONTENTSIZE_ERROR) return ret;
+
+ /* check for overflow */
+ if (totalDstSize + ret < totalDstSize) return ZSTD_CONTENTSIZE_ERROR;
+ totalDstSize += ret;
+ }
+ { size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);
+ if (ZSTD_isError(frameSrcSize)) {
+ return ZSTD_CONTENTSIZE_ERROR;
+ }
+
+ src = (const BYTE *)src + frameSrcSize;
+ srcSize -= frameSrcSize;
+ }
+ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
+
+ if (srcSize) return ZSTD_CONTENTSIZE_ERROR;
+
+ return totalDstSize;
+}
+
+/* ZSTD_getDecompressedSize() :
+ * compatible with legacy mode
+ * @return : decompressed size if known, 0 otherwise
+ note : 0 can mean any of the following :
+ - frame content is empty
+ - decompressed size field is not present in frame header
+ - frame header unknown / not supported
+ - frame header not complete (`srcSize` too small) */
+unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)
+{
+ unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);
+ ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);
+ return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;
+}
+
+
+/* ZSTD_decodeFrameHeader() :
+ * `headerSize` must be the size provided by ZSTD_frameHeaderSize().
+ * If multiple DDict references are enabled, also will choose the correct DDict to use.
+ * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */
+static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)
+{
+ size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);
+ if (ZSTD_isError(result)) return result; /* invalid header */
+ RETURN_ERROR_IF(result>0, srcSize_wrong, "headerSize too small");
+
+ /* Reference DDict requested by frame if dctx references multiple ddicts */
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {
+ ZSTD_DCtx_selectFrameDDict(dctx);
+ }
+
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /* Skip the dictID check in fuzzing mode, because it makes the search
+ * harder.
+ */
+ RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),
+ dictionary_wrong, "");
+#endif
+ dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;
+ if (dctx->validateChecksum) xxh64_reset(&dctx->xxhState, 0);
+ dctx->processedCSize += headerSize;
+ return 0;
+}
+
+static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)
+{
+ ZSTD_frameSizeInfo frameSizeInfo;
+ frameSizeInfo.compressedSize = ret;
+ frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;
+ return frameSizeInfo;
+}
+
+static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize)
+{
+ ZSTD_frameSizeInfo frameSizeInfo;
+ ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));
+
+
+ if ((srcSize >= ZSTD_SKIPPABLEHEADERSIZE)
+ && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);
+ assert(ZSTD_isError(frameSizeInfo.compressedSize) ||
+ frameSizeInfo.compressedSize <= srcSize);
+ return frameSizeInfo;
+ } else {
+ const BYTE* ip = (const BYTE*)src;
+ const BYTE* const ipstart = ip;
+ size_t remainingSize = srcSize;
+ size_t nbBlocks = 0;
+ ZSTD_frameHeader zfh;
+
+ /* Extract Frame Header */
+ { size_t const ret = ZSTD_getFrameHeader(&zfh, src, srcSize);
+ if (ZSTD_isError(ret))
+ return ZSTD_errorFrameSizeInfo(ret);
+ if (ret > 0)
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
+ }
+
+ ip += zfh.headerSize;
+ remainingSize -= zfh.headerSize;
+
+ /* Iterate over each block */
+ while (1) {
+ blockProperties_t blockProperties;
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);
+ if (ZSTD_isError(cBlockSize))
+ return ZSTD_errorFrameSizeInfo(cBlockSize);
+
+ if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
+
+ ip += ZSTD_blockHeaderSize + cBlockSize;
+ remainingSize -= ZSTD_blockHeaderSize + cBlockSize;
+ nbBlocks++;
+
+ if (blockProperties.lastBlock) break;
+ }
+
+ /* Final frame content checksum */
+ if (zfh.checksumFlag) {
+ if (remainingSize < 4)
+ return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));
+ ip += 4;
+ }
+
+ frameSizeInfo.compressedSize = (size_t)(ip - ipstart);
+ frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)
+ ? zfh.frameContentSize
+ : nbBlocks * zfh.blockSizeMax;
+ return frameSizeInfo;
+ }
+}
+
+/* ZSTD_findFrameCompressedSize() :
+ * compatible with legacy mode
+ * `src` must point to the start of a ZSTD frame, ZSTD legacy frame, or skippable frame
+ * `srcSize` must be at least as large as the frame contained
+ * @return : the compressed size of the frame starting at `src` */
+size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)
+{
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
+ return frameSizeInfo.compressedSize;
+}
+
+/* ZSTD_decompressBound() :
+ * compatible with legacy mode
+ * `src` must point to the start of a ZSTD frame or a skippeable frame
+ * `srcSize` must be at least as large as the frame contained
+ * @return : the maximum decompressed size of the compressed source
+ */
+unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
+{
+ unsigned long long bound = 0;
+ /* Iterate over each frame */
+ while (srcSize > 0) {
+ ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize);
+ size_t const compressedSize = frameSizeInfo.compressedSize;
+ unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;
+ if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)
+ return ZSTD_CONTENTSIZE_ERROR;
+ assert(srcSize >= compressedSize);
+ src = (const BYTE*)src + compressedSize;
+ srcSize -= compressedSize;
+ bound += decompressedBound;
+ }
+ return bound;
+}
+
+
+/*-*************************************************************
+ * Frame decoding
+ ***************************************************************/
+
+/* ZSTD_insertBlock() :
+ * insert `src` block into `dctx` history. Useful to track uncompressed blocks. */
+size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)
+{
+ DEBUGLOG(5, "ZSTD_insertBlock: %u bytes", (unsigned)blockSize);
+ ZSTD_checkContinuity(dctx, blockStart, blockSize);
+ dctx->previousDstEnd = (const char*)blockStart + blockSize;
+ return blockSize;
+}
+
+
+static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize)
+{
+ DEBUGLOG(5, "ZSTD_copyRawBlock");
+ RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, "");
+ if (dst == NULL) {
+ if (srcSize == 0) return 0;
+ RETURN_ERROR(dstBuffer_null, "");
+ }
+ ZSTD_memcpy(dst, src, srcSize);
+ return srcSize;
+}
+
+static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,
+ BYTE b,
+ size_t regenSize)
+{
+ RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, "");
+ if (dst == NULL) {
+ if (regenSize == 0) return 0;
+ RETURN_ERROR(dstBuffer_null, "");
+ }
+ ZSTD_memset(dst, b, regenSize);
+ return regenSize;
+}
+
+static void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, unsigned streaming)
+{
+ (void)dctx;
+ (void)uncompressedSize;
+ (void)compressedSize;
+ (void)streaming;
+}
+
+
+/*! ZSTD_decompressFrame() :
+ * @dctx must be properly initialized
+ * will update *srcPtr and *srcSizePtr,
+ * to make *srcPtr progress by one frame. */
+static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void** srcPtr, size_t *srcSizePtr)
+{
+ const BYTE* const istart = (const BYTE*)(*srcPtr);
+ const BYTE* ip = istart;
+ BYTE* const ostart = (BYTE*)dst;
+ BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;
+ BYTE* op = ostart;
+ size_t remainingSrcSize = *srcSizePtr;
+
+ DEBUGLOG(4, "ZSTD_decompressFrame (srcSize:%i)", (int)*srcSizePtr);
+
+ /* check */
+ RETURN_ERROR_IF(
+ remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,
+ srcSize_wrong, "");
+
+ /* Frame Header */
+ { size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(
+ ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);
+ if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;
+ RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,
+ srcSize_wrong, "");
+ FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , "");
+ ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;
+ }
+
+ /* Loop on each block */
+ while (1) {
+ size_t decodedSize;
+ blockProperties_t blockProperties;
+ size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);
+ if (ZSTD_isError(cBlockSize)) return cBlockSize;
+
+ ip += ZSTD_blockHeaderSize;
+ remainingSrcSize -= ZSTD_blockHeaderSize;
+ RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, "");
+
+ switch(blockProperties.blockType)
+ {
+ case bt_compressed:
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
+ break;
+ case bt_raw :
+ decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
+ break;
+ case bt_rle :
+ decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize);
+ break;
+ case bt_reserved :
+ default:
+ RETURN_ERROR(corruption_detected, "invalid block type");
+ }
+
+ if (ZSTD_isError(decodedSize)) return decodedSize;
+ if (dctx->validateChecksum)
+ xxh64_update(&dctx->xxhState, op, decodedSize);
+ if (decodedSize != 0)
+ op += decodedSize;
+ assert(ip != NULL);
+ ip += cBlockSize;
+ remainingSrcSize -= cBlockSize;
+ if (blockProperties.lastBlock) break;
+ }
+
+ if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {
+ RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,
+ corruption_detected, "");
+ }
+ if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */
+ RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, "");
+ if (!dctx->forceIgnoreChecksum) {
+ U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState);
+ U32 checkRead;
+ checkRead = MEM_readLE32(ip);
+ RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, "");
+ }
+ ip += 4;
+ remainingSrcSize -= 4;
+ }
+ ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);
+ /* Allow caller to get size read */
+ *srcPtr = ip;
+ *srcSizePtr = remainingSrcSize;
+ return (size_t)(op-ostart);
+}
+
+static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict, size_t dictSize,
+ const ZSTD_DDict* ddict)
+{
+ void* const dststart = dst;
+ int moreThan1Frame = 0;
+
+ DEBUGLOG(5, "ZSTD_decompressMultiFrame");
+ assert(dict==NULL || ddict==NULL); /* either dict or ddict set, not both */
+
+ if (ddict) {
+ dict = ZSTD_DDict_dictContent(ddict);
+ dictSize = ZSTD_DDict_dictSize(ddict);
+ }
+
+ while (srcSize >= ZSTD_startingInputLength(dctx->format)) {
+
+
+ { U32 const magicNumber = MEM_readLE32(src);
+ DEBUGLOG(4, "reading magic number %08X (expecting %08X)",
+ (unsigned)magicNumber, ZSTD_MAGICNUMBER);
+ if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {
+ size_t const skippableSize = readSkippableFrameSize(src, srcSize);
+ FORWARD_IF_ERROR(skippableSize, "readSkippableFrameSize failed");
+ assert(skippableSize <= srcSize);
+
+ src = (const BYTE *)src + skippableSize;
+ srcSize -= skippableSize;
+ continue;
+ } }
+
+ if (ddict) {
+ /* we were called from ZSTD_decompress_usingDDict */
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), "");
+ } else {
+ /* this will initialize correctly with no dict if dict == NULL, so
+ * use this in all cases but ddict */
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), "");
+ }
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
+
+ { const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,
+ &src, &srcSize);
+ RETURN_ERROR_IF(
+ (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)
+ && (moreThan1Frame==1),
+ srcSize_wrong,
+ "At least one frame successfully completed, "
+ "but following bytes are garbage: "
+ "it's more likely to be a srcSize error, "
+ "specifying more input bytes than size of frame(s). "
+ "Note: one could be unlucky, it might be a corruption error instead, "
+ "happening right at the place where we expect zstd magic bytes. "
+ "But this is _much_ less likely than a srcSize field error.");
+ if (ZSTD_isError(res)) return res;
+ assert(res <= dstCapacity);
+ if (res != 0)
+ dst = (BYTE*)dst + res;
+ dstCapacity -= res;
+ }
+ moreThan1Frame = 1;
+ } /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */
+
+ RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed");
+
+ return (size_t)((BYTE*)dst - (BYTE*)dststart);
+}
+
+size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const void* dict, size_t dictSize)
+{
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);
+}
+
+
+static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
+{
+ switch (dctx->dictUses) {
+ default:
+ assert(0 /* Impossible */);
+ ZSTD_FALLTHROUGH;
+ case ZSTD_dont_use:
+ ZSTD_clearDict(dctx);
+ return NULL;
+ case ZSTD_use_indefinitely:
+ return dctx->ddict;
+ case ZSTD_use_once:
+ dctx->dictUses = ZSTD_dont_use;
+ return dctx->ddict;
+ }
+}
+
+size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
+{
+ return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));
+}
+
+
+size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
+{
+#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
+ size_t regenSize;
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
+ RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
+ regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
+ ZSTD_freeDCtx(dctx);
+ return regenSize;
+#else /* stack mode */
+ ZSTD_DCtx dctx;
+ ZSTD_initDCtx_internal(&dctx);
+ return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);
+#endif
+}
+
+
+/*-**************************************
+* Advanced Streaming Decompression API
+* Bufferless and synchronous
+****************************************/
+size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }
+
+/*
+ * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed,
+ * we allow taking a partial block as the input. Currently only raw uncompressed blocks can
+ * be streamed.
+ *
+ * For blocks that can be streamed, this allows us to reduce the latency until we produce
+ * output, and avoid copying the input.
+ *
+ * @param inputSize - The total amount of input that the caller currently has.
+ */
+static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {
+ if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))
+ return dctx->expected;
+ if (dctx->bType != bt_raw)
+ return dctx->expected;
+ return BOUNDED(1, inputSize, dctx->expected);
+}
+
+ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
+ switch(dctx->stage)
+ {
+ default: /* should not happen */
+ assert(0);
+ ZSTD_FALLTHROUGH;
+ case ZSTDds_getFrameHeaderSize:
+ ZSTD_FALLTHROUGH;
+ case ZSTDds_decodeFrameHeader:
+ return ZSTDnit_frameHeader;
+ case ZSTDds_decodeBlockHeader:
+ return ZSTDnit_blockHeader;
+ case ZSTDds_decompressBlock:
+ return ZSTDnit_block;
+ case ZSTDds_decompressLastBlock:
+ return ZSTDnit_lastBlock;
+ case ZSTDds_checkChecksum:
+ return ZSTDnit_checksum;
+ case ZSTDds_decodeSkippableHeader:
+ ZSTD_FALLTHROUGH;
+ case ZSTDds_skipFrame:
+ return ZSTDnit_skippableFrame;
+ }
+}
+
+static int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }
+
+/* ZSTD_decompressContinue() :
+ * srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())
+ * @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)
+ * or an error code, which can be tested using ZSTD_isError() */
+size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)
+{
+ DEBUGLOG(5, "ZSTD_decompressContinue (srcSize:%u)", (unsigned)srcSize);
+ /* Sanity check */
+ RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, "not allowed");
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
+
+ dctx->processedCSize += srcSize;
+
+ switch (dctx->stage)
+ {
+ case ZSTDds_getFrameHeaderSize :
+ assert(src != NULL);
+ if (dctx->format == ZSTD_f_zstd1) { /* allows header */
+ assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */
+ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
+ dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */
+ dctx->stage = ZSTDds_decodeSkippableHeader;
+ return 0;
+ } }
+ dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);
+ if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;
+ ZSTD_memcpy(dctx->headerBuffer, src, srcSize);
+ dctx->expected = dctx->headerSize - srcSize;
+ dctx->stage = ZSTDds_decodeFrameHeader;
+ return 0;
+
+ case ZSTDds_decodeFrameHeader:
+ assert(src != NULL);
+ ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), "");
+ dctx->expected = ZSTD_blockHeaderSize;
+ dctx->stage = ZSTDds_decodeBlockHeader;
+ return 0;
+
+ case ZSTDds_decodeBlockHeader:
+ { blockProperties_t bp;
+ size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);
+ if (ZSTD_isError(cBlockSize)) return cBlockSize;
+ RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, "Block Size Exceeds Maximum");
+ dctx->expected = cBlockSize;
+ dctx->bType = bp.blockType;
+ dctx->rleSize = bp.origSize;
+ if (cBlockSize) {
+ dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;
+ return 0;
+ }
+ /* empty block */
+ if (bp.lastBlock) {
+ if (dctx->fParams.checksumFlag) {
+ dctx->expected = 4;
+ dctx->stage = ZSTDds_checkChecksum;
+ } else {
+ dctx->expected = 0; /* end of frame */
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ }
+ } else {
+ dctx->expected = ZSTD_blockHeaderSize; /* jump to next header */
+ dctx->stage = ZSTDds_decodeBlockHeader;
+ }
+ return 0;
+ }
+
+ case ZSTDds_decompressLastBlock:
+ case ZSTDds_decompressBlock:
+ DEBUGLOG(5, "ZSTD_decompressContinue: case ZSTDds_decompressBlock");
+ { size_t rSize;
+ switch(dctx->bType)
+ {
+ case bt_compressed:
+ DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
+ dctx->expected = 0; /* Streaming not supported */
+ break;
+ case bt_raw :
+ assert(srcSize <= dctx->expected);
+ rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);
+ FORWARD_IF_ERROR(rSize, "ZSTD_copyRawBlock failed");
+ assert(rSize == srcSize);
+ dctx->expected -= rSize;
+ break;
+ case bt_rle :
+ rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);
+ dctx->expected = 0; /* Streaming not supported */
+ break;
+ case bt_reserved : /* should never happen */
+ default:
+ RETURN_ERROR(corruption_detected, "invalid block type");
+ }
+ FORWARD_IF_ERROR(rSize, "");
+ RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum");
+ DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize);
+ dctx->decodedSize += rSize;
+ if (dctx->validateChecksum) xxh64_update(&dctx->xxhState, dst, rSize);
+ dctx->previousDstEnd = (char*)dst + rSize;
+
+ /* Stay on the same stage until we are finished streaming the block. */
+ if (dctx->expected > 0) {
+ return rSize;
+ }
+
+ if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */
+ DEBUGLOG(4, "ZSTD_decompressContinue: decoded size from frame : %u", (unsigned)dctx->decodedSize);
+ RETURN_ERROR_IF(
+ dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
+ && dctx->decodedSize != dctx->fParams.frameContentSize,
+ corruption_detected, "");
+ if (dctx->fParams.checksumFlag) { /* another round for frame checksum */
+ dctx->expected = 4;
+ dctx->stage = ZSTDds_checkChecksum;
+ } else {
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
+ dctx->expected = 0; /* ends here */
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ }
+ } else {
+ dctx->stage = ZSTDds_decodeBlockHeader;
+ dctx->expected = ZSTD_blockHeaderSize;
+ }
+ return rSize;
+ }
+
+ case ZSTDds_checkChecksum:
+ assert(srcSize == 4); /* guaranteed by dctx->expected */
+ {
+ if (dctx->validateChecksum) {
+ U32 const h32 = (U32)xxh64_digest(&dctx->xxhState);
+ U32 const check32 = MEM_readLE32(src);
+ DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32);
+ RETURN_ERROR_IF(check32 != h32, checksum_wrong, "");
+ }
+ ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);
+ dctx->expected = 0;
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ return 0;
+ }
+
+ case ZSTDds_decodeSkippableHeader:
+ assert(src != NULL);
+ assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);
+ ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */
+ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */
+ dctx->stage = ZSTDds_skipFrame;
+ return 0;
+
+ case ZSTDds_skipFrame:
+ dctx->expected = 0;
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ return 0;
+
+ default:
+ assert(0); /* impossible */
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
+ }
+}
+
+
+static size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+{
+ dctx->dictEnd = dctx->previousDstEnd;
+ dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
+ dctx->prefixStart = dict;
+ dctx->previousDstEnd = (const char*)dict + dictSize;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ dctx->dictContentBeginForFuzzing = dctx->prefixStart;
+ dctx->dictContentEndForFuzzing = dctx->previousDstEnd;
+#endif
+ return 0;
+}
+
+/*! ZSTD_loadDEntropy() :
+ * dict : must point at beginning of a valid zstd dictionary.
+ * @return : size of entropy tables read */
+size_t
+ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
+ const void* const dict, size_t const dictSize)
+{
+ const BYTE* dictPtr = (const BYTE*)dict;
+ const BYTE* const dictEnd = dictPtr + dictSize;
+
+ RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, "dict is too small");
+ assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY); /* dict must be valid */
+ dictPtr += 8; /* skip header = magic + dictID */
+
+ ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));
+ ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));
+ ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);
+ { void* const workspace = &entropy->LLTable; /* use fse tables as temporary workspace; implies fse tables are grouped together */
+ size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);
+#ifdef HUF_FORCE_DECOMPRESS_X1
+ /* in minimal huffman, we always use X1 variants */
+ size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,
+ dictPtr, dictEnd - dictPtr,
+ workspace, workspaceSize);
+#else
+ size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,
+ dictPtr, (size_t)(dictEnd - dictPtr),
+ workspace, workspaceSize);
+#endif
+ RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, "");
+ dictPtr += hSize;
+ }
+
+ { short offcodeNCount[MaxOff+1];
+ unsigned offcodeMaxValue = MaxOff, offcodeLog;
+ size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));
+ RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, "");
+ RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, "");
+ RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, "");
+ ZSTD_buildFSETable( entropy->OFTable,
+ offcodeNCount, offcodeMaxValue,
+ OF_base, OF_bits,
+ offcodeLog,
+ entropy->workspace, sizeof(entropy->workspace),
+ /* bmi2 */0);
+ dictPtr += offcodeHeaderSize;
+ }
+
+ { short matchlengthNCount[MaxML+1];
+ unsigned matchlengthMaxValue = MaxML, matchlengthLog;
+ size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
+ RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, "");
+ RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, "");
+ RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, "");
+ ZSTD_buildFSETable( entropy->MLTable,
+ matchlengthNCount, matchlengthMaxValue,
+ ML_base, ML_bits,
+ matchlengthLog,
+ entropy->workspace, sizeof(entropy->workspace),
+ /* bmi2 */ 0);
+ dictPtr += matchlengthHeaderSize;
+ }
+
+ { short litlengthNCount[MaxLL+1];
+ unsigned litlengthMaxValue = MaxLL, litlengthLog;
+ size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));
+ RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, "");
+ RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, "");
+ RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, "");
+ ZSTD_buildFSETable( entropy->LLTable,
+ litlengthNCount, litlengthMaxValue,
+ LL_base, LL_bits,
+ litlengthLog,
+ entropy->workspace, sizeof(entropy->workspace),
+ /* bmi2 */ 0);
+ dictPtr += litlengthHeaderSize;
+ }
+
+ RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, "");
+ { int i;
+ size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));
+ for (i=0; i<3; i++) {
+ U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;
+ RETURN_ERROR_IF(rep==0 || rep > dictContentSize,
+ dictionary_corrupted, "");
+ entropy->rep[i] = rep;
+ } }
+
+ return (size_t)(dictPtr - (const BYTE*)dict);
+}
+
+static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+{
+ if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);
+ { U32 const magic = MEM_readLE32(dict);
+ if (magic != ZSTD_MAGIC_DICTIONARY) {
+ return ZSTD_refDictContent(dctx, dict, dictSize); /* pure content mode */
+ } }
+ dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
+
+ /* load entropy tables */
+ { size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);
+ RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, "");
+ dict = (const char*)dict + eSize;
+ dictSize -= eSize;
+ }
+ dctx->litEntropy = dctx->fseEntropy = 1;
+
+ /* reference dictionary content */
+ return ZSTD_refDictContent(dctx, dict, dictSize);
+}
+
+size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)
+{
+ assert(dctx != NULL);
+ dctx->expected = ZSTD_startingInputLength(dctx->format); /* dctx->format must be properly set */
+ dctx->stage = ZSTDds_getFrameHeaderSize;
+ dctx->processedCSize = 0;
+ dctx->decodedSize = 0;
+ dctx->previousDstEnd = NULL;
+ dctx->prefixStart = NULL;
+ dctx->virtualStart = NULL;
+ dctx->dictEnd = NULL;
+ dctx->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */
+ dctx->litEntropy = dctx->fseEntropy = 0;
+ dctx->dictID = 0;
+ dctx->bType = bt_reserved;
+ ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));
+ ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */
+ dctx->LLTptr = dctx->entropy.LLTable;
+ dctx->MLTptr = dctx->entropy.MLTable;
+ dctx->OFTptr = dctx->entropy.OFTable;
+ dctx->HUFptr = dctx->entropy.hufTable;
+ return 0;
+}
+
+size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+{
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
+ if (dict && dictSize)
+ RETURN_ERROR_IF(
+ ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),
+ dictionary_corrupted, "");
+ return 0;
+}
+
+
+/* ====== ZSTD_DDict ====== */
+
+size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
+{
+ DEBUGLOG(4, "ZSTD_decompressBegin_usingDDict");
+ assert(dctx != NULL);
+ if (ddict) {
+ const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);
+ size_t const dictSize = ZSTD_DDict_dictSize(ddict);
+ const void* const dictEnd = dictStart + dictSize;
+ dctx->ddictIsCold = (dctx->dictEnd != dictEnd);
+ DEBUGLOG(4, "DDict is %s",
+ dctx->ddictIsCold ? "~cold~" : "hot!");
+ }
+ FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , "");
+ if (ddict) { /* NULL ddict is equivalent to no dictionary */
+ ZSTD_copyDDictParameters(dctx, ddict);
+ }
+ return 0;
+}
+
+/*! ZSTD_getDictID_fromDict() :
+ * Provides the dictID stored within dictionary.
+ * if @return == 0, the dictionary is not conformant with Zstandard specification.
+ * It can still be loaded, but as a content-only dictionary. */
+unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)
+{
+ if (dictSize < 8) return 0;
+ if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;
+ return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);
+}
+
+/*! ZSTD_getDictID_fromFrame() :
+ * Provides the dictID required to decompress frame stored within `src`.
+ * If @return == 0, the dictID could not be decoded.
+ * This could for one of the following reasons :
+ * - The frame does not require a dictionary (most common case).
+ * - The frame was built with dictID intentionally removed.
+ * Needed dictionary is a hidden information.
+ * Note : this use case also happens when using a non-conformant dictionary.
+ * - `srcSize` is too small, and as a result, frame header could not be decoded.
+ * Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.
+ * - This is not a Zstandard frame.
+ * When identifying the exact failure cause, it's possible to use
+ * ZSTD_getFrameHeader(), which will provide a more precise error code. */
+unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
+{
+ ZSTD_frameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0 };
+ size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);
+ if (ZSTD_isError(hError)) return 0;
+ return zfp.dictID;
+}
+
+
+/*! ZSTD_decompress_usingDDict() :
+* Decompression using a pre-digested Dictionary
+* Use dictionary without significant overhead. */
+size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ const ZSTD_DDict* ddict)
+{
+ /* pass content and size in case legacy frames are encountered */
+ return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,
+ NULL, 0,
+ ddict);
+}
+
+
+/*=====================================
+* Streaming decompression
+*====================================*/
+
+ZSTD_DStream* ZSTD_createDStream(void)
+{
+ DEBUGLOG(3, "ZSTD_createDStream");
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
+}
+
+ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
+{
+ return ZSTD_initStaticDCtx(workspace, workspaceSize);
+}
+
+ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
+{
+ return ZSTD_createDCtx_internal(customMem);
+}
+
+size_t ZSTD_freeDStream(ZSTD_DStream* zds)
+{
+ return ZSTD_freeDCtx(zds);
+}
+
+
+/* *** Initialization *** */
+
+size_t ZSTD_DStreamInSize(void) { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }
+size_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }
+
+size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,
+ const void* dict, size_t dictSize,
+ ZSTD_dictLoadMethod_e dictLoadMethod,
+ ZSTD_dictContentType_e dictContentType)
+{
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
+ ZSTD_clearDict(dctx);
+ if (dict && dictSize != 0) {
+ dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);
+ RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, "NULL pointer!");
+ dctx->ddict = dctx->ddictLocal;
+ dctx->dictUses = ZSTD_use_indefinitely;
+ }
+ return 0;
+}
+
+size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+{
+ return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
+}
+
+size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)
+{
+ return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
+}
+
+size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)
+{
+ FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), "");
+ dctx->dictUses = ZSTD_use_once;
+ return 0;
+}
+
+size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)
+{
+ return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);
+}
+
+
+/* ZSTD_initDStream_usingDict() :
+ * return : expected size, aka ZSTD_startingInputLength().
+ * this function cannot fail */
+size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)
+{
+ DEBUGLOG(4, "ZSTD_initDStream_usingDict");
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , "");
+ FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , "");
+ return ZSTD_startingInputLength(zds->format);
+}
+
+/* note : this variant can't fail */
+size_t ZSTD_initDStream(ZSTD_DStream* zds)
+{
+ DEBUGLOG(4, "ZSTD_initDStream");
+ return ZSTD_initDStream_usingDDict(zds, NULL);
+}
+
+/* ZSTD_initDStream_usingDDict() :
+ * ddict will just be referenced, and must outlive decompression session
+ * this function cannot fail */
+size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)
+{
+ FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , "");
+ FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , "");
+ return ZSTD_startingInputLength(dctx->format);
+}
+
+/* ZSTD_resetDStream() :
+ * return : expected size, aka ZSTD_startingInputLength().
+ * this function cannot fail */
+size_t ZSTD_resetDStream(ZSTD_DStream* dctx)
+{
+ FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), "");
+ return ZSTD_startingInputLength(dctx->format);
+}
+
+
+size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)
+{
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
+ ZSTD_clearDict(dctx);
+ if (ddict) {
+ dctx->ddict = ddict;
+ dctx->dictUses = ZSTD_use_indefinitely;
+ if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {
+ if (dctx->ddictSet == NULL) {
+ dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);
+ if (!dctx->ddictSet) {
+ RETURN_ERROR(memory_allocation, "Failed to allocate memory for hash set!");
+ }
+ }
+ assert(!dctx->staticSize); /* Impossible: ddictSet cannot have been allocated if static dctx */
+ FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), "");
+ }
+ }
+ return 0;
+}
+
+/* ZSTD_DCtx_setMaxWindowSize() :
+ * note : no direct equivalence in ZSTD_DCtx_setParameter,
+ * since this version sets windowSize, and the other sets windowLog */
+size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)
+{
+ ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);
+ size_t const min = (size_t)1 << bounds.lowerBound;
+ size_t const max = (size_t)1 << bounds.upperBound;
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
+ RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, "");
+ RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, "");
+ dctx->maxWindowSize = maxWindowSize;
+ return 0;
+}
+
+size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)
+{
+ return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);
+}
+
+ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
+{
+ ZSTD_bounds bounds = { 0, 0, 0 };
+ switch(dParam) {
+ case ZSTD_d_windowLogMax:
+ bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;
+ bounds.upperBound = ZSTD_WINDOWLOG_MAX;
+ return bounds;
+ case ZSTD_d_format:
+ bounds.lowerBound = (int)ZSTD_f_zstd1;
+ bounds.upperBound = (int)ZSTD_f_zstd1_magicless;
+ ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);
+ return bounds;
+ case ZSTD_d_stableOutBuffer:
+ bounds.lowerBound = (int)ZSTD_bm_buffered;
+ bounds.upperBound = (int)ZSTD_bm_stable;
+ return bounds;
+ case ZSTD_d_forceIgnoreChecksum:
+ bounds.lowerBound = (int)ZSTD_d_validateChecksum;
+ bounds.upperBound = (int)ZSTD_d_ignoreChecksum;
+ return bounds;
+ case ZSTD_d_refMultipleDDicts:
+ bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;
+ bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
+ return bounds;
+ default:;
+ }
+ bounds.error = ERROR(parameter_unsupported);
+ return bounds;
+}
+
+/* ZSTD_dParam_withinBounds:
+ * @return 1 if value is within dParam bounds,
+ * 0 otherwise */
+static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)
+{
+ ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);
+ if (ZSTD_isError(bounds.error)) return 0;
+ if (value < bounds.lowerBound) return 0;
+ if (value > bounds.upperBound) return 0;
+ return 1;
+}
+
+#define CHECK_DBOUNDS(p,v) { \
+ RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \
+}
+
+size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)
+{
+ switch (param) {
+ case ZSTD_d_windowLogMax:
+ *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);
+ return 0;
+ case ZSTD_d_format:
+ *value = (int)dctx->format;
+ return 0;
+ case ZSTD_d_stableOutBuffer:
+ *value = (int)dctx->outBufferMode;
+ return 0;
+ case ZSTD_d_forceIgnoreChecksum:
+ *value = (int)dctx->forceIgnoreChecksum;
+ return 0;
+ case ZSTD_d_refMultipleDDicts:
+ *value = (int)dctx->refMultipleDDicts;
+ return 0;
+ default:;
+ }
+ RETURN_ERROR(parameter_unsupported, "");
+}
+
+size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)
+{
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
+ switch(dParam) {
+ case ZSTD_d_windowLogMax:
+ if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;
+ CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);
+ dctx->maxWindowSize = ((size_t)1) << value;
+ return 0;
+ case ZSTD_d_format:
+ CHECK_DBOUNDS(ZSTD_d_format, value);
+ dctx->format = (ZSTD_format_e)value;
+ return 0;
+ case ZSTD_d_stableOutBuffer:
+ CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);
+ dctx->outBufferMode = (ZSTD_bufferMode_e)value;
+ return 0;
+ case ZSTD_d_forceIgnoreChecksum:
+ CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);
+ dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;
+ return 0;
+ case ZSTD_d_refMultipleDDicts:
+ CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);
+ if (dctx->staticSize != 0) {
+ RETURN_ERROR(parameter_unsupported, "Static dctx does not support multiple DDicts!");
+ }
+ dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;
+ return 0;
+ default:;
+ }
+ RETURN_ERROR(parameter_unsupported, "");
+}
+
+size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)
+{
+ if ( (reset == ZSTD_reset_session_only)
+ || (reset == ZSTD_reset_session_and_parameters) ) {
+ dctx->streamStage = zdss_init;
+ dctx->noForwardProgress = 0;
+ }
+ if ( (reset == ZSTD_reset_parameters)
+ || (reset == ZSTD_reset_session_and_parameters) ) {
+ RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, "");
+ ZSTD_clearDict(dctx);
+ ZSTD_DCtx_resetParameters(dctx);
+ }
+ return 0;
+}
+
+
+size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
+{
+ return ZSTD_sizeof_DCtx(dctx);
+}
+
+size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
+{
+ size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
+ /* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
+ unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
+ unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
+ size_t const minRBSize = (size_t) neededSize;
+ RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
+ frameParameter_windowTooLarge, "");
+ return minRBSize;
+}
+
+size_t ZSTD_estimateDStreamSize(size_t windowSize)
+{
+ size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
+ size_t const inBuffSize = blockSize; /* no block can be larger */
+ size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);
+ return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;
+}
+
+size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)
+{
+ U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX; /* note : should be user-selectable, but requires an additional parameter (or a dctx) */
+ ZSTD_frameHeader zfh;
+ size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);
+ if (ZSTD_isError(err)) return err;
+ RETURN_ERROR_IF(err>0, srcSize_wrong, "");
+ RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,
+ frameParameter_windowTooLarge, "");
+ return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);
+}
+
+
+/* ***** Decompression ***** */
+
+static int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
+{
+ return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;
+}
+
+static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)
+{
+ if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))
+ zds->oversizedDuration++;
+ else
+ zds->oversizedDuration = 0;
+}
+
+static int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)
+{
+ return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;
+}
+
+/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */
+static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)
+{
+ ZSTD_outBuffer const expect = zds->expectedOutBuffer;
+ /* No requirement when ZSTD_obm_stable is not enabled. */
+ if (zds->outBufferMode != ZSTD_bm_stable)
+ return 0;
+ /* Any buffer is allowed in zdss_init, this must be the same for every other call until
+ * the context is reset.
+ */
+ if (zds->streamStage == zdss_init)
+ return 0;
+ /* The buffer must match our expectation exactly. */
+ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)
+ return 0;
+ RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!");
+}
+
+/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()
+ * and updates the stage and the output buffer state. This call is extracted so it can be
+ * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.
+ * NOTE: You must break after calling this function since the streamStage is modified.
+ */
+static size_t ZSTD_decompressContinueStream(
+ ZSTD_DStream* zds, char** op, char* oend,
+ void const* src, size_t srcSize) {
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
+ if (zds->outBufferMode == ZSTD_bm_buffered) {
+ size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;
+ size_t const decodedSize = ZSTD_decompressContinue(zds,
+ zds->outBuff + zds->outStart, dstSize, src, srcSize);
+ FORWARD_IF_ERROR(decodedSize, "");
+ if (!decodedSize && !isSkipFrame) {
+ zds->streamStage = zdss_read;
+ } else {
+ zds->outEnd = zds->outStart + decodedSize;
+ zds->streamStage = zdss_flush;
+ }
+ } else {
+ /* Write directly into the output buffer */
+ size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);
+ size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);
+ FORWARD_IF_ERROR(decodedSize, "");
+ *op += decodedSize;
+ /* Flushing is not needed. */
+ zds->streamStage = zdss_read;
+ assert(*op <= oend);
+ assert(zds->outBufferMode == ZSTD_bm_stable);
+ }
+ return 0;
+}
+
+size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)
+{
+ const char* const src = (const char*)input->src;
+ const char* const istart = input->pos != 0 ? src + input->pos : src;
+ const char* const iend = input->size != 0 ? src + input->size : src;
+ const char* ip = istart;
+ char* const dst = (char*)output->dst;
+ char* const ostart = output->pos != 0 ? dst + output->pos : dst;
+ char* const oend = output->size != 0 ? dst + output->size : dst;
+ char* op = ostart;
+ U32 someMoreWork = 1;
+
+ DEBUGLOG(5, "ZSTD_decompressStream");
+ RETURN_ERROR_IF(
+ input->pos > input->size,
+ srcSize_wrong,
+ "forbidden. in: pos: %u vs size: %u",
+ (U32)input->pos, (U32)input->size);
+ RETURN_ERROR_IF(
+ output->pos > output->size,
+ dstSize_tooSmall,
+ "forbidden. out: pos: %u vs size: %u",
+ (U32)output->pos, (U32)output->size);
+ DEBUGLOG(5, "input size : %u", (U32)(input->size - input->pos));
+ FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), "");
+
+ while (someMoreWork) {
+ switch(zds->streamStage)
+ {
+ case zdss_init :
+ DEBUGLOG(5, "stage zdss_init => transparent reset ");
+ zds->streamStage = zdss_loadHeader;
+ zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+ zds->hostageByte = 0;
+ zds->expectedOutBuffer = *output;
+ ZSTD_FALLTHROUGH;
+
+ case zdss_loadHeader :
+ DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
+ { size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);
+ if (zds->refMultipleDDicts && zds->ddictSet) {
+ ZSTD_DCtx_selectFrameDDict(zds);
+ }
+ DEBUGLOG(5, "header size : %u", (U32)hSize);
+ if (ZSTD_isError(hSize)) {
+ return hSize; /* error */
+ }
+ if (hSize != 0) { /* need more input */
+ size_t const toLoad = hSize - zds->lhSize; /* if hSize!=0, hSize > zds->lhSize */
+ size_t const remainingInput = (size_t)(iend-ip);
+ assert(iend >= ip);
+ if (toLoad > remainingInput) { /* not enough input to load full header */
+ if (remainingInput > 0) {
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);
+ zds->lhSize += remainingInput;
+ }
+ input->pos = input->size;
+ return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */
+ }
+ assert(ip != NULL);
+ ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;
+ break;
+ } }
+
+ /* check for single-pass mode opportunity */
+ if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
+ && zds->fParams.frameType != ZSTD_skippableFrame
+ && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {
+ size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart));
+ if (cSize <= (size_t)(iend-istart)) {
+ /* shortcut : using single-pass mode */
+ size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));
+ if (ZSTD_isError(decompressedSize)) return decompressedSize;
+ DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()")
+ ip = istart + cSize;
+ op += decompressedSize;
+ zds->expected = 0;
+ zds->streamStage = zdss_init;
+ someMoreWork = 0;
+ break;
+ } }
+
+ /* Check output buffer is large enough for ZSTD_odm_stable. */
+ if (zds->outBufferMode == ZSTD_bm_stable
+ && zds->fParams.frameType != ZSTD_skippableFrame
+ && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
+ && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {
+ RETURN_ERROR(dstSize_tooSmall, "ZSTD_obm_stable passed but ZSTD_outBuffer is too small");
+ }
+
+ /* Consume header (see ZSTDds_decodeFrameHeader) */
+ DEBUGLOG(4, "Consume header");
+ FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), "");
+
+ if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */
+ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);
+ zds->stage = ZSTDds_skipFrame;
+ } else {
+ FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), "");
+ zds->expected = ZSTD_blockHeaderSize;
+ zds->stage = ZSTDds_decodeBlockHeader;
+ }
+
+ /* control buffer memory usage */
+ DEBUGLOG(4, "Control max memory usage (%u KB <= max %u KB)",
+ (U32)(zds->fParams.windowSize >>10),
+ (U32)(zds->maxWindowSize >> 10) );
+ zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
+ RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,
+ frameParameter_windowTooLarge, "");
+
+ /* Adapt buffer sizes to frame header instructions */
+ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);
+ size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered
+ ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize)
+ : 0;
+
+ ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);
+
+ { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);
+ int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);
+
+ if (tooSmall || tooLarge) {
+ size_t const bufferSize = neededInBuffSize + neededOutBuffSize;
+ DEBUGLOG(4, "inBuff : from %u to %u",
+ (U32)zds->inBuffSize, (U32)neededInBuffSize);
+ DEBUGLOG(4, "outBuff : from %u to %u",
+ (U32)zds->outBuffSize, (U32)neededOutBuffSize);
+ if (zds->staticSize) { /* static DCtx */
+ DEBUGLOG(4, "staticSize : %u", (U32)zds->staticSize);
+ assert(zds->staticSize >= sizeof(ZSTD_DCtx)); /* controlled at init */
+ RETURN_ERROR_IF(
+ bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),
+ memory_allocation, "");
+ } else {
+ ZSTD_customFree(zds->inBuff, zds->customMem);
+ zds->inBuffSize = 0;
+ zds->outBuffSize = 0;
+ zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);
+ RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, "");
+ }
+ zds->inBuffSize = neededInBuffSize;
+ zds->outBuff = zds->inBuff + zds->inBuffSize;
+ zds->outBuffSize = neededOutBuffSize;
+ } } }
+ zds->streamStage = zdss_read;
+ ZSTD_FALLTHROUGH;
+
+ case zdss_read:
+ DEBUGLOG(5, "stage zdss_read");
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));
+ DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize);
+ if (neededInSize==0) { /* end of frame */
+ zds->streamStage = zdss_init;
+ someMoreWork = 0;
+ break;
+ }
+ if ((size_t)(iend-ip) >= neededInSize) { /* decode directly from src */
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), "");
+ ip += neededInSize;
+ /* Function modifies the stage so we must break */
+ break;
+ } }
+ if (ip==iend) { someMoreWork = 0; break; } /* no more input */
+ zds->streamStage = zdss_load;
+ ZSTD_FALLTHROUGH;
+
+ case zdss_load:
+ { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
+ size_t const toLoad = neededInSize - zds->inPos;
+ int const isSkipFrame = ZSTD_isSkipFrame(zds);
+ size_t loadedSize;
+ /* At this point we shouldn't be decompressing a block that we can stream. */
+ assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip));
+ if (isSkipFrame) {
+ loadedSize = MIN(toLoad, (size_t)(iend-ip));
+ } else {
+ RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,
+ corruption_detected,
+ "should never happen");
+ loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));
+ }
+ ip += loadedSize;
+ zds->inPos += loadedSize;
+ if (loadedSize < toLoad) { someMoreWork = 0; break; } /* not enough input, wait for more */
+
+ /* decode loaded input */
+ zds->inPos = 0; /* input is consumed */
+ FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), "");
+ /* Function modifies the stage so we must break */
+ break;
+ }
+ case zdss_flush:
+ { size_t const toFlushSize = zds->outEnd - zds->outStart;
+ size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);
+ op += flushedSize;
+ zds->outStart += flushedSize;
+ if (flushedSize == toFlushSize) { /* flush completed */
+ zds->streamStage = zdss_read;
+ if ( (zds->outBuffSize < zds->fParams.frameContentSize)
+ && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {
+ DEBUGLOG(5, "restart filling outBuff from beginning (left:%i, needed:%u)",
+ (int)(zds->outBuffSize - zds->outStart),
+ (U32)zds->fParams.blockSizeMax);
+ zds->outStart = zds->outEnd = 0;
+ }
+ break;
+ } }
+ /* cannot complete flush */
+ someMoreWork = 0;
+ break;
+
+ default:
+ assert(0); /* impossible */
+ RETURN_ERROR(GENERIC, "impossible to reach"); /* some compiler require default to do something */
+ } }
+
+ /* result */
+ input->pos = (size_t)(ip - (const char*)(input->src));
+ output->pos = (size_t)(op - (char*)(output->dst));
+
+ /* Update the expected output buffer for ZSTD_obm_stable. */
+ zds->expectedOutBuffer = *output;
+
+ if ((ip==istart) && (op==ostart)) { /* no forward progress */
+ zds->noForwardProgress ++;
+ if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {
+ RETURN_ERROR_IF(op==oend, dstSize_tooSmall, "");
+ RETURN_ERROR_IF(ip==iend, srcSize_wrong, "");
+ assert(0);
+ }
+ } else {
+ zds->noForwardProgress = 0;
+ }
+ { size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);
+ if (!nextSrcSizeHint) { /* frame fully decoded */
+ if (zds->outEnd == zds->outStart) { /* output fully flushed */
+ if (zds->hostageByte) {
+ if (input->pos >= input->size) {
+ /* can't release hostage (not present) */
+ zds->streamStage = zdss_read;
+ return 1;
+ }
+ input->pos++; /* release hostage */
+ } /* zds->hostageByte */
+ return 0;
+ } /* zds->outEnd == zds->outStart */
+ if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */
+ input->pos--; /* note : pos > 0, otherwise, impossible to finish reading last block */
+ zds->hostageByte=1;
+ }
+ return 1;
+ } /* nextSrcSizeHint==0 */
+ nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block); /* preload header of next block */
+ assert(zds->inPos <= nextSrcSizeHint);
+ nextSrcSizeHint -= zds->inPos; /* part already loaded*/
+ return nextSrcSizeHint;
+ }
+}
+
+size_t ZSTD_decompressStream_simpleArgs (
+ ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity, size_t* dstPos,
+ const void* src, size_t srcSize, size_t* srcPos)
+{
+ ZSTD_outBuffer output = { dst, dstCapacity, *dstPos };
+ ZSTD_inBuffer input = { src, srcSize, *srcPos };
+ /* ZSTD_compress_generic() will check validity of dstPos and srcPos */
+ size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);
+ *dstPos = output.pos;
+ *srcPos = input.pos;
+ return cErr;
+}
diff --git a/lib/zstd/decompress/zstd_decompress_block.c b/lib/zstd/decompress/zstd_decompress_block.c
new file mode 100644
index 0000000..c1913b8
--- /dev/null
+++ b/lib/zstd/decompress/zstd_decompress_block.c
@@ -0,0 +1,2072 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/* zstd_decompress_block :
+ * this module takes care of decompressing _compressed_ block */
+
+/*-*******************************************************
+* Dependencies
+*********************************************************/
+#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
+#include "../common/compiler.h" /* prefetch */
+#include "../common/cpu.h" /* bmi2 */
+#include "../common/mem.h" /* low level memory routines */
+#define FSE_STATIC_LINKING_ONLY
+#include "../common/fse.h"
+#define HUF_STATIC_LINKING_ONLY
+#include "../common/huf.h"
+#include "../common/zstd_internal.h"
+#include "zstd_decompress_internal.h" /* ZSTD_DCtx */
+#include "zstd_ddict.h" /* ZSTD_DDictDictContent */
+#include "zstd_decompress_block.h"
+
+/*_*******************************************************
+* Macros
+**********************************************************/
+
+/* These two optional macros force the use one way or another of the two
+ * ZSTD_decompressSequences implementations. You can't force in both directions
+ * at the same time.
+ */
+#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+#error "Cannot force the use of the short and the long ZSTD_decompressSequences variants!"
+#endif
+
+
+/*_*******************************************************
+* Memory operations
+**********************************************************/
+static void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); }
+
+
+/*-*************************************************************
+ * Block decoding
+ ***************************************************************/
+
+/*! ZSTD_getcBlockSize() :
+ * Provides the size of compressed block from block header `src` */
+size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
+ blockProperties_t* bpPtr)
+{
+ RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong, "");
+
+ { U32 const cBlockHeader = MEM_readLE24(src);
+ U32 const cSize = cBlockHeader >> 3;
+ bpPtr->lastBlock = cBlockHeader & 1;
+ bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);
+ bpPtr->origSize = cSize; /* only useful for RLE */
+ if (bpPtr->blockType == bt_rle) return 1;
+ RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected, "");
+ return cSize;
+ }
+}
+
+/* Allocate buffer for literals, either overlapping current dst, or split between dst and litExtraBuffer, or stored entirely within litExtraBuffer */
+static void ZSTD_allocateLiteralsBuffer(ZSTD_DCtx* dctx, void* const dst, const size_t dstCapacity, const size_t litSize,
+ const streaming_operation streaming, const size_t expectedWriteSize, const unsigned splitImmediately)
+{
+ if (streaming == not_streaming && dstCapacity > ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH + litSize + WILDCOPY_OVERLENGTH)
+ {
+ /* room for litbuffer to fit without read faulting */
+ dctx->litBuffer = (BYTE*)dst + ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH;
+ dctx->litBufferEnd = dctx->litBuffer + litSize;
+ dctx->litBufferLocation = ZSTD_in_dst;
+ }
+ else if (litSize > ZSTD_LITBUFFEREXTRASIZE)
+ {
+ /* won't fit in litExtraBuffer, so it will be split between end of dst and extra buffer */
+ if (splitImmediately) {
+ /* won't fit in litExtraBuffer, so it will be split between end of dst and extra buffer */
+ dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;
+ dctx->litBufferEnd = dctx->litBuffer + litSize - ZSTD_LITBUFFEREXTRASIZE;
+ }
+ else {
+ /* initially this will be stored entirely in dst during huffman decoding, it will partially shifted to litExtraBuffer after */
+ dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize;
+ dctx->litBufferEnd = (BYTE*)dst + expectedWriteSize;
+ }
+ dctx->litBufferLocation = ZSTD_split;
+ }
+ else
+ {
+ /* fits entirely within litExtraBuffer, so no split is necessary */
+ dctx->litBuffer = dctx->litExtraBuffer;
+ dctx->litBufferEnd = dctx->litBuffer + litSize;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ }
+}
+
+/* Hidden declaration for fullbench */
+size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
+ const void* src, size_t srcSize,
+ void* dst, size_t dstCapacity, const streaming_operation streaming);
+/*! ZSTD_decodeLiteralsBlock() :
+ * Where it is possible to do so without being stomped by the output during decompression, the literals block will be stored
+ * in the dstBuffer. If there is room to do so, it will be stored in full in the excess dst space after where the current
+ * block will be output. Otherwise it will be stored at the end of the current dst blockspace, with a small portion being
+ * stored in dctx->litExtraBuffer to help keep it "ahead" of the current output write.
+ *
+ * @return : nb of bytes read from src (< srcSize )
+ * note : symbol not declared but exposed for fullbench */
+size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
+ const void* src, size_t srcSize, /* note : srcSize < BLOCKSIZE */
+ void* dst, size_t dstCapacity, const streaming_operation streaming)
+{
+ DEBUGLOG(5, "ZSTD_decodeLiteralsBlock");
+ RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, "");
+
+ { const BYTE* const istart = (const BYTE*) src;
+ symbolEncodingType_e const litEncType = (symbolEncodingType_e)(istart[0] & 3);
+
+ switch(litEncType)
+ {
+ case set_repeat:
+ DEBUGLOG(5, "set_repeat flag : re-using stats from previous compressed literals block");
+ RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, "");
+ ZSTD_FALLTHROUGH;
+
+ case set_compressed:
+ RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3");
+ { size_t lhSize, litSize, litCSize;
+ U32 singleStream=0;
+ U32 const lhlCode = (istart[0] >> 2) & 3;
+ U32 const lhc = MEM_readLE32(istart);
+ size_t hufSuccess;
+ size_t expectedWriteSize = MIN(ZSTD_BLOCKSIZE_MAX, dstCapacity);
+ switch(lhlCode)
+ {
+ case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
+ /* 2 - 2 - 10 - 10 */
+ singleStream = !lhlCode;
+ lhSize = 3;
+ litSize = (lhc >> 4) & 0x3FF;
+ litCSize = (lhc >> 14) & 0x3FF;
+ break;
+ case 2:
+ /* 2 - 2 - 14 - 14 */
+ lhSize = 4;
+ litSize = (lhc >> 4) & 0x3FFF;
+ litCSize = lhc >> 18;
+ break;
+ case 3:
+ /* 2 - 2 - 18 - 18 */
+ lhSize = 5;
+ litSize = (lhc >> 4) & 0x3FFFF;
+ litCSize = (lhc >> 22) + ((size_t)istart[4] << 10);
+ break;
+ }
+ RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled");
+ RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
+ RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, "");
+ RETURN_ERROR_IF(expectedWriteSize < litSize , dstSize_tooSmall, "");
+ ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 0);
+
+ /* prefetch huffman table if cold */
+ if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
+ PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable));
+ }
+
+ if (litEncType==set_repeat) {
+ if (singleStream) {
+ hufSuccess = HUF_decompress1X_usingDTable_bmi2(
+ dctx->litBuffer, litSize, istart+lhSize, litCSize,
+ dctx->HUFptr, ZSTD_DCtx_get_bmi2(dctx));
+ } else {
+ hufSuccess = HUF_decompress4X_usingDTable_bmi2(
+ dctx->litBuffer, litSize, istart+lhSize, litCSize,
+ dctx->HUFptr, ZSTD_DCtx_get_bmi2(dctx));
+ }
+ } else {
+ if (singleStream) {
+#if defined(HUF_FORCE_DECOMPRESS_X2)
+ hufSuccess = HUF_decompress1X_DCtx_wksp(
+ dctx->entropy.hufTable, dctx->litBuffer, litSize,
+ istart+lhSize, litCSize, dctx->workspace,
+ sizeof(dctx->workspace));
+#else
+ hufSuccess = HUF_decompress1X1_DCtx_wksp_bmi2(
+ dctx->entropy.hufTable, dctx->litBuffer, litSize,
+ istart+lhSize, litCSize, dctx->workspace,
+ sizeof(dctx->workspace), ZSTD_DCtx_get_bmi2(dctx));
+#endif
+ } else {
+ hufSuccess = HUF_decompress4X_hufOnly_wksp_bmi2(
+ dctx->entropy.hufTable, dctx->litBuffer, litSize,
+ istart+lhSize, litCSize, dctx->workspace,
+ sizeof(dctx->workspace), ZSTD_DCtx_get_bmi2(dctx));
+ }
+ }
+ if (dctx->litBufferLocation == ZSTD_split)
+ {
+ ZSTD_memcpy(dctx->litExtraBuffer, dctx->litBufferEnd - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);
+ ZSTD_memmove(dctx->litBuffer + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH, dctx->litBuffer, litSize - ZSTD_LITBUFFEREXTRASIZE);
+ dctx->litBuffer += ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;
+ dctx->litBufferEnd -= WILDCOPY_OVERLENGTH;
+ }
+
+ RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, "");
+
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ dctx->litEntropy = 1;
+ if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
+ return litCSize + lhSize;
+ }
+
+ case set_basic:
+ { size_t litSize, lhSize;
+ U32 const lhlCode = ((istart[0]) >> 2) & 3;
+ size_t expectedWriteSize = MIN(ZSTD_BLOCKSIZE_MAX, dstCapacity);
+ switch(lhlCode)
+ {
+ case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
+ lhSize = 1;
+ litSize = istart[0] >> 3;
+ break;
+ case 1:
+ lhSize = 2;
+ litSize = MEM_readLE16(istart) >> 4;
+ break;
+ case 3:
+ lhSize = 3;
+ litSize = MEM_readLE24(istart) >> 4;
+ break;
+ }
+
+ RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled");
+ RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, "");
+ ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);
+ if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
+ RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, "");
+ if (dctx->litBufferLocation == ZSTD_split)
+ {
+ ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize - ZSTD_LITBUFFEREXTRASIZE);
+ ZSTD_memcpy(dctx->litExtraBuffer, istart + lhSize + litSize - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);
+ }
+ else
+ {
+ ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize);
+ }
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ return lhSize+litSize;
+ }
+ /* direct reference into compressed stream */
+ dctx->litPtr = istart+lhSize;
+ dctx->litSize = litSize;
+ dctx->litBufferEnd = dctx->litPtr + litSize;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ return lhSize+litSize;
+ }
+
+ case set_rle:
+ { U32 const lhlCode = ((istart[0]) >> 2) & 3;
+ size_t litSize, lhSize;
+ size_t expectedWriteSize = MIN(ZSTD_BLOCKSIZE_MAX, dstCapacity);
+ switch(lhlCode)
+ {
+ case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
+ lhSize = 1;
+ litSize = istart[0] >> 3;
+ break;
+ case 1:
+ lhSize = 2;
+ litSize = MEM_readLE16(istart) >> 4;
+ break;
+ case 3:
+ lhSize = 3;
+ litSize = MEM_readLE24(istart) >> 4;
+ RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4");
+ break;
+ }
+ RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled");
+ RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
+ RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, "");
+ ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);
+ if (dctx->litBufferLocation == ZSTD_split)
+ {
+ ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize - ZSTD_LITBUFFEREXTRASIZE);
+ ZSTD_memset(dctx->litExtraBuffer, istart[lhSize], ZSTD_LITBUFFEREXTRASIZE);
+ }
+ else
+ {
+ ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize);
+ }
+ dctx->litPtr = dctx->litBuffer;
+ dctx->litSize = litSize;
+ return lhSize+1;
+ }
+ default:
+ RETURN_ERROR(corruption_detected, "impossible");
+ }
+ }
+}
+
+/* Default FSE distribution tables.
+ * These are pre-calculated FSE decoding tables using default distributions as defined in specification :
+ * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions
+ * They were generated programmatically with following method :
+ * - start from default distributions, present in /lib/common/zstd_internal.h
+ * - generate tables normally, using ZSTD_buildFSETable()
+ * - printout the content of tables
+ * - pretify output, report below, test with fuzzer to ensure it's correct */
+
+/* Default FSE distribution table for Literal Lengths */
+static const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, LL_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 4, 0}, { 16, 0, 4, 0},
+ { 32, 0, 5, 1}, { 0, 0, 5, 3},
+ { 0, 0, 5, 4}, { 0, 0, 5, 6},
+ { 0, 0, 5, 7}, { 0, 0, 5, 9},
+ { 0, 0, 5, 10}, { 0, 0, 5, 12},
+ { 0, 0, 6, 14}, { 0, 1, 5, 16},
+ { 0, 1, 5, 20}, { 0, 1, 5, 22},
+ { 0, 2, 5, 28}, { 0, 3, 5, 32},
+ { 0, 4, 5, 48}, { 32, 6, 5, 64},
+ { 0, 7, 5, 128}, { 0, 8, 6, 256},
+ { 0, 10, 6, 1024}, { 0, 12, 6, 4096},
+ { 32, 0, 4, 0}, { 0, 0, 4, 1},
+ { 0, 0, 5, 2}, { 32, 0, 5, 4},
+ { 0, 0, 5, 5}, { 32, 0, 5, 7},
+ { 0, 0, 5, 8}, { 32, 0, 5, 10},
+ { 0, 0, 5, 11}, { 0, 0, 6, 13},
+ { 32, 1, 5, 16}, { 0, 1, 5, 18},
+ { 32, 1, 5, 22}, { 0, 2, 5, 24},
+ { 32, 3, 5, 32}, { 0, 3, 5, 40},
+ { 0, 6, 4, 64}, { 16, 6, 4, 64},
+ { 32, 7, 5, 128}, { 0, 9, 6, 512},
+ { 0, 11, 6, 2048}, { 48, 0, 4, 0},
+ { 16, 0, 4, 1}, { 32, 0, 5, 2},
+ { 32, 0, 5, 3}, { 32, 0, 5, 5},
+ { 32, 0, 5, 6}, { 32, 0, 5, 8},
+ { 32, 0, 5, 9}, { 32, 0, 5, 11},
+ { 32, 0, 5, 12}, { 0, 0, 6, 15},
+ { 32, 1, 5, 18}, { 32, 1, 5, 20},
+ { 32, 2, 5, 24}, { 32, 2, 5, 28},
+ { 32, 3, 5, 40}, { 32, 4, 5, 48},
+ { 0, 16, 6,65536}, { 0, 15, 6,32768},
+ { 0, 14, 6,16384}, { 0, 13, 6, 8192},
+}; /* LL_defaultDTable */
+
+/* Default FSE distribution table for Offset Codes */
+static const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, OF_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 5, 0}, { 0, 6, 4, 61},
+ { 0, 9, 5, 509}, { 0, 15, 5,32765},
+ { 0, 21, 5,2097149}, { 0, 3, 5, 5},
+ { 0, 7, 4, 125}, { 0, 12, 5, 4093},
+ { 0, 18, 5,262141}, { 0, 23, 5,8388605},
+ { 0, 5, 5, 29}, { 0, 8, 4, 253},
+ { 0, 14, 5,16381}, { 0, 20, 5,1048573},
+ { 0, 2, 5, 1}, { 16, 7, 4, 125},
+ { 0, 11, 5, 2045}, { 0, 17, 5,131069},
+ { 0, 22, 5,4194301}, { 0, 4, 5, 13},
+ { 16, 8, 4, 253}, { 0, 13, 5, 8189},
+ { 0, 19, 5,524285}, { 0, 1, 5, 1},
+ { 16, 6, 4, 61}, { 0, 10, 5, 1021},
+ { 0, 16, 5,65533}, { 0, 28, 5,268435453},
+ { 0, 27, 5,134217725}, { 0, 26, 5,67108861},
+ { 0, 25, 5,33554429}, { 0, 24, 5,16777213},
+}; /* OF_defaultDTable */
+
+
+/* Default FSE distribution table for Match Lengths */
+static const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
+ { 1, 1, 1, ML_DEFAULTNORMLOG}, /* header : fastMode, tableLog */
+ /* nextState, nbAddBits, nbBits, baseVal */
+ { 0, 0, 6, 3}, { 0, 0, 4, 4},
+ { 32, 0, 5, 5}, { 0, 0, 5, 6},
+ { 0, 0, 5, 8}, { 0, 0, 5, 9},
+ { 0, 0, 5, 11}, { 0, 0, 6, 13},
+ { 0, 0, 6, 16}, { 0, 0, 6, 19},
+ { 0, 0, 6, 22}, { 0, 0, 6, 25},
+ { 0, 0, 6, 28}, { 0, 0, 6, 31},
+ { 0, 0, 6, 34}, { 0, 1, 6, 37},
+ { 0, 1, 6, 41}, { 0, 2, 6, 47},
+ { 0, 3, 6, 59}, { 0, 4, 6, 83},
+ { 0, 7, 6, 131}, { 0, 9, 6, 515},
+ { 16, 0, 4, 4}, { 0, 0, 4, 5},
+ { 32, 0, 5, 6}, { 0, 0, 5, 7},
+ { 32, 0, 5, 9}, { 0, 0, 5, 10},
+ { 0, 0, 6, 12}, { 0, 0, 6, 15},
+ { 0, 0, 6, 18}, { 0, 0, 6, 21},
+ { 0, 0, 6, 24}, { 0, 0, 6, 27},
+ { 0, 0, 6, 30}, { 0, 0, 6, 33},
+ { 0, 1, 6, 35}, { 0, 1, 6, 39},
+ { 0, 2, 6, 43}, { 0, 3, 6, 51},
+ { 0, 4, 6, 67}, { 0, 5, 6, 99},
+ { 0, 8, 6, 259}, { 32, 0, 4, 4},
+ { 48, 0, 4, 4}, { 16, 0, 4, 5},
+ { 32, 0, 5, 7}, { 32, 0, 5, 8},
+ { 32, 0, 5, 10}, { 32, 0, 5, 11},
+ { 0, 0, 6, 14}, { 0, 0, 6, 17},
+ { 0, 0, 6, 20}, { 0, 0, 6, 23},
+ { 0, 0, 6, 26}, { 0, 0, 6, 29},
+ { 0, 0, 6, 32}, { 0, 16, 6,65539},
+ { 0, 15, 6,32771}, { 0, 14, 6,16387},
+ { 0, 13, 6, 8195}, { 0, 12, 6, 4099},
+ { 0, 11, 6, 2051}, { 0, 10, 6, 1027},
+}; /* ML_defaultDTable */
+
+
+static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U8 nbAddBits)
+{
+ void* ptr = dt;
+ ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;
+ ZSTD_seqSymbol* const cell = dt + 1;
+
+ DTableH->tableLog = 0;
+ DTableH->fastMode = 0;
+
+ cell->nbBits = 0;
+ cell->nextState = 0;
+ assert(nbAddBits < 255);
+ cell->nbAdditionalBits = nbAddBits;
+ cell->baseValue = baseValue;
+}
+
+
+/* ZSTD_buildFSETable() :
+ * generate FSE decoding table for one symbol (ll, ml or off)
+ * cannot fail if input is valid =>
+ * all inputs are presumed validated at this stage */
+FORCE_INLINE_TEMPLATE
+void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U8* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize)
+{
+ ZSTD_seqSymbol* const tableDecode = dt+1;
+ U32 const maxSV1 = maxSymbolValue + 1;
+ U32 const tableSize = 1 << tableLog;
+
+ U16* symbolNext = (U16*)wksp;
+ BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1);
+ U32 highThreshold = tableSize - 1;
+
+
+ /* Sanity Checks */
+ assert(maxSymbolValue <= MaxSeq);
+ assert(tableLog <= MaxFSELog);
+ assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE);
+ (void)wkspSize;
+ /* Init, lay down lowprob symbols */
+ { ZSTD_seqSymbol_header DTableH;
+ DTableH.tableLog = tableLog;
+ DTableH.fastMode = 1;
+ { S16 const largeLimit= (S16)(1 << (tableLog-1));
+ U32 s;
+ for (s=0; s<maxSV1; s++) {
+ if (normalizedCounter[s]==-1) {
+ tableDecode[highThreshold--].baseValue = s;
+ symbolNext[s] = 1;
+ } else {
+ if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;
+ assert(normalizedCounter[s]>=0);
+ symbolNext[s] = (U16)normalizedCounter[s];
+ } } }
+ ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));
+ }
+
+ /* Spread symbols */
+ assert(tableSize <= 512);
+ /* Specialized symbol spreading for the case when there are
+ * no low probability (-1 count) symbols. When compressing
+ * small blocks we avoid low probability symbols to hit this
+ * case, since header decoding speed matters more.
+ */
+ if (highThreshold == tableSize - 1) {
+ size_t const tableMask = tableSize-1;
+ size_t const step = FSE_TABLESTEP(tableSize);
+ /* First lay down the symbols in order.
+ * We use a uint64_t to lay down 8 bytes at a time. This reduces branch
+ * misses since small blocks generally have small table logs, so nearly
+ * all symbols have counts <= 8. We ensure we have 8 bytes at the end of
+ * our buffer to handle the over-write.
+ */
+ {
+ U64 const add = 0x0101010101010101ull;
+ size_t pos = 0;
+ U64 sv = 0;
+ U32 s;
+ for (s=0; s<maxSV1; ++s, sv += add) {
+ int i;
+ int const n = normalizedCounter[s];
+ MEM_write64(spread + pos, sv);
+ for (i = 8; i < n; i += 8) {
+ MEM_write64(spread + pos + i, sv);
+ }
+ pos += n;
+ }
+ }
+ /* Now we spread those positions across the table.
+ * The benefit of doing it in two stages is that we avoid the the
+ * variable size inner loop, which caused lots of branch misses.
+ * Now we can run through all the positions without any branch misses.
+ * We unroll the loop twice, since that is what emperically worked best.
+ */
+ {
+ size_t position = 0;
+ size_t s;
+ size_t const unroll = 2;
+ assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
+ for (s = 0; s < (size_t)tableSize; s += unroll) {
+ size_t u;
+ for (u = 0; u < unroll; ++u) {
+ size_t const uPosition = (position + (u * step)) & tableMask;
+ tableDecode[uPosition].baseValue = spread[s + u];
+ }
+ position = (position + (unroll * step)) & tableMask;
+ }
+ assert(position == 0);
+ }
+ } else {
+ U32 const tableMask = tableSize-1;
+ U32 const step = FSE_TABLESTEP(tableSize);
+ U32 s, position = 0;
+ for (s=0; s<maxSV1; s++) {
+ int i;
+ int const n = normalizedCounter[s];
+ for (i=0; i<n; i++) {
+ tableDecode[position].baseValue = s;
+ position = (position + step) & tableMask;
+ while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
+ } }
+ assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
+ }
+
+ /* Build Decoding table */
+ {
+ U32 u;
+ for (u=0; u<tableSize; u++) {
+ U32 const symbol = tableDecode[u].baseValue;
+ U32 const nextState = symbolNext[symbol]++;
+ tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
+ tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
+ assert(nbAdditionalBits[symbol] < 255);
+ tableDecode[u].nbAdditionalBits = nbAdditionalBits[symbol];
+ tableDecode[u].baseValue = baseValue[symbol];
+ }
+ }
+}
+
+/* Avoids the FORCE_INLINE of the _body() function. */
+static void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U8* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize)
+{
+ ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
+}
+
+#if DYNAMIC_BMI2
+BMI2_TARGET_ATTRIBUTE static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U8* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize)
+{
+ ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
+}
+#endif
+
+void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U8* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+ ZSTD_buildFSETable_body_bmi2(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
+ return;
+ }
+#endif
+ (void)bmi2;
+ ZSTD_buildFSETable_body_default(dt, normalizedCounter, maxSymbolValue,
+ baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);
+}
+
+
+/*! ZSTD_buildSeqTable() :
+ * @return : nb bytes read from src,
+ * or an error code if it fails */
+static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,
+ symbolEncodingType_e type, unsigned max, U32 maxLog,
+ const void* src, size_t srcSize,
+ const U32* baseValue, const U8* nbAdditionalBits,
+ const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable,
+ int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize,
+ int bmi2)
+{
+ switch(type)
+ {
+ case set_rle :
+ RETURN_ERROR_IF(!srcSize, srcSize_wrong, "");
+ RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected, "");
+ { U32 const symbol = *(const BYTE*)src;
+ U32 const baseline = baseValue[symbol];
+ U8 const nbBits = nbAdditionalBits[symbol];
+ ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);
+ }
+ *DTablePtr = DTableSpace;
+ return 1;
+ case set_basic :
+ *DTablePtr = defaultTable;
+ return 0;
+ case set_repeat:
+ RETURN_ERROR_IF(!flagRepeatTable, corruption_detected, "");
+ /* prefetch FSE table if used */
+ if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {
+ const void* const pStart = *DTablePtr;
+ size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog));
+ PREFETCH_AREA(pStart, pSize);
+ }
+ return 0;
+ case set_compressed :
+ { unsigned tableLog;
+ S16 norm[MaxSeq+1];
+ size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);
+ RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, "");
+ RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, "");
+ ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2);
+ *DTablePtr = DTableSpace;
+ return headerSize;
+ }
+ default :
+ assert(0);
+ RETURN_ERROR(GENERIC, "impossible");
+ }
+}
+
+size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
+ const void* src, size_t srcSize)
+{
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* ip = istart;
+ int nbSeq;
+ DEBUGLOG(5, "ZSTD_decodeSeqHeaders");
+
+ /* check */
+ RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong, "");
+
+ /* SeqHead */
+ nbSeq = *ip++;
+ if (!nbSeq) {
+ *nbSeqPtr=0;
+ RETURN_ERROR_IF(srcSize != 1, srcSize_wrong, "");
+ return 1;
+ }
+ if (nbSeq > 0x7F) {
+ if (nbSeq == 0xFF) {
+ RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, "");
+ nbSeq = MEM_readLE16(ip) + LONGNBSEQ;
+ ip+=2;
+ } else {
+ RETURN_ERROR_IF(ip >= iend, srcSize_wrong, "");
+ nbSeq = ((nbSeq-0x80)<<8) + *ip++;
+ }
+ }
+ *nbSeqPtr = nbSeq;
+
+ /* FSE table descriptors */
+ RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, ""); /* minimum possible size: 1 byte for symbol encoding types */
+ { symbolEncodingType_e const LLtype = (symbolEncodingType_e)(*ip >> 6);
+ symbolEncodingType_e const OFtype = (symbolEncodingType_e)((*ip >> 4) & 3);
+ symbolEncodingType_e const MLtype = (symbolEncodingType_e)((*ip >> 2) & 3);
+ ip++;
+
+ /* Build DTables */
+ { size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,
+ LLtype, MaxLL, LLFSELog,
+ ip, iend-ip,
+ LL_base, LL_bits,
+ LL_defaultDTable, dctx->fseEntropy,
+ dctx->ddictIsCold, nbSeq,
+ dctx->workspace, sizeof(dctx->workspace),
+ ZSTD_DCtx_get_bmi2(dctx));
+ RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed");
+ ip += llhSize;
+ }
+
+ { size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,
+ OFtype, MaxOff, OffFSELog,
+ ip, iend-ip,
+ OF_base, OF_bits,
+ OF_defaultDTable, dctx->fseEntropy,
+ dctx->ddictIsCold, nbSeq,
+ dctx->workspace, sizeof(dctx->workspace),
+ ZSTD_DCtx_get_bmi2(dctx));
+ RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed");
+ ip += ofhSize;
+ }
+
+ { size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,
+ MLtype, MaxML, MLFSELog,
+ ip, iend-ip,
+ ML_base, ML_bits,
+ ML_defaultDTable, dctx->fseEntropy,
+ dctx->ddictIsCold, nbSeq,
+ dctx->workspace, sizeof(dctx->workspace),
+ ZSTD_DCtx_get_bmi2(dctx));
+ RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed");
+ ip += mlhSize;
+ }
+ }
+
+ return ip-istart;
+}
+
+
+typedef struct {
+ size_t litLength;
+ size_t matchLength;
+ size_t offset;
+} seq_t;
+
+typedef struct {
+ size_t state;
+ const ZSTD_seqSymbol* table;
+} ZSTD_fseState;
+
+typedef struct {
+ BIT_DStream_t DStream;
+ ZSTD_fseState stateLL;
+ ZSTD_fseState stateOffb;
+ ZSTD_fseState stateML;
+ size_t prevOffset[ZSTD_REP_NUM];
+} seqState_t;
+
+/*! ZSTD_overlapCopy8() :
+ * Copies 8 bytes from ip to op and updates op and ip where ip <= op.
+ * If the offset is < 8 then the offset is spread to at least 8 bytes.
+ *
+ * Precondition: *ip <= *op
+ * Postcondition: *op - *op >= 8
+ */
+HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) {
+ assert(*ip <= *op);
+ if (offset < 8) {
+ /* close range match, overlap */
+ static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 }; /* added */
+ static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 }; /* subtracted */
+ int const sub2 = dec64table[offset];
+ (*op)[0] = (*ip)[0];
+ (*op)[1] = (*ip)[1];
+ (*op)[2] = (*ip)[2];
+ (*op)[3] = (*ip)[3];
+ *ip += dec32table[offset];
+ ZSTD_copy4(*op+4, *ip);
+ *ip -= sub2;
+ } else {
+ ZSTD_copy8(*op, *ip);
+ }
+ *ip += 8;
+ *op += 8;
+ assert(*op - *ip >= 8);
+}
+
+/*! ZSTD_safecopy() :
+ * Specialized version of memcpy() that is allowed to READ up to WILDCOPY_OVERLENGTH past the input buffer
+ * and write up to 16 bytes past oend_w (op >= oend_w is allowed).
+ * This function is only called in the uncommon case where the sequence is near the end of the block. It
+ * should be fast for a single long sequence, but can be slow for several short sequences.
+ *
+ * @param ovtype controls the overlap detection
+ * - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.
+ * - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart.
+ * The src buffer must be before the dst buffer.
+ */
+static void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) {
+ ptrdiff_t const diff = op - ip;
+ BYTE* const oend = op + length;
+
+ assert((ovtype == ZSTD_no_overlap && (diff <= -8 || diff >= 8 || op >= oend_w)) ||
+ (ovtype == ZSTD_overlap_src_before_dst && diff >= 0));
+
+ if (length < 8) {
+ /* Handle short lengths. */
+ while (op < oend) *op++ = *ip++;
+ return;
+ }
+ if (ovtype == ZSTD_overlap_src_before_dst) {
+ /* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */
+ assert(length >= 8);
+ ZSTD_overlapCopy8(&op, &ip, diff);
+ length -= 8;
+ assert(op - ip >= 8);
+ assert(op <= oend);
+ }
+
+ if (oend <= oend_w) {
+ /* No risk of overwrite. */
+ ZSTD_wildcopy(op, ip, length, ovtype);
+ return;
+ }
+ if (op <= oend_w) {
+ /* Wildcopy until we get close to the end. */
+ assert(oend > oend_w);
+ ZSTD_wildcopy(op, ip, oend_w - op, ovtype);
+ ip += oend_w - op;
+ op += oend_w - op;
+ }
+ /* Handle the leftovers. */
+ while (op < oend) *op++ = *ip++;
+}
+
+/* ZSTD_safecopyDstBeforeSrc():
+ * This version allows overlap with dst before src, or handles the non-overlap case with dst after src
+ * Kept separate from more common ZSTD_safecopy case to avoid performance impact to the safecopy common case */
+static void ZSTD_safecopyDstBeforeSrc(BYTE* op, BYTE const* ip, ptrdiff_t length) {
+ ptrdiff_t const diff = op - ip;
+ BYTE* const oend = op + length;
+
+ if (length < 8 || diff > -8) {
+ /* Handle short lengths, close overlaps, and dst not before src. */
+ while (op < oend) *op++ = *ip++;
+ return;
+ }
+
+ if (op <= oend - WILDCOPY_OVERLENGTH && diff < -WILDCOPY_VECLEN) {
+ ZSTD_wildcopy(op, ip, oend - WILDCOPY_OVERLENGTH - op, ZSTD_no_overlap);
+ ip += oend - WILDCOPY_OVERLENGTH - op;
+ op += oend - WILDCOPY_OVERLENGTH - op;
+ }
+
+ /* Handle the leftovers. */
+ while (op < oend) *op++ = *ip++;
+}
+
+/* ZSTD_execSequenceEnd():
+ * This version handles cases that are near the end of the output buffer. It requires
+ * more careful checks to make sure there is no overflow. By separating out these hard
+ * and unlikely cases, we can speed up the common cases.
+ *
+ * NOTE: This function needs to be fast for a single long sequence, but doesn't need
+ * to be optimized for many small sequences, since those fall into ZSTD_execSequence().
+ */
+FORCE_NOINLINE
+size_t ZSTD_execSequenceEnd(BYTE* op,
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+ BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;
+
+ /* bounds checks : careful of address space overflow in 32-bit mode */
+ RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer");
+ RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer");
+ assert(op < op + sequenceLength);
+ assert(oLitEnd < op + sequenceLength);
+
+ /* copy literals */
+ ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, ZSTD_no_overlap);
+ op = oLitEnd;
+ *litPtr = iLitEnd;
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix */
+ RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, "");
+ match = dictEnd - (prefixStart - match);
+ if (match + sequence.matchLength <= dictEnd) {
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ ZSTD_memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ }
+ }
+ ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);
+ return sequenceLength;
+}
+
+/* ZSTD_execSequenceEndSplitLitBuffer():
+ * This version is intended to be used during instances where the litBuffer is still split. It is kept separate to avoid performance impact for the good case.
+ */
+FORCE_NOINLINE
+size_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op,
+ BYTE* const oend, const BYTE* const oend_w, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+
+
+ /* bounds checks : careful of address space overflow in 32-bit mode */
+ RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer");
+ RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer");
+ assert(op < op + sequenceLength);
+ assert(oLitEnd < op + sequenceLength);
+
+ /* copy literals */
+ RETURN_ERROR_IF(op > *litPtr && op < *litPtr + sequence.litLength, dstSize_tooSmall, "output should not catch up to and overwrite literal buffer");
+ ZSTD_safecopyDstBeforeSrc(op, *litPtr, sequence.litLength);
+ op = oLitEnd;
+ *litPtr = iLitEnd;
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix */
+ RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, "");
+ match = dictEnd - (prefixStart - match);
+ if (match + sequence.matchLength <= dictEnd) {
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ ZSTD_memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ }
+ }
+ ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);
+ return sequenceLength;
+}
+
+HINT_INLINE
+size_t ZSTD_execSequence(BYTE* op,
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH; /* risk : address space underflow on oend=NULL */
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+
+ assert(op != NULL /* Precondition */);
+ assert(oend_w < oend /* No underflow */);
+ /* Handle edge cases in a slow path:
+ * - Read beyond end of literals
+ * - Match end is within WILDCOPY_OVERLIMIT of oend
+ * - 32-bit mode and the match length overflows
+ */
+ if (UNLIKELY(
+ iLitEnd > litLimit ||
+ oMatchEnd > oend_w ||
+ (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))
+ return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
+
+ /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */
+ assert(op <= oLitEnd /* No overflow */);
+ assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);
+ assert(oMatchEnd <= oend /* No underflow */);
+ assert(iLitEnd <= litLimit /* Literal length is in bounds */);
+ assert(oLitEnd <= oend_w /* Can wildcopy literals */);
+ assert(oMatchEnd <= oend_w /* Can wildcopy matches */);
+
+ /* Copy Literals:
+ * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.
+ * We likely don't need the full 32-byte wildcopy.
+ */
+ assert(WILDCOPY_OVERLENGTH >= 16);
+ ZSTD_copy16(op, (*litPtr));
+ if (UNLIKELY(sequence.litLength > 16)) {
+ ZSTD_wildcopy(op + 16, (*litPtr) + 16, sequence.litLength - 16, ZSTD_no_overlap);
+ }
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* Copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix -> go into extDict */
+ RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, "");
+ match = dictEnd + (match - prefixStart);
+ if (match + sequence.matchLength <= dictEnd) {
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ ZSTD_memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ }
+ }
+ /* Match within prefix of 1 or more bytes */
+ assert(op <= oMatchEnd);
+ assert(oMatchEnd <= oend_w);
+ assert(match >= prefixStart);
+ assert(sequence.matchLength >= 1);
+
+ /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy
+ * without overlap checking.
+ */
+ if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {
+ /* We bet on a full wildcopy for matches, since we expect matches to be
+ * longer than literals (in general). In silesia, ~10% of matches are longer
+ * than 16 bytes.
+ */
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);
+ return sequenceLength;
+ }
+ assert(sequence.offset < WILDCOPY_VECLEN);
+
+ /* Copy 8 bytes and spread the offset to be >= 8. */
+ ZSTD_overlapCopy8(&op, &match, sequence.offset);
+
+ /* If the match length is > 8 bytes, then continue with the wildcopy. */
+ if (sequence.matchLength > 8) {
+ assert(op < oMatchEnd);
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8, ZSTD_overlap_src_before_dst);
+ }
+ return sequenceLength;
+}
+
+HINT_INLINE
+size_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,
+ BYTE* const oend, const BYTE* const oend_w, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+
+ assert(op != NULL /* Precondition */);
+ assert(oend_w < oend /* No underflow */);
+ /* Handle edge cases in a slow path:
+ * - Read beyond end of literals
+ * - Match end is within WILDCOPY_OVERLIMIT of oend
+ * - 32-bit mode and the match length overflows
+ */
+ if (UNLIKELY(
+ iLitEnd > litLimit ||
+ oMatchEnd > oend_w ||
+ (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))
+ return ZSTD_execSequenceEndSplitLitBuffer(op, oend, oend_w, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
+
+ /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */
+ assert(op <= oLitEnd /* No overflow */);
+ assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);
+ assert(oMatchEnd <= oend /* No underflow */);
+ assert(iLitEnd <= litLimit /* Literal length is in bounds */);
+ assert(oLitEnd <= oend_w /* Can wildcopy literals */);
+ assert(oMatchEnd <= oend_w /* Can wildcopy matches */);
+
+ /* Copy Literals:
+ * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.
+ * We likely don't need the full 32-byte wildcopy.
+ */
+ assert(WILDCOPY_OVERLENGTH >= 16);
+ ZSTD_copy16(op, (*litPtr));
+ if (UNLIKELY(sequence.litLength > 16)) {
+ ZSTD_wildcopy(op+16, (*litPtr)+16, sequence.litLength-16, ZSTD_no_overlap);
+ }
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* Copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix -> go into extDict */
+ RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, "");
+ match = dictEnd + (match - prefixStart);
+ if (match + sequence.matchLength <= dictEnd) {
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ ZSTD_memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ } }
+ /* Match within prefix of 1 or more bytes */
+ assert(op <= oMatchEnd);
+ assert(oMatchEnd <= oend_w);
+ assert(match >= prefixStart);
+ assert(sequence.matchLength >= 1);
+
+ /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy
+ * without overlap checking.
+ */
+ if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {
+ /* We bet on a full wildcopy for matches, since we expect matches to be
+ * longer than literals (in general). In silesia, ~10% of matches are longer
+ * than 16 bytes.
+ */
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);
+ return sequenceLength;
+ }
+ assert(sequence.offset < WILDCOPY_VECLEN);
+
+ /* Copy 8 bytes and spread the offset to be >= 8. */
+ ZSTD_overlapCopy8(&op, &match, sequence.offset);
+
+ /* If the match length is > 8 bytes, then continue with the wildcopy. */
+ if (sequence.matchLength > 8) {
+ assert(op < oMatchEnd);
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst);
+ }
+ return sequenceLength;
+}
+
+
+static void
+ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)
+{
+ const void* ptr = dt;
+ const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr;
+ DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
+ DEBUGLOG(6, "ZSTD_initFseState : val=%u using %u bits",
+ (U32)DStatePtr->state, DTableH->tableLog);
+ BIT_reloadDStream(bitD);
+ DStatePtr->table = dt + 1;
+}
+
+FORCE_INLINE_TEMPLATE void
+ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, U16 nextState, U32 nbBits)
+{
+ size_t const lowBits = BIT_readBits(bitD, nbBits);
+ DStatePtr->state = nextState + lowBits;
+}
+
+/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
+ * offset bits. But we can only read at most (STREAM_ACCUMULATOR_MIN_32 - 1)
+ * bits before reloading. This value is the maximum number of bytes we read
+ * after reloading when we are decoding long offsets.
+ */
+#define LONG_OFFSETS_MAX_EXTRA_BITS_32 \
+ (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32 \
+ ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32 \
+ : 0)
+
+typedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;
+
+FORCE_INLINE_TEMPLATE seq_t
+ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
+{
+ seq_t seq;
+ const ZSTD_seqSymbol* const llDInfo = seqState->stateLL.table + seqState->stateLL.state;
+ const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state;
+ const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state;
+ seq.matchLength = mlDInfo->baseValue;
+ seq.litLength = llDInfo->baseValue;
+ { U32 const ofBase = ofDInfo->baseValue;
+ BYTE const llBits = llDInfo->nbAdditionalBits;
+ BYTE const mlBits = mlDInfo->nbAdditionalBits;
+ BYTE const ofBits = ofDInfo->nbAdditionalBits;
+ BYTE const totalBits = llBits+mlBits+ofBits;
+
+ U16 const llNext = llDInfo->nextState;
+ U16 const mlNext = mlDInfo->nextState;
+ U16 const ofNext = ofDInfo->nextState;
+ U32 const llnbBits = llDInfo->nbBits;
+ U32 const mlnbBits = mlDInfo->nbBits;
+ U32 const ofnbBits = ofDInfo->nbBits;
+ /*
+ * As gcc has better branch and block analyzers, sometimes it is only
+ * valuable to mark likelyness for clang, it gives around 3-4% of
+ * performance.
+ */
+
+ /* sequence */
+ { size_t offset;
+ #if defined(__clang__)
+ if (LIKELY(ofBits > 1)) {
+ #else
+ if (ofBits > 1) {
+ #endif
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
+ assert(ofBits <= MaxOff);
+ if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
+ U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
+ offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ BIT_reloadDStream(&seqState->DStream);
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+ assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */
+ } else {
+ offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
+ }
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset;
+ } else {
+ U32 const ll0 = (llDInfo->baseValue == 0);
+ if (LIKELY((ofBits == 0))) {
+ offset = seqState->prevOffset[ll0];
+ seqState->prevOffset[1] = seqState->prevOffset[!ll0];
+ seqState->prevOffset[0] = offset;
+ } else {
+ offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);
+ { size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+ temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+ if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset = temp;
+ } } }
+ seq.offset = offset;
+ }
+
+ #if defined(__clang__)
+ if (UNLIKELY(mlBits > 0))
+ #else
+ if (mlBits > 0)
+ #endif
+ seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);
+
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
+ BIT_reloadDStream(&seqState->DStream);
+ if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+ /* Ensure there are enough bits to read the rest of data in 64-bit mode. */
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
+
+ #if defined(__clang__)
+ if (UNLIKELY(llBits > 0))
+ #else
+ if (llBits > 0)
+ #endif
+ seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);
+
+ if (MEM_32bits())
+ BIT_reloadDStream(&seqState->DStream);
+
+ DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
+ (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
+
+ ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits); /* <= 9 bits */
+ ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits); /* <= 9 bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
+ ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofNext, ofnbBits); /* <= 8 bits */
+ }
+
+ return seq;
+}
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+MEM_STATIC int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)
+{
+ size_t const windowSize = dctx->fParams.windowSize;
+ /* No dictionary used. */
+ if (dctx->dictContentEndForFuzzing == NULL) return 0;
+ /* Dictionary is our prefix. */
+ if (prefixStart == dctx->dictContentBeginForFuzzing) return 1;
+ /* Dictionary is not our ext-dict. */
+ if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0;
+ /* Dictionary is not within our window size. */
+ if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0;
+ /* Dictionary is active. */
+ return 1;
+}
+
+MEM_STATIC void ZSTD_assertValidSequence(
+ ZSTD_DCtx const* dctx,
+ BYTE const* op, BYTE const* oend,
+ seq_t const seq,
+ BYTE const* prefixStart, BYTE const* virtualStart)
+{
+#if DEBUGLEVEL >= 1
+ size_t const windowSize = dctx->fParams.windowSize;
+ size_t const sequenceSize = seq.litLength + seq.matchLength;
+ BYTE const* const oLitEnd = op + seq.litLength;
+ DEBUGLOG(6, "Checking sequence: litL=%u matchL=%u offset=%u",
+ (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
+ assert(op <= oend);
+ assert((size_t)(oend - op) >= sequenceSize);
+ assert(sequenceSize <= ZSTD_BLOCKSIZE_MAX);
+ if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) {
+ size_t const dictSize = (size_t)((char const*)dctx->dictContentEndForFuzzing - (char const*)dctx->dictContentBeginForFuzzing);
+ /* Offset must be within the dictionary. */
+ assert(seq.offset <= (size_t)(oLitEnd - virtualStart));
+ assert(seq.offset <= windowSize + dictSize);
+ } else {
+ /* Offset must be within our window. */
+ assert(seq.offset <= windowSize);
+ }
+#else
+ (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart;
+#endif
+}
+#endif
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+
+
+FORCE_INLINE_TEMPLATE size_t
+DONT_VECTORIZE
+ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ const BYTE* ip = (const BYTE*)seqStart;
+ const BYTE* const iend = ip + seqSize;
+ BYTE* const ostart = (BYTE*)dst;
+ BYTE* const oend = ostart + maxDstSize;
+ BYTE* op = ostart;
+ const BYTE* litPtr = dctx->litPtr;
+ const BYTE* litBufferEnd = dctx->litBufferEnd;
+ const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
+ const BYTE* const vBase = (const BYTE*) (dctx->virtualStart);
+ const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
+ DEBUGLOG(5, "ZSTD_decompressSequences_bodySplitLitBuffer");
+ (void)frame;
+
+ /* Regen sequences */
+ if (nbSeq) {
+ seqState_t seqState;
+ dctx->fseEntropy = 1;
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
+ RETURN_ERROR_IF(
+ ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
+ corruption_detected, "");
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+ assert(dst != NULL);
+
+ ZSTD_STATIC_ASSERT(
+ BIT_DStream_unfinished < BIT_DStream_completed &&
+ BIT_DStream_endOfBuffer < BIT_DStream_completed &&
+ BIT_DStream_completed < BIT_DStream_overflow);
+
+ /* decompress without overrunning litPtr begins */
+ {
+ seq_t sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ /* Align the decompression loop to 32 + 16 bytes.
+ *
+ * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression
+ * speed swings based on the alignment of the decompression loop. This
+ * performance swing is caused by parts of the decompression loop falling
+ * out of the DSB. The entire decompression loop should fit in the DSB,
+ * when it can't we get much worse performance. You can measure if you've
+ * hit the good case or the bad case with this perf command for some
+ * compressed file test.zst:
+ *
+ * perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \
+ * -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst
+ *
+ * If you see most cycles served out of the MITE you've hit the bad case.
+ * If you see most cycles served out of the DSB you've hit the good case.
+ * If it is pretty even then you may be in an okay case.
+ *
+ * This issue has been reproduced on the following CPUs:
+ * - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9
+ * Use Instruments->Counters to get DSB/MITE cycles.
+ * I never got performance swings, but I was able to
+ * go from the good case of mostly DSB to half of the
+ * cycles served from MITE.
+ * - Coffeelake: Intel i9-9900k
+ * - Coffeelake: Intel i7-9700k
+ *
+ * I haven't been able to reproduce the instability or DSB misses on any
+ * of the following CPUS:
+ * - Haswell
+ * - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH
+ * - Skylake
+ *
+ * Alignment is done for each of the three major decompression loops:
+ * - ZSTD_decompressSequences_bodySplitLitBuffer - presplit section of the literal buffer
+ * - ZSTD_decompressSequences_bodySplitLitBuffer - postsplit section of the literal buffer
+ * - ZSTD_decompressSequences_body
+ * Alignment choices are made to minimize large swings on bad cases and influence on performance
+ * from changes external to this code, rather than to overoptimize on the current commit.
+ *
+ * If you are seeing performance stability this script can help test.
+ * It tests on 4 commits in zstd where I saw performance change.
+ *
+ * https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4
+ */
+#if defined(__x86_64__)
+ __asm__(".p2align 6");
+# if __GNUC__ >= 7
+ /* good for gcc-7, gcc-9, and gcc-11 */
+ __asm__("nop");
+ __asm__(".p2align 5");
+ __asm__("nop");
+ __asm__(".p2align 4");
+# if __GNUC__ == 8 || __GNUC__ == 10
+ /* good for gcc-8 and gcc-10 */
+ __asm__("nop");
+ __asm__(".p2align 3");
+# endif
+# endif
+#endif
+
+ /* Handle the initial state where litBuffer is currently split between dst and litExtraBuffer */
+ for (; litPtr + sequence.litLength <= dctx->litBufferEnd; ) {
+ size_t const oneSeqSize = ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence.litLength - WILDCOPY_OVERLENGTH, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
+#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (UNLIKELY(!--nbSeq))
+ break;
+ BIT_reloadDStream(&(seqState.DStream));
+ sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ }
+
+ /* If there are more sequences, they will need to read literals from litExtraBuffer; copy over the remainder from dst and update litPtr and litEnd */
+ if (nbSeq > 0) {
+ const size_t leftoverLit = dctx->litBufferEnd - litPtr;
+ if (leftoverLit)
+ {
+ RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
+ ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
+ sequence.litLength -= leftoverLit;
+ op += leftoverLit;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ {
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
+#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (--nbSeq)
+ BIT_reloadDStream(&(seqState.DStream));
+ }
+ }
+ }
+
+ if (nbSeq > 0) /* there is remaining lit from extra buffer */
+ {
+
+#if defined(__x86_64__)
+ __asm__(".p2align 6");
+ __asm__("nop");
+# if __GNUC__ != 7
+ /* worse for gcc-7 better for gcc-8, gcc-9, and gcc-10 and clang */
+ __asm__(".p2align 4");
+ __asm__("nop");
+ __asm__(".p2align 3");
+# elif __GNUC__ >= 11
+ __asm__(".p2align 3");
+# else
+ __asm__(".p2align 5");
+ __asm__("nop");
+ __asm__(".p2align 3");
+# endif
+#endif
+
+ for (; ; ) {
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
+#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (UNLIKELY(!--nbSeq))
+ break;
+ BIT_reloadDStream(&(seqState.DStream));
+ }
+ }
+
+ /* check if reached exact end */
+ DEBUGLOG(5, "ZSTD_decompressSequences_bodySplitLitBuffer: after decode loop, remaining nbSeq : %i", nbSeq);
+ RETURN_ERROR_IF(nbSeq, corruption_detected, "");
+ RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, "");
+ /* save reps for next block */
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
+ }
+
+ /* last literal segment */
+ if (dctx->litBufferLocation == ZSTD_split) /* split hasn't been reached yet, first get dst then copy litExtraBuffer */
+ {
+ size_t const lastLLSize = litBufferEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memmove(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ }
+ { size_t const lastLLSize = litBufferEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memcpy(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ }
+
+ return op-ostart;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+DONT_VECTORIZE
+ZSTD_decompressSequences_body(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ const BYTE* ip = (const BYTE*)seqStart;
+ const BYTE* const iend = ip + seqSize;
+ BYTE* const ostart = (BYTE*)dst;
+ BYTE* const oend = dctx->litBufferLocation == ZSTD_not_in_dst ? ostart + maxDstSize : dctx->litBuffer;
+ BYTE* op = ostart;
+ const BYTE* litPtr = dctx->litPtr;
+ const BYTE* const litEnd = litPtr + dctx->litSize;
+ const BYTE* const prefixStart = (const BYTE*)(dctx->prefixStart);
+ const BYTE* const vBase = (const BYTE*)(dctx->virtualStart);
+ const BYTE* const dictEnd = (const BYTE*)(dctx->dictEnd);
+ DEBUGLOG(5, "ZSTD_decompressSequences_body");
+ (void)frame;
+
+ /* Regen sequences */
+ if (nbSeq) {
+ seqState_t seqState;
+ dctx->fseEntropy = 1;
+ { U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
+ RETURN_ERROR_IF(
+ ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend - ip)),
+ corruption_detected, "");
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+ assert(dst != NULL);
+
+ ZSTD_STATIC_ASSERT(
+ BIT_DStream_unfinished < BIT_DStream_completed &&
+ BIT_DStream_endOfBuffer < BIT_DStream_completed &&
+ BIT_DStream_completed < BIT_DStream_overflow);
+
+#if defined(__x86_64__)
+ __asm__(".p2align 6");
+ __asm__("nop");
+# if __GNUC__ >= 7
+ __asm__(".p2align 5");
+ __asm__("nop");
+ __asm__(".p2align 3");
+# else
+ __asm__(".p2align 4");
+ __asm__("nop");
+ __asm__(".p2align 3");
+# endif
+#endif
+
+ for ( ; ; ) {
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
+#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (UNLIKELY(!--nbSeq))
+ break;
+ BIT_reloadDStream(&(seqState.DStream));
+ }
+
+ /* check if reached exact end */
+ DEBUGLOG(5, "ZSTD_decompressSequences_body: after decode loop, remaining nbSeq : %i", nbSeq);
+ RETURN_ERROR_IF(nbSeq, corruption_detected, "");
+ RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, "");
+ /* save reps for next block */
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
+ }
+
+ /* last literal segment */
+ { size_t const lastLLSize = litEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memcpy(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ }
+
+ return op-ostart;
+}
+
+static size_t
+ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+
+static size_t
+ZSTD_decompressSequencesSplitLitBuffer_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,
+ const BYTE* const prefixStart, const BYTE* const dictEnd)
+{
+ prefetchPos += sequence.litLength;
+ { const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart;
+ const BYTE* const match = matchBase + prefetchPos - sequence.offset; /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.
+ * No consequence though : memory address is only used for prefetching, not for dereferencing */
+ PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE); /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */
+ }
+ return prefetchPos + sequence.matchLength;
+}
+
+/* This decoding function employs prefetching
+ * to reduce latency impact of cache misses.
+ * It's generally employed when block contains a significant portion of long-distance matches
+ * or when coupled with a "cold" dictionary */
+FORCE_INLINE_TEMPLATE size_t
+ZSTD_decompressSequencesLong_body(
+ ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ const BYTE* ip = (const BYTE*)seqStart;
+ const BYTE* const iend = ip + seqSize;
+ BYTE* const ostart = (BYTE*)dst;
+ BYTE* const oend = dctx->litBufferLocation == ZSTD_in_dst ? dctx->litBuffer : ostart + maxDstSize;
+ BYTE* op = ostart;
+ const BYTE* litPtr = dctx->litPtr;
+ const BYTE* litBufferEnd = dctx->litBufferEnd;
+ const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
+ const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart);
+ const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
+ (void)frame;
+
+ /* Regen sequences */
+ if (nbSeq) {
+#define STORED_SEQS 8
+#define STORED_SEQS_MASK (STORED_SEQS-1)
+#define ADVANCED_SEQS STORED_SEQS
+ seq_t sequences[STORED_SEQS];
+ int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);
+ seqState_t seqState;
+ int seqNb;
+ size_t prefetchPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */
+
+ dctx->fseEntropy = 1;
+ { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
+ assert(dst != NULL);
+ assert(iend >= ip);
+ RETURN_ERROR_IF(
+ ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),
+ corruption_detected, "");
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+
+ /* prepare in advance */
+ for (seqNb=0; (BIT_reloadDStream(&seqState.DStream) <= BIT_DStream_completed) && (seqNb<seqAdvance); seqNb++) {
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
+ sequences[seqNb] = sequence;
+ }
+ RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, "");
+
+ /* decompress without stomping litBuffer */
+ for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb < nbSeq); seqNb++) {
+ seq_t sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ size_t oneSeqSize;
+
+ if (dctx->litBufferLocation == ZSTD_split && litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength > dctx->litBufferEnd)
+ {
+ /* lit buffer is reaching split point, empty out the first buffer and transition to litExtraBuffer */
+ const size_t leftoverLit = dctx->litBufferEnd - litPtr;
+ if (leftoverLit)
+ {
+ RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
+ ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
+ sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength -= leftoverLit;
+ op += leftoverLit;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
+#endif
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+
+ prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
+ sequences[seqNb & STORED_SEQS_MASK] = sequence;
+ op += oneSeqSize;
+ }
+ else
+ {
+ /* lit buffer is either wholly contained in first or second split, or not split at all*/
+ oneSeqSize = dctx->litBufferLocation == ZSTD_split ?
+ ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength - WILDCOPY_OVERLENGTH, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :
+ ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
+#endif
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+
+ prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
+ sequences[seqNb & STORED_SEQS_MASK] = sequence;
+ op += oneSeqSize;
+ }
+ }
+ RETURN_ERROR_IF(seqNb<nbSeq, corruption_detected, "");
+
+ /* finish queue */
+ seqNb -= seqAdvance;
+ for ( ; seqNb<nbSeq ; seqNb++) {
+ seq_t *sequence = &(sequences[seqNb&STORED_SEQS_MASK]);
+ if (dctx->litBufferLocation == ZSTD_split && litPtr + sequence->litLength > dctx->litBufferEnd)
+ {
+ const size_t leftoverLit = dctx->litBufferEnd - litPtr;
+ if (leftoverLit)
+ {
+ RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
+ ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
+ sequence->litLength -= leftoverLit;
+ op += leftoverLit;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ {
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);
+#endif
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ op += oneSeqSize;
+ }
+ }
+ else
+ {
+ size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ?
+ ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence->litLength - WILDCOPY_OVERLENGTH, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :
+ ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);
+#endif
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ op += oneSeqSize;
+ }
+ }
+
+ /* save reps for next block */
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
+ }
+
+ /* last literal segment */
+ if (dctx->litBufferLocation == ZSTD_split) /* first deplete literal buffer in dst, then copy litExtraBuffer */
+ {
+ size_t const lastLLSize = litBufferEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memmove(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ }
+ { size_t const lastLLSize = litBufferEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memmove(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ }
+
+ return op-ostart;
+}
+
+static size_t
+ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
+
+
+
+#if DYNAMIC_BMI2
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+static BMI2_TARGET_ATTRIBUTE size_t
+DONT_VECTORIZE
+ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+static BMI2_TARGET_ATTRIBUTE size_t
+DONT_VECTORIZE
+ZSTD_decompressSequencesSplitLitBuffer_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+static BMI2_TARGET_ATTRIBUTE size_t
+ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
+
+#endif /* DYNAMIC_BMI2 */
+
+typedef size_t (*ZSTD_decompressSequences_t)(
+ ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame);
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+static size_t
+ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequences");
+#if DYNAMIC_BMI2
+ if (ZSTD_DCtx_get_bmi2(dctx)) {
+ return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+ }
+#endif
+ return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+static size_t
+ZSTD_decompressSequencesSplitLitBuffer(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequencesSplitLitBuffer");
+#if DYNAMIC_BMI2
+ if (ZSTD_DCtx_get_bmi2(dctx)) {
+ return ZSTD_decompressSequencesSplitLitBuffer_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+ }
+#endif
+ return ZSTD_decompressSequencesSplitLitBuffer_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
+
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+/* ZSTD_decompressSequencesLong() :
+ * decompression function triggered when a minimum share of offsets is considered "long",
+ * aka out of cache.
+ * note : "long" definition seems overloaded here, sometimes meaning "wider than bitstream register", and sometimes meaning "farther than memory cache distance".
+ * This function will try to mitigate main memory latency through the use of prefetching */
+static size_t
+ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequencesLong");
+#if DYNAMIC_BMI2
+ if (ZSTD_DCtx_get_bmi2(dctx)) {
+ return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+ }
+#endif
+ return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */
+
+
+
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+/* ZSTD_getLongOffsetsShare() :
+ * condition : offTable must be valid
+ * @return : "share" of long offsets (arbitrarily defined as > (1<<23))
+ * compared to maximum possible of (1<<OffFSELog) */
+static unsigned
+ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable)
+{
+ const void* ptr = offTable;
+ U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;
+ const ZSTD_seqSymbol* table = offTable + 1;
+ U32 const max = 1 << tableLog;
+ U32 u, total = 0;
+ DEBUGLOG(5, "ZSTD_getLongOffsetsShare: (tableLog=%u)", tableLog);
+
+ assert(max <= (1 << OffFSELog)); /* max not too large */
+ for (u=0; u<max; u++) {
+ if (table[u].nbAdditionalBits > 22) total += 1;
+ }
+
+ assert(tableLog <= OffFSELog);
+ total <<= (OffFSELog - tableLog); /* scale to OffFSELog */
+
+ return total;
+}
+#endif
+
+size_t
+ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, const int frame, const streaming_operation streaming)
+{ /* blockType == blockCompressed */
+ const BYTE* ip = (const BYTE*)src;
+ /* isLongOffset must be true if there are long offsets.
+ * Offsets are long if they are larger than 2^STREAM_ACCUMULATOR_MIN.
+ * We don't expect that to be the case in 64-bit mode.
+ * In block mode, window size is not known, so we have to be conservative.
+ * (note: but it could be evaluated from current-lowLimit)
+ */
+ ZSTD_longOffset_e const isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (!frame || (dctx->fParams.windowSize > (1ULL << STREAM_ACCUMULATOR_MIN))));
+ DEBUGLOG(5, "ZSTD_decompressBlock_internal (size : %u)", (U32)srcSize);
+
+ RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong, "");
+
+ /* Decode literals section */
+ { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, streaming);
+ DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
+ if (ZSTD_isError(litCSize)) return litCSize;
+ ip += litCSize;
+ srcSize -= litCSize;
+ }
+
+ /* Build Decoding Tables */
+ {
+ /* These macros control at build-time which decompressor implementation
+ * we use. If neither is defined, we do some inspection and dispatch at
+ * runtime.
+ */
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+ int usePrefetchDecoder = dctx->ddictIsCold;
+#endif
+ int nbSeq;
+ size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);
+ if (ZSTD_isError(seqHSize)) return seqHSize;
+ ip += seqHSize;
+ srcSize -= seqHSize;
+
+ RETURN_ERROR_IF(dst == NULL && nbSeq > 0, dstSize_tooSmall, "NULL not handled");
+
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+ if ( !usePrefetchDecoder
+ && (!frame || (dctx->fParams.windowSize > (1<<24)))
+ && (nbSeq>ADVANCED_SEQS) ) { /* could probably use a larger nbSeq limit */
+ U32 const shareLongOffsets = ZSTD_getLongOffsetsShare(dctx->OFTptr);
+ U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */
+ usePrefetchDecoder = (shareLongOffsets >= minShare);
+ }
+#endif
+
+ dctx->ddictIsCold = 0;
+
+#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \
+ !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)
+ if (usePrefetchDecoder)
+#endif
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
+ return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
+#endif
+
+#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+ /* else */
+ if (dctx->litBufferLocation == ZSTD_split)
+ return ZSTD_decompressSequencesSplitLitBuffer(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
+ else
+ return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
+#endif
+ }
+}
+
+
+void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)
+{
+ if (dst != dctx->previousDstEnd && dstSize > 0) { /* not contiguous */
+ dctx->dictEnd = dctx->previousDstEnd;
+ dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));
+ dctx->prefixStart = dst;
+ dctx->previousDstEnd = dst;
+ }
+}
+
+
+size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize)
+{
+ size_t dSize;
+ ZSTD_checkContinuity(dctx, dst, dstCapacity);
+ dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0, not_streaming);
+ dctx->previousDstEnd = (char*)dst + dSize;
+ return dSize;
+}
diff --git a/lib/zstd/decompress/zstd_decompress_block.h b/lib/zstd/decompress/zstd_decompress_block.h
new file mode 100644
index 0000000..3d2d57a
--- /dev/null
+++ b/lib/zstd/decompress/zstd_decompress_block.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+#ifndef ZSTD_DEC_BLOCK_H
+#define ZSTD_DEC_BLOCK_H
+
+/*-*******************************************************
+ * Dependencies
+ *********************************************************/
+#include "../common/zstd_deps.h" /* size_t */
+#include <linux/zstd.h> /* DCtx, and some public functions */
+#include "../common/zstd_internal.h" /* blockProperties_t, and some public functions */
+#include "zstd_decompress_internal.h" /* ZSTD_seqSymbol */
+
+
+/* === Prototypes === */
+
+/* note: prototypes already published within `zstd.h` :
+ * ZSTD_decompressBlock()
+ */
+
+/* note: prototypes already published within `zstd_internal.h` :
+ * ZSTD_getcBlockSize()
+ * ZSTD_decodeSeqHeaders()
+ */
+
+
+ /* Streaming state is used to inform allocation of the literal buffer */
+typedef enum {
+ not_streaming = 0,
+ is_streaming = 1
+} streaming_operation;
+
+/* ZSTD_decompressBlock_internal() :
+ * decompress block, starting at `src`,
+ * into destination buffer `dst`.
+ * @return : decompressed block size,
+ * or an error code (which can be tested using ZSTD_isError())
+ */
+size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, const int frame, const streaming_operation streaming);
+
+/* ZSTD_buildFSETable() :
+ * generate FSE decoding table for one symbol (ll, ml or off)
+ * this function must be called with valid parameters only
+ * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.)
+ * in which case it cannot fail.
+ * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is
+ * defined in zstd_decompress_internal.h.
+ * Internal use only.
+ */
+void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
+ const short* normalizedCounter, unsigned maxSymbolValue,
+ const U32* baseValue, const U8* nbAdditionalBits,
+ unsigned tableLog, void* wksp, size_t wkspSize,
+ int bmi2);
+
+
+#endif /* ZSTD_DEC_BLOCK_H */
diff --git a/lib/zstd/decompress/zstd_decompress_internal.h b/lib/zstd/decompress/zstd_decompress_internal.h
new file mode 100644
index 0000000..98102ed
--- /dev/null
+++ b/lib/zstd/decompress/zstd_decompress_internal.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+
+/* zstd_decompress_internal:
+ * objects and definitions shared within lib/decompress modules */
+
+ #ifndef ZSTD_DECOMPRESS_INTERNAL_H
+ #define ZSTD_DECOMPRESS_INTERNAL_H
+
+
+/*-*******************************************************
+ * Dependencies
+ *********************************************************/
+#include "../common/mem.h" /* BYTE, U16, U32 */
+#include "../common/zstd_internal.h" /* constants : MaxLL, MaxML, MaxOff, LLFSELog, etc. */
+
+
+
+/*-*******************************************************
+ * Constants
+ *********************************************************/
+static UNUSED_ATTR const U32 LL_base[MaxLL+1] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 18, 20, 22, 24, 28, 32, 40,
+ 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,
+ 0x2000, 0x4000, 0x8000, 0x10000 };
+
+static UNUSED_ATTR const U32 OF_base[MaxOff+1] = {
+ 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D,
+ 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD,
+ 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
+ 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
+
+static UNUSED_ATTR const U8 OF_bits[MaxOff+1] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31 };
+
+static UNUSED_ATTR const U32 ML_base[MaxML+1] = {
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 37, 39, 41, 43, 47, 51, 59,
+ 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,
+ 0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };
+
+
+/*-*******************************************************
+ * Decompression types
+ *********************************************************/
+ typedef struct {
+ U32 fastMode;
+ U32 tableLog;
+ } ZSTD_seqSymbol_header;
+
+ typedef struct {
+ U16 nextState;
+ BYTE nbAdditionalBits;
+ BYTE nbBits;
+ U32 baseValue;
+ } ZSTD_seqSymbol;
+
+ #define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log)))
+
+#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64))
+#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32))
+
+typedef struct {
+ ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */
+ ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */
+ ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */
+ HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */
+ U32 rep[ZSTD_REP_NUM];
+ U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32];
+} ZSTD_entropyDTables_t;
+
+typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,
+ ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,
+ ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,
+ ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;
+
+typedef enum { zdss_init=0, zdss_loadHeader,
+ zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;
+
+typedef enum {
+ ZSTD_use_indefinitely = -1, /* Use the dictionary indefinitely */
+ ZSTD_dont_use = 0, /* Do not use the dictionary (if one exists free it) */
+ ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */
+} ZSTD_dictUses_e;
+
+/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */
+typedef struct {
+ const ZSTD_DDict** ddictPtrTable;
+ size_t ddictPtrTableSize;
+ size_t ddictPtrCount;
+} ZSTD_DDictHashSet;
+
+#ifndef ZSTD_DECODER_INTERNAL_BUFFER
+# define ZSTD_DECODER_INTERNAL_BUFFER (1 << 16)
+#endif
+
+#define ZSTD_LBMIN 64
+#define ZSTD_LBMAX (128 << 10)
+
+/* extra buffer, compensates when dst is not large enough to store litBuffer */
+#define ZSTD_LITBUFFEREXTRASIZE BOUNDED(ZSTD_LBMIN, ZSTD_DECODER_INTERNAL_BUFFER, ZSTD_LBMAX)
+
+typedef enum {
+ ZSTD_not_in_dst = 0, /* Stored entirely within litExtraBuffer */
+ ZSTD_in_dst = 1, /* Stored entirely within dst (in memory after current output write) */
+ ZSTD_split = 2 /* Split between litExtraBuffer and dst */
+} ZSTD_litLocation_e;
+
+struct ZSTD_DCtx_s
+{
+ const ZSTD_seqSymbol* LLTptr;
+ const ZSTD_seqSymbol* MLTptr;
+ const ZSTD_seqSymbol* OFTptr;
+ const HUF_DTable* HUFptr;
+ ZSTD_entropyDTables_t entropy;
+ U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; /* space needed when building huffman tables */
+ const void* previousDstEnd; /* detect continuity */
+ const void* prefixStart; /* start of current segment */
+ const void* virtualStart; /* virtual start of previous segment if it was just before current one */
+ const void* dictEnd; /* end of previous segment */
+ size_t expected;
+ ZSTD_frameHeader fParams;
+ U64 processedCSize;
+ U64 decodedSize;
+ blockType_e bType; /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */
+ ZSTD_dStage stage;
+ U32 litEntropy;
+ U32 fseEntropy;
+ struct xxh64_state xxhState;
+ size_t headerSize;
+ ZSTD_format_e format;
+ ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum; /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */
+ U32 validateChecksum; /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */
+ const BYTE* litPtr;
+ ZSTD_customMem customMem;
+ size_t litSize;
+ size_t rleSize;
+ size_t staticSize;
+#if DYNAMIC_BMI2 != 0
+ int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
+#endif
+
+ /* dictionary */
+ ZSTD_DDict* ddictLocal;
+ const ZSTD_DDict* ddict; /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */
+ U32 dictID;
+ int ddictIsCold; /* if == 1 : dictionary is "new" for working context, and presumed "cold" (not in cpu cache) */
+ ZSTD_dictUses_e dictUses;
+ ZSTD_DDictHashSet* ddictSet; /* Hash set for multiple ddicts */
+ ZSTD_refMultipleDDicts_e refMultipleDDicts; /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */
+
+ /* streaming */
+ ZSTD_dStreamStage streamStage;
+ char* inBuff;
+ size_t inBuffSize;
+ size_t inPos;
+ size_t maxWindowSize;
+ char* outBuff;
+ size_t outBuffSize;
+ size_t outStart;
+ size_t outEnd;
+ size_t lhSize;
+ U32 hostageByte;
+ int noForwardProgress;
+ ZSTD_bufferMode_e outBufferMode;
+ ZSTD_outBuffer expectedOutBuffer;
+
+ /* workspace */
+ BYTE* litBuffer;
+ const BYTE* litBufferEnd;
+ ZSTD_litLocation_e litBufferLocation;
+ BYTE litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE + WILDCOPY_OVERLENGTH]; /* literal buffer can be split between storage within dst and within this scratch buffer */
+ BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
+
+ size_t oversizedDuration;
+
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ void const* dictContentBeginForFuzzing;
+ void const* dictContentEndForFuzzing;
+#endif
+
+ /* Tracing */
+}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
+
+MEM_STATIC int ZSTD_DCtx_get_bmi2(const struct ZSTD_DCtx_s *dctx) {
+#if DYNAMIC_BMI2 != 0
+ return dctx->bmi2;
+#else
+ (void)dctx;
+ return 0;
+#endif
+}
+
+/*-*******************************************************
+ * Shared internal functions
+ *********************************************************/
+
+/*! ZSTD_loadDEntropy() :
+ * dict : must point at beginning of a valid zstd dictionary.
+ * @return : size of dictionary header (size of magic number + dict ID + entropy tables) */
+size_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,
+ const void* const dict, size_t const dictSize);
+
+/*! ZSTD_checkContinuity() :
+ * check if next `dst` follows previous position, where decompression ended.
+ * If yes, do nothing (continue on current segment).
+ * If not, classify previous segment as "external dictionary", and start a new segment.
+ * This function cannot fail. */
+void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize);
+
+
+#endif /* ZSTD_DECOMPRESS_INTERNAL_H */
diff --git a/lib/zstd/decompress_sources.h b/lib/zstd/decompress_sources.h
new file mode 100644
index 0000000..a06ca18
--- /dev/null
+++ b/lib/zstd/decompress_sources.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+/*
+ * This file includes every .c file needed for decompression.
+ * It is used by lib/decompress_unzstd.c to include the decompression
+ * source into the translation-unit, so it can be used for kernel
+ * decompression.
+ */
+
+/*
+ * Disable the ASM Huffman implementation because we need to
+ * include all the sources.
+ */
+#define ZSTD_DISABLE_ASM 1
+
+#include "common/debug.c"
+#include "common/entropy_common.c"
+#include "common/error_private.c"
+#include "common/fse_decompress.c"
+#include "common/zstd_common.c"
+#include "decompress/huf_decompress.c"
+#include "decompress/zstd_ddict.c"
+#include "decompress/zstd_decompress.c"
+#include "decompress/zstd_decompress_block.c"
+#include "zstd_decompress_module.c"
diff --git a/lib/zstd/entropy_common.c b/lib/zstd/entropy_common.c
deleted file mode 100644
index 071fef9..0000000
--- a/lib/zstd/entropy_common.c
+++ /dev/null
@@ -1,213 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
-/*
- * Common functions of New Generation Entropy library
- * Copyright (C) 2016, Yann Collet.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- */
-
-/* *************************************
-* Dependencies
-***************************************/
-#include "error_private.h" /* ERR_*, ERROR */
-#include "fse.h"
-#include "huf.h"
-#include "mem.h"
-
-/*=== Version ===*/
-unsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }
-
-/*=== Error Management ===*/
-unsigned FSE_isError(size_t code) { return ERR_isError(code); }
-
-unsigned HUF_isError(size_t code) { return ERR_isError(code); }
-
-/*-**************************************************************
-* FSE NCount encoding-decoding
-****************************************************************/
-size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSVPtr, unsigned *tableLogPtr, const void *headerBuffer, size_t hbSize)
-{
- const BYTE *const istart = (const BYTE *)headerBuffer;
- const BYTE *const iend = istart + hbSize;
- const BYTE *ip = istart;
- int nbBits;
- int remaining;
- int threshold;
- U32 bitStream;
- int bitCount;
- unsigned charnum = 0;
- int previous0 = 0;
-
- if (hbSize < 4)
- return ERROR(srcSize_wrong);
- bitStream = ZSTD_readLE32(ip);
- nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */
- if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX)
- return ERROR(tableLog_tooLarge);
- bitStream >>= 4;
- bitCount = 4;
- *tableLogPtr = nbBits;
- remaining = (1 << nbBits) + 1;
- threshold = 1 << nbBits;
- nbBits++;
-
- while ((remaining > 1) & (charnum <= *maxSVPtr)) {
- if (previous0) {
- unsigned n0 = charnum;
- while ((bitStream & 0xFFFF) == 0xFFFF) {
- n0 += 24;
- if (ip < iend - 5) {
- ip += 2;
- bitStream = ZSTD_readLE32(ip) >> bitCount;
- } else {
- bitStream >>= 16;
- bitCount += 16;
- }
- }
- while ((bitStream & 3) == 3) {
- n0 += 3;
- bitStream >>= 2;
- bitCount += 2;
- }
- n0 += bitStream & 3;
- bitCount += 2;
- if (n0 > *maxSVPtr)
- return ERROR(maxSymbolValue_tooSmall);
- while (charnum < n0)
- normalizedCounter[charnum++] = 0;
- if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
- ip += bitCount >> 3;
- bitCount &= 7;
- bitStream = ZSTD_readLE32(ip) >> bitCount;
- } else {
- bitStream >>= 2;
- }
- }
- {
- int const max = (2 * threshold - 1) - remaining;
- int count;
-
- if ((bitStream & (threshold - 1)) < (U32)max) {
- count = bitStream & (threshold - 1);
- bitCount += nbBits - 1;
- } else {
- count = bitStream & (2 * threshold - 1);
- if (count >= threshold)
- count -= max;
- bitCount += nbBits;
- }
-
- count--; /* extra accuracy */
- remaining -= count < 0 ? -count : count; /* -1 means +1 */
- normalizedCounter[charnum++] = (short)count;
- previous0 = !count;
- while (remaining < threshold) {
- nbBits--;
- threshold >>= 1;
- }
-
- if ((ip <= iend - 7) || (ip + (bitCount >> 3) <= iend - 4)) {
- ip += bitCount >> 3;
- bitCount &= 7;
- } else {
- bitCount -= (int)(8 * (iend - 4 - ip));
- ip = iend - 4;
- }
- bitStream = ZSTD_readLE32(ip) >> (bitCount & 31);
- }
- } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
- if (remaining != 1)
- return ERROR(corruption_detected);
- if (bitCount > 32)
- return ERROR(corruption_detected);
- *maxSVPtr = charnum - 1;
-
- ip += (bitCount + 7) >> 3;
- return ip - istart;
-}
-
-/*! HUF_readStats() :
- Read compact Huffman tree, saved by HUF_writeCTable().
- `huffWeight` is destination buffer.
- `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.
- @return : size read from `src` , or an error Code .
- Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
-*/
-size_t HUF_readStats_wksp(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
-{
- U32 weightTotal;
- const BYTE *ip = (const BYTE *)src;
- size_t iSize;
- size_t oSize;
-
- if (!srcSize)
- return ERROR(srcSize_wrong);
- iSize = ip[0];
- /* memset(huffWeight, 0, hwSize); */ /* is not necessary, even though some analyzer complain ... */
-
- if (iSize >= 128) { /* special header */
- oSize = iSize - 127;
- iSize = ((oSize + 1) / 2);
- if (iSize + 1 > srcSize)
- return ERROR(srcSize_wrong);
- if (oSize >= hwSize)
- return ERROR(corruption_detected);
- ip += 1;
- {
- U32 n;
- for (n = 0; n < oSize; n += 2) {
- huffWeight[n] = ip[n / 2] >> 4;
- huffWeight[n + 1] = ip[n / 2] & 15;
- }
- }
- } else { /* header compressed with FSE (normal case) */
- if (iSize + 1 > srcSize)
- return ERROR(srcSize_wrong);
- oSize = FSE_decompress_wksp(huffWeight, hwSize - 1, ip + 1, iSize, 6, workspace, workspaceSize); /* max (hwSize-1) values decoded, as last one is implied */
- if (FSE_isError(oSize))
- return oSize;
- }
-
- /* collect weight stats */
- memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
- weightTotal = 0;
- {
- U32 n;
- for (n = 0; n < oSize; n++) {
- if (huffWeight[n] >= HUF_TABLELOG_MAX)
- return ERROR(corruption_detected);
- rankStats[huffWeight[n]]++;
- weightTotal += (1 << huffWeight[n]) >> 1;
- }
- }
- if (weightTotal == 0)
- return ERROR(corruption_detected);
-
- /* get last non-null symbol weight (implied, total must be 2^n) */
- {
- U32 const tableLog = BIT_highbit32(weightTotal) + 1;
- if (tableLog > HUF_TABLELOG_MAX)
- return ERROR(corruption_detected);
- *tableLogPtr = tableLog;
- /* determine last weight */
- {
- U32 const total = 1 << tableLog;
- U32 const rest = total - weightTotal;
- U32 const verif = 1 << BIT_highbit32(rest);
- U32 const lastWeight = BIT_highbit32(rest) + 1;
- if (verif != rest)
- return ERROR(corruption_detected); /* last value must be a clean power of 2 */
- huffWeight[oSize] = (BYTE)lastWeight;
- rankStats[lastWeight]++;
- }
- }
-
- /* check tree construction validity */
- if ((rankStats[1] < 2) || (rankStats[1] & 1))
- return ERROR(corruption_detected); /* by construction : at least 2 elts of rank 1, must be even */
-
- /* results */
- *nbSymbolsPtr = (U32)(oSize + 1);
- return iSize + 1;
-}
diff --git a/lib/zstd/error_private.h b/lib/zstd/error_private.h
deleted file mode 100644
index d4824e2..0000000
--- a/lib/zstd/error_private.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
-/**
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
- * All rights reserved.
- */
-
-/* Note : this module is expected to remain private, do not expose it */
-
-#ifndef ERROR_H_MODULE
-#define ERROR_H_MODULE
-
-/* ****************************************
-* Dependencies
-******************************************/
-#include <linux/types.h> /* size_t */
-#include <linux/zstd.h> /* enum list */
-
-/* ****************************************
-* Compiler-specific
-******************************************/
-#define ERR_STATIC static __attribute__((unused))
-
-/*-****************************************
-* Customization (error_public.h)
-******************************************/
-typedef ZSTD_ErrorCode ERR_enum;
-#define PREFIX(name) ZSTD_error_##name
-
-/*-****************************************
-* Error codes handling
-******************************************/
-#define ERROR(name) ((size_t)-PREFIX(name))
-
-ERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }
-
-ERR_STATIC ERR_enum ERR_getErrorCode(size_t code)
-{
- if (!ERR_isError(code))
- return (ERR_enum)0;
- return (ERR_enum)(0 - code);
-}
-
-#endif /* ERROR_H_MODULE */
diff --git a/lib/zstd/fse.h b/lib/zstd/fse.h
deleted file mode 100644
index 42f80ff..0000000
--- a/lib/zstd/fse.h
+++ /dev/null
@@ -1,545 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause) */
-/*
- * FSE : Finite State Entropy codec
- * Public Prototypes declaration
- * Copyright (C) 2013-2016, Yann Collet.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- */
-#ifndef FSE_H
-#define FSE_H
-
-/*-*****************************************
-* Dependencies
-******************************************/
-#include <linux/types.h> /* size_t, ptrdiff_t */
-
-/*-*****************************************
-* FSE_PUBLIC_API : control library symbols visibility
-******************************************/
-#define FSE_PUBLIC_API
-
-/*------ Version ------*/
-#define FSE_VERSION_MAJOR 0
-#define FSE_VERSION_MINOR 9
-#define FSE_VERSION_RELEASE 0
-
-#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE
-#define FSE_QUOTE(str) #str
-#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)
-#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)
-
-#define FSE_VERSION_NUMBER (FSE_VERSION_MAJOR * 100 * 100 + FSE_VERSION_MINOR * 100 + FSE_VERSION_RELEASE)
-FSE_PUBLIC_API unsigned FSE_versionNumber(void); /**< library version number; to be used when checking dll version */
-
-/*-*****************************************
-* Tool functions
-******************************************/
-FSE_PUBLIC_API size_t FSE_compressBound(size_t size); /* maximum compressed size */
-
-/* Error Management */
-FSE_PUBLIC_API unsigned FSE_isError(size_t code); /* tells if a return value is an error code */
-
-/*-*****************************************
-* FSE detailed API
-******************************************/
-/*!
-FSE_compress() does the following:
-1. count symbol occurrence from source[] into table count[]
-2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)
-3. save normalized counters to memory buffer using writeNCount()
-4. build encoding table 'CTable' from normalized counters
-5. encode the data stream using encoding table 'CTable'
-
-FSE_decompress() does the following:
-1. read normalized counters with readNCount()
-2. build decoding table 'DTable' from normalized counters
-3. decode the data stream using decoding table 'DTable'
-
-The following API allows targeting specific sub-functions for advanced tasks.
-For example, it's possible to compress several blocks using the same 'CTable',
-or to save and provide normalized distribution using external method.
-*/
-
-/* *** COMPRESSION *** */
-/*! FSE_optimalTableLog():
- dynamically downsize 'tableLog' when conditions are met.
- It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.
- @return : recommended tableLog (necessarily <= 'maxTableLog') */
-FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
-
-/*! FSE_normalizeCount():
- normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)
- 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).
- @return : tableLog,
- or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_normalizeCount(short *normalizedCounter, unsigned tableLog, const unsigned *count, size_t srcSize, unsigned maxSymbolValue);
-
-/*! FSE_NCountWriteBound():
- Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.
- Typically useful for allocation purpose. */
-FSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);
-
-/*! FSE_writeNCount():
- Compactly save 'normalizedCounter' into 'buffer'.
- @return : size of the compressed table,
- or an errorCode, which can be tested using FSE_isError(). */
-FSE_PUBLIC_API size_t FSE_writeNCount(void *buffer, size_t bufferSize, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);
-
-/*! Constructor and Destructor of FSE_CTable.
- Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */
-typedef unsigned FSE_CTable; /* don't allocate that. It's only meant to be more restrictive than void* */
-
-/*! FSE_compress_usingCTable():
- Compress `src` using `ct` into `dst` which must be already allocated.
- @return : size of compressed data (<= `dstCapacity`),
- or 0 if compressed data could not fit into `dst`,
- or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_compress_usingCTable(void *dst, size_t dstCapacity, const void *src, size_t srcSize, const FSE_CTable *ct);
-
-/*!
-Tutorial :
-----------
-The first step is to count all symbols. FSE_count() does this job very fast.
-Result will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.
-'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]
-maxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)
-FSE_count() will return the number of occurrence of the most frequent symbol.
-This can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.
-If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
-
-The next step is to normalize the frequencies.
-FSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.
-It also guarantees a minimum of 1 to any Symbol with frequency >= 1.
-You can use 'tableLog'==0 to mean "use default tableLog value".
-If you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),
-which will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means "default").
-
-The result of FSE_normalizeCount() will be saved into a table,
-called 'normalizedCounter', which is a table of signed short.
-'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.
-The return value is tableLog if everything proceeded as expected.
-It is 0 if there is a single symbol within distribution.
-If there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).
-
-'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().
-'buffer' must be already allocated.
-For guaranteed success, buffer size must be at least FSE_headerBound().
-The result of the function is the number of bytes written into 'buffer'.
-If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).
-
-'normalizedCounter' can then be used to create the compression table 'CTable'.
-The space required by 'CTable' must be already allocated, using FSE_createCTable().
-You can then use FSE_buildCTable() to fill 'CTable'.
-If there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).
-
-'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().
-Similar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'
-The function returns the size of compressed data (without header), necessarily <= `dstCapacity`.
-If it returns '0', compressed data could not fit into 'dst'.
-If there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).
-*/
-
-/* *** DECOMPRESSION *** */
-
-/*! FSE_readNCount():
- Read compactly saved 'normalizedCounter' from 'rBuffer'.
- @return : size read from 'rBuffer',
- or an errorCode, which can be tested using FSE_isError().
- maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */
-FSE_PUBLIC_API size_t FSE_readNCount(short *normalizedCounter, unsigned *maxSymbolValuePtr, unsigned *tableLogPtr, const void *rBuffer, size_t rBuffSize);
-
-/*! Constructor and Destructor of FSE_DTable.
- Note that its size depends on 'tableLog' */
-typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */
-
-/*! FSE_buildDTable():
- Builds 'dt', which must be already allocated, using FSE_createDTable().
- return : 0, or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize);
-
-/*! FSE_decompress_usingDTable():
- Decompress compressed source `cSrc` of size `cSrcSize` using `dt`
- into `dst` which must be already allocated.
- @return : size of regenerated data (necessarily <= `dstCapacity`),
- or an errorCode, which can be tested using FSE_isError() */
-FSE_PUBLIC_API size_t FSE_decompress_usingDTable(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt);
-
-/*!
-Tutorial :
-----------
-(Note : these functions only decompress FSE-compressed blocks.
- If block is uncompressed, use memcpy() instead
- If block is a single repeated byte, use memset() instead )
-
-The first step is to obtain the normalized frequencies of symbols.
-This can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().
-'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.
-In practice, that means it's necessary to know 'maxSymbolValue' beforehand,
-or size the table to handle worst case situations (typically 256).
-FSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.
-The result of FSE_readNCount() is the number of bytes read from 'rBuffer'.
-Note that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.
-If there is an error, the function will return an error code, which can be tested using FSE_isError().
-
-The next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.
-This is performed by the function FSE_buildDTable().
-The space required by 'FSE_DTable' must be already allocated using FSE_createDTable().
-If there is an error, the function will return an error code, which can be tested using FSE_isError().
-
-`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().
-`cSrcSize` must be strictly correct, otherwise decompression will fail.
-FSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).
-If there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)
-*/
-
-/* *** Dependency *** */
-#include "bitstream.h"
-
-/* *****************************************
-* Static allocation
-*******************************************/
-/* FSE buffer bounds */
-#define FSE_NCOUNTBOUND 512
-#define FSE_BLOCKBOUND(size) (size + (size >> 7))
-#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
-
-/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */
-#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1 << (maxTableLog - 1)) + ((maxSymbolValue + 1) * 2))
-#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1 << maxTableLog))
-
-/* *****************************************
-* FSE advanced API
-*******************************************/
-/* FSE_count_wksp() :
- * Same as FSE_count(), but using an externally provided scratch buffer.
- * `workSpace` size must be table of >= `1024` unsigned
- */
-size_t FSE_count_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *source, size_t sourceSize, unsigned *workSpace);
-
-/* FSE_countFast_wksp() :
- * Same as FSE_countFast(), but using an externally provided scratch buffer.
- * `workSpace` must be a table of minimum `1024` unsigned
- */
-size_t FSE_countFast_wksp(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize, unsigned *workSpace);
-
-/*! FSE_count_simple
- * Same as FSE_countFast(), but does not use any additional memory (not even on stack).
- * This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr` (presuming it's also the size of `count`).
-*/
-size_t FSE_count_simple(unsigned *count, unsigned *maxSymbolValuePtr, const void *src, size_t srcSize);
-
-unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);
-/**< same as FSE_optimalTableLog(), which used `minus==2` */
-
-size_t FSE_buildCTable_raw(FSE_CTable *ct, unsigned nbBits);
-/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */
-
-size_t FSE_buildCTable_rle(FSE_CTable *ct, unsigned char symbolValue);
-/**< build a fake FSE_CTable, designed to compress always the same symbolValue */
-
-/* FSE_buildCTable_wksp() :
- * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
- * `wkspSize` must be >= `(1<<tableLog)`.
- */
-size_t FSE_buildCTable_wksp(FSE_CTable *ct, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workSpace, size_t wkspSize);
-
-size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits);
-/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */
-
-size_t FSE_buildDTable_rle(FSE_DTable *dt, unsigned char symbolValue);
-/**< build a fake FSE_DTable, designed to always generate the same symbolValue */
-
-size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workspace, size_t workspaceSize);
-/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */
-
-/* *****************************************
-* FSE symbol compression API
-*******************************************/
-/*!
- This API consists of small unitary functions, which highly benefit from being inlined.
- Hence their body are included in next section.
-*/
-typedef struct {
- ptrdiff_t value;
- const void *stateTable;
- const void *symbolTT;
- unsigned stateLog;
-} FSE_CState_t;
-
-static void FSE_initCState(FSE_CState_t *CStatePtr, const FSE_CTable *ct);
-
-static void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *CStatePtr, unsigned symbol);
-
-static void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *CStatePtr);
-
-/**<
-These functions are inner components of FSE_compress_usingCTable().
-They allow the creation of custom streams, mixing multiple tables and bit sources.
-
-A key property to keep in mind is that encoding and decoding are done **in reverse direction**.
-So the first symbol you will encode is the last you will decode, like a LIFO stack.
-
-You will need a few variables to track your CStream. They are :
-
-FSE_CTable ct; // Provided by FSE_buildCTable()
-BIT_CStream_t bitStream; // bitStream tracking structure
-FSE_CState_t state; // State tracking structure (can have several)
-
-
-The first thing to do is to init bitStream and state.
- size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);
- FSE_initCState(&state, ct);
-
-Note that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();
-You can then encode your input data, byte after byte.
-FSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.
-Remember decoding will be done in reverse direction.
- FSE_encodeByte(&bitStream, &state, symbol);
-
-At any time, you can also add any bit sequence.
-Note : maximum allowed nbBits is 25, for compatibility with 32-bits decoders
- BIT_addBits(&bitStream, bitField, nbBits);
-
-The above methods don't commit data to memory, they just store it into local register, for speed.
-Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).
-Writing data to memory is a manual operation, performed by the flushBits function.
- BIT_flushBits(&bitStream);
-
-Your last FSE encoding operation shall be to flush your last state value(s).
- FSE_flushState(&bitStream, &state);
-
-Finally, you must close the bitStream.
-The function returns the size of CStream in bytes.
-If data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)
-If there is an error, it returns an errorCode (which can be tested using FSE_isError()).
- size_t size = BIT_closeCStream(&bitStream);
-*/
-
-/* *****************************************
-* FSE symbol decompression API
-*******************************************/
-typedef struct {
- size_t state;
- const void *table; /* precise table may vary, depending on U16 */
-} FSE_DState_t;
-
-static void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt);
-
-static unsigned char FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
-
-static unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr);
-
-/**<
-Let's now decompose FSE_decompress_usingDTable() into its unitary components.
-You will decode FSE-encoded symbols from the bitStream,
-and also any other bitFields you put in, **in reverse order**.
-
-You will need a few variables to track your bitStream. They are :
-
-BIT_DStream_t DStream; // Stream context
-FSE_DState_t DState; // State context. Multiple ones are possible
-FSE_DTable* DTablePtr; // Decoding table, provided by FSE_buildDTable()
-
-The first thing to do is to init the bitStream.
- errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);
-
-You should then retrieve your initial state(s)
-(in reverse flushing order if you have several ones) :
- errorCode = FSE_initDState(&DState, &DStream, DTablePtr);
-
-You can then decode your data, symbol after symbol.
-For information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.
-Keep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).
- unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);
-
-You can retrieve any bitfield you eventually stored into the bitStream (in reverse order)
-Note : maximum allowed nbBits is 25, for 32-bits compatibility
- size_t bitField = BIT_readBits(&DStream, nbBits);
-
-All above operations only read from local register (which size depends on size_t).
-Refueling the register from memory is manually performed by the reload method.
- endSignal = FSE_reloadDStream(&DStream);
-
-BIT_reloadDStream() result tells if there is still some more data to read from DStream.
-BIT_DStream_unfinished : there is still some data left into the DStream.
-BIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.
-BIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.
-BIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.
-
-When reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,
-to properly detect the exact end of stream.
-After each decoded symbol, check if DStream is fully consumed using this simple test :
- BIT_reloadDStream(&DStream) >= BIT_DStream_completed
-
-When it's done, verify decompression is fully completed, by checking both DStream and the relevant states.
-Checking if DStream has reached its end is performed by :
- BIT_endOfDStream(&DStream);
-Check also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.
- FSE_endOfDState(&DState);
-*/
-
-/* *****************************************
-* FSE unsafe API
-*******************************************/
-static unsigned char FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD);
-/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */
-
-/* *****************************************
-* Implementation of inlined functions
-*******************************************/
-typedef struct {
- int deltaFindState;
- U32 deltaNbBits;
-} FSE_symbolCompressionTransform; /* total 8 bytes */
-
-ZSTD_STATIC void FSE_initCState(FSE_CState_t *statePtr, const FSE_CTable *ct)
-{
- const void *ptr = ct;
- const U16 *u16ptr = (const U16 *)ptr;
- const U32 tableLog = ZSTD_read16(ptr);
- statePtr->value = (ptrdiff_t)1 << tableLog;
- statePtr->stateTable = u16ptr + 2;
- statePtr->symbolTT = ((const U32 *)ct + 1 + (tableLog ? (1 << (tableLog - 1)) : 1));
- statePtr->stateLog = tableLog;
-}
-
-/*! FSE_initCState2() :
-* Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)
-* uses the smallest state value possible, saving the cost of this symbol */
-ZSTD_STATIC void FSE_initCState2(FSE_CState_t *statePtr, const FSE_CTable *ct, U32 symbol)
-{
- FSE_initCState(statePtr, ct);
- {
- const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
- const U16 *stateTable = (const U16 *)(statePtr->stateTable);
- U32 nbBitsOut = (U32)((symbolTT.deltaNbBits + (1 << 15)) >> 16);
- statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;
- statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
- }
-}
-
-ZSTD_STATIC void FSE_encodeSymbol(BIT_CStream_t *bitC, FSE_CState_t *statePtr, U32 symbol)
-{
- const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform *)(statePtr->symbolTT))[symbol];
- const U16 *const stateTable = (const U16 *)(statePtr->stateTable);
- U32 nbBitsOut = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);
- BIT_addBits(bitC, statePtr->value, nbBitsOut);
- statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];
-}
-
-ZSTD_STATIC void FSE_flushCState(BIT_CStream_t *bitC, const FSE_CState_t *statePtr)
-{
- BIT_addBits(bitC, statePtr->value, statePtr->stateLog);
- BIT_flushBits(bitC);
-}
-
-/* ====== Decompression ====== */
-
-typedef struct {
- U16 tableLog;
- U16 fastMode;
-} FSE_DTableHeader; /* sizeof U32 */
-
-typedef struct {
- unsigned short newState;
- unsigned char symbol;
- unsigned char nbBits;
-} FSE_decode_t; /* size == U32 */
-
-ZSTD_STATIC void FSE_initDState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD, const FSE_DTable *dt)
-{
- const void *ptr = dt;
- const FSE_DTableHeader *const DTableH = (const FSE_DTableHeader *)ptr;
- DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);
- BIT_reloadDStream(bitD);
- DStatePtr->table = dt + 1;
-}
-
-ZSTD_STATIC BYTE FSE_peekSymbol(const FSE_DState_t *DStatePtr)
-{
- FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
- return DInfo.symbol;
-}
-
-ZSTD_STATIC void FSE_updateState(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
-{
- FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
- U32 const nbBits = DInfo.nbBits;
- size_t const lowBits = BIT_readBits(bitD, nbBits);
- DStatePtr->state = DInfo.newState + lowBits;
-}
-
-ZSTD_STATIC BYTE FSE_decodeSymbol(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
-{
- FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
- U32 const nbBits = DInfo.nbBits;
- BYTE const symbol = DInfo.symbol;
- size_t const lowBits = BIT_readBits(bitD, nbBits);
-
- DStatePtr->state = DInfo.newState + lowBits;
- return symbol;
-}
-
-/*! FSE_decodeSymbolFast() :
- unsafe, only works if no symbol has a probability > 50% */
-ZSTD_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t *DStatePtr, BIT_DStream_t *bitD)
-{
- FSE_decode_t const DInfo = ((const FSE_decode_t *)(DStatePtr->table))[DStatePtr->state];
- U32 const nbBits = DInfo.nbBits;
- BYTE const symbol = DInfo.symbol;
- size_t const lowBits = BIT_readBitsFast(bitD, nbBits);
-
- DStatePtr->state = DInfo.newState + lowBits;
- return symbol;
-}
-
-ZSTD_STATIC unsigned FSE_endOfDState(const FSE_DState_t *DStatePtr) { return DStatePtr->state == 0; }
-
-/* **************************************************************
-* Tuning parameters
-****************************************************************/
-/*!MEMORY_USAGE :
-* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
-* Increasing memory usage improves compression ratio
-* Reduced memory usage can improve speed, due to cache effect
-* Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */
-#ifndef FSE_MAX_MEMORY_USAGE
-#define FSE_MAX_MEMORY_USAGE 14
-#endif
-#ifndef FSE_DEFAULT_MEMORY_USAGE
-#define FSE_DEFAULT_MEMORY_USAGE 13
-#endif
-
-/*!FSE_MAX_SYMBOL_VALUE :
-* Maximum symbol value authorized.
-* Required for proper stack allocation */
-#ifndef FSE_MAX_SYMBOL_VALUE
-#define FSE_MAX_SYMBOL_VALUE 255
-#endif
-
-/* **************************************************************
-* template functions type & suffix
-****************************************************************/
-#define FSE_FUNCTION_TYPE BYTE
-#define FSE_FUNCTION_EXTENSION
-#define FSE_DECODE_TYPE FSE_decode_t
-
-/* ***************************************************************
-* Constants
-*****************************************************************/
-#define FSE_MAX_TABLELOG (FSE_MAX_MEMORY_USAGE - 2)
-#define FSE_MAX_TABLESIZE (1U << FSE_MAX_TABLELOG)
-#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE - 1)
-#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE - 2)
-#define FSE_MIN_TABLELOG 5
-
-#define FSE_TABLELOG_ABSOLUTE_MAX 15
-#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX
-#error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported"
-#endif
-
-#define FSE_TABLESTEP(tableSize) ((tableSize >> 1) + (tableSize >> 3) + 3)
-
-#endif /* FSE_H */
diff --git a/lib/zstd/fse_decompress.c b/lib/zstd/fse_decompress.c
deleted file mode 100644
index 3b4522b..0000000
--- a/lib/zstd/fse_decompress.c
+++ /dev/null
@@ -1,302 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
-/*
- * FSE : Finite State Entropy decoder
- * Copyright (C) 2013-2015, Yann Collet.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- */
-
-/* **************************************************************
-* Compiler specifics
-****************************************************************/
-#define FORCE_INLINE static __always_inline
-
-/* **************************************************************
-* Includes
-****************************************************************/
-#include "bitstream.h"
-#include "fse.h"
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/string.h> /* memcpy, memset */
-
-/* **************************************************************
-* Error Management
-****************************************************************/
-#define FSE_isError ERR_isError
-#define FSE_STATIC_ASSERT(c) \
- { \
- enum { FSE_static_assert = 1 / (int)(!!(c)) }; \
- } /* use only *after* variable declarations */
-
-/* check and forward error code */
-#define CHECK_F(f) \
- { \
- size_t const e = f; \
- if (FSE_isError(e)) \
- return e; \
- }
-
-/* **************************************************************
-* Templates
-****************************************************************/
-/*
- designed to be included
- for type-specific functions (template emulation in C)
- Objective is to write these functions only once, for improved maintenance
-*/
-
-/* safety checks */
-#ifndef FSE_FUNCTION_EXTENSION
-#error "FSE_FUNCTION_EXTENSION must be defined"
-#endif
-#ifndef FSE_FUNCTION_TYPE
-#error "FSE_FUNCTION_TYPE must be defined"
-#endif
-
-/* Function names */
-#define FSE_CAT(X, Y) X##Y
-#define FSE_FUNCTION_NAME(X, Y) FSE_CAT(X, Y)
-#define FSE_TYPE_NAME(X, Y) FSE_CAT(X, Y)
-
-/* Function templates */
-
-size_t FSE_buildDTable_wksp(FSE_DTable *dt, const short *normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void *workspace, size_t workspaceSize)
-{
- void *const tdPtr = dt + 1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
- FSE_DECODE_TYPE *const tableDecode = (FSE_DECODE_TYPE *)(tdPtr);
- U16 *symbolNext = (U16 *)workspace;
-
- U32 const maxSV1 = maxSymbolValue + 1;
- U32 const tableSize = 1 << tableLog;
- U32 highThreshold = tableSize - 1;
-
- /* Sanity Checks */
- if (workspaceSize < sizeof(U16) * (FSE_MAX_SYMBOL_VALUE + 1))
- return ERROR(tableLog_tooLarge);
- if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE)
- return ERROR(maxSymbolValue_tooLarge);
- if (tableLog > FSE_MAX_TABLELOG)
- return ERROR(tableLog_tooLarge);
-
- /* Init, lay down lowprob symbols */
- {
- FSE_DTableHeader DTableH;
- DTableH.tableLog = (U16)tableLog;
- DTableH.fastMode = 1;
- {
- S16 const largeLimit = (S16)(1 << (tableLog - 1));
- U32 s;
- for (s = 0; s < maxSV1; s++) {
- if (normalizedCounter[s] == -1) {
- tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;
- symbolNext[s] = 1;
- } else {
- if (normalizedCounter[s] >= largeLimit)
- DTableH.fastMode = 0;
- symbolNext[s] = normalizedCounter[s];
- }
- }
- }
- memcpy(dt, &DTableH, sizeof(DTableH));
- }
-
- /* Spread symbols */
- {
- U32 const tableMask = tableSize - 1;
- U32 const step = FSE_TABLESTEP(tableSize);
- U32 s, position = 0;
- for (s = 0; s < maxSV1; s++) {
- int i;
- for (i = 0; i < normalizedCounter[s]; i++) {
- tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
- position = (position + step) & tableMask;
- while (position > highThreshold)
- position = (position + step) & tableMask; /* lowprob area */
- }
- }
- if (position != 0)
- return ERROR(GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
- }
-
- /* Build Decoding table */
- {
- U32 u;
- for (u = 0; u < tableSize; u++) {
- FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
- U16 nextState = symbolNext[symbol]++;
- tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32((U32)nextState));
- tableDecode[u].newState = (U16)((nextState << tableDecode[u].nbBits) - tableSize);
- }
- }
-
- return 0;
-}
-
-/*-*******************************************************
-* Decompression (Byte symbols)
-*********************************************************/
-size_t FSE_buildDTable_rle(FSE_DTable *dt, BYTE symbolValue)
-{
- void *ptr = dt;
- FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
- void *dPtr = dt + 1;
- FSE_decode_t *const cell = (FSE_decode_t *)dPtr;
-
- DTableH->tableLog = 0;
- DTableH->fastMode = 0;
-
- cell->newState = 0;
- cell->symbol = symbolValue;
- cell->nbBits = 0;
-
- return 0;
-}
-
-size_t FSE_buildDTable_raw(FSE_DTable *dt, unsigned nbBits)
-{
- void *ptr = dt;
- FSE_DTableHeader *const DTableH = (FSE_DTableHeader *)ptr;
- void *dPtr = dt + 1;
- FSE_decode_t *const dinfo = (FSE_decode_t *)dPtr;
- const unsigned tableSize = 1 << nbBits;
- const unsigned tableMask = tableSize - 1;
- const unsigned maxSV1 = tableMask + 1;
- unsigned s;
-
- /* Sanity checks */
- if (nbBits < 1)
- return ERROR(GENERIC); /* min size */
-
- /* Build Decoding Table */
- DTableH->tableLog = (U16)nbBits;
- DTableH->fastMode = 1;
- for (s = 0; s < maxSV1; s++) {
- dinfo[s].newState = 0;
- dinfo[s].symbol = (BYTE)s;
- dinfo[s].nbBits = (BYTE)nbBits;
- }
-
- return 0;
-}
-
-FORCE_INLINE size_t FSE_decompress_usingDTable_generic(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt,
- const unsigned fast)
-{
- BYTE *const ostart = (BYTE *)dst;
- BYTE *op = ostart;
- BYTE *const omax = op + maxDstSize;
- BYTE *const olimit = omax - 3;
-
- BIT_DStream_t bitD;
- FSE_DState_t state1;
- FSE_DState_t state2;
-
- /* Init */
- CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));
-
- FSE_initDState(&state1, &bitD, dt);
- FSE_initDState(&state2, &bitD, dt);
-
-#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)
-
- /* 4 symbols per loop */
- for (; (BIT_reloadDStream(&bitD) == BIT_DStream_unfinished) & (op < olimit); op += 4) {
- op[0] = FSE_GETSYMBOL(&state1);
-
- if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
- BIT_reloadDStream(&bitD);
-
- op[1] = FSE_GETSYMBOL(&state2);
-
- if (FSE_MAX_TABLELOG * 4 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
- {
- if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) {
- op += 2;
- break;
- }
- }
-
- op[2] = FSE_GETSYMBOL(&state1);
-
- if (FSE_MAX_TABLELOG * 2 + 7 > sizeof(bitD.bitContainer) * 8) /* This test must be static */
- BIT_reloadDStream(&bitD);
-
- op[3] = FSE_GETSYMBOL(&state2);
- }
-
- /* tail */
- /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */
- while (1) {
- if (op > (omax - 2))
- return ERROR(dstSize_tooSmall);
- *op++ = FSE_GETSYMBOL(&state1);
- if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
- *op++ = FSE_GETSYMBOL(&state2);
- break;
- }
-
- if (op > (omax - 2))
- return ERROR(dstSize_tooSmall);
- *op++ = FSE_GETSYMBOL(&state2);
- if (BIT_reloadDStream(&bitD) == BIT_DStream_overflow) {
- *op++ = FSE_GETSYMBOL(&state1);
- break;
- }
- }
-
- return op - ostart;
-}
-
-size_t FSE_decompress_usingDTable(void *dst, size_t originalSize, const void *cSrc, size_t cSrcSize, const FSE_DTable *dt)
-{
- const void *ptr = dt;
- const FSE_DTableHeader *DTableH = (const FSE_DTableHeader *)ptr;
- const U32 fastMode = DTableH->fastMode;
-
- /* select fast mode (static) */
- if (fastMode)
- return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);
- return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);
-}
-
-size_t FSE_decompress_wksp(void *dst, size_t dstCapacity, const void *cSrc, size_t cSrcSize, unsigned maxLog, void *workspace, size_t workspaceSize)
-{
- const BYTE *const istart = (const BYTE *)cSrc;
- const BYTE *ip = istart;
- unsigned tableLog;
- unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;
- size_t NCountLength;
-
- FSE_DTable *dt;
- short *counting;
- size_t spaceUsed32 = 0;
-
- FSE_STATIC_ASSERT(sizeof(FSE_DTable) == sizeof(U32));
-
- dt = (FSE_DTable *)((U32 *)workspace + spaceUsed32);
- spaceUsed32 += FSE_DTABLE_SIZE_U32(maxLog);
- counting = (short *)((U32 *)workspace + spaceUsed32);
- spaceUsed32 += ALIGN(sizeof(short) * (FSE_MAX_SYMBOL_VALUE + 1), sizeof(U32)) >> 2;
-
- if ((spaceUsed32 << 2) > workspaceSize)
- return ERROR(tableLog_tooLarge);
- workspace = (U32 *)workspace + spaceUsed32;
- workspaceSize -= (spaceUsed32 << 2);
-
- /* normal FSE decoding mode */
- NCountLength = FSE_readNCount(counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
- if (FSE_isError(NCountLength))
- return NCountLength;
- // if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); /* too small input size; supposed to be already checked in NCountLength, only remaining
- // case : NCountLength==cSrcSize */
- if (tableLog > maxLog)
- return ERROR(tableLog_tooLarge);
- ip += NCountLength;
- cSrcSize -= NCountLength;
-
- CHECK_F(FSE_buildDTable_wksp(dt, counting, maxSymbolValue, tableLog, workspace, workspaceSize));
-
- return FSE_decompress_usingDTable(dst, dstCapacity, ip, cSrcSize, dt); /* always return, even if it is an error code */
-}
diff --git a/lib/zstd/huf.h b/lib/zstd/huf.h
deleted file mode 100644
index 01630f5..0000000
--- a/lib/zstd/huf.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause) */
-/*
- * Huffman coder, part of New Generation Entropy library
- * header file
- * Copyright (C) 2013-2016, Yann Collet.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- */
-#ifndef HUF_H_298734234
-#define HUF_H_298734234
-
-/* *** Dependencies *** */
-#include <linux/types.h> /* size_t */
-
-/* *** Tool functions *** */
-#define HUF_BLOCKSIZE_MAX (128 * 1024) /**< maximum input size for a single block compressed with HUF_compress */
-size_t HUF_compressBound(size_t size); /**< maximum compressed size (worst case) */
-
-/* Error Management */
-unsigned HUF_isError(size_t code); /**< tells if a return value is an error code */
-
-/* *** Advanced function *** */
-
-/** HUF_compress4X_wksp() :
-* Same as HUF_compress2(), but uses externally allocated `workSpace`, which must be a table of >= 1024 unsigned */
-size_t HUF_compress4X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
- size_t wkspSize); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
-
-/* *** Dependencies *** */
-#include "mem.h" /* U32 */
-
-/* *** Constants *** */
-#define HUF_TABLELOG_MAX 12 /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
-#define HUF_TABLELOG_DEFAULT 11 /* tableLog by default, when not specified */
-#define HUF_SYMBOLVALUE_MAX 255
-
-#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
-#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
-#error "HUF_TABLELOG_MAX is too large !"
-#endif
-
-/* ****************************************
-* Static allocation
-******************************************/
-/* HUF buffer bounds */
-#define HUF_CTABLEBOUND 129
-#define HUF_BLOCKBOUND(size) (size + (size >> 8) + 8) /* only true if incompressible pre-filtered with fast heuristic */
-#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */
-
-/* static allocation of HUF's Compression Table */
-#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
- U32 name##hb[maxSymbolValue + 1]; \
- void *name##hv = &(name##hb); \
- HUF_CElt *name = (HUF_CElt *)(name##hv) /* no final ; */
-
-/* static allocation of HUF's DTable */
-typedef U32 HUF_DTable;
-#define HUF_DTABLE_SIZE(maxTableLog) (1 + (1 << (maxTableLog)))
-#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = {((U32)((maxTableLog)-1) * 0x01000001)}
-#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = {((U32)(maxTableLog)*0x01000001)}
-
-/* The workspace must have alignment at least 4 and be at least this large */
-#define HUF_COMPRESS_WORKSPACE_SIZE (6 << 10)
-#define HUF_COMPRESS_WORKSPACE_SIZE_U32 (HUF_COMPRESS_WORKSPACE_SIZE / sizeof(U32))
-
-/* The workspace must have alignment at least 4 and be at least this large */
-#define HUF_DECOMPRESS_WORKSPACE_SIZE (3 << 10)
-#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))
-
-/* ****************************************
-* Advanced decompression functions
-******************************************/
-size_t HUF_decompress4X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize); /**< decodes RLE and uncompressed */
-size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
- size_t workspaceSize); /**< considers RLE and uncompressed as errors */
-size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
- size_t workspaceSize); /**< single-symbol decoder */
-size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
- size_t workspaceSize); /**< double-symbols decoder */
-
-/* ****************************************
-* HUF detailed API
-******************************************/
-/*!
-HUF_compress() does the following:
-1. count symbol occurrence from source[] into table count[] using FSE_count()
-2. (optional) refine tableLog using HUF_optimalTableLog()
-3. build Huffman table from count using HUF_buildCTable()
-4. save Huffman table to memory buffer using HUF_writeCTable_wksp()
-5. encode the data stream using HUF_compress4X_usingCTable()
-
-The following API allows targeting specific sub-functions for advanced tasks.
-For example, it's possible to compress several blocks using the same 'CTable',
-or to save and regenerate 'CTable' using external methods.
-*/
-/* FSE_count() : find it within "fse.h" */
-unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);
-typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */
-size_t HUF_writeCTable_wksp(void *dst, size_t maxDstSize, const HUF_CElt *CTable, unsigned maxSymbolValue, unsigned huffLog, void *workspace, size_t workspaceSize);
-size_t HUF_compress4X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
-
-typedef enum {
- HUF_repeat_none, /**< Cannot use the previous table */
- HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1,
- 4}X_repeat */
- HUF_repeat_valid /**< Can use the previous table and it is asumed to be valid */
-} HUF_repeat;
-/** HUF_compress4X_repeat() :
-* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
-* If it uses hufTable it does not modify hufTable or repeat.
-* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
-* If preferRepeat then the old table will always be used if valid. */
-size_t HUF_compress4X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
- size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
- int preferRepeat); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
-
-/** HUF_buildCTable_wksp() :
- * Same as HUF_buildCTable(), but using externally allocated scratch buffer.
- * `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as a table of 1024 unsigned.
- */
-size_t HUF_buildCTable_wksp(HUF_CElt *tree, const U32 *count, U32 maxSymbolValue, U32 maxNbBits, void *workSpace, size_t wkspSize);
-
-/*! HUF_readStats() :
- Read compact Huffman tree, saved by HUF_writeCTable().
- `huffWeight` is destination buffer.
- @return : size read from `src` , or an error Code .
- Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */
-size_t HUF_readStats_wksp(BYTE *huffWeight, size_t hwSize, U32 *rankStats, U32 *nbSymbolsPtr, U32 *tableLogPtr, const void *src, size_t srcSize,
- void *workspace, size_t workspaceSize);
-
-/** HUF_readCTable() :
-* Loading a CTable saved with HUF_writeCTable() */
-size_t HUF_readCTable_wksp(HUF_CElt *CTable, unsigned maxSymbolValue, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
-
-/*
-HUF_decompress() does the following:
-1. select the decompression algorithm (X2, X4) based on pre-computed heuristics
-2. build Huffman table from save, using HUF_readDTableXn()
-3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable
-*/
-
-/** HUF_selectDecoder() :
-* Tells which decoder is likely to decode faster,
-* based on a set of pre-determined metrics.
-* @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
-* Assumption : 0 < cSrcSize < dstSize <= 128 KB */
-U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize);
-
-size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
-size_t HUF_readDTableX4_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize);
-
-size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
-size_t HUF_decompress4X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
-size_t HUF_decompress4X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
-
-/* single stream variants */
-
-size_t HUF_compress1X_wksp(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
- size_t wkspSize); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
-size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, size_t srcSize, const HUF_CElt *CTable);
-/** HUF_compress1X_repeat() :
-* Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
-* If it uses hufTable it does not modify hufTable or repeat.
-* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
-* If preferRepeat then the old table will always be used if valid. */
-size_t HUF_compress1X_repeat(void *dst, size_t dstSize, const void *src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void *workSpace,
- size_t wkspSize, HUF_CElt *hufTable, HUF_repeat *repeat,
- int preferRepeat); /**< `workSpace` must be a table of at least HUF_COMPRESS_WORKSPACE_SIZE_U32 unsigned */
-
-size_t HUF_decompress1X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize);
-size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
- size_t workspaceSize); /**< single-symbol decoder */
-size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace,
- size_t workspaceSize); /**< double-symbols decoder */
-
-size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize,
- const HUF_DTable *DTable); /**< automatic selection of sing or double symbol decoder, based on DTable */
-size_t HUF_decompress1X2_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
-size_t HUF_decompress1X4_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable);
-
-#endif /* HUF_H_298734234 */
diff --git a/lib/zstd/huf_decompress.c b/lib/zstd/huf_decompress.c
deleted file mode 100644
index 97145b0..0000000
--- a/lib/zstd/huf_decompress.c
+++ /dev/null
@@ -1,930 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 or BSD-2-Clause)
-/*
- * Huffman decoder, part of New Generation Entropy library
- * Copyright (C) 2013-2016, Yann Collet.
- *
- * You can contact the author at :
- * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy
- */
-
-/* **************************************************************
-* Compiler specifics
-****************************************************************/
-#define FORCE_INLINE static __always_inline
-
-/* **************************************************************
-* Dependencies
-****************************************************************/
-#include "bitstream.h" /* BIT_* */
-#include "fse.h" /* header compression */
-#include "huf.h"
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/string.h> /* memcpy, memset */
-
-/* **************************************************************
-* Error Management
-****************************************************************/
-#define HUF_STATIC_ASSERT(c) \
- { \
- enum { HUF_static_assert = 1 / (int)(!!(c)) }; \
- } /* use only *after* variable declarations */
-
-/*-***************************/
-/* generic DTableDesc */
-/*-***************************/
-
-typedef struct {
- BYTE maxTableLog;
- BYTE tableType;
- BYTE tableLog;
- BYTE reserved;
-} DTableDesc;
-
-static DTableDesc HUF_getDTableDesc(const HUF_DTable *table)
-{
- DTableDesc dtd;
- memcpy(&dtd, table, sizeof(dtd));
- return dtd;
-}
-
-/*-***************************/
-/* single-symbol decoding */
-/*-***************************/
-
-typedef struct {
- BYTE byte;
- BYTE nbBits;
-} HUF_DEltX2; /* single-symbol decoding */
-
-size_t HUF_readDTableX2_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
-{
- U32 tableLog = 0;
- U32 nbSymbols = 0;
- size_t iSize;
- void *const dtPtr = DTable + 1;
- HUF_DEltX2 *const dt = (HUF_DEltX2 *)dtPtr;
-
- U32 *rankVal;
- BYTE *huffWeight;
- size_t spaceUsed32 = 0;
-
- rankVal = (U32 *)workspace + spaceUsed32;
- spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1;
- huffWeight = (BYTE *)((U32 *)workspace + spaceUsed32);
- spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
-
- if ((spaceUsed32 << 2) > workspaceSize)
- return ERROR(tableLog_tooLarge);
- workspace = (U32 *)workspace + spaceUsed32;
- workspaceSize -= (spaceUsed32 << 2);
-
- HUF_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));
- /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */
-
- iSize = HUF_readStats_wksp(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
- if (HUF_isError(iSize))
- return iSize;
-
- /* Table header */
- {
- DTableDesc dtd = HUF_getDTableDesc(DTable);
- if (tableLog > (U32)(dtd.maxTableLog + 1))
- return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */
- dtd.tableType = 0;
- dtd.tableLog = (BYTE)tableLog;
- memcpy(DTable, &dtd, sizeof(dtd));
- }
-
- /* Calculate starting value for each rank */
- {
- U32 n, nextRankStart = 0;
- for (n = 1; n < tableLog + 1; n++) {
- U32 const curr = nextRankStart;
- nextRankStart += (rankVal[n] << (n - 1));
- rankVal[n] = curr;
- }
- }
-
- /* fill DTable */
- {
- U32 n;
- for (n = 0; n < nbSymbols; n++) {
- U32 const w = huffWeight[n];
- U32 const length = (1 << w) >> 1;
- U32 u;
- HUF_DEltX2 D;
- D.byte = (BYTE)n;
- D.nbBits = (BYTE)(tableLog + 1 - w);
- for (u = rankVal[w]; u < rankVal[w] + length; u++)
- dt[u] = D;
- rankVal[w] += length;
- }
- }
-
- return iSize;
-}
-
-static BYTE HUF_decodeSymbolX2(BIT_DStream_t *Dstream, const HUF_DEltX2 *dt, const U32 dtLog)
-{
- size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */
- BYTE const c = dt[val].byte;
- BIT_skipBits(Dstream, dt[val].nbBits);
- return c;
-}
-
-#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \
- if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
- HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
-
-#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \
- if (ZSTD_64bits()) \
- HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)
-
-FORCE_INLINE size_t HUF_decodeStreamX2(BYTE *p, BIT_DStream_t *const bitDPtr, BYTE *const pEnd, const HUF_DEltX2 *const dt, const U32 dtLog)
-{
- BYTE *const pStart = p;
-
- /* up to 4 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd - 4)) {
- HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
- }
-
- /* closer to the end */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
-
- /* no more data to retrieve from bitstream, hence no need to reload */
- while (p < pEnd)
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
-
- return pEnd - pStart;
-}
-
-static size_t HUF_decompress1X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- BYTE *op = (BYTE *)dst;
- BYTE *const oend = op + dstSize;
- const void *dtPtr = DTable + 1;
- const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
- BIT_DStream_t bitD;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- U32 const dtLog = dtd.tableLog;
-
- {
- size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
- if (HUF_isError(errorCode))
- return errorCode;
- }
-
- HUF_decodeStreamX2(op, &bitD, oend, dt, dtLog);
-
- /* check */
- if (!BIT_endOfDStream(&bitD))
- return ERROR(corruption_detected);
-
- return dstSize;
-}
-
-size_t HUF_decompress1X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- DTableDesc dtd = HUF_getDTableDesc(DTable);
- if (dtd.tableType != 0)
- return ERROR(GENERIC);
- return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
-}
-
-size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
-{
- const BYTE *ip = (const BYTE *)cSrc;
-
- size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
- if (HUF_isError(hSize))
- return hSize;
- if (hSize >= cSrcSize)
- return ERROR(srcSize_wrong);
- ip += hSize;
- cSrcSize -= hSize;
-
- return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
-}
-
-static size_t HUF_decompress4X2_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- /* Check */
- if (cSrcSize < 10)
- return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
-
- {
- const BYTE *const istart = (const BYTE *)cSrc;
- BYTE *const ostart = (BYTE *)dst;
- BYTE *const oend = ostart + dstSize;
- const void *const dtPtr = DTable + 1;
- const HUF_DEltX2 *const dt = (const HUF_DEltX2 *)dtPtr;
-
- /* Init */
- BIT_DStream_t bitD1;
- BIT_DStream_t bitD2;
- BIT_DStream_t bitD3;
- BIT_DStream_t bitD4;
- size_t const length1 = ZSTD_readLE16(istart);
- size_t const length2 = ZSTD_readLE16(istart + 2);
- size_t const length3 = ZSTD_readLE16(istart + 4);
- size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
- const BYTE *const istart1 = istart + 6; /* jumpTable */
- const BYTE *const istart2 = istart1 + length1;
- const BYTE *const istart3 = istart2 + length2;
- const BYTE *const istart4 = istart3 + length3;
- const size_t segmentSize = (dstSize + 3) / 4;
- BYTE *const opStart2 = ostart + segmentSize;
- BYTE *const opStart3 = opStart2 + segmentSize;
- BYTE *const opStart4 = opStart3 + segmentSize;
- BYTE *op1 = ostart;
- BYTE *op2 = opStart2;
- BYTE *op3 = opStart3;
- BYTE *op4 = opStart4;
- U32 endSignal;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- U32 const dtLog = dtd.tableLog;
-
- if (length4 > cSrcSize)
- return ERROR(corruption_detected); /* overflow */
- {
- size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
- if (HUF_isError(errorCode))
- return errorCode;
- }
- {
- size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
- if (HUF_isError(errorCode))
- return errorCode;
- }
- {
- size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
- if (HUF_isError(errorCode))
- return errorCode;
- }
- {
- size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
- if (HUF_isError(errorCode))
- return errorCode;
- }
-
- /* 16-32 symbols per loop (4-8 symbols per stream) */
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- for (; (endSignal == BIT_DStream_unfinished) && (op4 < (oend - 7));) {
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- }
-
- /* check corruption */
- if (op1 > opStart2)
- return ERROR(corruption_detected);
- if (op2 > opStart3)
- return ERROR(corruption_detected);
- if (op3 > opStart4)
- return ERROR(corruption_detected);
- /* note : op4 supposed already verified within main loop */
-
- /* finish bitStreams one by one */
- HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);
- HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);
- HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);
- HUF_decodeStreamX2(op4, &bitD4, oend, dt, dtLog);
-
- /* check */
- endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
- if (!endSignal)
- return ERROR(corruption_detected);
-
- /* decoded size */
- return dstSize;
- }
-}
-
-size_t HUF_decompress4X2_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- DTableDesc dtd = HUF_getDTableDesc(DTable);
- if (dtd.tableType != 0)
- return ERROR(GENERIC);
- return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
-}
-
-size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
-{
- const BYTE *ip = (const BYTE *)cSrc;
-
- size_t const hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
- if (HUF_isError(hSize))
- return hSize;
- if (hSize >= cSrcSize)
- return ERROR(srcSize_wrong);
- ip += hSize;
- cSrcSize -= hSize;
-
- return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
-}
-
-/* *************************/
-/* double-symbols decoding */
-/* *************************/
-typedef struct {
- U16 sequence;
- BYTE nbBits;
- BYTE length;
-} HUF_DEltX4; /* double-symbols decoding */
-
-typedef struct {
- BYTE symbol;
- BYTE weight;
-} sortedSymbol_t;
-
-/* HUF_fillDTableX4Level2() :
- * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
-static void HUF_fillDTableX4Level2(HUF_DEltX4 *DTable, U32 sizeLog, const U32 consumed, const U32 *rankValOrigin, const int minWeight,
- const sortedSymbol_t *sortedSymbols, const U32 sortedListSize, U32 nbBitsBaseline, U16 baseSeq)
-{
- HUF_DEltX4 DElt;
- U32 rankVal[HUF_TABLELOG_MAX + 1];
-
- /* get pre-calculated rankVal */
- memcpy(rankVal, rankValOrigin, sizeof(rankVal));
-
- /* fill skipped values */
- if (minWeight > 1) {
- U32 i, skipSize = rankVal[minWeight];
- ZSTD_writeLE16(&(DElt.sequence), baseSeq);
- DElt.nbBits = (BYTE)(consumed);
- DElt.length = 1;
- for (i = 0; i < skipSize; i++)
- DTable[i] = DElt;
- }
-
- /* fill DTable */
- {
- U32 s;
- for (s = 0; s < sortedListSize; s++) { /* note : sortedSymbols already skipped */
- const U32 symbol = sortedSymbols[s].symbol;
- const U32 weight = sortedSymbols[s].weight;
- const U32 nbBits = nbBitsBaseline - weight;
- const U32 length = 1 << (sizeLog - nbBits);
- const U32 start = rankVal[weight];
- U32 i = start;
- const U32 end = start + length;
-
- ZSTD_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
- DElt.nbBits = (BYTE)(nbBits + consumed);
- DElt.length = 2;
- do {
- DTable[i++] = DElt;
- } while (i < end); /* since length >= 1 */
-
- rankVal[weight] += length;
- }
- }
-}
-
-typedef U32 rankVal_t[HUF_TABLELOG_MAX][HUF_TABLELOG_MAX + 1];
-typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
-
-static void HUF_fillDTableX4(HUF_DEltX4 *DTable, const U32 targetLog, const sortedSymbol_t *sortedList, const U32 sortedListSize, const U32 *rankStart,
- rankVal_t rankValOrigin, const U32 maxWeight, const U32 nbBitsBaseline)
-{
- U32 rankVal[HUF_TABLELOG_MAX + 1];
- const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
- const U32 minBits = nbBitsBaseline - maxWeight;
- U32 s;
-
- memcpy(rankVal, rankValOrigin, sizeof(rankVal));
-
- /* fill DTable */
- for (s = 0; s < sortedListSize; s++) {
- const U16 symbol = sortedList[s].symbol;
- const U32 weight = sortedList[s].weight;
- const U32 nbBits = nbBitsBaseline - weight;
- const U32 start = rankVal[weight];
- const U32 length = 1 << (targetLog - nbBits);
-
- if (targetLog - nbBits >= minBits) { /* enough room for a second symbol */
- U32 sortedRank;
- int minWeight = nbBits + scaleLog;
- if (minWeight < 1)
- minWeight = 1;
- sortedRank = rankStart[minWeight];
- HUF_fillDTableX4Level2(DTable + start, targetLog - nbBits, nbBits, rankValOrigin[nbBits], minWeight, sortedList + sortedRank,
- sortedListSize - sortedRank, nbBitsBaseline, symbol);
- } else {
- HUF_DEltX4 DElt;
- ZSTD_writeLE16(&(DElt.sequence), symbol);
- DElt.nbBits = (BYTE)(nbBits);
- DElt.length = 1;
- {
- U32 const end = start + length;
- U32 u;
- for (u = start; u < end; u++)
- DTable[u] = DElt;
- }
- }
- rankVal[weight] += length;
- }
-}
-
-size_t HUF_readDTableX4_wksp(HUF_DTable *DTable, const void *src, size_t srcSize, void *workspace, size_t workspaceSize)
-{
- U32 tableLog, maxW, sizeOfSort, nbSymbols;
- DTableDesc dtd = HUF_getDTableDesc(DTable);
- U32 const maxTableLog = dtd.maxTableLog;
- size_t iSize;
- void *dtPtr = DTable + 1; /* force compiler to avoid strict-aliasing */
- HUF_DEltX4 *const dt = (HUF_DEltX4 *)dtPtr;
- U32 *rankStart;
-
- rankValCol_t *rankVal;
- U32 *rankStats;
- U32 *rankStart0;
- sortedSymbol_t *sortedSymbol;
- BYTE *weightList;
- size_t spaceUsed32 = 0;
-
- HUF_STATIC_ASSERT((sizeof(rankValCol_t) & 3) == 0);
-
- rankVal = (rankValCol_t *)((U32 *)workspace + spaceUsed32);
- spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;
- rankStats = (U32 *)workspace + spaceUsed32;
- spaceUsed32 += HUF_TABLELOG_MAX + 1;
- rankStart0 = (U32 *)workspace + spaceUsed32;
- spaceUsed32 += HUF_TABLELOG_MAX + 2;
- sortedSymbol = (sortedSymbol_t *)((U32 *)workspace + spaceUsed32);
- spaceUsed32 += ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;
- weightList = (BYTE *)((U32 *)workspace + spaceUsed32);
- spaceUsed32 += ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;
-
- if ((spaceUsed32 << 2) > workspaceSize)
- return ERROR(tableLog_tooLarge);
- workspace = (U32 *)workspace + spaceUsed32;
- workspaceSize -= (spaceUsed32 << 2);
-
- rankStart = rankStart0 + 1;
- memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));
-
- HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */
- if (maxTableLog > HUF_TABLELOG_MAX)
- return ERROR(tableLog_tooLarge);
- /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
-
- iSize = HUF_readStats_wksp(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize, workspace, workspaceSize);
- if (HUF_isError(iSize))
- return iSize;
-
- /* check result */
- if (tableLog > maxTableLog)
- return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
-
- /* find maxWeight */
- for (maxW = tableLog; rankStats[maxW] == 0; maxW--) {
- } /* necessarily finds a solution before 0 */
-
- /* Get start index of each weight */
- {
- U32 w, nextRankStart = 0;
- for (w = 1; w < maxW + 1; w++) {
- U32 curr = nextRankStart;
- nextRankStart += rankStats[w];
- rankStart[w] = curr;
- }
- rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
- sizeOfSort = nextRankStart;
- }
-
- /* sort symbols by weight */
- {
- U32 s;
- for (s = 0; s < nbSymbols; s++) {
- U32 const w = weightList[s];
- U32 const r = rankStart[w]++;
- sortedSymbol[r].symbol = (BYTE)s;
- sortedSymbol[r].weight = (BYTE)w;
- }
- rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
- }
-
- /* Build rankVal */
- {
- U32 *const rankVal0 = rankVal[0];
- {
- int const rescale = (maxTableLog - tableLog) - 1; /* tableLog <= maxTableLog */
- U32 nextRankVal = 0;
- U32 w;
- for (w = 1; w < maxW + 1; w++) {
- U32 curr = nextRankVal;
- nextRankVal += rankStats[w] << (w + rescale);
- rankVal0[w] = curr;
- }
- }
- {
- U32 const minBits = tableLog + 1 - maxW;
- U32 consumed;
- for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {
- U32 *const rankValPtr = rankVal[consumed];
- U32 w;
- for (w = 1; w < maxW + 1; w++) {
- rankValPtr[w] = rankVal0[w] >> consumed;
- }
- }
- }
- }
-
- HUF_fillDTableX4(dt, maxTableLog, sortedSymbol, sizeOfSort, rankStart0, rankVal, maxW, tableLog + 1);
-
- dtd.tableLog = (BYTE)maxTableLog;
- dtd.tableType = 1;
- memcpy(DTable, &dtd, sizeof(dtd));
- return iSize;
-}
-
-static U32 HUF_decodeSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
-{
- size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt + val, 2);
- BIT_skipBits(DStream, dt[val].nbBits);
- return dt[val].length;
-}
-
-static U32 HUF_decodeLastSymbolX4(void *op, BIT_DStream_t *DStream, const HUF_DEltX4 *dt, const U32 dtLog)
-{
- size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- memcpy(op, dt + val, 1);
- if (dt[val].length == 1)
- BIT_skipBits(DStream, dt[val].nbBits);
- else {
- if (DStream->bitsConsumed < (sizeof(DStream->bitContainer) * 8)) {
- BIT_skipBits(DStream, dt[val].nbBits);
- if (DStream->bitsConsumed > (sizeof(DStream->bitContainer) * 8))
- /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
- DStream->bitsConsumed = (sizeof(DStream->bitContainer) * 8);
- }
- }
- return 1;
-}
-
-#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \
- if (ZSTD_64bits() || (HUF_TABLELOG_MAX <= 12)) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \
- if (ZSTD_64bits()) \
- ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)
-
-FORCE_INLINE size_t HUF_decodeStreamX4(BYTE *p, BIT_DStream_t *bitDPtr, BYTE *const pEnd, const HUF_DEltX4 *const dt, const U32 dtLog)
-{
- BYTE *const pStart = p;
-
- /* up to 8 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd - (sizeof(bitDPtr->bitContainer) - 1))) {
- HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_1(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
- }
-
- /* closer to end : up to 2 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd - 2))
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr);
-
- while (p <= pEnd - 2)
- HUF_DECODE_SYMBOLX4_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
-
- if (p < pEnd)
- p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);
-
- return p - pStart;
-}
-
-static size_t HUF_decompress1X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- BIT_DStream_t bitD;
-
- /* Init */
- {
- size_t const errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);
- if (HUF_isError(errorCode))
- return errorCode;
- }
-
- /* decode */
- {
- BYTE *const ostart = (BYTE *)dst;
- BYTE *const oend = ostart + dstSize;
- const void *const dtPtr = DTable + 1; /* force compiler to not use strict-aliasing */
- const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- HUF_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);
- }
-
- /* check */
- if (!BIT_endOfDStream(&bitD))
- return ERROR(corruption_detected);
-
- /* decoded size */
- return dstSize;
-}
-
-size_t HUF_decompress1X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- DTableDesc dtd = HUF_getDTableDesc(DTable);
- if (dtd.tableType != 1)
- return ERROR(GENERIC);
- return HUF_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
-}
-
-size_t HUF_decompress1X4_DCtx_wksp(HUF_DTable *DCtx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
-{
- const BYTE *ip = (const BYTE *)cSrc;
-
- size_t const hSize = HUF_readDTableX4_wksp(DCtx, cSrc, cSrcSize, workspace, workspaceSize);
- if (HUF_isError(hSize))
- return hSize;
- if (hSize >= cSrcSize)
- return ERROR(srcSize_wrong);
- ip += hSize;
- cSrcSize -= hSize;
-
- return HUF_decompress1X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx);
-}
-
-static size_t HUF_decompress4X4_usingDTable_internal(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- if (cSrcSize < 10)
- return ERROR(corruption_detected); /* strict minimum : jump table + 1 byte per stream */
-
- {
- const BYTE *const istart = (const BYTE *)cSrc;
- BYTE *const ostart = (BYTE *)dst;
- BYTE *const oend = ostart + dstSize;
- const void *const dtPtr = DTable + 1;
- const HUF_DEltX4 *const dt = (const HUF_DEltX4 *)dtPtr;
-
- /* Init */
- BIT_DStream_t bitD1;
- BIT_DStream_t bitD2;
- BIT_DStream_t bitD3;
- BIT_DStream_t bitD4;
- size_t const length1 = ZSTD_readLE16(istart);
- size_t const length2 = ZSTD_readLE16(istart + 2);
- size_t const length3 = ZSTD_readLE16(istart + 4);
- size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);
- const BYTE *const istart1 = istart + 6; /* jumpTable */
- const BYTE *const istart2 = istart1 + length1;
- const BYTE *const istart3 = istart2 + length2;
- const BYTE *const istart4 = istart3 + length3;
- size_t const segmentSize = (dstSize + 3) / 4;
- BYTE *const opStart2 = ostart + segmentSize;
- BYTE *const opStart3 = opStart2 + segmentSize;
- BYTE *const opStart4 = opStart3 + segmentSize;
- BYTE *op1 = ostart;
- BYTE *op2 = opStart2;
- BYTE *op3 = opStart3;
- BYTE *op4 = opStart4;
- U32 endSignal;
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- U32 const dtLog = dtd.tableLog;
-
- if (length4 > cSrcSize)
- return ERROR(corruption_detected); /* overflow */
- {
- size_t const errorCode = BIT_initDStream(&bitD1, istart1, length1);
- if (HUF_isError(errorCode))
- return errorCode;
- }
- {
- size_t const errorCode = BIT_initDStream(&bitD2, istart2, length2);
- if (HUF_isError(errorCode))
- return errorCode;
- }
- {
- size_t const errorCode = BIT_initDStream(&bitD3, istart3, length3);
- if (HUF_isError(errorCode))
- return errorCode;
- }
- {
- size_t const errorCode = BIT_initDStream(&bitD4, istart4, length4);
- if (HUF_isError(errorCode))
- return errorCode;
- }
-
- /* 16-32 symbols per loop (4-8 symbols per stream) */
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- for (; (endSignal == BIT_DStream_unfinished) & (op4 < (oend - (sizeof(bitD4.bitContainer) - 1)));) {
- HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX4_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX4_0(op2, &bitD2);
- HUF_DECODE_SYMBOLX4_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX4_0(op4, &bitD4);
-
- endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);
- }
-
- /* check corruption */
- if (op1 > opStart2)
- return ERROR(corruption_detected);
- if (op2 > opStart3)
- return ERROR(corruption_detected);
- if (op3 > opStart4)
- return ERROR(corruption_detected);
- /* note : op4 already verified within main loop */
-
- /* finish bitStreams one by one */
- HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);
- HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);
- HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);
- HUF_decodeStreamX4(op4, &bitD4, oend, dt, dtLog);
-
- /* check */
- {
- U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);
- if (!endCheck)
- return ERROR(corruption_detected);
- }
-
- /* decoded size */
- return dstSize;
- }
-}
-
-size_t HUF_decompress4X4_usingDTable(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- DTableDesc dtd = HUF_getDTableDesc(DTable);
- if (dtd.tableType != 1)
- return ERROR(GENERIC);
- return HUF_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);
-}
-
-size_t HUF_decompress4X4_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
-{
- const BYTE *ip = (const BYTE *)cSrc;
-
- size_t hSize = HUF_readDTableX4_wksp(dctx, cSrc, cSrcSize, workspace, workspaceSize);
- if (HUF_isError(hSize))
- return hSize;
- if (hSize >= cSrcSize)
- return ERROR(srcSize_wrong);
- ip += hSize;
- cSrcSize -= hSize;
-
- return HUF_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);
-}
-
-/* ********************************/
-/* Generic decompression selector */
-/* ********************************/
-
-size_t HUF_decompress1X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
- : HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
-}
-
-size_t HUF_decompress4X_usingDTable(void *dst, size_t maxDstSize, const void *cSrc, size_t cSrcSize, const HUF_DTable *DTable)
-{
- DTableDesc const dtd = HUF_getDTableDesc(DTable);
- return dtd.tableType ? HUF_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable)
- : HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);
-}
-
-typedef struct {
- U32 tableTime;
- U32 decode256Time;
-} algo_time_t;
-static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] = {
- /* single, double, quad */
- {{0, 0}, {1, 1}, {2, 2}}, /* Q==0 : impossible */
- {{0, 0}, {1, 1}, {2, 2}}, /* Q==1 : impossible */
- {{38, 130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */
- {{448, 128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */
- {{556, 128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */
- {{714, 128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */
- {{883, 128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */
- {{897, 128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */
- {{926, 128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */
- {{947, 128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */
- {{1107, 128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */
- {{1177, 128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */
- {{1242, 128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */
- {{1349, 128}, {2644, 106}, {5260, 106}}, /* Q ==13 : 81-87% */
- {{1455, 128}, {2422, 124}, {4174, 124}}, /* Q ==14 : 87-93% */
- {{722, 128}, {1891, 145}, {1936, 146}}, /* Q ==15 : 93-99% */
-};
-
-/** HUF_selectDecoder() :
-* Tells which decoder is likely to decode faster,
-* based on a set of pre-determined metrics.
-* @return : 0==HUF_decompress4X2, 1==HUF_decompress4X4 .
-* Assumption : 0 < cSrcSize < dstSize <= 128 KB */
-U32 HUF_selectDecoder(size_t dstSize, size_t cSrcSize)
-{
- /* decoder timing evaluation */
- U32 const Q = (U32)(cSrcSize * 16 / dstSize); /* Q < 16 since dstSize > cSrcSize */
- U32 const D256 = (U32)(dstSize >> 8);
- U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
- U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
- DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, for cache eviction */
-
- return DTime1 < DTime0;
-}
-
-typedef size_t (*decompressionAlgo)(void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize);
-
-size_t HUF_decompress4X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
-{
- /* validation checks */
- if (dstSize == 0)
- return ERROR(dstSize_tooSmall);
- if (cSrcSize > dstSize)
- return ERROR(corruption_detected); /* invalid */
- if (cSrcSize == dstSize) {
- memcpy(dst, cSrc, dstSize);
- return dstSize;
- } /* not compressed */
- if (cSrcSize == 1) {
- memset(dst, *(const BYTE *)cSrc, dstSize);
- return dstSize;
- } /* RLE */
-
- {
- U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
- return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
- : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
- }
-}
-
-size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
-{
- /* validation checks */
- if (dstSize == 0)
- return ERROR(dstSize_tooSmall);
- if ((cSrcSize >= dstSize) || (cSrcSize <= 1))
- return ERROR(corruption_detected); /* invalid */
-
- {
- U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
- return algoNb ? HUF_decompress4X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
- : HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
- }
-}
-
-size_t HUF_decompress1X_DCtx_wksp(HUF_DTable *dctx, void *dst, size_t dstSize, const void *cSrc, size_t cSrcSize, void *workspace, size_t workspaceSize)
-{
- /* validation checks */
- if (dstSize == 0)
- return ERROR(dstSize_tooSmall);
- if (cSrcSize > dstSize)
- return ERROR(corruption_detected); /* invalid */
- if (cSrcSize == dstSize) {
- memcpy(dst, cSrc, dstSize);
- return dstSize;
- } /* not compressed */
- if (cSrcSize == 1) {
- memset(dst, *(const BYTE *)cSrc, dstSize);
- return dstSize;
- } /* RLE */
-
- {
- U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);
- return algoNb ? HUF_decompress1X4_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize)
- : HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workspace, workspaceSize);
- }
-}
diff --git a/lib/zstd/mem.h b/lib/zstd/mem.h
deleted file mode 100644
index 7225b39..0000000
--- a/lib/zstd/mem.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
-/**
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
- * All rights reserved.
- */
-
-#ifndef MEM_H_MODULE
-#define MEM_H_MODULE
-
-/*-****************************************
-* Dependencies
-******************************************/
-#include <asm/unaligned.h>
-#include <compiler.h>
-#include <linux/string.h> /* memcpy */
-#include <linux/types.h> /* size_t, ptrdiff_t */
-
-/*-****************************************
-* Compiler specifics
-******************************************/
-#define ZSTD_STATIC static __inline __attribute__((unused))
-
-/*-**************************************************************
-* Basic Types
-*****************************************************************/
-typedef uint8_t BYTE;
-typedef uint16_t U16;
-typedef int16_t S16;
-typedef uint32_t U32;
-typedef int32_t S32;
-typedef uint64_t U64;
-typedef int64_t S64;
-typedef ptrdiff_t iPtrDiff;
-typedef uintptr_t uPtrDiff;
-
-/*-**************************************************************
-* Memory I/O
-*****************************************************************/
-ZSTD_STATIC unsigned ZSTD_32bits(void) { return sizeof(size_t) == 4; }
-ZSTD_STATIC unsigned ZSTD_64bits(void) { return sizeof(size_t) == 8; }
-
-#if defined(__LITTLE_ENDIAN)
-#define ZSTD_LITTLE_ENDIAN 1
-#else
-#define ZSTD_LITTLE_ENDIAN 0
-#endif
-
-ZSTD_STATIC unsigned ZSTD_isLittleEndian(void) { return ZSTD_LITTLE_ENDIAN; }
-
-ZSTD_STATIC U16 ZSTD_read16(const void *memPtr) { return get_unaligned((const U16 *)memPtr); }
-
-ZSTD_STATIC U32 ZSTD_read32(const void *memPtr) { return get_unaligned((const U32 *)memPtr); }
-
-ZSTD_STATIC U64 ZSTD_read64(const void *memPtr) { return get_unaligned((const U64 *)memPtr); }
-
-ZSTD_STATIC size_t ZSTD_readST(const void *memPtr) { return get_unaligned((const size_t *)memPtr); }
-
-ZSTD_STATIC void ZSTD_write16(void *memPtr, U16 value) { put_unaligned(value, (U16 *)memPtr); }
-
-ZSTD_STATIC void ZSTD_write32(void *memPtr, U32 value) { put_unaligned(value, (U32 *)memPtr); }
-
-ZSTD_STATIC void ZSTD_write64(void *memPtr, U64 value) { put_unaligned(value, (U64 *)memPtr); }
-
-/*=== Little endian r/w ===*/
-
-ZSTD_STATIC U16 ZSTD_readLE16(const void *memPtr) { return get_unaligned_le16(memPtr); }
-
-ZSTD_STATIC void ZSTD_writeLE16(void *memPtr, U16 val) { put_unaligned_le16(val, memPtr); }
-
-ZSTD_STATIC U32 ZSTD_readLE24(const void *memPtr) { return ZSTD_readLE16(memPtr) + (((const BYTE *)memPtr)[2] << 16); }
-
-ZSTD_STATIC void ZSTD_writeLE24(void *memPtr, U32 val)
-{
- ZSTD_writeLE16(memPtr, (U16)val);
- ((BYTE *)memPtr)[2] = (BYTE)(val >> 16);
-}
-
-ZSTD_STATIC U32 ZSTD_readLE32(const void *memPtr) { return get_unaligned_le32(memPtr); }
-
-ZSTD_STATIC void ZSTD_writeLE32(void *memPtr, U32 val32) { put_unaligned_le32(val32, memPtr); }
-
-ZSTD_STATIC U64 ZSTD_readLE64(const void *memPtr) { return get_unaligned_le64(memPtr); }
-
-ZSTD_STATIC void ZSTD_writeLE64(void *memPtr, U64 val64) { put_unaligned_le64(val64, memPtr); }
-
-ZSTD_STATIC size_t ZSTD_readLEST(const void *memPtr)
-{
- if (ZSTD_32bits())
- return (size_t)ZSTD_readLE32(memPtr);
- else
- return (size_t)ZSTD_readLE64(memPtr);
-}
-
-ZSTD_STATIC void ZSTD_writeLEST(void *memPtr, size_t val)
-{
- if (ZSTD_32bits())
- ZSTD_writeLE32(memPtr, (U32)val);
- else
- ZSTD_writeLE64(memPtr, (U64)val);
-}
-
-/*=== Big endian r/w ===*/
-
-ZSTD_STATIC U32 ZSTD_readBE32(const void *memPtr) { return get_unaligned_be32(memPtr); }
-
-ZSTD_STATIC void ZSTD_writeBE32(void *memPtr, U32 val32) { put_unaligned_be32(val32, memPtr); }
-
-ZSTD_STATIC U64 ZSTD_readBE64(const void *memPtr) { return get_unaligned_be64(memPtr); }
-
-ZSTD_STATIC void ZSTD_writeBE64(void *memPtr, U64 val64) { put_unaligned_be64(val64, memPtr); }
-
-ZSTD_STATIC size_t ZSTD_readBEST(const void *memPtr)
-{
- if (ZSTD_32bits())
- return (size_t)ZSTD_readBE32(memPtr);
- else
- return (size_t)ZSTD_readBE64(memPtr);
-}
-
-ZSTD_STATIC void ZSTD_writeBEST(void *memPtr, size_t val)
-{
- if (ZSTD_32bits())
- ZSTD_writeBE32(memPtr, (U32)val);
- else
- ZSTD_writeBE64(memPtr, (U64)val);
-}
-
-/* function safe only for comparisons */
-ZSTD_STATIC U32 ZSTD_readMINMATCH(const void *memPtr, U32 length)
-{
- switch (length) {
- default:
- case 4: return ZSTD_read32(memPtr);
- case 3:
- if (ZSTD_isLittleEndian())
- return ZSTD_read32(memPtr) << 8;
- else
- return ZSTD_read32(memPtr) >> 8;
- }
-}
-
-#endif /* MEM_H_MODULE */
diff --git a/lib/zstd/zstd.c b/lib/zstd/zstd.c
index bf9cd19..3a2abc8 100644
--- a/lib/zstd/zstd.c
+++ b/lib/zstd/zstd.c
@@ -13,14 +13,12 @@
int zstd_decompress(struct abuf *in, struct abuf *out)
{
- ZSTD_DStream *dstream;
- ZSTD_inBuffer in_buf;
- ZSTD_outBuffer out_buf;
+ zstd_dctx *ctx;
+ size_t wsize, len;
void *workspace;
- size_t wsize;
int ret;
- wsize = ZSTD_DStreamWorkspaceBound(abuf_size(in));
+ wsize = zstd_dctx_workspace_bound();
workspace = malloc(wsize);
if (!workspace) {
debug("%s: cannot allocate workspace of size %zu\n", __func__,
@@ -28,36 +26,35 @@
return -ENOMEM;
}
- dstream = ZSTD_initDStream(abuf_size(in), workspace, wsize);
- if (!dstream) {
- log_err("%s: ZSTD_initDStream failed\n", __func__);
+ ctx = zstd_init_dctx(workspace, wsize);
+ if (!ctx) {
+ log_err("%s: zstd_init_dctx() failed\n", __func__);
ret = -EPERM;
goto do_free;
}
- in_buf.src = abuf_data(in);
- in_buf.pos = 0;
- in_buf.size = abuf_size(in);
-
- out_buf.dst = abuf_data(out);
- out_buf.pos = 0;
- out_buf.size = abuf_size(out);
-
- while (1) {
- size_t res;
-
- res = ZSTD_decompressStream(dstream, &out_buf, &in_buf);
- if (ZSTD_isError(res)) {
- ret = ZSTD_getErrorCode(res);
- log_err("ZSTD_decompressStream error %d\n", ret);
- goto do_free;
- }
-
- if (in_buf.pos >= abuf_size(in) || !res)
- break;
+ /*
+ * Find out how large the frame actually is, there may be junk at
+ * the end of the frame that zstd_decompress_dctx() can't handle.
+ */
+ len = zstd_find_frame_compressed_size(abuf_data(in), abuf_size(in));
+ if (zstd_is_error(len)) {
+ log_err("%s: failed to detect compressed size: %d\n", __func__,
+ zstd_get_error_code(len));
+ ret = -EINVAL;
+ goto do_free;
}
- ret = out_buf.pos;
+ len = zstd_decompress_dctx(ctx, abuf_data(out), abuf_size(out),
+ abuf_data(in), len);
+ if (zstd_is_error(len)) {
+ log_err("%s: failed to decompress: %d\n", __func__,
+ zstd_get_error_code(len));
+ ret = -EINVAL;
+ goto do_free;
+ }
+
+ ret = len;
do_free:
free(workspace);
return ret;
diff --git a/lib/zstd/zstd_common.c b/lib/zstd/zstd_common.c
deleted file mode 100644
index 6b2c79e..0000000
--- a/lib/zstd/zstd_common.c
+++ /dev/null
@@ -1,66 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear)
-/**
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
- * All rights reserved.
- */
-
-/*-*************************************
-* Dependencies
-***************************************/
-#include "error_private.h"
-#include "zstd_internal.h" /* declaration of ZSTD_isError, ZSTD_getErrorName, ZSTD_getErrorCode, ZSTD_getErrorString, ZSTD_versionNumber */
-#include <malloc.h>
-#include <linux/kernel.h>
-
-/*=**************************************************************
-* Custom allocator
-****************************************************************/
-
-#define stack_push(stack, size) \
- ({ \
- void *const ptr = ZSTD_PTR_ALIGN((stack)->ptr); \
- (stack)->ptr = (char *)ptr + (size); \
- (stack)->ptr <= (stack)->end ? ptr : NULL; \
- })
-
-ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize)
-{
- ZSTD_customMem stackMem = {ZSTD_stackAlloc, ZSTD_stackFree, workspace};
- ZSTD_stack *stack = (ZSTD_stack *)workspace;
- /* Verify preconditions */
- if (!workspace || workspaceSize < sizeof(ZSTD_stack) || workspace != ZSTD_PTR_ALIGN(workspace)) {
- ZSTD_customMem error = {NULL, NULL, NULL};
- return error;
- }
- /* Initialize the stack */
- stack->ptr = workspace;
- stack->end = (char *)workspace + workspaceSize;
- stack_push(stack, sizeof(ZSTD_stack));
- return stackMem;
-}
-
-void *ZSTD_stackAllocAll(void *opaque, size_t *size)
-{
- ZSTD_stack *stack = (ZSTD_stack *)opaque;
- *size = (BYTE const *)stack->end - (BYTE *)ZSTD_PTR_ALIGN(stack->ptr);
- return stack_push(stack, *size);
-}
-
-void *ZSTD_stackAlloc(void *opaque, size_t size)
-{
- ZSTD_stack *stack = (ZSTD_stack *)opaque;
- return stack_push(stack, size);
-}
-void ZSTD_stackFree(void *opaque, void *address)
-{
- (void)opaque;
- (void)address;
-}
-
-void *ZSTD_malloc(size_t size, ZSTD_customMem customMem) { return customMem.customAlloc(customMem.opaque, size); }
-
-void ZSTD_free(void *ptr, ZSTD_customMem customMem)
-{
- if (ptr != NULL)
- customMem.customFree(customMem.opaque, ptr);
-}
diff --git a/lib/zstd/zstd_common_module.c b/lib/zstd/zstd_common_module.c
new file mode 100644
index 0000000..73b97c2
--- /dev/null
+++ b/lib/zstd/zstd_common_module.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#include <linux/compat.h>
+
+#include "common/huf.h"
+#include "common/fse.h"
+#include "common/zstd_internal.h"
+
+// Export symbols shared by compress and decompress into a common module
+
+#undef ZSTD_isError /* defined within zstd_internal.h */
+EXPORT_SYMBOL_GPL(FSE_readNCount);
+EXPORT_SYMBOL_GPL(HUF_readStats);
+EXPORT_SYMBOL_GPL(HUF_readStats_wksp);
+EXPORT_SYMBOL_GPL(ZSTD_isError);
+EXPORT_SYMBOL_GPL(ZSTD_getErrorName);
+EXPORT_SYMBOL_GPL(ZSTD_getErrorCode);
+EXPORT_SYMBOL_GPL(ZSTD_customMalloc);
+EXPORT_SYMBOL_GPL(ZSTD_customCalloc);
+EXPORT_SYMBOL_GPL(ZSTD_customFree);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Zstd Common");
diff --git a/lib/zstd/zstd_decompress_module.c b/lib/zstd/zstd_decompress_module.c
new file mode 100644
index 0000000..06cf3e4
--- /dev/null
+++ b/lib/zstd/zstd_decompress_module.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#include <linux/kernel.h>
+#include <linux/compat.h>
+#include <linux/string.h>
+#include <linux/zstd.h>
+
+#include "common/zstd_deps.h"
+
+/* Common symbols. zstd_compress must depend on zstd_decompress. */
+
+unsigned int zstd_is_error(size_t code)
+{
+ return ZSTD_isError(code);
+}
+EXPORT_SYMBOL(zstd_is_error);
+
+zstd_error_code zstd_get_error_code(size_t code)
+{
+ return ZSTD_getErrorCode(code);
+}
+EXPORT_SYMBOL(zstd_get_error_code);
+
+const char *zstd_get_error_name(size_t code)
+{
+ return ZSTD_getErrorName(code);
+}
+EXPORT_SYMBOL(zstd_get_error_name);
+
+/* Decompression symbols. */
+
+size_t zstd_dctx_workspace_bound(void)
+{
+ return ZSTD_estimateDCtxSize();
+}
+EXPORT_SYMBOL(zstd_dctx_workspace_bound);
+
+zstd_dctx *zstd_init_dctx(void *workspace, size_t workspace_size)
+{
+ if (workspace == NULL)
+ return NULL;
+ return ZSTD_initStaticDCtx(workspace, workspace_size);
+}
+EXPORT_SYMBOL(zstd_init_dctx);
+
+size_t zstd_decompress_dctx(zstd_dctx *dctx, void *dst, size_t dst_capacity,
+ const void *src, size_t src_size)
+{
+ return ZSTD_decompressDCtx(dctx, dst, dst_capacity, src, src_size);
+}
+EXPORT_SYMBOL(zstd_decompress_dctx);
+
+size_t zstd_dstream_workspace_bound(size_t max_window_size)
+{
+ return ZSTD_estimateDStreamSize(max_window_size);
+}
+EXPORT_SYMBOL(zstd_dstream_workspace_bound);
+
+zstd_dstream *zstd_init_dstream(size_t max_window_size, void *workspace,
+ size_t workspace_size)
+{
+ if (workspace == NULL)
+ return NULL;
+ (void)max_window_size;
+ return ZSTD_initStaticDStream(workspace, workspace_size);
+}
+EXPORT_SYMBOL(zstd_init_dstream);
+
+size_t zstd_reset_dstream(zstd_dstream *dstream)
+{
+ return ZSTD_resetDStream(dstream);
+}
+EXPORT_SYMBOL(zstd_reset_dstream);
+
+size_t zstd_decompress_stream(zstd_dstream *dstream, zstd_out_buffer *output,
+ zstd_in_buffer *input)
+{
+ return ZSTD_decompressStream(dstream, output, input);
+}
+EXPORT_SYMBOL(zstd_decompress_stream);
+
+size_t zstd_find_frame_compressed_size(const void *src, size_t src_size)
+{
+ return ZSTD_findFrameCompressedSize(src, src_size);
+}
+EXPORT_SYMBOL(zstd_find_frame_compressed_size);
+
+size_t zstd_get_frame_header(zstd_frame_header *header, const void *src,
+ size_t src_size)
+{
+ return ZSTD_getFrameHeader(header, src, src_size);
+}
+EXPORT_SYMBOL(zstd_get_frame_header);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Zstd Decompressor");
diff --git a/lib/zstd/zstd_internal.h b/lib/zstd/zstd_internal.h
deleted file mode 100644
index 551340c..0000000
--- a/lib/zstd/zstd_internal.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
-/**
- * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
- * All rights reserved.
- */
-
-#ifndef ZSTD_CCOMMON_H_MODULE
-#define ZSTD_CCOMMON_H_MODULE
-
-/*-*******************************************************
-* Compiler specifics
-*********************************************************/
-#define FORCE_INLINE static __always_inline
-#define FORCE_NOINLINE static noinline
-
-/*-*************************************
-* Dependencies
-***************************************/
-#include "error_private.h"
-#include "mem.h"
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/xxhash.h>
-#include <linux/zstd.h>
-
-/*-*************************************
-* shared macros
-***************************************/
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define CHECK_F(f) \
- { \
- size_t const errcod = f; \
- if (ERR_isError(errcod)) \
- return errcod; \
- } /* check and Forward error code */
-#define CHECK_E(f, e) \
- { \
- size_t const errcod = f; \
- if (ERR_isError(errcod)) \
- return ERROR(e); \
- } /* check and send Error code */
-#define ZSTD_STATIC_ASSERT(c) \
- { \
- enum { ZSTD_static_assert = 1 / (int)(!!(c)) }; \
- }
-
-/*-*************************************
-* Common constants
-***************************************/
-#define ZSTD_OPT_NUM (1 << 12)
-#define ZSTD_DICT_MAGIC 0xEC30A437 /* v0.7+ */
-
-#define ZSTD_REP_NUM 3 /* number of repcodes */
-#define ZSTD_REP_CHECK (ZSTD_REP_NUM) /* number of repcodes to check by the optimal parser */
-#define ZSTD_REP_MOVE (ZSTD_REP_NUM - 1)
-#define ZSTD_REP_MOVE_OPT (ZSTD_REP_NUM)
-static const U32 repStartValue[ZSTD_REP_NUM] = {1, 4, 8};
-
-#define KB *(1 << 10)
-#define MB *(1 << 20)
-#define GB *(1U << 30)
-
-#define BIT7 128
-#define BIT6 64
-#define BIT5 32
-#define BIT4 16
-#define BIT1 2
-#define BIT0 1
-
-#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
-static const size_t ZSTD_fcs_fieldSize[4] = {0, 2, 4, 8};
-static const size_t ZSTD_did_fieldSize[4] = {0, 1, 2, 4};
-
-#define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
-static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
-typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
-
-#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
-#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */) /* for a non-null block */
-
-#define HufLog 12
-typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingType_e;
-
-#define LONGNBSEQ 0x7F00
-
-#define MINMATCH 3
-#define EQUAL_READ32 4
-
-#define Litbits 8
-#define MaxLit ((1 << Litbits) - 1)
-#define MaxML 52
-#define MaxLL 35
-#define MaxOff 28
-#define MaxSeq MAX(MaxLL, MaxML) /* Assumption : MaxOff < MaxLL,MaxML */
-#define MLFSELog 9
-#define LLFSELog 9
-#define OffFSELog 8
-
-static const U32 LL_bits[MaxLL + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-static const S16 LL_defaultNorm[MaxLL + 1] = {4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, -1, -1, -1, -1};
-#define LL_DEFAULTNORMLOG 6 /* for static allocation */
-static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
-
-static const U32 ML_bits[MaxML + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-static const S16 ML_defaultNorm[MaxML + 1] = {1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1};
-#define ML_DEFAULTNORMLOG 6 /* for static allocation */
-static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
-
-static const S16 OF_defaultNorm[MaxOff + 1] = {1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1};
-#define OF_DEFAULTNORMLOG 5 /* for static allocation */
-static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
-
-/*-*******************************************
-* Shared functions to include for inlining
-*********************************************/
-ZSTD_STATIC void ZSTD_copy8(void *dst, const void *src) {
- memcpy(dst, src, 8);
-}
-/*! ZSTD_wildcopy() :
-* custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */
-#define WILDCOPY_OVERLENGTH 8
-ZSTD_STATIC void ZSTD_wildcopy(void *dst, const void *src, ptrdiff_t length)
-{
- const BYTE* ip = (const BYTE*)src;
- BYTE* op = (BYTE*)dst;
- BYTE* const oend = op + length;
- /* Work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81388.
- * Avoid the bad case where the loop only runs once by handling the
- * special case separately. This doesn't trigger the bug because it
- * doesn't involve pointer/integer overflow.
- */
- if (length <= 8)
- return ZSTD_copy8(dst, src);
- do {
- ZSTD_copy8(op, ip);
- op += 8;
- ip += 8;
- } while (op < oend);
-}
-
-/*-*******************************************
-* Private interfaces
-*********************************************/
-typedef struct ZSTD_stats_s ZSTD_stats_t;
-
-typedef struct {
- U32 off;
- U32 len;
-} ZSTD_match_t;
-
-typedef struct {
- U32 price;
- U32 off;
- U32 mlen;
- U32 litlen;
- U32 rep[ZSTD_REP_NUM];
-} ZSTD_optimal_t;
-
-typedef struct seqDef_s {
- U32 offset;
- U16 litLength;
- U16 matchLength;
-} seqDef;
-
-typedef struct {
- seqDef *sequencesStart;
- seqDef *sequences;
- BYTE *litStart;
- BYTE *lit;
- BYTE *llCode;
- BYTE *mlCode;
- BYTE *ofCode;
- U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */
- U32 longLengthPos;
- /* opt */
- ZSTD_optimal_t *priceTable;
- ZSTD_match_t *matchTable;
- U32 *matchLengthFreq;
- U32 *litLengthFreq;
- U32 *litFreq;
- U32 *offCodeFreq;
- U32 matchLengthSum;
- U32 matchSum;
- U32 litLengthSum;
- U32 litSum;
- U32 offCodeSum;
- U32 log2matchLengthSum;
- U32 log2matchSum;
- U32 log2litLengthSum;
- U32 log2litSum;
- U32 log2offCodeSum;
- U32 factor;
- U32 staticPrices;
- U32 cachedPrice;
- U32 cachedLitLength;
- const BYTE *cachedLiterals;
-} seqStore_t;
-
-const seqStore_t *ZSTD_getSeqStore(const ZSTD_CCtx *ctx);
-void ZSTD_seqToCodes(const seqStore_t *seqStorePtr);
-int ZSTD_isSkipFrame(ZSTD_DCtx *dctx);
-
-/*= Custom memory allocation functions */
-typedef void *(*ZSTD_allocFunction)(void *opaque, size_t size);
-typedef void (*ZSTD_freeFunction)(void *opaque, void *address);
-typedef struct {
- ZSTD_allocFunction customAlloc;
- ZSTD_freeFunction customFree;
- void *opaque;
-} ZSTD_customMem;
-
-void *ZSTD_malloc(size_t size, ZSTD_customMem customMem);
-void ZSTD_free(void *ptr, ZSTD_customMem customMem);
-
-/*====== stack allocation ======*/
-
-typedef struct {
- void *ptr;
- const void *end;
-} ZSTD_stack;
-
-#define ZSTD_ALIGN(x) ALIGN(x, sizeof(size_t))
-#define ZSTD_PTR_ALIGN(p) PTR_ALIGN(p, sizeof(size_t))
-
-ZSTD_customMem ZSTD_initStack(void *workspace, size_t workspaceSize);
-
-void *ZSTD_stackAllocAll(void *opaque, size_t *size);
-void *ZSTD_stackAlloc(void *opaque, size_t size);
-void ZSTD_stackFree(void *opaque, void *address);
-
-/*====== common function ======*/
-
-ZSTD_STATIC U32 ZSTD_highbit32(U32 val) { return 31 - __builtin_clz(val); }
-
-/* hidden functions */
-
-/* ZSTD_invalidateRepCodes() :
- * ensures next compression will not use repcodes from previous block.
- * Note : only works with regular variant;
- * do not use with extDict variant ! */
-void ZSTD_invalidateRepCodes(ZSTD_CCtx *cctx);
-
-size_t ZSTD_freeCCtx(ZSTD_CCtx *cctx);
-size_t ZSTD_freeDCtx(ZSTD_DCtx *dctx);
-size_t ZSTD_freeCDict(ZSTD_CDict *cdict);
-size_t ZSTD_freeDDict(ZSTD_DDict *cdict);
-size_t ZSTD_freeCStream(ZSTD_CStream *zcs);
-size_t ZSTD_freeDStream(ZSTD_DStream *zds);
-
-#endif /* ZSTD_CCOMMON_H_MODULE */
diff --git a/lib/zstd/zstd_opt.h b/lib/zstd/zstd_opt.h
deleted file mode 100644
index af0aaf5..0000000
--- a/lib/zstd/zstd_opt.h
+++ /dev/null
@@ -1,1004 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause-Clear) */
-/**
- * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
- * All rights reserved.
- */
-
-/* Note : this file is intended to be included within zstd_compress.c */
-
-#ifndef ZSTD_OPT_H_91842398743
-#define ZSTD_OPT_H_91842398743
-
-#define ZSTD_LITFREQ_ADD 2
-#define ZSTD_FREQ_DIV 4
-#define ZSTD_MAX_PRICE (1 << 30)
-
-/*-*************************************
-* Price functions for optimal parser
-***************************************/
-FORCE_INLINE void ZSTD_setLog2Prices(seqStore_t *ssPtr)
-{
- ssPtr->log2matchLengthSum = ZSTD_highbit32(ssPtr->matchLengthSum + 1);
- ssPtr->log2litLengthSum = ZSTD_highbit32(ssPtr->litLengthSum + 1);
- ssPtr->log2litSum = ZSTD_highbit32(ssPtr->litSum + 1);
- ssPtr->log2offCodeSum = ZSTD_highbit32(ssPtr->offCodeSum + 1);
- ssPtr->factor = 1 + ((ssPtr->litSum >> 5) / ssPtr->litLengthSum) + ((ssPtr->litSum << 1) / (ssPtr->litSum + ssPtr->matchSum));
-}
-
-ZSTD_STATIC void ZSTD_rescaleFreqs(seqStore_t *ssPtr, const BYTE *src, size_t srcSize)
-{
- unsigned u;
-
- ssPtr->cachedLiterals = NULL;
- ssPtr->cachedPrice = ssPtr->cachedLitLength = 0;
- ssPtr->staticPrices = 0;
-
- if (ssPtr->litLengthSum == 0) {
- if (srcSize <= 1024)
- ssPtr->staticPrices = 1;
-
- for (u = 0; u <= MaxLit; u++)
- ssPtr->litFreq[u] = 0;
- for (u = 0; u < srcSize; u++)
- ssPtr->litFreq[src[u]]++;
-
- ssPtr->litSum = 0;
- ssPtr->litLengthSum = MaxLL + 1;
- ssPtr->matchLengthSum = MaxML + 1;
- ssPtr->offCodeSum = (MaxOff + 1);
- ssPtr->matchSum = (ZSTD_LITFREQ_ADD << Litbits);
-
- for (u = 0; u <= MaxLit; u++) {
- ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> ZSTD_FREQ_DIV);
- ssPtr->litSum += ssPtr->litFreq[u];
- }
- for (u = 0; u <= MaxLL; u++)
- ssPtr->litLengthFreq[u] = 1;
- for (u = 0; u <= MaxML; u++)
- ssPtr->matchLengthFreq[u] = 1;
- for (u = 0; u <= MaxOff; u++)
- ssPtr->offCodeFreq[u] = 1;
- } else {
- ssPtr->matchLengthSum = 0;
- ssPtr->litLengthSum = 0;
- ssPtr->offCodeSum = 0;
- ssPtr->matchSum = 0;
- ssPtr->litSum = 0;
-
- for (u = 0; u <= MaxLit; u++) {
- ssPtr->litFreq[u] = 1 + (ssPtr->litFreq[u] >> (ZSTD_FREQ_DIV + 1));
- ssPtr->litSum += ssPtr->litFreq[u];
- }
- for (u = 0; u <= MaxLL; u++) {
- ssPtr->litLengthFreq[u] = 1 + (ssPtr->litLengthFreq[u] >> (ZSTD_FREQ_DIV + 1));
- ssPtr->litLengthSum += ssPtr->litLengthFreq[u];
- }
- for (u = 0; u <= MaxML; u++) {
- ssPtr->matchLengthFreq[u] = 1 + (ssPtr->matchLengthFreq[u] >> ZSTD_FREQ_DIV);
- ssPtr->matchLengthSum += ssPtr->matchLengthFreq[u];
- ssPtr->matchSum += ssPtr->matchLengthFreq[u] * (u + 3);
- }
- ssPtr->matchSum *= ZSTD_LITFREQ_ADD;
- for (u = 0; u <= MaxOff; u++) {
- ssPtr->offCodeFreq[u] = 1 + (ssPtr->offCodeFreq[u] >> ZSTD_FREQ_DIV);
- ssPtr->offCodeSum += ssPtr->offCodeFreq[u];
- }
- }
-
- ZSTD_setLog2Prices(ssPtr);
-}
-
-FORCE_INLINE U32 ZSTD_getLiteralPrice(seqStore_t *ssPtr, U32 litLength, const BYTE *literals)
-{
- U32 price, u;
-
- if (ssPtr->staticPrices)
- return ZSTD_highbit32((U32)litLength + 1) + (litLength * 6);
-
- if (litLength == 0)
- return ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[0] + 1);
-
- /* literals */
- if (ssPtr->cachedLiterals == literals) {
- U32 const additional = litLength - ssPtr->cachedLitLength;
- const BYTE *literals2 = ssPtr->cachedLiterals + ssPtr->cachedLitLength;
- price = ssPtr->cachedPrice + additional * ssPtr->log2litSum;
- for (u = 0; u < additional; u++)
- price -= ZSTD_highbit32(ssPtr->litFreq[literals2[u]] + 1);
- ssPtr->cachedPrice = price;
- ssPtr->cachedLitLength = litLength;
- } else {
- price = litLength * ssPtr->log2litSum;
- for (u = 0; u < litLength; u++)
- price -= ZSTD_highbit32(ssPtr->litFreq[literals[u]] + 1);
-
- if (litLength >= 12) {
- ssPtr->cachedLiterals = literals;
- ssPtr->cachedPrice = price;
- ssPtr->cachedLitLength = litLength;
- }
- }
-
- /* literal Length */
- {
- const BYTE LL_deltaCode = 19;
- const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
- price += LL_bits[llCode] + ssPtr->log2litLengthSum - ZSTD_highbit32(ssPtr->litLengthFreq[llCode] + 1);
- }
-
- return price;
-}
-
-FORCE_INLINE U32 ZSTD_getPrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength, const int ultra)
-{
- /* offset */
- U32 price;
- BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
-
- if (seqStorePtr->staticPrices)
- return ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + ZSTD_highbit32((U32)matchLength + 1) + 16 + offCode;
-
- price = offCode + seqStorePtr->log2offCodeSum - ZSTD_highbit32(seqStorePtr->offCodeFreq[offCode] + 1);
- if (!ultra && offCode >= 20)
- price += (offCode - 19) * 2;
-
- /* match Length */
- {
- const BYTE ML_deltaCode = 36;
- const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
- price += ML_bits[mlCode] + seqStorePtr->log2matchLengthSum - ZSTD_highbit32(seqStorePtr->matchLengthFreq[mlCode] + 1);
- }
-
- return price + ZSTD_getLiteralPrice(seqStorePtr, litLength, literals) + seqStorePtr->factor;
-}
-
-ZSTD_STATIC void ZSTD_updatePrice(seqStore_t *seqStorePtr, U32 litLength, const BYTE *literals, U32 offset, U32 matchLength)
-{
- U32 u;
-
- /* literals */
- seqStorePtr->litSum += litLength * ZSTD_LITFREQ_ADD;
- for (u = 0; u < litLength; u++)
- seqStorePtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;
-
- /* literal Length */
- {
- const BYTE LL_deltaCode = 19;
- const BYTE llCode = (litLength > 63) ? (BYTE)ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];
- seqStorePtr->litLengthFreq[llCode]++;
- seqStorePtr->litLengthSum++;
- }
-
- /* match offset */
- {
- BYTE const offCode = (BYTE)ZSTD_highbit32(offset + 1);
- seqStorePtr->offCodeSum++;
- seqStorePtr->offCodeFreq[offCode]++;
- }
-
- /* match Length */
- {
- const BYTE ML_deltaCode = 36;
- const BYTE mlCode = (matchLength > 127) ? (BYTE)ZSTD_highbit32(matchLength) + ML_deltaCode : ML_Code[matchLength];
- seqStorePtr->matchLengthFreq[mlCode]++;
- seqStorePtr->matchLengthSum++;
- }
-
- ZSTD_setLog2Prices(seqStorePtr);
-}
-
-#define SET_PRICE(pos, mlen_, offset_, litlen_, price_) \
- { \
- while (last_pos < pos) { \
- opt[last_pos + 1].price = ZSTD_MAX_PRICE; \
- last_pos++; \
- } \
- opt[pos].mlen = mlen_; \
- opt[pos].off = offset_; \
- opt[pos].litlen = litlen_; \
- opt[pos].price = price_; \
- }
-
-/* Update hashTable3 up to ip (excluded)
- Assumption : always within prefix (i.e. not within extDict) */
-FORCE_INLINE
-U32 ZSTD_insertAndFindFirstIndexHash3(ZSTD_CCtx *zc, const BYTE *ip)
-{
- U32 *const hashTable3 = zc->hashTable3;
- U32 const hashLog3 = zc->hashLog3;
- const BYTE *const base = zc->base;
- U32 idx = zc->nextToUpdate3;
- const U32 target = zc->nextToUpdate3 = (U32)(ip - base);
- const size_t hash3 = ZSTD_hash3Ptr(ip, hashLog3);
-
- while (idx < target) {
- hashTable3[ZSTD_hash3Ptr(base + idx, hashLog3)] = idx;
- idx++;
- }
-
- return hashTable3[hash3];
-}
-
-/*-*************************************
-* Binary Tree search
-***************************************/
-static U32 ZSTD_insertBtAndGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, U32 nbCompares, const U32 mls, U32 extDict,
- ZSTD_match_t *matches, const U32 minMatchLen)
-{
- const BYTE *const base = zc->base;
- const U32 curr = (U32)(ip - base);
- const U32 hashLog = zc->params.cParams.hashLog;
- const size_t h = ZSTD_hashPtr(ip, hashLog, mls);
- U32 *const hashTable = zc->hashTable;
- U32 matchIndex = hashTable[h];
- U32 *const bt = zc->chainTable;
- const U32 btLog = zc->params.cParams.chainLog - 1;
- const U32 btMask = (1U << btLog) - 1;
- size_t commonLengthSmaller = 0, commonLengthLarger = 0;
- const BYTE *const dictBase = zc->dictBase;
- const U32 dictLimit = zc->dictLimit;
- const BYTE *const dictEnd = dictBase + dictLimit;
- const BYTE *const prefixStart = base + dictLimit;
- const U32 btLow = btMask >= curr ? 0 : curr - btMask;
- const U32 windowLow = zc->lowLimit;
- U32 *smallerPtr = bt + 2 * (curr & btMask);
- U32 *largerPtr = bt + 2 * (curr & btMask) + 1;
- U32 matchEndIdx = curr + 8;
- U32 dummy32; /* to be nullified at the end */
- U32 mnum = 0;
-
- const U32 minMatch = (mls == 3) ? 3 : 4;
- size_t bestLength = minMatchLen - 1;
-
- if (minMatch == 3) { /* HC3 match finder */
- U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(zc, ip);
- if (matchIndex3 > windowLow && (curr - matchIndex3 < (1 << 18))) {
- const BYTE *match;
- size_t currMl = 0;
- if ((!extDict) || matchIndex3 >= dictLimit) {
- match = base + matchIndex3;
- if (match[bestLength] == ip[bestLength])
- currMl = ZSTD_count(ip, match, iLimit);
- } else {
- match = dictBase + matchIndex3;
- if (ZSTD_readMINMATCH(match, MINMATCH) ==
- ZSTD_readMINMATCH(ip, MINMATCH)) /* assumption : matchIndex3 <= dictLimit-4 (by table construction) */
- currMl = ZSTD_count_2segments(ip + MINMATCH, match + MINMATCH, iLimit, dictEnd, prefixStart) + MINMATCH;
- }
-
- /* save best solution */
- if (currMl > bestLength) {
- bestLength = currMl;
- matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex3;
- matches[mnum].len = (U32)currMl;
- mnum++;
- if (currMl > ZSTD_OPT_NUM)
- goto update;
- if (ip + currMl == iLimit)
- goto update; /* best possible, and avoid read overflow*/
- }
- }
- }
-
- hashTable[h] = curr; /* Update Hash Table */
-
- while (nbCompares-- && (matchIndex > windowLow)) {
- U32 *nextPtr = bt + 2 * (matchIndex & btMask);
- size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
- const BYTE *match;
-
- if ((!extDict) || (matchIndex + matchLength >= dictLimit)) {
- match = base + matchIndex;
- if (match[matchLength] == ip[matchLength]) {
- matchLength += ZSTD_count(ip + matchLength + 1, match + matchLength + 1, iLimit) + 1;
- }
- } else {
- match = dictBase + matchIndex;
- matchLength += ZSTD_count_2segments(ip + matchLength, match + matchLength, iLimit, dictEnd, prefixStart);
- if (matchIndex + matchLength >= dictLimit)
- match = base + matchIndex; /* to prepare for next usage of match[matchLength] */
- }
-
- if (matchLength > bestLength) {
- if (matchLength > matchEndIdx - matchIndex)
- matchEndIdx = matchIndex + (U32)matchLength;
- bestLength = matchLength;
- matches[mnum].off = ZSTD_REP_MOVE_OPT + curr - matchIndex;
- matches[mnum].len = (U32)matchLength;
- mnum++;
- if (matchLength > ZSTD_OPT_NUM)
- break;
- if (ip + matchLength == iLimit) /* equal : no way to know if inf or sup */
- break; /* drop, to guarantee consistency (miss a little bit of compression) */
- }
-
- if (match[matchLength] < ip[matchLength]) {
- /* match is smaller than curr */
- *smallerPtr = matchIndex; /* update smaller idx */
- commonLengthSmaller = matchLength; /* all smaller will now have at least this guaranteed common length */
- if (matchIndex <= btLow) {
- smallerPtr = &dummy32;
- break;
- } /* beyond tree size, stop the search */
- smallerPtr = nextPtr + 1; /* new "smaller" => larger of match */
- matchIndex = nextPtr[1]; /* new matchIndex larger than previous (closer to curr) */
- } else {
- /* match is larger than curr */
- *largerPtr = matchIndex;
- commonLengthLarger = matchLength;
- if (matchIndex <= btLow) {
- largerPtr = &dummy32;
- break;
- } /* beyond tree size, stop the search */
- largerPtr = nextPtr;
- matchIndex = nextPtr[0];
- }
- }
-
- *smallerPtr = *largerPtr = 0;
-
-update:
- zc->nextToUpdate = (matchEndIdx > curr + 8) ? matchEndIdx - 8 : curr + 1;
- return mnum;
-}
-
-/** Tree updater, providing best match */
-static U32 ZSTD_BtGetAllMatches(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls, ZSTD_match_t *matches,
- const U32 minMatchLen)
-{
- if (ip < zc->base + zc->nextToUpdate)
- return 0; /* skipped area */
- ZSTD_updateTree(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 0, matches, minMatchLen);
-}
-
-static U32 ZSTD_BtGetAllMatches_selectMLS(ZSTD_CCtx *zc, /* Index table will be updated */
- const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
- ZSTD_match_t *matches, const U32 minMatchLen)
-{
- switch (matchLengthSearch) {
- case 3: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
- default:
- case 4: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
- case 5: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
- case 7:
- case 6: return ZSTD_BtGetAllMatches(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
- }
-}
-
-/** Tree updater, providing best match */
-static U32 ZSTD_BtGetAllMatches_extDict(ZSTD_CCtx *zc, const BYTE *const ip, const BYTE *const iLimit, const U32 maxNbAttempts, const U32 mls,
- ZSTD_match_t *matches, const U32 minMatchLen)
-{
- if (ip < zc->base + zc->nextToUpdate)
- return 0; /* skipped area */
- ZSTD_updateTree_extDict(zc, ip, iLimit, maxNbAttempts, mls);
- return ZSTD_insertBtAndGetAllMatches(zc, ip, iLimit, maxNbAttempts, mls, 1, matches, minMatchLen);
-}
-
-static U32 ZSTD_BtGetAllMatches_selectMLS_extDict(ZSTD_CCtx *zc, /* Index table will be updated */
- const BYTE *ip, const BYTE *const iHighLimit, const U32 maxNbAttempts, const U32 matchLengthSearch,
- ZSTD_match_t *matches, const U32 minMatchLen)
-{
- switch (matchLengthSearch) {
- case 3: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 3, matches, minMatchLen);
- default:
- case 4: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 4, matches, minMatchLen);
- case 5: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 5, matches, minMatchLen);
- case 7:
- case 6: return ZSTD_BtGetAllMatches_extDict(zc, ip, iHighLimit, maxNbAttempts, 6, matches, minMatchLen);
- }
-}
-
-/*-*******************************
-* Optimal parser
-*********************************/
-FORCE_INLINE
-void ZSTD_compressBlock_opt_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
-{
- seqStore_t *seqStorePtr = &(ctx->seqStore);
- const BYTE *const istart = (const BYTE *)src;
- const BYTE *ip = istart;
- const BYTE *anchor = istart;
- const BYTE *const iend = istart + srcSize;
- const BYTE *const ilimit = iend - 8;
- const BYTE *const base = ctx->base;
- const BYTE *const prefixStart = base + ctx->dictLimit;
-
- const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
- const U32 sufficient_len = ctx->params.cParams.targetLength;
- const U32 mls = ctx->params.cParams.searchLength;
- const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
-
- ZSTD_optimal_t *opt = seqStorePtr->priceTable;
- ZSTD_match_t *matches = seqStorePtr->matchTable;
- const BYTE *inr;
- U32 offset, rep[ZSTD_REP_NUM];
-
- /* init */
- ctx->nextToUpdate3 = ctx->nextToUpdate;
- ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
- ip += (ip == prefixStart);
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- rep[i] = ctx->rep[i];
- }
-
- /* Match Loop */
- while (ip < ilimit) {
- U32 cur, match_num, last_pos, litlen, price;
- U32 u, mlen, best_mlen, best_off, litLength;
- memset(opt, 0, sizeof(ZSTD_optimal_t));
- last_pos = 0;
- litlen = (U32)(ip - anchor);
-
- /* check repCode */
- {
- U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
- for (i = (ip == anchor); i < last_i; i++) {
- const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
- if ((repCur > 0) && (repCur < (S32)(ip - prefixStart)) &&
- (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repCur, minMatch))) {
- mlen = (U32)ZSTD_count(ip + minMatch, ip + minMatch - repCur, iend) + minMatch;
- if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen;
- best_off = i;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
- best_off = i - (ip == anchor);
- do {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
- mlen--;
- } while (mlen >= minMatch);
- }
- }
- }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, ip, iend, maxSearches, mls, matches, minMatch);
-
- if (!last_pos && !match_num) {
- ip++;
- continue;
- }
-
- if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num - 1].len;
- best_off = matches[match_num - 1].off;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
-
- /* set prices using matches at position = 0 */
- best_mlen = (last_pos) ? last_pos : minMatch;
- for (u = 0; u < match_num; u++) {
- mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
- best_mlen = matches[u].len;
- while (mlen <= best_mlen) {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, matches[u].off, litlen, price); /* note : macro modifies last_pos */
- mlen++;
- }
- }
-
- if (last_pos < minMatch) {
- ip++;
- continue;
- }
-
- /* initialize opt[0] */
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- opt[0].rep[i] = rep[i];
- }
- opt[0].mlen = 1;
- opt[0].litlen = litlen;
-
- /* check further positions */
- for (cur = 1; cur <= last_pos; cur++) {
- inr = ip + cur;
-
- if (opt[cur - 1].mlen == 1) {
- litlen = opt[cur - 1].litlen + 1;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
- } else
- price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
- } else {
- litlen = 1;
- price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
- }
-
- if (cur > last_pos || price <= opt[cur].price)
- SET_PRICE(cur, 1, 0, litlen, price);
-
- if (cur == last_pos)
- break;
-
- if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
- continue;
-
- mlen = opt[cur].mlen;
- if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
- opt[cur].rep[2] = opt[cur - mlen].rep[1];
- opt[cur].rep[1] = opt[cur - mlen].rep[0];
- opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
- } else {
- opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
- opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
- opt[cur].rep[0] =
- ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
- }
-
- best_mlen = minMatch;
- {
- U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
- for (i = (opt[cur].mlen != 1); i < last_i; i++) { /* check rep */
- const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
- if ((repCur > 0) && (repCur < (S32)(inr - prefixStart)) &&
- (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(inr - repCur, minMatch))) {
- mlen = (U32)ZSTD_count(inr + minMatch, inr + minMatch - repCur, iend) + minMatch;
-
- if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen;
- best_off = i;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- best_off = i - (opt[cur].mlen != 1);
- if (mlen > best_mlen)
- best_mlen = mlen;
-
- do {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
- best_off, mlen - MINMATCH, ultra);
- } else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
- SET_PRICE(cur + mlen, mlen, i, litlen, price);
- mlen--;
- } while (mlen >= minMatch);
- }
- }
- }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS(ctx, inr, iend, maxSearches, mls, matches, best_mlen);
-
- if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num - 1].len;
- best_off = matches[match_num - 1].off;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- /* set prices using matches at position = cur */
- for (u = 0; u < match_num; u++) {
- mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
- best_mlen = matches[u].len;
-
- while (mlen <= best_mlen) {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen)
- price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
- matches[u].off - 1, mlen - MINMATCH, ultra);
- else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
- SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
-
- mlen++;
- }
- }
- }
-
- best_mlen = opt[last_pos].mlen;
- best_off = opt[last_pos].off;
- cur = last_pos - best_mlen;
-
- /* store sequence */
-_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
- opt[0].mlen = 1;
-
- while (1) {
- mlen = opt[cur].mlen;
- offset = opt[cur].off;
- opt[cur].mlen = best_mlen;
- opt[cur].off = best_off;
- best_mlen = mlen;
- best_off = offset;
- if (mlen > cur)
- break;
- cur -= mlen;
- }
-
- for (u = 0; u <= last_pos;) {
- u += opt[u].mlen;
- }
-
- for (cur = 0; cur < last_pos;) {
- mlen = opt[cur].mlen;
- if (mlen == 1) {
- ip++;
- cur++;
- continue;
- }
- offset = opt[cur].off;
- cur += mlen;
- litLength = (U32)(ip - anchor);
-
- if (offset > ZSTD_REP_MOVE_OPT) {
- rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = offset - ZSTD_REP_MOVE_OPT;
- offset--;
- } else {
- if (offset != 0) {
- best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
- if (offset != 1)
- rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = best_off;
- }
- if (litLength == 0)
- offset--;
- }
-
- ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
- anchor = ip = ip + mlen;
- }
- } /* for (cur=0; cur < last_pos; ) */
-
- /* Save reps for next block */
- {
- int i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- ctx->repToConfirm[i] = rep[i];
- }
-
- /* Last Literals */
- {
- size_t const lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-FORCE_INLINE
-void ZSTD_compressBlock_opt_extDict_generic(ZSTD_CCtx *ctx, const void *src, size_t srcSize, const int ultra)
-{
- seqStore_t *seqStorePtr = &(ctx->seqStore);
- const BYTE *const istart = (const BYTE *)src;
- const BYTE *ip = istart;
- const BYTE *anchor = istart;
- const BYTE *const iend = istart + srcSize;
- const BYTE *const ilimit = iend - 8;
- const BYTE *const base = ctx->base;
- const U32 lowestIndex = ctx->lowLimit;
- const U32 dictLimit = ctx->dictLimit;
- const BYTE *const prefixStart = base + dictLimit;
- const BYTE *const dictBase = ctx->dictBase;
- const BYTE *const dictEnd = dictBase + dictLimit;
-
- const U32 maxSearches = 1U << ctx->params.cParams.searchLog;
- const U32 sufficient_len = ctx->params.cParams.targetLength;
- const U32 mls = ctx->params.cParams.searchLength;
- const U32 minMatch = (ctx->params.cParams.searchLength == 3) ? 3 : 4;
-
- ZSTD_optimal_t *opt = seqStorePtr->priceTable;
- ZSTD_match_t *matches = seqStorePtr->matchTable;
- const BYTE *inr;
-
- /* init */
- U32 offset, rep[ZSTD_REP_NUM];
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- rep[i] = ctx->rep[i];
- }
-
- ctx->nextToUpdate3 = ctx->nextToUpdate;
- ZSTD_rescaleFreqs(seqStorePtr, (const BYTE *)src, srcSize);
- ip += (ip == prefixStart);
-
- /* Match Loop */
- while (ip < ilimit) {
- U32 cur, match_num, last_pos, litlen, price;
- U32 u, mlen, best_mlen, best_off, litLength;
- U32 curr = (U32)(ip - base);
- memset(opt, 0, sizeof(ZSTD_optimal_t));
- last_pos = 0;
- opt[0].litlen = (U32)(ip - anchor);
-
- /* check repCode */
- {
- U32 i, last_i = ZSTD_REP_CHECK + (ip == anchor);
- for (i = (ip == anchor); i < last_i; i++) {
- const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : rep[i];
- const U32 repIndex = (U32)(curr - repCur);
- const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE *const repMatch = repBase + repIndex;
- if ((repCur > 0 && repCur <= (S32)curr) &&
- (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
- && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
- /* repcode detected we should take it */
- const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
- mlen = (U32)ZSTD_count_2segments(ip + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
-
- if (mlen > sufficient_len || mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen;
- best_off = i;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
-
- best_off = i - (ip == anchor);
- litlen = opt[0].litlen;
- do {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, i, litlen, price); /* note : macro modifies last_pos */
- mlen--;
- } while (mlen >= minMatch);
- }
- }
- }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, ip, iend, maxSearches, mls, matches, minMatch); /* first search (depth 0) */
-
- if (!last_pos && !match_num) {
- ip++;
- continue;
- }
-
- {
- U32 i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- opt[0].rep[i] = rep[i];
- }
- opt[0].mlen = 1;
-
- if (match_num && (matches[match_num - 1].len > sufficient_len || matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num - 1].len;
- best_off = matches[match_num - 1].off;
- cur = 0;
- last_pos = 1;
- goto _storeSequence;
- }
-
- best_mlen = (last_pos) ? last_pos : minMatch;
-
- /* set prices using matches at position = 0 */
- for (u = 0; u < match_num; u++) {
- mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
- best_mlen = matches[u].len;
- litlen = opt[0].litlen;
- while (mlen <= best_mlen) {
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
- if (mlen > last_pos || price < opt[mlen].price)
- SET_PRICE(mlen, mlen, matches[u].off, litlen, price);
- mlen++;
- }
- }
-
- if (last_pos < minMatch) {
- ip++;
- continue;
- }
-
- /* check further positions */
- for (cur = 1; cur <= last_pos; cur++) {
- inr = ip + cur;
-
- if (opt[cur - 1].mlen == 1) {
- litlen = opt[cur - 1].litlen + 1;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - litlen);
- } else
- price = ZSTD_getLiteralPrice(seqStorePtr, litlen, anchor);
- } else {
- litlen = 1;
- price = opt[cur - 1].price + ZSTD_getLiteralPrice(seqStorePtr, litlen, inr - 1);
- }
-
- if (cur > last_pos || price <= opt[cur].price)
- SET_PRICE(cur, 1, 0, litlen, price);
-
- if (cur == last_pos)
- break;
-
- if (inr > ilimit) /* last match must start at a minimum distance of 8 from oend */
- continue;
-
- mlen = opt[cur].mlen;
- if (opt[cur].off > ZSTD_REP_MOVE_OPT) {
- opt[cur].rep[2] = opt[cur - mlen].rep[1];
- opt[cur].rep[1] = opt[cur - mlen].rep[0];
- opt[cur].rep[0] = opt[cur].off - ZSTD_REP_MOVE_OPT;
- } else {
- opt[cur].rep[2] = (opt[cur].off > 1) ? opt[cur - mlen].rep[1] : opt[cur - mlen].rep[2];
- opt[cur].rep[1] = (opt[cur].off > 0) ? opt[cur - mlen].rep[0] : opt[cur - mlen].rep[1];
- opt[cur].rep[0] =
- ((opt[cur].off == ZSTD_REP_MOVE_OPT) && (mlen != 1)) ? (opt[cur - mlen].rep[0] - 1) : (opt[cur - mlen].rep[opt[cur].off]);
- }
-
- best_mlen = minMatch;
- {
- U32 i, last_i = ZSTD_REP_CHECK + (mlen != 1);
- for (i = (mlen != 1); i < last_i; i++) {
- const S32 repCur = (i == ZSTD_REP_MOVE_OPT) ? (opt[cur].rep[0] - 1) : opt[cur].rep[i];
- const U32 repIndex = (U32)(curr + cur - repCur);
- const BYTE *const repBase = repIndex < dictLimit ? dictBase : base;
- const BYTE *const repMatch = repBase + repIndex;
- if ((repCur > 0 && repCur <= (S32)(curr + cur)) &&
- (((U32)((dictLimit - 1) - repIndex) >= 3) & (repIndex > lowestIndex)) /* intentional overflow */
- && (ZSTD_readMINMATCH(inr, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch))) {
- /* repcode detected */
- const BYTE *const repEnd = repIndex < dictLimit ? dictEnd : iend;
- mlen = (U32)ZSTD_count_2segments(inr + minMatch, repMatch + minMatch, iend, repEnd, prefixStart) + minMatch;
-
- if (mlen > sufficient_len || cur + mlen >= ZSTD_OPT_NUM) {
- best_mlen = mlen;
- best_off = i;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- best_off = i - (opt[cur].mlen != 1);
- if (mlen > best_mlen)
- best_mlen = mlen;
-
- do {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen) {
- price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, inr - litlen,
- best_off, mlen - MINMATCH, ultra);
- } else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, best_off, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, best_off, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || price <= opt[cur + mlen].price)
- SET_PRICE(cur + mlen, mlen, i, litlen, price);
- mlen--;
- } while (mlen >= minMatch);
- }
- }
- }
-
- match_num = ZSTD_BtGetAllMatches_selectMLS_extDict(ctx, inr, iend, maxSearches, mls, matches, minMatch);
-
- if (match_num > 0 && (matches[match_num - 1].len > sufficient_len || cur + matches[match_num - 1].len >= ZSTD_OPT_NUM)) {
- best_mlen = matches[match_num - 1].len;
- best_off = matches[match_num - 1].off;
- last_pos = cur + 1;
- goto _storeSequence;
- }
-
- /* set prices using matches at position = cur */
- for (u = 0; u < match_num; u++) {
- mlen = (u > 0) ? matches[u - 1].len + 1 : best_mlen;
- best_mlen = matches[u].len;
-
- while (mlen <= best_mlen) {
- if (opt[cur].mlen == 1) {
- litlen = opt[cur].litlen;
- if (cur > litlen)
- price = opt[cur - litlen].price + ZSTD_getPrice(seqStorePtr, litlen, ip + cur - litlen,
- matches[u].off - 1, mlen - MINMATCH, ultra);
- else
- price = ZSTD_getPrice(seqStorePtr, litlen, anchor, matches[u].off - 1, mlen - MINMATCH, ultra);
- } else {
- litlen = 0;
- price = opt[cur].price + ZSTD_getPrice(seqStorePtr, 0, NULL, matches[u].off - 1, mlen - MINMATCH, ultra);
- }
-
- if (cur + mlen > last_pos || (price < opt[cur + mlen].price))
- SET_PRICE(cur + mlen, mlen, matches[u].off, litlen, price);
-
- mlen++;
- }
- }
- } /* for (cur = 1; cur <= last_pos; cur++) */
-
- best_mlen = opt[last_pos].mlen;
- best_off = opt[last_pos].off;
- cur = last_pos - best_mlen;
-
- /* store sequence */
-_storeSequence: /* cur, last_pos, best_mlen, best_off have to be set */
- opt[0].mlen = 1;
-
- while (1) {
- mlen = opt[cur].mlen;
- offset = opt[cur].off;
- opt[cur].mlen = best_mlen;
- opt[cur].off = best_off;
- best_mlen = mlen;
- best_off = offset;
- if (mlen > cur)
- break;
- cur -= mlen;
- }
-
- for (u = 0; u <= last_pos;) {
- u += opt[u].mlen;
- }
-
- for (cur = 0; cur < last_pos;) {
- mlen = opt[cur].mlen;
- if (mlen == 1) {
- ip++;
- cur++;
- continue;
- }
- offset = opt[cur].off;
- cur += mlen;
- litLength = (U32)(ip - anchor);
-
- if (offset > ZSTD_REP_MOVE_OPT) {
- rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = offset - ZSTD_REP_MOVE_OPT;
- offset--;
- } else {
- if (offset != 0) {
- best_off = (offset == ZSTD_REP_MOVE_OPT) ? (rep[0] - 1) : (rep[offset]);
- if (offset != 1)
- rep[2] = rep[1];
- rep[1] = rep[0];
- rep[0] = best_off;
- }
-
- if (litLength == 0)
- offset--;
- }
-
- ZSTD_updatePrice(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
- ZSTD_storeSeq(seqStorePtr, litLength, anchor, offset, mlen - MINMATCH);
- anchor = ip = ip + mlen;
- }
- } /* for (cur=0; cur < last_pos; ) */
-
- /* Save reps for next block */
- {
- int i;
- for (i = 0; i < ZSTD_REP_NUM; i++)
- ctx->repToConfirm[i] = rep[i];
- }
-
- /* Last Literals */
- {
- size_t lastLLSize = iend - anchor;
- memcpy(seqStorePtr->lit, anchor, lastLLSize);
- seqStorePtr->lit += lastLLSize;
- }
-}
-
-#endif /* ZSTD_OPT_H_91842398743 */
diff --git a/net/bootp.c b/net/bootp.c
index 7ac0093..cae0419 100644
--- a/net/bootp.c
+++ b/net/bootp.c
@@ -44,15 +44,15 @@
#define PORT_BOOTPS 67 /* BOOTP server UDP port */
#define PORT_BOOTPC 68 /* BOOTP client UDP port */
-#ifndef CONFIG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
-#define CONFIG_DHCP_MIN_EXT_LEN 64
+#ifndef CFG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
+#define CFG_DHCP_MIN_EXT_LEN 64
#endif
-#ifndef CONFIG_BOOTP_ID_CACHE_SIZE
-#define CONFIG_BOOTP_ID_CACHE_SIZE 4
+#ifndef CFG_BOOTP_ID_CACHE_SIZE
+#define CFG_BOOTP_ID_CACHE_SIZE 4
#endif
-u32 bootp_ids[CONFIG_BOOTP_ID_CACHE_SIZE];
+u32 bootp_ids[CFG_BOOTP_ID_CACHE_SIZE];
unsigned int bootp_num_ids;
int bootp_try;
ulong bootp_start;
@@ -611,8 +611,8 @@
*e++ = 255; /* End of the list */
/* Pad to minimal length */
-#ifdef CONFIG_DHCP_MIN_EXT_LEN
- while ((e - start) < CONFIG_DHCP_MIN_EXT_LEN)
+#ifdef CFG_DHCP_MIN_EXT_LEN
+ while ((e - start) < CFG_DHCP_MIN_EXT_LEN)
*e++ = 0;
#endif
diff --git a/net/eth-uclass.c b/net/eth-uclass.c
index f41da4b..b01a910 100644
--- a/net/eth-uclass.c
+++ b/net/eth-uclass.c
@@ -38,9 +38,12 @@
* struct eth_uclass_priv - The structure attached to the uclass itself
*
* @current: The Ethernet device that the network functions are using
+ * @no_bootdevs: true to skip binding Ethernet bootdevs (this is a negative flag
+ * so that the default value enables it)
*/
struct eth_uclass_priv {
struct udevice *current;
+ bool no_bootdevs;
};
/* eth_errno - This stores the most recent failure code from DM functions */
@@ -59,6 +62,14 @@
return uclass_get_priv(uc);
}
+void eth_set_enable_bootdevs(bool enable)
+{
+ struct eth_uclass_priv *priv = eth_get_uclass_priv();
+
+ if (priv)
+ priv->no_bootdevs = !enable;
+}
+
void eth_set_current_to_next(void)
{
struct eth_uclass_priv *uc_priv;
@@ -477,6 +488,7 @@
static int eth_post_bind(struct udevice *dev)
{
+ struct eth_uclass_priv *priv = uclass_get_priv(dev->uclass);
int ret;
if (strchr(dev->name, ' ')) {
@@ -488,7 +500,7 @@
#ifdef CONFIG_DM_ETH_PHY
eth_phy_binds_nodes(dev);
#endif
- if (CONFIG_IS_ENABLED(BOOTDEV_ETH)) {
+ if (CONFIG_IS_ENABLED(BOOTDEV_ETH) && !priv->no_bootdevs) {
ret = bootdev_setup_for_dev(dev, "eth_bootdev");
if (ret)
return log_msg_ret("bootdev", ret);
diff --git a/net/eth_bootdev.c b/net/eth_bootdev.c
index b735966..13e5fcd 100644
--- a/net/eth_bootdev.c
+++ b/net/eth_bootdev.c
@@ -6,6 +6,8 @@
* Written by Simon Glass <sjg@chromium.org>
*/
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
#include <common.h>
#include <bootdev.h>
#include <bootflow.h>
@@ -13,8 +15,10 @@
#include <bootmeth.h>
#include <distro.h>
#include <dm.h>
+#include <init.h>
#include <log.h>
#include <net.h>
+#include <test/test.h>
static int eth_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
struct bootflow *bflow)
@@ -23,7 +27,7 @@
int ret;
/* Must be an Ethernet device */
- ret = bootflow_iter_uses_network(iter);
+ ret = bootflow_iter_check_net(iter);
if (ret)
return log_msg_ret("net", ret);
@@ -41,30 +45,8 @@
if (!bflow->name)
return log_msg_ret("name", -ENOMEM);
- /*
- * There is not a direct interface to the network stack so run
- * everything through the command-line interpreter for now.
- *
- * Don't bother checking the result of dhcp. It can fail with:
- *
- * DHCP client bound to address 192.168.4.50 (4 ms)
- * *** Warning: no boot file name; using 'C0A80432.img'
- * Using smsc95xx_eth device
- * TFTP from server 192.168.4.1; our IP address is 192.168.4.50
- * Filename 'C0A80432.img'.
- * Load address: 0x200000
- * Loading: *
- * TFTP error: 'File not found' (1)
- *
- * This is not a real failure, since we don't actually care if the
- * boot file exists.
- */
- log_debug("running dhcp\n");
- run_command("dhcp", 0);
- bflow->state = BOOTFLOWST_MEDIA;
-
/* See distro_pxe_read_bootflow() for the standard impl of this */
- log_debug("dhcp complete - reading bootflow with method %s\n",
+ log_debug("dhcp complete - reading bootflow with method '%s'\n",
bflow->method->name);
ret = bootmeth_read_bootflow(bflow->method, bflow);
log_debug("reading bootflow returned %d\n", ret);
@@ -78,7 +60,36 @@
{
struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
- ucp->prio = BOOTDEVP_4_NET_BASE;
+ ucp->prio = BOOTDEVP_6_NET_BASE;
+
+ return 0;
+}
+
+static int eth_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ if (!test_eth_enabled())
+ return 0;
+
+ /* init PCI first since this is often used to provide Ehternet */
+ if (IS_ENABLED(CONFIG_PCI)) {
+ ret = pci_init();
+ if (ret)
+ log_warning("Failed to init PCI (%dE)\n", ret);
+ }
+
+ /*
+ * Ethernet devices can also come from USB, but that is a higher
+ * priority (BOOTDEVP_5_SCAN_SLOW) than ethernet, so it should have been
+ * enumerated already. If something like 'bootflow scan dhcp' is used
+ * then the user will need to run 'usb start' first.
+ */
+ if (IS_ENABLED(CONFIG_CMD_DHCP)) {
+ ret = dhcp_run(0, NULL, false);
+ if (ret)
+ return -EINVAL;
+ }
return 0;
}
@@ -99,3 +110,10 @@
.bind = eth_bootdev_bind,
.of_match = eth_bootdev_ids,
};
+
+BOOTDEV_HUNTER(eth_bootdev_hunt) = {
+ .prio = BOOTDEVP_6_NET_BASE,
+ .uclass = UCLASS_ETH,
+ .hunt = eth_bootdev_hunt,
+ .drv = DM_DRIVER_REF(eth_bootdev),
+};
diff --git a/net/fastboot.c b/net/fastboot.c
index 139233b..96bdf54 100644
--- a/net/fastboot.c
+++ b/net/fastboot.c
@@ -42,7 +42,6 @@
static void boot_downloaded_image(void);
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
/**
* fastboot_udp_send_info() - Send an INFO packet during long commands.
*
@@ -104,7 +103,6 @@
fastboot_udp_send_info(msg);
}
}
-#endif
/**
* fastboot_send() - Sends a packet in response to received fastboot packet
@@ -309,9 +307,9 @@
fastboot_our_port = CONFIG_UDP_FUNCTION_FASTBOOT_PORT;
-#if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
- fastboot_set_progress_callback(fastboot_timed_send_info);
-#endif
+ if (CONFIG_IS_ENABLED(FASTBOOT_FLASH))
+ fastboot_set_progress_callback(fastboot_timed_send_info);
+
net_set_udp_handler(fastboot_handler);
/* zero out server ether in case the server ip has changed */
diff --git a/net/net.c b/net/net.c
index 57da9bd..c9a749f 100644
--- a/net/net.c
+++ b/net/net.c
@@ -106,6 +106,7 @@
#endif
#include <watchdog.h>
#include <linux/compiler.h>
+#include <test/test.h>
#include "arp.h"
#include "bootp.h"
#include "cdp.h"
@@ -465,6 +466,9 @@
debug_cond(DEBUG_INT_STATE, "--- net_loop Init\n");
net_init_loop();
+ if (!test_eth_enabled())
+ return 0;
+
switch (net_check_prereq(protocol)) {
case 1:
/* network not configured */
diff --git a/scripts/coccicheck b/scripts/coccicheck
index dccaea3..00b22e6 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -54,7 +54,7 @@
# inspected there.
#
# --profile will not output if --very-quiet is used, so avoid it.
-echo $SPFLAGS | egrep -e "--profile|--show-trying" 2>&1 > /dev/null
+echo $SPFLAGS | grep -Ee "--profile|--show-trying" 2>&1 > /dev/null
if [ $? -eq 0 ]; then
FLAGS="--quiet"
fi
diff --git a/test/Kconfig b/test/Kconfig
index 9f4641a..4650282 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -69,7 +69,7 @@
config UT_COMPRESSION
bool "Unit test for compression"
depends on UNIT_TEST
- depends on CMDLINE && GZIP_COMPRESSED && BZIP2 && LZMA && LZO && LZ4
+ depends on CMDLINE && GZIP_COMPRESSED && BZIP2 && LZMA && LZO && LZ4 && ZSTD
default y
help
Enables tests for compression and decompression routines for simple
diff --git a/test/boot/Makefile b/test/boot/Makefile
index d724629..22ed61c 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -5,6 +5,8 @@
obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_EXPO) += expo.o
+
ifdef CONFIG_OF_LIVE
obj-$(CONFIG_BOOTMETH_VBE_SIMPLE) += vbe_simple.o
endif
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 1c2a79f..ef5215b 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -102,22 +102,89 @@
static int bootdev_test_labels(struct unit_test_state *uts)
{
struct udevice *dev, *media;
+ int mflags = 0;
- ut_assertok(bootdev_find_by_label("mmc2", &dev));
+ ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags));
ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
+ ut_asserteq(0, mflags);
media = dev_get_parent(dev);
ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
ut_asserteq_str("mmc2", media->name);
+ /* Check method flags */
+ ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
+ ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
+ mflags);
+
/* Check invalid uclass */
- ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev));
+ ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev, &mflags));
/* Check unknown sequence number */
- ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev));
+ ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags));
return 0;
}
-BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV);
+
+/* Check bootdev_find_by_any() */
+static int bootdev_test_any(struct unit_test_state *uts)
+{
+ struct udevice *dev, *media;
+ int mflags;
+
+ /*
+ * with ethernet enabled we have 8 devices ahead of the mmc ones:
+ *
+ * ut_assertok(run_command("bootdev list", 0));
+ * Seq Probed Status Uclass Name
+ * --- ------ ------ -------- ------------------
+ * 0 [ + ] OK ethernet eth@10002000.bootdev
+ * 1 [ ] OK ethernet eth@10003000.bootdev
+ * 2 [ ] OK ethernet sbe5.bootdev
+ * 3 [ ] OK ethernet eth@10004000.bootdev
+ * 4 [ ] OK ethernet phy-test-eth.bootdev
+ * 5 [ ] OK ethernet dsa-test-eth.bootdev
+ * 6 [ ] OK ethernet dsa-test@0.bootdev
+ * 7 [ ] OK ethernet dsa-test@1.bootdev
+ * 8 [ ] OK mmc mmc2.bootdev
+ * 9 [ + ] OK mmc mmc1.bootdev
+ * a [ ] OK mmc mmc0.bootdev
+ */
+ console_record_reset_enable();
+ ut_assertok(bootdev_find_by_any("8", &dev, &mflags));
+ ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_DEV, mflags);
+ media = dev_get_parent(dev);
+ ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
+ ut_asserteq_str("mmc2", media->name);
+ ut_assert_console_end();
+
+ /* there should not be this many bootdevs */
+ ut_asserteq(-ENODEV, bootdev_find_by_any("50", &dev, &mflags));
+ ut_assert_nextline("Cannot find '50' (err=-19)");
+ ut_assert_console_end();
+
+ /* Check method flags */
+ ut_assertok(bootdev_find_by_any("pxe", &dev, &mflags));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
+
+ /* Check invalid uclass */
+ mflags = 123;
+ ut_asserteq(-EINVAL, bootdev_find_by_any("fred0", &dev, &mflags));
+ ut_assert_nextline("Unknown uclass 'fred0' in label");
+ ut_assert_nextline("Cannot find bootdev 'fred0' (err=-22)");
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_any, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV);
/* Check bootdev ordering with the bootdev-order property */
static int bootdev_test_order(struct unit_test_state *uts)
@@ -135,20 +202,31 @@
* mmc2 - nothing connected
*/
ut_assertok(env_set("boot_targets", NULL));
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
ut_asserteq(2, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
bootflow_iter_uninit(&iter);
/* Use the environment variable to override it */
ut_assertok(env_set("boot_targets", "mmc1 mmc2"));
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(2, iter.num_devs);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
bootflow_iter_uninit(&iter);
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check default bootdev ordering */
+static int bootdev_test_order_default(struct unit_test_state *uts)
+{
+ struct bootflow_iter iter;
+ struct bootflow bflow;
+
/*
* Now drop both orderings, to check the default (prioriy/sequence)
* ordering
@@ -156,31 +234,19 @@
ut_assertok(env_set("boot_targets", NULL));
ut_assertok(bootstd_test_drop_bootdev_order(uts));
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
- ut_asserteq(3, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name);
- ut_asserteq_str("mmc0.bootdev", iter.dev_order[2]->name);
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
- /*
- * Check that adding aliases for the bootdevs works. We just fake it by
- * setting the sequence numbers directly.
- */
- iter.dev_order[0]->seq_ = 0;
- iter.dev_order[1]->seq_ = 3;
- iter.dev_order[2]->seq_ = 2;
- bootflow_iter_uninit(&iter);
-
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(3, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
- ut_asserteq_str("mmc0.bootdev", iter.dev_order[1]->name);
- ut_asserteq_str("mmc1.bootdev", iter.dev_order[2]->name);
+ ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
bootflow_iter_uninit(&iter);
return 0;
}
-BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+BOOTSTD_TEST(bootdev_test_order_default, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
/* Check bootdev ordering with the uclass priority */
static int bootdev_test_prio(struct unit_test_state *uts)
@@ -190,6 +256,11 @@
struct bootflow bflow;
struct udevice *blk;
+ test_set_skip_delays(true);
+
+ /* disable ethernet since the hunter will run dhcp */
+ test_set_eth_enable(false);
+
/* Start up USB which gives us three additional bootdevs */
usb_started = false;
ut_assertok(run_command("usb start", 0));
@@ -198,26 +269,440 @@
/* 3 MMC and 3 USB bootdevs: MMC should come before USB */
console_record_reset_enable();
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(6, iter.num_devs);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
ut_asserteq_str("usb_mass_storage.lun0.bootdev",
- iter.dev_order[3]->name);
+ iter.dev_used[3]->name);
- ut_assertok(bootdev_get_sibling_blk(iter.dev_order[3], &blk));
+ ut_assertok(bootdev_get_sibling_blk(iter.dev_used[3], &blk));
ut_asserteq_str("usb_mass_storage.lun0", blk->name);
/* adjust the priority of the first USB bootdev to the highest */
- ucp = dev_get_uclass_plat(iter.dev_order[3]);
- ucp->prio = 1;
+ ucp = dev_get_uclass_plat(iter.dev_used[3]);
+ ucp->prio = BOOTDEVP_1_PRE_SCAN;
+ /* try again but enable hunting, which brings in SCSI */
bootflow_iter_uninit(&iter);
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
- ut_asserteq(6, iter.num_devs);
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWF_HUNT,
+ &bflow));
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(7, iter.num_devs);
ut_asserteq_str("usb_mass_storage.lun0.bootdev",
- iter.dev_order[0]->name);
- ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name);
+ iter.dev_used[0]->name);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
return 0;
}
BOOTSTD_TEST(bootdev_test_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check listing hunters */
+static int bootdev_test_hunter(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+
+ test_set_skip_delays(true);
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ console_record_reset_enable();
+ bootdev_list_hunters(std);
+ ut_assert_nextline("Prio Used Uclass Hunter");
+ ut_assert_nextlinen("----");
+ ut_assert_nextline(" 6 ethernet eth_bootdev");
+ ut_assert_nextline(" 1 simple_bus (none)");
+ ut_assert_nextline(" 5 ide ide_bootdev");
+ ut_assert_nextline(" 2 mmc mmc_bootdev");
+ ut_assert_nextline(" 4 nvme nvme_bootdev");
+ ut_assert_nextline(" 4 scsi scsi_bootdev");
+ ut_assert_nextline(" 4 spi_flash sf_bootdev");
+ ut_assert_nextline(" 5 usb usb_bootdev");
+ ut_assert_nextline(" 4 virtio virtio_bootdev");
+ ut_assert_nextline("(total hunters: 9)");
+ ut_assert_console_end();
+
+ ut_assertok(bootdev_hunt("usb1", false));
+ ut_assert_nextline(
+ "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
+ ut_assert_console_end();
+
+ /* USB is sixth in the list, so bit 7 */
+ ut_asserteq(BIT(7), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootdev hunt' command */
+static int bootdev_test_cmd_hunt(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+
+ test_set_skip_delays(true);
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ console_record_reset_enable();
+ ut_assertok(run_command("bootdev hunt -l", 0));
+ ut_assert_nextline("Prio Used Uclass Hunter");
+ ut_assert_nextlinen("----");
+ ut_assert_nextline(" 6 ethernet eth_bootdev");
+ ut_assert_skip_to_line("(total hunters: 9)");
+ ut_assert_console_end();
+
+ /* Use the MMC hunter and see that it updates */
+ ut_assertok(run_command("bootdev hunt mmc", 0));
+ ut_assertok(run_command("bootdev hunt -l", 0));
+ ut_assert_skip_to_line(" 5 ide ide_bootdev");
+ ut_assert_nextline(" 2 * mmc mmc_bootdev");
+ ut_assert_skip_to_line("(total hunters: 9)");
+ ut_assert_console_end();
+
+ /* Scan all hunters */
+ test_set_eth_enable(false);
+ test_set_skip_delays(true);
+ ut_assertok(run_command("bootdev hunt", 0));
+ ut_assert_nextline("Hunting with: ethernet");
+
+ /* This is the extension feature which has no uclass at present */
+ ut_assert_nextline("Hunting with: simple_bus");
+ ut_assert_nextline("Found 2 extension board(s).");
+ ut_assert_nextline("Hunting with: ide");
+ ut_assert_nextline("Bus 0: not available ");
+
+ /* mmc hunter has already been used so should not run again */
+
+ ut_assert_nextline("Hunting with: nvme");
+ ut_assert_nextline("Hunting with: scsi");
+ ut_assert_nextline("scanning bus for devices...");
+ ut_assert_skip_to_line("Hunting with: spi_flash");
+ ut_assert_nextline("Hunting with: usb");
+ ut_assert_nextline(
+ "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
+ ut_assert_nextline("Hunting with: virtio");
+ ut_assert_console_end();
+
+ /* List available hunters */
+ ut_assertok(run_command("bootdev hunt -l", 0));
+ ut_assert_nextlinen("Prio");
+ ut_assert_nextlinen("----");
+ ut_assert_nextline(" 6 * ethernet eth_bootdev");
+ ut_assert_nextline(" 1 * simple_bus (none)");
+ ut_assert_nextline(" 5 * ide ide_bootdev");
+ ut_assert_nextline(" 2 * mmc mmc_bootdev");
+ ut_assert_nextline(" 4 * nvme nvme_bootdev");
+ ut_assert_nextline(" 4 * scsi scsi_bootdev");
+ ut_assert_nextline(" 4 * spi_flash sf_bootdev");
+ ut_assert_nextline(" 5 * usb usb_bootdev");
+ ut_assert_nextline(" 4 * virtio virtio_bootdev");
+ ut_assert_nextline("(total hunters: 9)");
+ ut_assert_console_end();
+
+ ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_cmd_hunt, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV);
+
+/* Check searching for bootdevs using the hunters */
+static int bootdev_test_hunt_scan(struct unit_test_state *uts)
+{
+ struct bootflow_iter iter;
+ struct bootstd_priv *std;
+ struct bootflow bflow;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ ut_assertok(bootstd_test_drop_bootdev_order(uts));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter,
+ BOOTFLOWF_SHOW | BOOTFLOWF_HUNT |
+ BOOTFLOWF_SKIP_GLOBAL, &bflow));
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunt_scan, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check that only bootable partitions are processed */
+static int bootdev_test_bootable(struct unit_test_state *uts)
+{
+ struct bootflow_iter iter;
+ struct bootflow bflow;
+ struct udevice *blk;
+
+ memset(&iter, '\0', sizeof(iter));
+ memset(&bflow, '\0', sizeof(bflow));
+ iter.part = 0;
+ ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk));
+ iter.dev = blk;
+ ut_assertok(device_find_next_child(&iter.dev));
+ uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
+
+ /*
+ * initially we don't have any knowledge of which partitions are
+ * bootable, but mmc1 has two partitions, with the first one being
+ * bootable
+ */
+ iter.part = 2;
+ ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+ ut_asserteq(0, iter.first_bootable);
+
+ /* scan with part == 0 to get the partition info */
+ iter.part = 0;
+ ut_asserteq(-ENOENT, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+ ut_asserteq(1, iter.first_bootable);
+
+ /* now it will refuse to use non-bootable partitions */
+ iter.part = 2;
+ ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_bootable, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check hunting for bootdev of a particular priority */
+static int bootdev_test_hunt_prio(struct unit_test_state *uts)
+{
+ test_set_skip_delays(true);
+
+ console_record_reset_enable();
+ ut_assertok(bootdev_hunt_prio(BOOTDEVP_4_SCAN_FAST, false));
+ ut_assert_nextline("scanning bus for devices...");
+ ut_assert_skip_to_line(" Type: Hard Disk");
+ ut_assert_nextlinen(" Capacity:");
+ ut_assert_console_end();
+
+ /* now try a different priority, verbosely */
+ ut_assertok(bootdev_hunt_prio(BOOTDEVP_5_SCAN_SLOW, true));
+ ut_assert_nextline("Hunting with: ide");
+ ut_assert_nextline("Bus 0: not available ");
+ ut_assert_nextline("Hunting with: usb");
+ ut_assert_nextline(
+ "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunt_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check hunting for bootdevs with a particular label */
+static int bootdev_test_hunt_label(struct unit_test_state *uts)
+{
+ struct udevice *dev, *old;
+ struct bootstd_priv *std;
+ int mflags;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ /* scan an unknown uclass */
+ console_record_reset_enable();
+ old = (void *)&mflags; /* arbitrary pointer to check against dev */
+ dev = old;
+ mflags = 123;
+ ut_asserteq(-EINVAL,
+ bootdev_hunt_and_find_by_label("fred", &dev, &mflags));
+ ut_assert_nextline("Unknown uclass 'fred' in label");
+ ut_asserteq_ptr(old, dev);
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
+ ut_asserteq(0, std->hunters_used);
+
+ /* scan an invalid mmc controllers */
+ ut_asserteq(-ENOENT,
+ bootdev_hunt_and_find_by_label("mmc4", &dev, &mflags));
+ ut_asserteq_ptr(old, dev);
+ ut_asserteq(123, mflags);
+ ut_assert_nextline("Unknown seq 4 for label 'mmc4'");
+ ut_assert_console_end();
+
+ ut_assertok(bootstd_test_check_mmc_hunter(uts));
+
+ /* scan for a particular mmc controller */
+ ut_assertok(bootdev_hunt_and_find_by_label("mmc1", &dev, &mflags));
+ ut_assertnonnull(dev);
+ ut_asserteq_str("mmc1.bootdev", dev->name);
+ ut_asserteq(0, mflags);
+ ut_assert_console_end();
+
+ /* scan all of usb */
+ test_set_skip_delays(true);
+ ut_assertok(bootdev_hunt_and_find_by_label("usb", &dev, &mflags));
+ ut_assertnonnull(dev);
+ ut_asserteq_str("usb_mass_storage.lun0.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
+ ut_assert_nextlinen("Bus usb@1: scanning bus usb@1");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check iterating to the next label in a list */
+static int bootdev_test_next_label(struct unit_test_state *uts)
+{
+ const char *const labels[] = {"mmc0", "scsi", "dhcp", "pxe", NULL};
+ struct bootflow_iter iter;
+ struct bootstd_priv *std;
+ struct bootflow bflow;
+ struct udevice *dev;
+ int mflags;
+
+ test_set_eth_enable(false);
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ memset(&iter, '\0', sizeof(iter));
+ memset(&bflow, '\0', sizeof(bflow));
+ iter.part = 0;
+ uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
+ iter.cur_label = -1;
+ iter.labels = labels;
+
+ dev = NULL;
+ mflags = 123;
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ console_record_reset_enable();
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("mmc0.bootdev", dev->name);
+ ut_asserteq(0, mflags);
+
+ ut_assertok(bootstd_test_check_mmc_hunter(uts));
+
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ ut_assert_nextline("scanning bus for devices...");
+ ut_assert_skip_to_line(
+ " Capacity: 1.9 MB = 0.0 GB (4095 x 512)");
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("scsi.id0lun0.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
+
+ /* SCSI is sixth in the list, so bit 5 */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5), std->hunters_used);
+
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("eth@10002000.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
+ mflags);
+
+ /* dhcp: Ethernet is first so bit 0 */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
+
+ ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
+ ut_assert_console_end();
+ ut_assertnonnull(dev);
+ ut_asserteq_str("eth@10002000.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
+
+ /* pxe: Ethernet is first so bit 0 */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
+
+ mflags = 123;
+ ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags));
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
+
+ /* no change */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_next_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV | UT_TESTF_SF_BOOTDEV);
+
+
+/* Check iterating to the next prioirty in a list */
+static int bootdev_test_next_prio(struct unit_test_state *uts)
+{
+ struct bootflow_iter iter;
+ struct bootstd_priv *std;
+ struct bootflow bflow;
+ struct udevice *dev;
+ int ret;
+
+ test_set_eth_enable(false);
+ test_set_skip_delays(true);
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ memset(&iter, '\0', sizeof(iter));
+ memset(&bflow, '\0', sizeof(bflow));
+ iter.part = 0;
+ uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
+ iter.cur_prio = 0;
+ iter.flags = BOOTFLOWF_SHOW;
+
+ dev = NULL;
+ console_record_reset_enable();
+ ut_assertok(bootdev_next_prio(&iter, &dev));
+ ut_assertnonnull(dev);
+ ut_asserteq_str("mmc2.bootdev", dev->name);
+
+ /* hunt flag not set, so this should not use any hunters */
+ ut_asserteq(0, std->hunters_used);
+ ut_assert_console_end();
+
+ /* now try again with hunting enabled */
+ iter.flags = BOOTFLOWF_SHOW | BOOTFLOWF_HUNT;
+ iter.cur_prio = 0;
+ iter.part = 0;
+
+ ut_assertok(bootdev_next_prio(&iter, &dev));
+ ut_asserteq_str("mmc2.bootdev", dev->name);
+ ut_assert_nextline("Hunting with: simple_bus");
+ ut_assert_nextline("Found 2 extension board(s).");
+ ut_assert_nextline("Hunting with: mmc");
+ ut_assert_console_end();
+
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
+
+ ut_assertok(bootdev_next_prio(&iter, &dev));
+ ut_asserteq_str("mmc1.bootdev", dev->name);
+
+ ut_assertok(bootdev_next_prio(&iter, &dev));
+ ut_asserteq_str("mmc0.bootdev", dev->name);
+ ut_assert_console_end();
+
+ ut_assertok(bootdev_next_prio(&iter, &dev));
+ ut_asserteq_str("spi.bin@0.bootdev", dev->name);
+ ut_assert_skip_to_line("Hunting with: spi_flash");
+
+ /*
+ * this scans all bootdevs of priority BOOTDEVP_4_SCAN_FAST before it
+ * starts looking at the devices, so we se virtio as well
+ */
+ ut_assert_nextline("Hunting with: virtio");
+ ut_assert_nextlinen("SF: Detected m25p16");
+
+ ut_assertok(bootdev_next_prio(&iter, &dev));
+ ut_asserteq_str("spi.bin@1.bootdev", dev->name);
+ ut_assert_nextlinen("SF: Detected m25p16");
+ ut_assert_console_end();
+
+ /* keep going until there are no more bootdevs */
+ do {
+ ret = bootdev_next_prio(&iter, &dev);
+ } while (!ret);
+ ut_asserteq(-ENODEV, ret);
+ ut_assertnull(dev);
+ ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
+
+ ut_assert_skip_to_line("Hunting with: ethernet");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_next_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_SF_BOOTDEV);
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index e1e0708..b9284fc 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -11,14 +11,23 @@
#include <bootflow.h>
#include <bootmeth.h>
#include <bootstd.h>
+#include <cli.h>
#include <dm.h>
+#include <expo.h>
#ifdef CONFIG_SANDBOX
#include <asm/test.h>
#endif
+#include <dm/device-internal.h>
#include <dm/lists.h>
#include <test/suites.h>
#include <test/ut.h>
#include "bootstd_common.h"
+#include "../../boot/bootflow_internal.h"
+#include "../../boot/scene_internal.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+extern U_BOOT_DRIVER(bootmeth_script);
static int inject_response(struct unit_test_state *uts)
{
@@ -42,11 +51,14 @@
console_record_reset_enable();
ut_assertok(run_command("bootdev select 1", 0));
ut_assert_console_end();
- ut_assertok(run_command("bootflow scan -l", 0));
+ ut_assertok(run_command("bootflow scan -lH", 0));
ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
ut_assert_nextline("Seq Method State Uclass Part Name Filename");
ut_assert_nextlinen("---");
+ ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
+ ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
+ ut_assert_nextline("No more bootdevs");
ut_assert_nextlinen("---");
ut_assert_nextline("(1 bootflow, 1 valid)");
ut_assert_console_end();
@@ -64,28 +76,53 @@
}
BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
-/* Check 'bootflow scan' with a name / label / seq */
+/* Check 'bootflow scan' with a label / seq */
static int bootflow_cmd_label(struct unit_test_state *uts)
{
+ test_set_eth_enable(false);
+
console_record_reset_enable();
- ut_assertok(run_command("bootflow scan -l mmc1", 0));
- ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'");
+ ut_assertok(run_command("bootflow scan -lH mmc1", 0));
+ ut_assert_nextline("Scanning for bootflows with label 'mmc1'");
ut_assert_skip_to_line("(1 bootflow, 1 valid)");
ut_assert_console_end();
- ut_assertok(run_command("bootflow scan -l mmc0.bootdev", 0));
- ut_assert_nextline("Scanning for bootflows in bootdev 'mmc0.bootdev'");
+ ut_assertok(run_command("bootflow scan -lH 0", 0));
+ ut_assert_nextline("Scanning for bootflows with label '0'");
ut_assert_skip_to_line("(0 bootflows, 0 valid)");
ut_assert_console_end();
- ut_assertok(run_command("bootflow scan -l 0", 0));
- ut_assert_nextline("Scanning for bootflows in bootdev 'mmc2.bootdev'");
+ /*
+ * with ethernet enabled we have 8 devices ahead of the mmc ones:
+ *
+ * ut_assertok(run_command("bootdev list", 0));
+ * Seq Probed Status Uclass Name
+ * --- ------ ------ -------- ------------------
+ * 0 [ + ] OK ethernet eth@10002000.bootdev
+ * 1 [ ] OK ethernet eth@10003000.bootdev
+ * 2 [ ] OK ethernet sbe5.bootdev
+ * 3 [ ] OK ethernet eth@10004000.bootdev
+ * 4 [ ] OK ethernet phy-test-eth.bootdev
+ * 5 [ ] OK ethernet dsa-test-eth.bootdev
+ * 6 [ ] OK ethernet dsa-test@0.bootdev
+ * 7 [ ] OK ethernet dsa-test@1.bootdev
+ * 8 [ ] OK mmc mmc2.bootdev
+ * 9 [ + ] OK mmc mmc1.bootdev
+ * a [ ] OK mmc mmc0.bootdev
+ */
+ ut_assertok(run_command("bootflow scan -lH 9", 0));
+ ut_assert_nextline("Scanning for bootflows with label '9'");
+ ut_assert_skip_to_line("(1 bootflow, 1 valid)");
+
+ ut_assertok(run_command("bootflow scan -lH 0", 0));
+ ut_assert_nextline("Scanning for bootflows with label '0'");
ut_assert_skip_to_line("(0 bootflows, 0 valid)");
ut_assert_console_end();
return 0;
}
-BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+ UT_TESTF_ETH_BOOTDEV);
/* Check 'bootflow scan/list' commands using all bootdevs */
static int bootflow_cmd_glob(struct unit_test_state *uts)
@@ -93,7 +130,7 @@
ut_assertok(bootstd_test_drop_bootdev_order(uts));
console_record_reset_enable();
- ut_assertok(run_command("bootflow scan -lG", 0));
+ ut_assertok(run_command("bootflow scan -lGH", 0));
ut_assert_nextline("Scanning for bootflows in all bootdevs");
ut_assert_nextline("Seq Method State Uclass Part Name Filename");
ut_assert_nextlinen("---");
@@ -125,7 +162,7 @@
ut_assertok(bootstd_test_drop_bootdev_order(uts));
console_record_reset_enable();
- ut_assertok(run_command("bootflow scan -aleG", 0));
+ ut_assertok(run_command("bootflow scan -aleGH", 0));
ut_assert_nextline("Scanning for bootflows in all bootdevs");
ut_assert_nextline("Seq Method State Uclass Part Name Filename");
ut_assert_nextlinen("---");
@@ -188,6 +225,9 @@
ut_assert_nextline("Filename: /extlinux/extlinux.conf");
ut_assert_nextlinen("Buffer: ");
ut_assert_nextline("Size: 253 (595 bytes)");
+ ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)");
+ ut_assert_nextline("Logo: (none)");
+ ut_assert_nextline("FDT: <NULL>");
ut_assert_nextline("Error: 0");
ut_assert_console_end();
@@ -236,7 +276,8 @@
/* The first device is mmc2.bootdev which has no media */
ut_asserteq(-EPROTONOSUPPORT,
- bootflow_scan_first(&iter, BOOTFLOWF_ALL | BOOTFLOWF_SKIP_GLOBAL, &bflow));
+ bootflow_scan_first(NULL, NULL, &iter,
+ BOOTFLOWF_ALL | BOOTFLOWF_SKIP_GLOBAL, &bflow));
ut_asserteq(2, iter.num_methods);
ut_asserteq(0, iter.cur_method);
ut_asserteq(0, iter.part);
@@ -304,8 +345,8 @@
ut_asserteq(BOOTFLOWST_FS, bflow.state);
bootflow_free(&bflow);
- /* Then more to partition 2 which doesn't exist */
- ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
+ /* Then more to partition 2 which exists but is not bootable */
+ ut_asserteq(-EINVAL, bootflow_scan_next(&iter, &bflow));
ut_asserteq(2, iter.num_methods);
ut_asserteq(0, iter.cur_method);
ut_asserteq(2, iter.part);
@@ -327,22 +368,24 @@
/* Check using the system bootdev */
static int bootflow_system(struct unit_test_state *uts)
{
- struct udevice *dev;
+ struct udevice *bootstd, *dev;
if (!IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR))
return -EAGAIN;
- ut_assertok(uclass_get_device_by_name(UCLASS_BOOTMETH, "efi_mgr",
- &dev));
+ ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+ ut_assertok(device_bind(bootstd, DM_DRIVER_GET(bootmeth_efi_mgr),
+ "efi_mgr", 0, ofnode_null(), &dev));
+ ut_assertok(device_probe(dev));
sandbox_set_fake_efi_mgr_dev(dev, true);
/* We should get a single 'bootmgr' method right at the end */
bootstd_clear_glob();
console_record_reset_enable();
- ut_assertok(run_command("bootflow scan -l", 0));
+ ut_assertok(run_command("bootflow scan -lH", 0));
ut_assert_skip_to_line(
" 0 efi_mgr ready (none) 0 <NULL> <NULL>");
ut_assert_skip_to_line("No more bootdevs");
- ut_assert_skip_to_line("(5 bootflows, 5 valid)");
+ ut_assert_skip_to_line("(2 bootflows, 2 valid)");
ut_assert_console_end();
return 0;
@@ -369,11 +412,11 @@
bootstd_clear_glob();
console_record_reset_enable();
ut_assertok(inject_response(uts));
- ut_assertok(run_command("bootflow scan -lb", 0));
+ ut_assertok(run_command("bootflow scan -lbH", 0));
/* Try to boot the bootmgr flow, which will fail */
console_record_reset_enable();
- ut_assertok(bootflow_scan_first(&iter, 0, &bflow));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
ut_asserteq(3, iter.num_methods);
ut_asserteq_str("sandbox", iter.method->name);
ut_assertok(inject_response(uts));
@@ -405,7 +448,7 @@
*/
console_record_reset_enable();
ut_assertok(bootmeth_set_order("efi firmware0"));
- ut_assertok(run_command("bootflow scan -lG", 0));
+ ut_assertok(run_command("bootflow scan -lGH", 0));
ut_assert_nextline("Scanning for bootflows in all bootdevs");
ut_assert_nextline(
"Seq Method State Uclass Part Name Filename");
@@ -414,7 +457,7 @@
ut_assert_nextline("(0 bootflows, 0 valid)");
ut_assert_console_end();
- ut_assertok(run_command("bootflow scan -l", 0));
+ ut_assertok(run_command("bootflow scan -lH", 0));
ut_assert_nextline("Scanning for bootflows in all bootdevs");
ut_assert_nextline(
"Seq Method State Uclass Part Name Filename");
@@ -460,3 +503,182 @@
return 0;
}
BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/**
+ * prep_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
+ *
+ * @uts: Unit test state
+ * Returns 0 on success, -ve on failure
+ */
+static int prep_mmc4_bootdev(struct unit_test_state *uts)
+{
+ static const char *order[] = {"mmc2", "mmc1", "mmc4", NULL};
+ struct udevice *dev, *bootstd;
+ struct bootstd_priv *std;
+ const char **old_order;
+ ofnode node;
+
+ /* Enable the mmc4 node since we need a second bootflow */
+ node = ofnode_path("/mmc4");
+ ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
+
+ /* Enable the script bootmeth too */
+ ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+ ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_script),
+ "bootmeth_script", 0, ofnode_null(), &dev));
+
+ /* Change the order to include mmc4 */
+ std = dev_get_priv(bootstd);
+ old_order = std->bootdev_order;
+ std->bootdev_order = order;
+
+ console_record_reset_enable();
+ ut_assertok(run_command("bootflow scan", 0));
+ ut_assert_console_end();
+
+ /* Restore the order used by the device tree */
+ std->bootdev_order = old_order;
+
+ return 0;
+}
+
+/* Check 'bootflow menu' to select a bootflow */
+static int bootflow_cmd_menu(struct unit_test_state *uts)
+{
+ char prev[3];
+
+ ut_assertok(prep_mmc4_bootdev(uts));
+
+ /* Add keypresses to move to and select the second one in the list */
+ prev[0] = CTL_CH('n');
+ prev[1] = '\r';
+ prev[2] = '\0';
+ ut_asserteq(2, console_in_puts(prev));
+
+ ut_assertok(run_command("bootflow menu", 0));
+ ut_assert_nextline("Selected: Armbian");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check searching for a single bootdev using the hunters */
+static int bootflow_cmd_hunt_single(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+ console_record_reset_enable();
+ ut_assertok(run_command("bootflow scan -l mmc1", 0));
+ ut_assert_nextline("Scanning for bootflows with label 'mmc1'");
+ ut_assert_skip_to_line("(1 bootflow, 1 valid)");
+ ut_assert_console_end();
+
+ /* check that the hunter was used */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_hunt_single, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check searching for a uclass label using the hunters */
+static int bootflow_cmd_hunt_label(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ test_set_skip_delays(true);
+ test_set_eth_enable(false);
+ ut_assertok(bootstd_test_drop_bootdev_order(uts));
+
+ console_record_reset_enable();
+ ut_assertok(run_command("bootflow scan -l mmc", 0));
+
+ /* check that the hunter was used */
+ ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
+
+ /* check that we got the mmc1 bootflow */
+ ut_assert_nextline("Scanning for bootflows with label 'mmc'");
+ ut_assert_nextlinen("Seq");
+ ut_assert_nextlinen("---");
+ ut_assert_nextline("Hunting with: simple_bus");
+ ut_assert_nextline("Found 2 extension board(s).");
+ ut_assert_nextline("Hunting with: mmc");
+ ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':");
+ ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':");
+ ut_assert_nextline(
+ " 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
+ ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':");
+ ut_assert_skip_to_line("(1 bootflow, 1 valid)");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_cmd_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/**
+ * check_font() - Check that the font size for an item matches expectations
+ *
+ * @uts: Unit test state
+ * @scn: Scene containing the text object
+ * @id: ID of the text object
+ * Returns 0 on success, -ve on failure
+ */
+static int check_font(struct unit_test_state *uts, struct scene *scn, uint id,
+ int font_size)
+{
+ struct scene_obj_txt *txt;
+
+ txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
+ ut_assertnonnull(txt);
+
+ ut_asserteq(font_size, txt->font_size);
+
+ return 0;
+}
+
+/* Check themes work with a bootflow menu */
+static int bootflow_menu_theme(struct unit_test_state *uts)
+{
+ const int font_size = 30;
+ struct scene *scn;
+ struct expo *exp;
+ ofnode node;
+ int i;
+
+ ut_assertok(prep_mmc4_bootdev(uts));
+
+ ut_assertok(bootflow_menu_new(&exp));
+ node = ofnode_path("/bootstd/theme");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(bootflow_menu_apply_theme(exp, node));
+
+ scn = expo_lookup_scene_id(exp, MAIN);
+ ut_assertnonnull(scn);
+
+ /*
+ * Check that the txt objects have the correct font size from the
+ * device tree node: bootstd/theme
+ *
+ * Check both menu items, since there are two bootflows
+ */
+ ut_assertok(check_font(uts, scn, OBJ_PROMPT, font_size));
+ ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size));
+ for (i = 0; i < 2; i++) {
+ ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size));
+ ut_assertok(check_font(uts, scn, ITEM_KEY + i, font_size));
+ ut_assertok(check_font(uts, scn, ITEM_LABEL + i, font_size));
+ }
+
+ expo_destroy(exp);
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_menu_theme, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/boot/bootstd_common.c b/test/boot/bootstd_common.c
index 7a40836..e71a297 100644
--- a/test/boot/bootstd_common.c
+++ b/test/boot/bootstd_common.c
@@ -7,6 +7,7 @@
*/
#include <common.h>
+#include <bootdev.h>
#include <bootstd.h>
#include <dm.h>
#include <memalign.h>
@@ -67,6 +68,24 @@
return 0;
}
+int bootstd_test_check_mmc_hunter(struct unit_test_state *uts)
+{
+ struct bootdev_hunter *start, *mmc;
+ struct bootstd_priv *std;
+ uint seq;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ /* check that the hunter was used */
+ start = ll_entry_start(struct bootdev_hunter, bootdev_hunter);
+ mmc = BOOTDEV_HUNTER_GET(mmc_bootdev_hunter);
+ seq = mmc - start;
+ ut_asserteq(BIT(seq), std->hunters_used);
+
+ return 0;
+}
+
int do_ut_bootstd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct unit_test *tests = UNIT_TEST_SUITE_START(bootstd_test);
diff --git a/test/boot/bootstd_common.h b/test/boot/bootstd_common.h
index c5e0fd1..136a79b 100644
--- a/test/boot/bootstd_common.h
+++ b/test/boot/bootstd_common.h
@@ -20,6 +20,11 @@
#define TEST_VERSION "U-Boot v2022.04-local2"
#define TEST_VERNUM 0x00010002
+enum {
+ MAX_HUNTER = 8,
+ MMC_HUNTER = 3, /* ID of MMC hunter */
+};
+
struct unit_test_state;
/**
@@ -40,4 +45,12 @@
*/
int bootstd_setup_for_tests(void);
+/**
+ * bootstd_test_check_mmc_hunter() - Check that the mmc bootdev hunter was used
+ *
+ * @uts: Unit test state to use for ut_assert...() functions
+ * Returns: 0 if OK (used), other value on error (not used)
+ */
+int bootstd_test_check_mmc_hunter(struct unit_test_state *uts);
+
#endif
diff --git a/test/boot/expo.c b/test/boot/expo.c
new file mode 100644
index 0000000..7104dff
--- /dev/null
+++ b/test/boot/expo.c
@@ -0,0 +1,539 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <expo.h>
+#include <menu.h>
+#include <video.h>
+#include <linux/input.h>
+#include <test/suites.h>
+#include <test/ut.h>
+#include "bootstd_common.h"
+#include "../../boot/scene_internal.h"
+
+enum {
+ /* scenes */
+ SCENE1 = 7,
+ SCENE2,
+
+ /* objects */
+ OBJ_LOGO,
+ OBJ_TEXT,
+ OBJ_TEXT2,
+ OBJ_MENU,
+ OBJ_MENU_TITLE,
+
+ /* strings */
+ STR_TEXT,
+ STR_TEXT2,
+ STR_MENU_TITLE,
+ STR_POINTER_TEXT,
+
+ STR_ITEM1_LABEL,
+ STR_ITEM1_DESC,
+ STR_ITEM1_KEY,
+ STR_ITEM1_PREVIEW,
+
+ STR_ITEM2_LABEL,
+ STR_ITEM2_DESC,
+ STR_ITEM2_KEY,
+ STR_ITEM2_PREVIEW,
+
+ /* menu items */
+ ITEM1,
+ ITEM1_LABEL,
+ ITEM1_DESC,
+ ITEM1_KEY,
+ ITEM1_PREVIEW,
+
+ ITEM2,
+ ITEM2_LABEL,
+ ITEM2_DESC,
+ ITEM2_KEY,
+ ITEM2_PREVIEW,
+
+ /* pointer to current item */
+ POINTER_TEXT,
+};
+
+#define BAD_POINTER ((void *)1)
+
+/* names for various things */
+#define EXPO_NAME "my menus"
+#define SCENE_NAME1 "main"
+#define SCENE_NAME2 "second"
+#define SCENE_TITLE "Main Menu"
+#define LOGO_NAME "logo"
+
+/* Check base expo support */
+static int expo_base(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct expo *exp;
+ ulong start_mem;
+ char name[100];
+ int i;
+
+ ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+
+ start_mem = ut_check_free();
+
+ exp = NULL;
+ strcpy(name, EXPO_NAME);
+ ut_assertok(expo_new(name, NULL, &exp));
+ *name = '\0';
+ ut_assertnonnull(exp);
+ ut_asserteq(0, exp->scene_id);
+ ut_asserteq(0, exp->next_id);
+
+ /* Make sure the name was allocated */
+ ut_assertnonnull(exp->name);
+ ut_asserteq_str(EXPO_NAME, exp->name);
+
+ ut_assertok(expo_set_display(exp, dev));
+ expo_destroy(exp);
+ ut_assertok(ut_check_delta(start_mem));
+
+ /* test handling out-of-memory conditions */
+ for (i = 0; i < 2; i++) {
+ struct expo *exp2;
+
+ malloc_enable_testing(i);
+ exp2 = BAD_POINTER;
+ ut_asserteq(-ENOMEM, expo_new(EXPO_NAME, NULL, &exp2));
+ ut_asserteq_ptr(BAD_POINTER, exp2);
+ malloc_disable_testing();
+ }
+
+ return 0;
+}
+BOOTSTD_TEST(expo_base, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check creating a scene */
+static int expo_scene(struct unit_test_state *uts)
+{
+ struct scene *scn;
+ struct expo *exp;
+ ulong start_mem;
+ char name[100];
+ int id;
+
+ start_mem = ut_check_free();
+
+ ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
+
+ scn = NULL;
+ ut_asserteq(0, exp->next_id);
+ strcpy(name, SCENE_NAME1);
+ id = scene_new(exp, name, SCENE1, &scn);
+ *name = '\0';
+ ut_assertnonnull(scn);
+ ut_asserteq(SCENE1, id);
+ ut_asserteq(SCENE1 + 1, exp->next_id);
+ ut_asserteq_ptr(exp, scn->expo);
+
+ /* Make sure the name was allocated */
+ ut_assertnonnull(scn->name);
+ ut_asserteq_str(SCENE_NAME1, scn->name);
+
+ /* Set the title */
+ strcpy(name, SCENE_TITLE);
+ ut_assertok(scene_title_set(scn, name));
+ *name = '\0';
+ ut_assertnonnull(scn->title);
+ ut_asserteq_str(SCENE_TITLE, scn->title);
+
+ /* Use an allocated ID */
+ scn = NULL;
+ id = scene_new(exp, SCENE_NAME2, 0, &scn);
+ ut_assertnonnull(scn);
+ ut_asserteq(SCENE2, id);
+ ut_asserteq(SCENE2 + 1, exp->next_id);
+ ut_asserteq_ptr(exp, scn->expo);
+
+ ut_asserteq_str(SCENE_NAME2, scn->name);
+
+ expo_destroy(exp);
+
+ ut_assertok(ut_check_delta(start_mem));
+
+ return 0;
+}
+BOOTSTD_TEST(expo_scene, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check creating a scene with objects */
+static int expo_object(struct unit_test_state *uts)
+{
+ struct scene_obj_img *img;
+ struct scene_obj_txt *txt;
+ struct scene *scn;
+ struct expo *exp;
+ ulong start_mem;
+ char name[100];
+ char *data;
+ int id;
+
+ start_mem = ut_check_free();
+
+ ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
+ id = scene_new(exp, SCENE_NAME1, SCENE1, &scn);
+ ut_assert(id > 0);
+
+ ut_asserteq(0, scene_obj_count(scn));
+
+ data = NULL;
+ strcpy(name, LOGO_NAME);
+ id = scene_img(scn, name, OBJ_LOGO, data, &img);
+ ut_assert(id > 0);
+ *name = '\0';
+ ut_assertnonnull(img);
+ ut_asserteq(OBJ_LOGO, id);
+ ut_asserteq(OBJ_LOGO + 1, exp->next_id);
+ ut_asserteq_ptr(scn, img->obj.scene);
+ ut_asserteq(SCENEOBJT_IMAGE, img->obj.type);
+
+ ut_asserteq_ptr(data, img->data);
+
+ /* Make sure the name was allocated */
+ ut_assertnonnull(scn->name);
+ ut_asserteq_str(SCENE_NAME1, scn->name);
+
+ ut_asserteq(1, scene_obj_count(scn));
+
+ id = scene_txt_str(scn, "text", OBJ_TEXT, STR_TEXT, "my string", &txt);
+ ut_assert(id > 0);
+ ut_assertnonnull(txt);
+ ut_asserteq(OBJ_TEXT, id);
+ ut_asserteq(SCENEOBJT_TEXT, txt->obj.type);
+ ut_asserteq(2, scene_obj_count(scn));
+
+ /* Check passing NULL as the final parameter */
+ id = scene_txt_str(scn, "text2", OBJ_TEXT2, STR_TEXT2, "another string",
+ NULL);
+ ut_assert(id > 0);
+ ut_asserteq(3, scene_obj_count(scn));
+
+ expo_destroy(exp);
+
+ ut_assertok(ut_check_delta(start_mem));
+
+ return 0;
+}
+BOOTSTD_TEST(expo_object, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check setting object attributes */
+static int expo_object_attr(struct unit_test_state *uts)
+{
+ struct scene_obj_menu *menu;
+ struct scene_obj_img *img;
+ struct scene_obj_txt *txt;
+ struct scene *scn;
+ struct expo *exp;
+ ulong start_mem;
+ char name[100];
+ char *data;
+ int id;
+
+ start_mem = ut_check_free();
+
+ ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
+ id = scene_new(exp, SCENE_NAME1, SCENE1, &scn);
+ ut_assert(id > 0);
+
+ data = NULL;
+ id = scene_img(scn, LOGO_NAME, OBJ_LOGO, data, &img);
+ ut_assert(id > 0);
+
+ ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 123, 456));
+ ut_asserteq(123, img->obj.x);
+ ut_asserteq(456, img->obj.y);
+
+ ut_asserteq(-ENOENT, scene_obj_set_pos(scn, OBJ_TEXT2, 0, 0));
+
+ id = scene_txt_str(scn, "text", OBJ_TEXT, STR_TEXT, "my string", &txt);
+ ut_assert(id > 0);
+
+ strcpy(name, "font2");
+ ut_assertok(scene_txt_set_font(scn, OBJ_TEXT, name, 42));
+ ut_asserteq_ptr(name, txt->font_name);
+ ut_asserteq(42, txt->font_size);
+
+ ut_asserteq(-ENOENT, scene_txt_set_font(scn, OBJ_TEXT2, name, 42));
+
+ id = scene_menu(scn, "main", OBJ_MENU, &menu);
+ ut_assert(id > 0);
+
+ ut_assertok(scene_menu_set_title(scn, OBJ_MENU, OBJ_TEXT));
+
+ ut_asserteq(-ENOENT, scene_menu_set_title(scn, OBJ_TEXT2, OBJ_TEXT));
+ ut_asserteq(-EINVAL, scene_menu_set_title(scn, OBJ_MENU, OBJ_TEXT2));
+
+ expo_destroy(exp);
+
+ ut_assertok(ut_check_delta(start_mem));
+
+ return 0;
+}
+BOOTSTD_TEST(expo_object_attr, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check creating a scene with a menu */
+static int expo_object_menu(struct unit_test_state *uts)
+{
+ struct scene_obj_menu *menu;
+ struct scene_menitem *item;
+ int id, label_id, desc_id, key_id, pointer_id, preview_id;
+ struct scene_obj_txt *ptr, *name1, *desc1, *key1, *tit, *prev1;
+ struct scene *scn;
+ struct expo *exp;
+ ulong start_mem;
+
+ start_mem = ut_check_free();
+
+ ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
+ id = scene_new(exp, SCENE_NAME1, SCENE1, &scn);
+ ut_assert(id > 0);
+
+ id = scene_menu(scn, "main", OBJ_MENU, &menu);
+ ut_assert(id > 0);
+ ut_assertnonnull(menu);
+ ut_asserteq(OBJ_MENU, id);
+ ut_asserteq(SCENEOBJT_MENU, menu->obj.type);
+ ut_asserteq(0, menu->title_id);
+ ut_asserteq(0, menu->pointer_id);
+
+ ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400));
+ ut_asserteq(50, menu->obj.x);
+ ut_asserteq(400, menu->obj.y);
+
+ id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
+ "Main Menu", &tit);
+ ut_assert(id > 0);
+ ut_assertok(scene_menu_set_title(scn, OBJ_MENU, OBJ_MENU_TITLE));
+ ut_asserteq(OBJ_MENU_TITLE, menu->title_id);
+
+ pointer_id = scene_txt_str(scn, "cur_item", POINTER_TEXT,
+ STR_POINTER_TEXT, ">", &ptr);
+ ut_assert(pointer_id > 0);
+
+ ut_assertok(scene_menu_set_pointer(scn, OBJ_MENU, POINTER_TEXT));
+ ut_asserteq(POINTER_TEXT, menu->pointer_id);
+
+ label_id = scene_txt_str(scn, "label1", ITEM1_LABEL, STR_ITEM1_LABEL,
+ "Play", &name1);
+ ut_assert(label_id > 0);
+
+ desc_id = scene_txt_str(scn, "desc1", ITEM1_DESC, STR_ITEM1_DESC,
+ "Lord Melchett", &desc1);
+ ut_assert(desc_id > 0);
+
+ key_id = scene_txt_str(scn, "item1-key", ITEM1_KEY, STR_ITEM1_KEY, "1",
+ &key1);
+ ut_assert(key_id > 0);
+
+ preview_id = scene_txt_str(scn, "item1-preview", ITEM1_PREVIEW,
+ STR_ITEM1_PREVIEW, "(preview1)", &prev1);
+ ut_assert(preview_id > 0);
+
+ id = scene_menuitem(scn, OBJ_MENU, "linux", ITEM1, ITEM1_KEY,
+ ITEM1_LABEL, ITEM1_DESC, ITEM1_PREVIEW, 0, &item);
+ ut_asserteq(ITEM1, id);
+ ut_asserteq(id, item->id);
+ ut_asserteq(key_id, item->key_id);
+ ut_asserteq(label_id, item->label_id);
+ ut_asserteq(desc_id, item->desc_id);
+ ut_asserteq(preview_id, item->preview_id);
+
+ /* adding an item should cause the first item to become current */
+ ut_asserteq(id, menu->cur_item_id);
+
+ /* the title should be at the top */
+ ut_asserteq(menu->obj.x, tit->obj.x);
+ ut_asserteq(menu->obj.y, tit->obj.y);
+
+ /* the first item should be next */
+ ut_asserteq(menu->obj.x, name1->obj.x);
+ ut_asserteq(menu->obj.y + 32, name1->obj.y);
+
+ ut_asserteq(menu->obj.x + 230, key1->obj.x);
+ ut_asserteq(menu->obj.y + 32, key1->obj.y);
+
+ ut_asserteq(menu->obj.x + 200, ptr->obj.x);
+ ut_asserteq(menu->obj.y + 32, ptr->obj.y);
+
+ ut_asserteq(menu->obj.x + 280, desc1->obj.x);
+ ut_asserteq(menu->obj.y + 32, desc1->obj.y);
+
+ ut_asserteq(-4, prev1->obj.x);
+ ut_asserteq(menu->obj.y + 32, prev1->obj.y);
+ ut_asserteq(false, prev1->obj.hide);
+
+ expo_destroy(exp);
+
+ ut_assertok(ut_check_delta(start_mem));
+
+ return 0;
+}
+BOOTSTD_TEST(expo_object_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check rendering a scene */
+static int expo_render_image(struct unit_test_state *uts)
+{
+ struct scene_obj_menu *menu;
+ struct scene *scn, *scn2;
+ struct expo_action act;
+ struct scene_obj *obj;
+ struct udevice *dev;
+ struct expo *exp;
+ int id;
+
+ console_record_reset_enable();
+ ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+
+ ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
+ id = scene_new(exp, SCENE_NAME1, SCENE1, &scn);
+ ut_assert(id > 0);
+ ut_assertok(expo_set_display(exp, dev));
+
+ id = scene_img(scn, "logo", OBJ_LOGO, video_get_u_boot_logo(), NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 50, 20));
+
+ id = scene_txt_str(scn, "text", OBJ_TEXT, STR_TEXT, "my string", NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_txt_set_font(scn, OBJ_TEXT, "cantoraone_regular",
+ 40));
+ ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT, 400, 100));
+
+ id = scene_txt_str(scn, "text", OBJ_TEXT2, STR_TEXT2, "another string",
+ NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_txt_set_font(scn, OBJ_TEXT2, "nimbus_sans_l_regular",
+ 60));
+ ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT2, 200, 600));
+
+ id = scene_menu(scn, "main", OBJ_MENU, &menu);
+ ut_assert(id > 0);
+
+ id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
+ "Main Menu", NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_menu_set_title(scn, OBJ_MENU, OBJ_MENU_TITLE));
+
+ id = scene_txt_str(scn, "cur_item", POINTER_TEXT, STR_POINTER_TEXT, ">",
+ NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_menu_set_pointer(scn, OBJ_MENU, POINTER_TEXT));
+
+ id = scene_txt_str(scn, "label1", ITEM1_LABEL, STR_ITEM1_LABEL, "Play",
+ NULL);
+ ut_assert(id > 0);
+ id = scene_txt_str(scn, "item1 txt", ITEM1_DESC, STR_ITEM1_DESC,
+ "Lord Melchett", NULL);
+ ut_assert(id > 0);
+ id = scene_txt_str(scn, "item1-key", ITEM1_KEY, STR_ITEM1_KEY, "1",
+ NULL);
+ ut_assert(id > 0);
+ id = scene_img(scn, "item1-preview", ITEM1_PREVIEW,
+ video_get_u_boot_logo(), NULL);
+ id = scene_menuitem(scn, OBJ_MENU, "item1", ITEM1, ITEM1_KEY,
+ ITEM1_LABEL, ITEM1_DESC, ITEM1_PREVIEW, 0, NULL);
+ ut_assert(id > 0);
+
+ id = scene_txt_str(scn, "label2", ITEM2_LABEL, STR_ITEM2_LABEL, "Now",
+ NULL);
+ ut_assert(id > 0);
+ id = scene_txt_str(scn, "item2 txt", ITEM2_DESC, STR_ITEM2_DESC,
+ "Lord Percy", NULL);
+ ut_assert(id > 0);
+ id = scene_txt_str(scn, "item2-key", ITEM2_KEY, STR_ITEM2_KEY, "2",
+ NULL);
+ ut_assert(id > 0);
+ id = scene_img(scn, "item2-preview", ITEM2_PREVIEW,
+ video_get_u_boot_logo(), NULL);
+ ut_assert(id > 0);
+
+ id = scene_menuitem(scn, OBJ_MENU, "item2", ITEM2, ITEM2_KEY,
+ ITEM2_LABEL, ITEM2_DESC, ITEM2_PREVIEW, 0, NULL);
+ ut_assert(id > 0);
+
+ ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400));
+
+ scn2 = expo_lookup_scene_id(exp, SCENE1);
+ ut_asserteq_ptr(scn, scn2);
+ scn2 = expo_lookup_scene_id(exp, SCENE2);
+ ut_assertnull(scn2);
+
+ /* render without a scene */
+ ut_asserteq(-ECHILD, expo_render(exp));
+
+ /* render it */
+ expo_set_scene_id(exp, SCENE1);
+ ut_assertok(expo_render(exp));
+
+ /* move down */
+ ut_assertok(expo_send_key(exp, BKEY_DOWN));
+
+ ut_assertok(expo_action_get(exp, &act));
+
+ ut_asserteq(EXPOACT_POINT, act.type);
+ ut_asserteq(ITEM2, act.select.id);
+ ut_assertok(expo_render(exp));
+
+ /* make sure only the preview for the second item is shown */
+ obj = scene_obj_find(scn, ITEM1_PREVIEW, SCENEOBJT_NONE);
+ ut_asserteq(true, obj->hide);
+
+ obj = scene_obj_find(scn, ITEM2_PREVIEW, SCENEOBJT_NONE);
+ ut_asserteq(false, obj->hide);
+
+ /* select it */
+ ut_assertok(expo_send_key(exp, BKEY_SELECT));
+
+ ut_assertok(expo_action_get(exp, &act));
+ ut_asserteq(EXPOACT_SELECT, act.type);
+ ut_asserteq(ITEM2, act.select.id);
+
+ /* make sure the action doesn't come again */
+ ut_asserteq(-EAGAIN, expo_action_get(exp, &act));
+
+ /* make sure there was no console output */
+ ut_assert_console_end();
+
+ /* now try in text mode */
+ exp_set_text_mode(exp, true);
+ ut_assertok(expo_render(exp));
+
+ ut_assert_nextline("U-Boot : Boot Menu");
+ ut_assert_nextline("%s", "");
+ ut_assert_nextline("Main Menu");
+ ut_assert_nextline("%s", "");
+ ut_assert_nextline(" 1 Play Lord Melchett");
+ ut_assert_nextline(" > 2 Now Lord Percy");
+
+ /* Move back up to the first item */
+ ut_assertok(expo_send_key(exp, BKEY_UP));
+
+ ut_assertok(expo_action_get(exp, &act));
+
+ ut_asserteq(EXPOACT_POINT, act.type);
+ ut_asserteq(ITEM1, act.select.id);
+
+ ut_assertok(expo_render(exp));
+ ut_assert_nextline("U-Boot : Boot Menu");
+ ut_assert_nextline("%s", "");
+ ut_assert_nextline("Main Menu");
+ ut_assert_nextline("%s", "");
+ ut_assert_nextline(" > 1 Play Lord Melchett");
+ ut_assert_nextline(" 2 Now Lord Percy");
+
+ ut_assert_console_end();
+
+ expo_destroy(exp);
+
+ return 0;
+}
+BOOTSTD_TEST(expo_render_image, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index bc961df..09e410e 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -8,7 +8,7 @@
ifdef CONFIG_CONSOLE_RECORD
obj-$(CONFIG_CMD_PAUSE) += test_pause.o
endif
-obj-y += mem.o
+obj-y += exit.o mem.o
obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
obj-$(CONFIG_CMD_FDT) += fdt.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o
diff --git a/test/cmd/exit.c b/test/cmd/exit.c
new file mode 100644
index 0000000..ca34abe
--- /dev/null
+++ b/test/cmd/exit.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for exit command
+ *
+ * Copyright 2022 Marek Vasut <marex@denx.de>
+ */
+
+#include <common.h>
+#include <console.h>
+#include <mapmem.h>
+#include <asm/global_data.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Declare a new exit test */
+#define EXIT_TEST(_name, _flags) UNIT_TEST(_name, _flags, exit_test)
+
+/* Test 'exit addr' getting/setting address */
+static int cmd_exit_test(struct unit_test_state *uts)
+{
+ int i;
+
+ /*
+ * Test 'exit' with parameter -3, -2, -1, 0, 1, 2, 3 . Use all those
+ * parameters to cover also the special return value -2 that is used
+ * in HUSH to detect exit command.
+ *
+ * Always test whether 'exit' command:
+ * - exits out of the 'run' command
+ * - return value is propagated out of the 'run' command
+ * - return value can be tested on outside of 'run' command
+ * - return value can be printed outside of 'run' command
+ */
+ for (i = -3; i <= 3; i++) {
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; exit %d ; echo baz' ; run foo ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("%d", i > 0 ? i : 0);
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; exit %d ; echo baz' ; run foo && echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ if (i <= 0)
+ ut_assert_nextline("quux");
+ ut_assert_nextline("%d", i > 0 ? i : 0);
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; exit %d ; echo baz' ; run foo || echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ if (i > 0)
+ ut_assert_nextline("quux");
+ /* Either 'exit' returns 0, or 'echo quux' returns 0 */
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+ }
+
+ /* Validate that 'exit' behaves the same way as 'exit 0' */
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo && echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("quux");
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo || echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ /* Either 'exit' returns 0, or 'echo quux' returns 0 */
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+
+ /* Validate that return value still propagates from 'run' command */
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo && echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("quux");
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo || echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ /* The 'true' returns 0 */
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("1");
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo && echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("1");
+ ut_assertok(ut_check_console_end(uts));
+
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo || echo quux ; echo $?", i));
+ ut_assert_nextline("bar");
+ ut_assert_nextline("quux");
+ /* The 'echo quux' returns 0 */
+ ut_assert_nextline("0");
+ ut_assertok(ut_check_console_end(uts));
+
+ return 0;
+}
+
+EXIT_TEST(cmd_exit_test, UT_TESTF_CONSOLE_REC);
+
+int do_ut_exit(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct unit_test *tests = UNIT_TEST_SUITE_START(exit_test);
+ const int n_ents = UNIT_TEST_SUITE_COUNT(exit_test);
+
+ return cmd_ut_category("cmd_exit", "exit_test_", tests, n_ents,
+ argc, argv);
+}
diff --git a/test/cmd/font.c b/test/cmd/font.c
index 7a4156a..adb3539 100644
--- a/test/cmd/font.c
+++ b/test/cmd/font.c
@@ -33,7 +33,7 @@
ut_assertok(ut_check_console_end(uts));
ut_asserteq_str("nimbus_sans_l_regular",
- vidconsole_get_font(dev, &size));
+ vidconsole_get_font_size(dev, &size));
ut_asserteq(18, size);
max_metrics = 1;
@@ -53,14 +53,14 @@
ut_assertok(ut_check_console_end(uts));
ut_asserteq_str("cantoraone_regular",
- vidconsole_get_font(dev, &size));
+ vidconsole_get_font_size(dev, &size));
ut_asserteq(40, size);
ut_assertok(run_command("font size 30", 0));
ut_assertok(ut_check_console_end(uts));
ut_asserteq_str("cantoraone_regular",
- vidconsole_get_font(dev, &size));
+ vidconsole_get_font_size(dev, &size));
ut_asserteq(30, size);
return 0;
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 2736582..1713d0d 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -65,6 +65,7 @@
#if defined(CONFIG_UT_ENV)
U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""),
#endif
+ U_BOOT_CMD_MKENT(exit, CONFIG_SYS_MAXARGS, 1, do_ut_exit, "", ""),
#ifdef CONFIG_CMD_FDT
U_BOOT_CMD_MKENT(fdt, CONFIG_SYS_MAXARGS, 1, do_ut_fdt, "", ""),
#endif
@@ -188,7 +189,7 @@
"\nfdt - fdt command"
#endif
#ifdef CONFIG_CONSOLE_TRUETYPE
- "\nut font - font command\n"
+ "\nut font - font command"
#endif
#ifdef CONFIG_CMD_LOADM
"\nloadm - loadm command parameters and loading memory blob"
diff --git a/test/compression.c b/test/compression.c
index 82e29c9..3df9081 100644
--- a/test/compression.c
+++ b/test/compression.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
+#include <abuf.h>
#include <bootm.h>
#include <command.h>
#include <gzip.h>
@@ -22,6 +23,7 @@
#include <lzma/LzmaTools.h>
#include <linux/lzo.h>
+#include <linux/zstd.h>
#include <test/compression.h>
#include <test/suites.h>
#include <test/ut.h>
@@ -53,7 +55,7 @@
"\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef"
"\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a"
"\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48";
-static const unsigned long bzip2_compressed_size = 240;
+static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1;
/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */
static const char lzma_compressed[] =
@@ -72,7 +74,7 @@
"\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3"
"\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff"
"\xfd\xf5\x50\x8d\xca";
-static const unsigned long lzma_compressed_size = 229;
+static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1;
/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */
static const char lzo_compressed[] =
@@ -97,7 +99,7 @@
"\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f"
"\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73"
"\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00";
-static const unsigned long lzo_compressed_size = 334;
+static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1;
/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */
static const char lz4_compressed[] =
@@ -119,7 +121,24 @@
"\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01"
"\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00"
"\x9d\x12\x8c\x9d";
-static const unsigned long lz4_compressed_size = 276;
+static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1;
+
+/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */
+static const char zstd_compressed[] =
+ "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17"
+ "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78"
+ "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4"
+ "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67"
+ "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f"
+ "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6"
+ "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2"
+ "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd"
+ "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3"
+ "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21"
+ "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55"
+ "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95"
+ "\x01\xe4\xf4\x6e\xfa";
+static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1;
#define TEST_BUFFER_SIZE 512
@@ -296,6 +315,45 @@
return (ret != 0);
}
+static int compress_using_zstd(struct unit_test_state *uts,
+ void *in, unsigned long in_size,
+ void *out, unsigned long out_max,
+ unsigned long *out_size)
+{
+ /* There is no zstd compression in u-boot, so fake it. */
+ ut_asserteq(in_size, strlen(plain));
+ ut_asserteq_mem(plain, in, in_size);
+
+ if (zstd_compressed_size > out_max)
+ return -1;
+
+ memcpy(out, zstd_compressed, zstd_compressed_size);
+ if (out_size)
+ *out_size = zstd_compressed_size;
+
+ return 0;
+}
+
+static int uncompress_using_zstd(struct unit_test_state *uts,
+ void *in, unsigned long in_size,
+ void *out, unsigned long out_max,
+ unsigned long *out_size)
+{
+ struct abuf in_buf, out_buf;
+ int ret;
+
+ abuf_init_set(&in_buf, in, in_size);
+ abuf_init_set(&out_buf, out, out_max);
+
+ ret = zstd_decompress(&in_buf, &out_buf);
+ if (ret >= 0) {
+ *out_size = ret;
+ ret = 0;
+ }
+
+ return ret;
+}
+
#define errcheck(statement) if (!(statement)) { \
fprintf(stderr, "\tFailed: %s\n", #statement); \
ret = 1; \
@@ -321,42 +379,48 @@
/* Compress works as expected. */
printf("\torig_size:%lu\n", buf->orig_size);
memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE);
- errcheck(compress(uts, buf->orig_buf, buf->orig_size,
+ ut_assertok(compress(uts, buf->orig_buf, buf->orig_size,
buf->compressed_buf, buf->compressed_size,
- &buf->compressed_size) == 0);
+ &buf->compressed_size));
printf("\tcompressed_size:%lu\n", buf->compressed_size);
- errcheck(buf->compressed_size > 0);
- errcheck(buf->compressed_size < buf->orig_size);
- errcheck(((char *)buf->compressed_buf)[buf->compressed_size - 1] !=
- 'A');
- errcheck(((char *)buf->compressed_buf)[buf->compressed_size] == 'A');
+ ut_assert(buf->compressed_size > 0);
+ ut_assert(buf->compressed_size < buf->orig_size);
+ ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1]
+ != 'A');
+ ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A');
/* Uncompresses with space remaining. */
- errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
+ ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
buf->uncompressed_buf, buf->uncompressed_size,
- &buf->uncompressed_size) == 0);
+ &buf->uncompressed_size));
printf("\tuncompressed_size:%lu\n", buf->uncompressed_size);
- errcheck(buf->uncompressed_size == buf->orig_size);
- errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
- buf->orig_size) == 0);
+ ut_asserteq(buf->uncompressed_size, buf->orig_size);
+ ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
/* Uncompresses with exactly the right size output buffer. */
memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
- errcheck(uncompress(uts, buf->compressed_buf, buf->compressed_size,
+ ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size,
buf->uncompressed_buf, buf->orig_size,
- &buf->uncompressed_size) == 0);
- errcheck(buf->uncompressed_size == buf->orig_size);
- errcheck(memcmp(buf->orig_buf, buf->uncompressed_buf,
- buf->orig_size) == 0);
- errcheck(((char *)buf->uncompressed_buf)[buf->orig_size] == 'A');
+ &buf->uncompressed_size));
+ ut_asserteq(buf->uncompressed_size, buf->orig_size);
+ ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
+ ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A');
+
+ /* Uncompresses with trailing garbage in input buffer. */
+ memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE);
+ ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4,
+ buf->uncompressed_buf, buf->uncompressed_size,
+ &buf->uncompressed_size));
+ ut_asserteq(buf->uncompressed_size, buf->orig_size);
+ ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size);
/* Make sure compression does not over-run. */
memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE);
ret = compress(uts, buf->orig_buf, buf->orig_size,
buf->compare_buf, buf->compressed_size - 1,
NULL);
- errcheck(((char *)buf->compare_buf)[buf->compressed_size] == 'A');
- errcheck(ret != 0);
+ ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A');
+ ut_assert(ret != 0);
printf("\tcompress does not overrun\n");
/* Make sure decompression does not over-run. */
@@ -364,15 +428,12 @@
ret = uncompress(uts, buf->compressed_buf, buf->compressed_size,
buf->compare_buf, buf->uncompressed_size - 1,
NULL);
- errcheck(((char *)buf->compare_buf)[buf->uncompressed_size - 1] == 'A');
- errcheck(ret != 0);
+ ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A');
+ ut_assert(ret != 0);
printf("\tuncompress does not overrun\n");
/* Got here, everything is fine. */
- ret = 0;
-
-out:
- return ret;
+ return 0;
}
static int run_test(struct unit_test_state *uts, char *name,
@@ -440,6 +501,13 @@
}
COMPRESSION_TEST(compression_test_lz4, 0);
+static int compression_test_zstd(struct unit_test_state *uts)
+{
+ return run_test(uts, "zstd", compress_using_zstd,
+ uncompress_using_zstd);
+}
+COMPRESSION_TEST(compression_test_zstd, 0);
+
static int compress_using_none(struct unit_test_state *uts,
void *in, unsigned long in_size,
void *out, unsigned long out_max,
@@ -530,6 +598,12 @@
}
COMPRESSION_TEST(compression_test_bootm_lz4, 0);
+static int compression_test_bootm_zstd(struct unit_test_state *uts)
+{
+ return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd);
+}
+COMPRESSION_TEST(compression_test_bootm_zstd, 0);
+
static int compression_test_bootm_none(struct unit_test_state *uts)
{
return run_bootm_test(uts, IH_COMP_NONE, compress_using_none);
diff --git a/test/dm/part.c b/test/dm/part.c
index 78dd847..35e99ee 100644
--- a/test/dm/part.c
+++ b/test/dm/part.c
@@ -11,8 +11,8 @@
#include <dm/test.h>
#include <test/ut.h>
-static inline int do_test(struct unit_test_state *uts, int expected,
- const char *part_str, bool whole)
+static int do_test(struct unit_test_state *uts, int expected,
+ const char *part_str, bool whole)
{
struct blk_desc *mmc_dev_desc;
struct disk_partition part_info;
@@ -43,7 +43,7 @@
},
};
- ut_asserteq(1, blk_get_device_by_str("mmc", "1", &mmc_dev_desc));
+ ut_asserteq(2, blk_get_device_by_str("mmc", "2", &mmc_dev_desc));
if (CONFIG_IS_ENABLED(RANDOM_UUID)) {
gen_rand_uuid_str(parts[0].uuid, UUID_STR_FORMAT_STD);
gen_rand_uuid_str(parts[1].uuid, UUID_STR_FORMAT_STD);
@@ -54,11 +54,8 @@
oldbootdevice = env_get("bootdevice");
-#define test(expected, part_str, whole) do { \
- ret = do_test(uts, expected, part_str, whole); \
- if (ret) \
- goto out; \
-} while (0)
+#define test(expected, part_str, whole) \
+ ut_assertok(do_test(uts, expected, part_str, whole))
env_set("bootdevice", NULL);
test(-ENODEV, NULL, true);
@@ -66,7 +63,7 @@
env_set("bootdevice", "0");
test(0, NULL, true);
test(0, "", true);
- env_set("bootdevice", "1");
+ env_set("bootdevice", "2");
test(1, NULL, false);
test(1, "", false);
test(1, "-", false);
@@ -77,8 +74,8 @@
test(0, ".0", true);
test(0, ".0:0", true);
test(-EINVAL, "#test1", true);
- test(1, "1", false);
- test(1, "1", true);
+ test(1, "2", false);
+ test(1, "2", true);
test(-ENOENT, "1:0", false);
test(0, "1:0", true);
test(1, "1:1", false);
@@ -88,12 +85,24 @@
test(1, "1.0:1", false);
test(2, "1.0:2", false);
test(-EINVAL, "1#bogus", false);
- test(1, "1#test1", false);
- test(2, "1#test2", false);
+ test(1, "2#test1", false);
+ test(2, "2#test2", false);
ret = 0;
-out:
env_set("bootdevice", oldbootdevice);
return ret;
}
DM_TEST(dm_test_part, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+static int dm_test_part_bootable(struct unit_test_state *uts)
+{
+ struct blk_desc *desc;
+ struct udevice *dev;
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &dev));
+ desc = dev_get_uclass_plat(dev);
+ ut_asserteq(1, part_get_bootable(desc));
+
+ return 0;
+}
+DM_TEST(dm_test_part_bootable, UT_TESTF_SCAN_FDT);
diff --git a/test/dm/virtio_device.c b/test/dm/virtio_device.c
index b5c4523..fdda4da 100644
--- a/test/dm/virtio_device.c
+++ b/test/dm/virtio_device.c
@@ -100,6 +100,7 @@
static int dm_test_virtio_remove(struct unit_test_state *uts)
{
struct udevice *bus, *dev;
+ u8 status;
/* check probe success */
ut_assertok(uclass_first_device_err(UCLASS_VIRTIO, &bus));
@@ -117,6 +118,8 @@
ut_asserteq(-EKEYREJECTED, device_remove(bus, DM_REMOVE_ACTIVE_ALL));
ut_asserteq(false, device_active(dev));
+ virtio_get_status(dev, &status);
+ ut_assertok(status);
return 0;
}
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index b877481..dec2634 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -462,22 +462,22 @@
FAIL=0
# Check if the ls is showing correct results for 2.5 gb file
- grep -A7 "Test Case 1 " "$1" | egrep -iq "2621440000 *$4"
+ grep -A7 "Test Case 1 " "$1" | grep -Eiq "2621440000 *$4"
pass_fail "TC1: ls of $4"
# Check if the ls is showing correct results for 1 mb file
- grep -A7 "Test Case 1 " "$1" | egrep -iq "1048576 *$3"
+ grep -A7 "Test Case 1 " "$1" | grep -Eiq "1048576 *$3"
pass_fail "TC1: ls of $3"
# Check size command on 1MB.file
- egrep -A3 "Test Case 2a " "$1" | grep -q "filesize=100000"
+ grep -A3 "Test Case 2a " "$1" | grep -q "filesize=100000"
pass_fail "TC2: size of $3"
# Check size command on 1MB.file via a path using '..'
- egrep -A3 "Test Case 2b " "$1" | grep -q "filesize=100000"
+ grep -A3 "Test Case 2b " "$1" | grep -q "filesize=100000"
pass_fail "TC2: size of $3 via a path using '..'"
# Check size command on 2.5GB.file
- egrep -A3 "Test Case 3 " "$1" | grep -q "filesize=9c400000"
+ grep -A3 "Test Case 3 " "$1" | grep -q "filesize=9c400000"
pass_fail "TC3: size of $4"
# Check read full mb of 1MB.file
diff --git a/test/py/tests/bootstd/armbian.bmp.xz b/test/py/tests/bootstd/armbian.bmp.xz
new file mode 100644
index 0000000..ad137ea
--- /dev/null
+++ b/test/py/tests/bootstd/armbian.bmp.xz
Binary files differ
diff --git a/test/py/tests/bootstd/mmc1.img.xz b/test/py/tests/bootstd/mmc1.img.xz
index 4e7f39b..cebf7b9 100644
--- a/test/py/tests/bootstd/mmc1.img.xz
+++ b/test/py/tests/bootstd/mmc1.img.xz
Binary files differ
diff --git a/test/py/tests/bootstd/mmc4.img.xz b/test/py/tests/bootstd/mmc4.img.xz
new file mode 100644
index 0000000..f4db011
--- /dev/null
+++ b/test/py/tests/bootstd/mmc4.img.xz
Binary files differ
diff --git a/test/py/tests/test_android/test_avb.py b/test/py/tests/test_android/test_avb.py
index a3f8831..bc5c5b5 100644
--- a/test/py/tests/test_android/test_avb.py
+++ b/test/py/tests/test_android/test_avb.py
@@ -39,6 +39,7 @@
@pytest.mark.buildconfigspec('cmd_avb')
@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.notbuildconfigspec('sandbox')
def test_avb_mmc_uuid(u_boot_console):
"""Check if 'avb get_uuid' works, compare results with
'part list mmc 1' output
@@ -97,6 +98,7 @@
@pytest.mark.buildconfigspec('cmd_avb')
@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.notbuildconfigspec('sandbox')
def test_avb_mmc_read(u_boot_console):
"""Test mmc read operation
"""
diff --git a/test/py/tests/test_dm.py b/test/py/tests/test_dm.py
index ea93061..68d4ea1 100644
--- a/test/py/tests/test_dm.py
+++ b/test/py/tests/test_dm.py
@@ -16,6 +16,44 @@
for driver in drivers:
assert driver in response
+ # check sorting - output looks something like this:
+ # testacpi 0 [ ] testacpi_drv |-- acpi-test
+ # testacpi 1 [ ] testacpi_drv | `-- child
+ # pci_emul_p 1 [ ] pci_emul_parent_drv |-- pci-emul2
+ # pci_emul 5 [ ] sandbox_swap_case_em | `-- emul2@1f,0
+
+ # The number of '| ' and '--' matches indicate the indent level. We start
+ # checking sorting only after UCLASS_AXI_EMUL after which the names should
+ # be sorted.
+
+ response = u_boot_console.run_command('dm tree -s')
+ lines = response.split('\n')[2:]
+ stack = [] # holds where we were up to at the previous indent level
+ prev = '' # uclass name of previous line
+ start = False
+ for line in lines:
+ indent = line.count('| ') + ('--' in line)
+ cur = line.split()[0]
+ if not start:
+ if cur != 'axi_emul':
+ continue
+ start = True
+
+ # Handle going up or down an indent level
+ if indent > len(stack):
+ stack.append(prev)
+ prev = ''
+ elif indent < len(stack):
+ prev = stack.pop()
+
+ # Check that the current uclass name is not alphabetically before the
+ # previous one
+ if 'emul' not in cur and cur < prev:
+ print('indent', cur >= prev, indent, prev, cur, stack)
+ assert cur >= prev
+ prev = cur
+
+
@pytest.mark.buildconfigspec('cmd_dm')
def test_dm_drivers(u_boot_console):
"""Test that each driver in `dm compat` is also listed in `dm drivers`."""
diff --git a/test/py/tests/test_env.py b/test/py/tests/test_env.py
index 6d08565..00bcccd 100644
--- a/test/py/tests/test_env.py
+++ b/test/py/tests/test_env.py
@@ -8,6 +8,7 @@
import os
import os.path
+import re
from subprocess import call, CalledProcessError
import tempfile
@@ -173,6 +174,29 @@
response = state_test_env.u_boot_console.run_command('printenv %s' % var)
assert response == ('%s=%s' % (var, value))
+@pytest.mark.boardspec('sandbox')
+def test_env_initial_env_file(u_boot_console):
+ """Test that the u-boot-initial-env make target works"""
+ cons = u_boot_console
+ builddir = 'O=' + cons.config.build_dir
+ envfile = cons.config.build_dir + '/u-boot-initial-env'
+
+ # remove if already exists from an older run
+ try:
+ os.remove(envfile)
+ except:
+ pass
+
+ u_boot_utils.run_and_log(cons, ['make', builddir, 'u-boot-initial-env'])
+
+ assert os.path.exists(envfile)
+
+ # assume that every environment has a board variable, e.g. board=sandbox
+ with open(envfile, 'r') as file:
+ env = file.read()
+ regex = re.compile('board=.+\\n')
+ assert re.search(regex, env)
+
def test_env_echo_exists(state_test_env):
"""Test echoing a variable that exists."""
diff --git a/test/py/tests/test_gpt.py b/test/py/tests/test_gpt.py
index cb44e1d..73bfbf7 100644
--- a/test/py/tests/test_gpt.py
+++ b/test/py/tests/test_gpt.py
@@ -136,6 +136,29 @@
@pytest.mark.boardspec('sandbox')
@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_part_type_uuid(state_disk_image, u_boot_console):
+ """Test the gpt partittion type UUID command."""
+
+ u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+ output = u_boot_console.run_command('part type host 0:1')
+ assert '0fc63daf-8483-4772-8e79-3d69d8477de4' in output
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
+@pytest.mark.requiredtool('sgdisk')
+def test_gpt_part_type_save_uuid(state_disk_image, u_boot_console):
+ """Test the gpt partittion type to save UUID into a string."""
+
+ if u_boot_console.config.buildconfig.get('config_cmd_gpt', 'n') != 'y':
+ pytest.skip('gpt command not supported')
+ u_boot_console.run_command('host bind 0 ' + state_disk_image.path)
+ output = u_boot_console.run_command('part type host 0:1 newguid')
+ output = u_boot_console.run_command('printenv newguid')
+ assert '0fc63daf-8483-4772-8e79-3d69d8477de4' in output
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_gpt')
@pytest.mark.buildconfigspec('cmd_gpt_rename')
@pytest.mark.buildconfigspec('cmd_part')
@pytest.mark.requiredtool('sgdisk')
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index bab8b97..e8c8a6d 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+import getpass
import gzip
import os
import os.path
@@ -13,34 +14,222 @@
"""Create a directory if it doesn't already exist
Args:
- dirname: Name of directory to create
+ dirname (str): Name of directory to create
"""
if not os.path.exists(dirname):
os.mkdir(dirname)
-def setup_bootflow_image(u_boot_console):
- """Create a 20MB disk image with a single FAT partition"""
- cons = u_boot_console
- fname = os.path.join(cons.config.source_dir, 'mmc1.img')
+def setup_image(cons, mmc_dev, part_type, second_part=False):
+ """Create a 20MB disk image with a single partition
+
+ Args:
+ cons (ConsoleBase): Console to use
+ mmc_dev (int): MMC device number to use, e.g. 1
+ part_type (int): Partition type, e.g. 0xc for FAT32
+ second_part (bool): True to contain a small second partition
+
+ Returns:
+ tuple:
+ str: Filename of MMC image
+ str: Directory name of 'mnt' directory
+ """
+ fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img')
mnt = os.path.join(cons.config.persistent_data_dir, 'mnt')
mkdir_cond(mnt)
+ spec = f'type={part_type:x}, size=18M, bootable'
+ if second_part:
+ spec += '\ntype=c'
+
u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname)
u_boot_utils.run_and_log(cons, 'sudo sfdisk %s' % fname,
- stdin=b'type=c')
+ stdin=spec.encode('utf-8'))
+ return fname, mnt
+
+def mount_image(cons, fname, mnt, fstype):
+ """Create a filesystem and mount it on partition 1
+
+ Args:
+ cons (ConsoleBase): Console to use
+ fname (str): Filename of MMC image
+ mnt (str): Directory name of 'mnt' directory
+ fstype (str): Filesystem type ('vfat' or 'ext4')
+
+ Returns:
+ str: Name of loop device used
+ """
+ out = u_boot_utils.run_and_log(cons, 'sudo losetup --show -f -P %s' % fname)
+ loop = out.strip()
+ part = f'{loop}p1'
+ u_boot_utils.run_and_log(cons, f'sudo mkfs.{fstype} {part}')
+ opts = ''
+ if fstype == 'vfat':
+ opts += f' -o uid={os.getuid()},gid={os.getgid()}'
+ u_boot_utils.run_and_log(cons, f'sudo mount -o loop {part} {mnt}{opts}')
+ u_boot_utils.run_and_log(cons, f'sudo chown {getpass.getuser()} {mnt}')
+ return loop
+
+def copy_prepared_image(cons, mmc_dev, fname):
+ """Use a prepared image since we cannot create one
+
+ Args:
+ cons (ConsoleBase): Console touse
+ mmc_dev (int): MMC device number
+ fname (str): Filename of MMC image
+ """
+ infname = os.path.join(cons.config.source_dir,
+ f'test/py/tests/bootstd/mmc{mmc_dev}.img.xz')
+ u_boot_utils.run_and_log(
+ cons,
+ ['sh', '-c', 'xz -dc %s >%s' % (infname, fname)])
+
+def setup_bootmenu_image(cons):
+ """Create a 20MB disk image with a single ext4 partition
+
+ This is modelled on Armbian 22.08 Jammy
+ """
+ mmc_dev = 4
+ fname, mnt = setup_image(cons, mmc_dev, 0x83)
loop = None
mounted = False
complete = False
try:
- out = u_boot_utils.run_and_log(cons,
- 'sudo losetup --show -f -P %s' % fname)
- loop = out.strip()
- fatpart = '%sp1' % loop
- u_boot_utils.run_and_log(cons, 'sudo mkfs.vfat %s' % fatpart)
+ loop = mount_image(cons, fname, mnt, 'ext4')
+ mounted = True
+
+ vmlinux = 'Image'
+ initrd = 'uInitrd'
+ dtbdir = 'dtb'
+ script = '''# DO NOT EDIT THIS FILE
+#
+# Please edit /boot/armbianEnv.txt to set supported parameters
+#
+
+setenv load_addr "0x9000000"
+setenv overlay_error "false"
+# default values
+setenv rootdev "/dev/mmcblk%dp1"
+setenv verbosity "1"
+setenv console "both"
+setenv bootlogo "false"
+setenv rootfstype "ext4"
+setenv docker_optimizations "on"
+setenv earlycon "off"
+
+echo "Boot script loaded from ${devtype} ${devnum}"
+
+if test -e ${devtype} ${devnum} ${prefix}armbianEnv.txt; then
+ load ${devtype} ${devnum} ${load_addr} ${prefix}armbianEnv.txt
+ env import -t ${load_addr} ${filesize}
+fi
+
+if test "${logo}" = "disabled"; then setenv logo "logo.nologo"; fi
+
+if test "${console}" = "display" || test "${console}" = "both"; then setenv consoleargs "console=tty1"; fi
+if test "${console}" = "serial" || test "${console}" = "both"; then setenv consoleargs "console=ttyS2,1500000 ${consoleargs}"; fi
+if test "${earlycon}" = "on"; then setenv consoleargs "earlycon ${consoleargs}"; fi
+if test "${bootlogo}" = "true"; then setenv consoleargs "bootsplash.bootfile=bootsplash.armbian ${consoleargs}"; fi
+
+# get PARTUUID of first partition on SD/eMMC the boot script was loaded from
+if test "${devtype}" = "mmc"; then part uuid mmc ${devnum}:1 partuuid; fi
+
+setenv bootargs "root=${rootdev} rootwait rootfstype=${rootfstype} ${consoleargs} consoleblank=0 loglevel=${verbosity} ubootpart=${partuuid} usb-storage.quirks=${usbstoragequirks} ${extraargs} ${extraboardargs}"
+
+if test "${docker_optimizations}" = "on"; then setenv bootargs "${bootargs} cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory swapaccount=1"; fi
+
+load ${devtype} ${devnum} ${ramdisk_addr_r} ${prefix}uInitrd
+load ${devtype} ${devnum} ${kernel_addr_r} ${prefix}Image
+
+load ${devtype} ${devnum} ${fdt_addr_r} ${prefix}dtb/${fdtfile}
+fdt addr ${fdt_addr_r}
+fdt resize 65536
+for overlay_file in ${overlays}; do
+ if load ${devtype} ${devnum} ${load_addr} ${prefix}dtb/rockchip/overlay/${overlay_prefix}-${overlay_file}.dtbo; then
+ echo "Applying kernel provided DT overlay ${overlay_prefix}-${overlay_file}.dtbo"
+ fdt apply ${load_addr} || setenv overlay_error "true"
+ fi
+done
+for overlay_file in ${user_overlays}; do
+ if load ${devtype} ${devnum} ${load_addr} ${prefix}overlay-user/${overlay_file}.dtbo; then
+ echo "Applying user provided DT overlay ${overlay_file}.dtbo"
+ fdt apply ${load_addr} || setenv overlay_error "true"
+ fi
+done
+if test "${overlay_error}" = "true"; then
+ echo "Error applying DT overlays, restoring original DT"
+ load ${devtype} ${devnum} ${fdt_addr_r} ${prefix}dtb/${fdtfile}
+else
+ if load ${devtype} ${devnum} ${load_addr} ${prefix}dtb/rockchip/overlay/${overlay_prefix}-fixup.scr; then
+ echo "Applying kernel provided DT fixup script (${overlay_prefix}-fixup.scr)"
+ source ${load_addr}
+ fi
+ if test -e ${devtype} ${devnum} ${prefix}fixup.scr; then
+ load ${devtype} ${devnum} ${load_addr} ${prefix}fixup.scr
+ echo "Applying user provided fixup script (fixup.scr)"
+ source ${load_addr}
+ fi
+fi
+booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
+
+# Recompile with:
+# mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr
+''' % (mmc_dev)
+ bootdir = os.path.join(mnt, 'boot')
+ mkdir_cond(bootdir)
+ cmd_fname = os.path.join(bootdir, 'boot.cmd')
+ scr_fname = os.path.join(bootdir, 'boot.scr')
+ with open(cmd_fname, 'w') as outf:
+ print(script, file=outf)
+
+ infname = os.path.join(cons.config.source_dir,
+ 'test/py/tests/bootstd/armbian.bmp.xz')
+ bmp_file = os.path.join(bootdir, 'boot.bmp')
u_boot_utils.run_and_log(
- cons, 'sudo mount -o loop %s %s -o uid=%d,gid=%d' %
- (fatpart, mnt, os.getuid(), os.getgid()))
+ cons,
+ ['sh', '-c', f'xz -dc {infname} >{bmp_file}'])
+
+ u_boot_utils.run_and_log(
+ cons, f'mkimage -C none -A arm -T script -d {cmd_fname} {scr_fname}')
+
+ kernel = 'vmlinuz-5.15.63-rockchip64'
+ target = os.path.join(bootdir, kernel)
+ with open(target, 'wb') as outf:
+ print('kernel', outf)
+
+ symlink = os.path.join(bootdir, 'Image')
+ if os.path.exists(symlink):
+ os.remove(symlink)
+ u_boot_utils.run_and_log(
+ cons, f'echo here {kernel} {symlink}')
+ os.symlink(kernel, symlink)
+
+ u_boot_utils.run_and_log(
+ cons, f'mkimage -C none -A arm -T script -d {cmd_fname} {scr_fname}')
+ complete = True
+
+ except ValueError as exc:
+ print('Falled to create image, failing back to prepared copy: %s',
+ str(exc))
+ finally:
+ if mounted:
+ u_boot_utils.run_and_log(cons, 'sudo umount %s' % mnt)
+ if loop:
+ u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop)
+
+ if not complete:
+ copy_prepared_image(cons, mmc_dev, fname)
+
+def setup_bootflow_image(cons):
+ """Create a 20MB disk image with a single FAT partition"""
+ mmc_dev = 1
+ fname, mnt = setup_image(cons, mmc_dev, 0xc, second_part=True)
+
+ loop = None
+ mounted = False
+ complete = False
+ try:
+ loop = mount_image(cons, fname, mnt, 'vfat')
mounted = True
vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl'
@@ -90,12 +279,7 @@
u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop)
if not complete:
- # Use a prepared image since we cannot create one
- infname = os.path.join(cons.config.source_dir,
- 'test/py/tests/bootstd/mmc1.img.xz')
- u_boot_utils.run_and_log(
- cons,
- ['sh', '-c', 'xz -dc %s >%s' % (infname, fname)])
+ copy_prepared_image(cons, mmc_dev, fname)
@pytest.mark.buildconfigspec('ut_dm')
@@ -134,6 +318,7 @@
"""Initialise data for bootflow tests"""
setup_bootflow_image(u_boot_console)
+ setup_bootmenu_image(u_boot_console)
# Restart so that the new mmc1.img is picked up
u_boot_console.restart_uboot()
diff --git a/test/str_ut.c b/test/str_ut.c
index 5a84434..fa9328e 100644
--- a/test/str_ut.c
+++ b/test/str_ut.c
@@ -274,6 +274,88 @@
}
STR_TEST(str_trailing, 0);
+static int test_str_to_list(struct unit_test_state *uts)
+{
+ const char **ptr;
+ ulong start;
+
+ /* check out of memory */
+ start = ut_check_delta(0);
+ malloc_enable_testing(0);
+ ut_assertnull(str_to_list(""));
+ ut_assertok(ut_check_delta(start));
+
+ ut_assertnull(str_to_list("this is a test"));
+ ut_assertok(ut_check_delta(start));
+
+ malloc_enable_testing(1);
+ ut_assertnull(str_to_list("this is a test"));
+ ut_assertok(ut_check_delta(start));
+
+ /* for an empty string, only one nalloc is needed */
+ malloc_enable_testing(1);
+ ptr = str_to_list("");
+ ut_assertnonnull(ptr);
+ ut_assertnull(ptr[0]);
+ str_free_list(ptr);
+ ut_assertok(ut_check_delta(start));
+
+ malloc_disable_testing();
+
+ /* test the same again, without any nalloc restrictions */
+ ptr = str_to_list("");
+ ut_assertnonnull(ptr);
+ ut_assertnull(ptr[0]);
+ str_free_list(ptr);
+ ut_assertok(ut_check_delta(start));
+
+ /* test a single string */
+ start = ut_check_delta(0);
+ ptr = str_to_list("hi");
+ ut_assertnonnull(ptr);
+ ut_assertnonnull(ptr[0]);
+ ut_asserteq_str("hi", ptr[0]);
+ ut_assertnull(ptr[1]);
+ str_free_list(ptr);
+ ut_assertok(ut_check_delta(start));
+
+ /* test two strings */
+ ptr = str_to_list("hi there");
+ ut_assertnonnull(ptr);
+ ut_assertnonnull(ptr[0]);
+ ut_asserteq_str("hi", ptr[0]);
+ ut_assertnonnull(ptr[1]);
+ ut_asserteq_str("there", ptr[1]);
+ ut_assertnull(ptr[2]);
+ str_free_list(ptr);
+ ut_assertok(ut_check_delta(start));
+
+ /* test leading, trailing and multiple spaces */
+ ptr = str_to_list(" more space ");
+ ut_assertnonnull(ptr);
+ ut_assertnonnull(ptr[0]);
+ ut_asserteq_str("", ptr[0]);
+ ut_assertnonnull(ptr[1]);
+ ut_asserteq_str("more", ptr[1]);
+ ut_assertnonnull(ptr[2]);
+ ut_asserteq_str("", ptr[2]);
+ ut_assertnonnull(ptr[3]);
+ ut_asserteq_str("space", ptr[3]);
+ ut_assertnonnull(ptr[4]);
+ ut_asserteq_str("", ptr[4]);
+ ut_assertnonnull(ptr[5]);
+ ut_asserteq_str("", ptr[5]);
+ ut_assertnull(ptr[6]);
+ str_free_list(ptr);
+ ut_assertok(ut_check_delta(start));
+
+ /* test freeing a NULL pointer */
+ str_free_list(NULL);
+
+ return 0;
+}
+STR_TEST(test_str_to_list, 0);
+
int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct unit_test *tests = UNIT_TEST_SUITE_START(str_test);
diff --git a/test/test-main.c b/test/test-main.c
index 5931e94..ea959f4 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -10,6 +10,7 @@
#include <cyclic.h>
#include <dm.h>
#include <event.h>
+#include <net.h>
#include <of_live.h>
#include <os.h>
#include <dm/ofnode.h>
@@ -296,17 +297,28 @@
uts->start = mallinfo();
- if (test->flags & UT_TESTF_SCAN_PDATA) {
+ if (test->flags & UT_TESTF_SCAN_PDATA)
ut_assertok(dm_scan_plat(false));
- ut_assertok(dm_scan_other(false));
- }
if (test->flags & UT_TESTF_PROBE_TEST)
ut_assertok(do_autoprobe(uts));
if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
- (test->flags & UT_TESTF_SCAN_FDT))
+ (test->flags & UT_TESTF_SCAN_FDT)) {
+ /*
+ * only set this if we know the ethernet uclass will be created
+ */
+ eth_set_enable_bootdevs(test->flags & UT_TESTF_ETH_BOOTDEV);
+ test_sf_set_enable_bootdevs(test->flags & UT_TESTF_SF_BOOTDEV);
ut_assertok(dm_extended_scan(false));
+ }
+
+ /*
+ * Do this after FDT scan since dm_scan_other() in bootstd-uclass.c
+ * checks for the existence of bootstd
+ */
+ if (test->flags & UT_TESTF_SCAN_PDATA)
+ ut_assertok(dm_scan_other(false));
if (IS_ENABLED(CONFIG_SANDBOX) && (test->flags & UT_TESTF_OTHER_FDT)) {
/* make sure the other FDT is available */
@@ -635,9 +647,5 @@
else
printf("Failures: %d\n", uts.fail_count);
- /* Best efforts only...ignore errors */
- if (has_dm_tests)
- dm_test_restore(uts.of_root);
-
return ret;
}
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index 69e4b00..03a99a1 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -487,6 +487,14 @@
since it is assumed that images are XIP and the offsets already include the
address.
+While U-Boot's symbol updating is handled automatically by the u-boot-spl
+entry type (and others), it is possible to use this feature with any blob. To
+do this, add a `write-symbols` (boolean) property to the node, set the ELF
+filename using `elf-filename` and set 'elf-base-sym' to the base symbol for the
+start of the binary image (this defaults to `__image_copy_start` which is what
+U-Boot uses). See `testBlobSymbol()` for an example.
+
+.. _binman_fdt:
Access to binman entry offsets at run time (fdt)
------------------------------------------------
@@ -607,6 +615,14 @@
this size. If this is not provided, it will be set to the size of the
contents.
+min-size:
+ Sets the minimum size of the entry. This size includes explicit padding
+ ('pad-before' and 'pad-after'), but not padding added to meet alignment
+ requirements. While this does not affect the contents of the entry within
+ binman itself (the padding is performed only when its parent section is
+ assembled), the end result will be that the entry ends with the padding
+ bytes, so may grow. Defaults to 0.
+
pad-before:
Padding before the contents of the entry. Normally this is 0, meaning
that the contents start at the beginning of the entry. This can be used
@@ -689,6 +705,15 @@
`no-expanded` property disables this just for a single entry. Put the
`no-expanded` boolean property in the node to select this behaviour.
+optional:
+ External blobs are normally required to be present for the image to be
+ built (but see `External blobs`_). This properly allows an entry to be
+ optional, so that when it is cannot be found, this problem is ignored and
+ an empty file is used for this blob. This should be used only when the blob
+ is entirely optional and is not needed for correct operation of the image.
+ Note that missing, optional blobs do not produce a non-zero exit code from
+ binman, although it does show a warning about the missing external blob.
+
The attributes supported for images and sections are described below. Several
are similar to those for entries.
@@ -782,6 +807,37 @@
symlink:
Adds a symlink to the image with string given in the symlink property.
+overlap:
+ Indicates that this entry overlaps with others in the same section. These
+ entries should appear at the end of the section. Overlapping entries are not
+ packed with other entries, but their contents are written over other entries
+ in the section. Overlapping entries must have an explicit offset and size.
+
+write-symbols:
+ Indicates that the blob should be updated with symbol values calculated by
+ binman. This is automatic for certain entry types, e.g. `u-boot-spl`. See
+ binman_syms_ for more information.
+
+elf-filename:
+ Sets the file name of a blob's associated ELF file. For example, if the
+ blob is `zephyr.bin` then the ELF file may be `zephyr.elf`. This allows
+ binman to locate symbols and understand the structure of the blob. See
+ binman_syms_ for more information.
+
+elf-base-sym:
+ Sets the name of the ELF symbol that points to the start of a blob. For
+ U-Boot this is `__image_copy_start` and that is the default used by binman
+ if this property is missing. For other projects, a difference symbol may be
+ needed. Add this symbol to the properties for the blob so that symbols can
+ be read correctly. See binman_syms_ for more information.
+
+offset-from-elf:
+ Sets the offset of an entry based on a symbol value in an another entry.
+ The format is <&phandle>, "sym_name", <offset> where phandle is the entry
+ containing the blob (with associated ELF file providing symbols), <sym_name>
+ is the symbol to lookup (relative to elf-base-sym) and <offset> is an offset
+ to add to that value.
+
Examples of the above options can be found in the tests. See the
tools/binman/test directory.
@@ -836,6 +892,11 @@
renamed to 'ro-u-boot' and 'rw-u-boot'. This can be useful to
distinguish binaries with otherwise identical names.
+filename:
+ This allows the contents of the section to be written to a file in the
+ output directory. This can sometimes be useful to use the data in one
+ section in different image, since there is currently no way to share data
+ beteen images other than through files.
Image Properties
----------------
@@ -1007,6 +1068,28 @@
entry args are provided by the U-Boot Makefile.
+Optional entries
+----------------
+
+Some entries need to exist only if certain conditions are met. For example, an
+entry may want to appear in the image only if a file has a particular format.
+Obviously the entry must exist in the image description for it to be processed
+at all, so a way needs to be found to have the entry remove itself.
+
+To handle this, when entry.ObtainContents() is called, the entry can call
+entry.mark_absent() to mark itself as absent, passing a suitable message as the
+reason.
+
+Any absent entries are dropped immediately after ObtainContents() has been
+called on all entries.
+
+It is not possible for an entry to mark itself absent at any other point in the
+processing. It must happen in the ObtainContents() method.
+
+The effect is as if the entry had never been present at all, since the image
+is packed without it and it disappears from the list of entries.
+
+
Compression
-----------
@@ -1683,7 +1766,8 @@
Note: for sections, this also checks that the entries do not overlap, nor extend
outside the section. If the section does not have a defined size, the size is
-set large enough to hold all the entries.
+set large enough to hold all the entries. For entries that are explicitly marked
+as overlapping, this check is skipped.
6. SetImagePos() - sets the image position of every entry. This is the absolute
position 'image-pos', as opposed to 'offset' which is relative to the containing
diff --git a/tools/binman/btool/mkimage.py b/tools/binman/btool/mkimage.py
index da5f344..d5b407c 100644
--- a/tools/binman/btool/mkimage.py
+++ b/tools/binman/btool/mkimage.py
@@ -22,7 +22,7 @@
# pylint: disable=R0913
def run(self, reset_timestamp=False, output_fname=None, external=False,
- pad=None):
+ pad=None, align=None):
"""Run mkimage
Args:
@@ -33,6 +33,7 @@
pad: Bytes to use for padding the FIT devicetree output. This allows
other things to be easily added later, if required, such as
signatures
+ align: Bytes to use for alignment of the FIT and its external data
version: True to get the mkimage version
"""
args = []
@@ -40,6 +41,8 @@
args.append('-E')
if pad:
args += ['-p', f'{pad:x}']
+ if align:
+ args += ['-B', f'{align:x}']
if reset_timestamp:
args.append('-t')
if output_fname:
diff --git a/tools/binman/control.py b/tools/binman/control.py
index 964c698..e647400 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -552,6 +552,7 @@
image.SetAllowMissing(allow_missing)
image.SetAllowFakeBlob(allow_fake_blobs)
image.GetEntryContents()
+ image.drop_absent()
image.GetEntryOffsets()
# We need to pack the entries to figure out where everything
@@ -593,12 +594,14 @@
image.BuildImage()
if write_map:
image.WriteMap()
+
missing_list = []
image.CheckMissing(missing_list)
if missing_list:
tout.warning("Image '%s' is missing external blobs and is non-functional: %s" %
(image.name, ' '.join([e.name for e in missing_list])))
_ShowHelpForMissingBlobs(missing_list)
+
faked_list = []
image.CheckFakedBlobs(faked_list)
if faked_list:
@@ -606,6 +609,15 @@
"Image '%s' has faked external blobs and is non-functional: %s" %
(image.name, ' '.join([os.path.basename(e.GetDefaultFilename())
for e in faked_list])))
+
+ optional_list = []
+ image.CheckOptional(optional_list)
+ if optional_list:
+ tout.warning(
+ "Image '%s' is missing external blobs but is still functional: %s" %
+ (image.name, ' '.join([e.name for e in optional_list])))
+ _ShowHelpForMissingBlobs(optional_list)
+
missing_bintool_list = []
image.check_missing_bintools(missing_bintool_list)
if missing_bintool_list:
diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index fe50bf5..3cc8a38 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -210,7 +210,31 @@
raise ValueError('%s has size %d: only 4 and 8 are supported' %
(msg, sym.size))
-def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False):
+def GetSymbolOffset(elf_fname, sym_name, base_sym=None):
+ """Read the offset of a symbol compared to base symbol
+
+ This is useful for obtaining the value of a single symbol relative to the
+ base of a binary blob.
+
+ Args:
+ elf_fname: Filename of the ELF file to read
+ sym_name (str): Name of symbol to read
+ base_sym (str): Base symbol to sue to calculate the offset (or None to
+ use '__image_copy_start'
+
+ Returns:
+ int: Offset of the symbol relative to the base symbol
+ """
+ if not base_sym:
+ base_sym = '__image_copy_start'
+ fname = tools.get_input_filename(elf_fname)
+ syms = GetSymbols(fname, [base_sym, sym_name])
+ base = syms[base_sym].address
+ val = syms[sym_name].address
+ return val - base
+
+def LookupAndWriteSymbols(elf_fname, entry, section, is_elf=False,
+ base_sym=None):
"""Replace all symbols in an entry with their correct values
The entry contents is updated so that values for referenced symbols will be
@@ -223,7 +247,10 @@
entry
entry: Entry to process
section: Section which can be used to lookup symbol values
+ base_sym: Base symbol marking the start of the image
"""
+ if not base_sym:
+ base_sym = '__image_copy_start'
fname = tools.get_input_filename(elf_fname)
syms = GetSymbols(fname, ['image', 'binman'])
if is_elf:
@@ -243,7 +270,7 @@
if not syms:
tout.debug('LookupAndWriteSymbols: no syms')
return
- base = syms.get('__image_copy_start')
+ base = syms.get(base_sym)
if not base and not is_elf:
tout.debug('LookupAndWriteSymbols: no base')
return
@@ -518,3 +545,18 @@
rend = start + segment['p_filesz']
segments.append((i, segment['p_paddr'], data[start:rend]))
return segments, entry
+
+def is_valid(data):
+ """Check if some binary data is a valid ELF file
+
+ Args:
+ data (bytes): Bytes to check
+
+ Returns:
+ bool: True if a valid Elf file, False if not
+ """
+ try:
+ DecodeElf(data, 0)
+ return True
+ except ELFError:
+ return False
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index 75b867c..8cb55eb 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -242,7 +242,7 @@
end = offset['embed_end'].offset
data = tools.read_file(fname)
embed_data = data[start:end]
- expect = struct.pack('<III', 0x1234, 0x5678, 0)
+ expect = struct.pack('<IIIII', 2, 3, 0x1234, 0x5678, 0)
self.assertEqual(expect, embed_data)
def testEmbedFail(self):
@@ -348,6 +348,27 @@
finally:
elf.ELF_TOOLS = old_val
+ def test_is_valid(self):
+ """Test is_valid()"""
+ self.assertEqual(False, elf.is_valid(b''))
+ self.assertEqual(False, elf.is_valid(b'1234'))
+
+ fname = self.ElfTestFile('elf_sections')
+ data = tools.read_file(fname)
+ self.assertEqual(True, elf.is_valid(data))
+ self.assertEqual(False, elf.is_valid(data[4:]))
+
+ def test_get_symbol_offset(self):
+ fname = self.ElfTestFile('embed_data')
+ syms = elf.GetSymbols(fname, ['embed_start', 'embed'])
+ expected = syms['embed'].address - syms['embed_start'].address
+ val = elf.GetSymbolOffset(fname, 'embed', 'embed_start')
+ self.assertEqual(expected, val)
+
+ with self.assertRaises(KeyError) as e:
+ elf.GetSymbolOffset(fname, 'embed')
+ self.assertIn('__image_copy_start', str(e.exception))
+
if __name__ == '__main__':
unittest.main()
diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index 3dc32db..7a04a61 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -216,9 +216,9 @@
obtained from the list of available device-tree files, managed by the
'state' module.
-Additional Properties / Entry arguments:
- - prepend: Header type to use:
- length: 32-bit length header
+Additional attributes:
+ prepend: Header used (e.g. 'length')
+
.. _etype_blob_ext:
@@ -604,6 +604,11 @@
Indicates that the contents of the FIT are external and provides the
external offset. This is passed to mkimage via the -E and -p flags.
+ fit,align
+ Indicates what alignment to use for the FIT and its external data,
+ and provides the alignment to use. This is passed to mkimage via
+ the -B flag.
+
fit,fdt-list
Indicates the entry argument which provides the list of device tree
files for the gen-fdt-nodes operation (as below). This is often
@@ -716,6 +721,12 @@
fit,data
Generates a `data = <...>` property with the contents of the segment
+ fit,firmware
+ Generates a `firmware = <...>` property. Provides a list of possible
+ nodes to be used as the `firmware` property value. The first valid
+ node is picked as the firmware. Any remaining valid nodes is
+ prepended to the `loadable` property generated by `fit,loadables`
+
fit,loadables
Generates a `loadable = <...>` property with a list of the generated
nodes (including all nodes if this operation is used multiple times)
@@ -757,6 +768,9 @@
atf-bl31 {
};
+ hash {
+ algo = "sha256";
+ };
};
@tee-SEQ {
@@ -772,6 +786,9 @@
tee-os {
};
+ hash {
+ algo = "sha256";
+ };
};
};
@@ -780,7 +797,7 @@
@config-SEQ {
description = "conf-NAME.dtb";
fdt = "fdt-SEQ";
- firmware = "u-boot";
+ fit,firmware = "atf-1", "u-boot";
fit,loadables;
};
};
@@ -800,6 +817,10 @@
arch = "arm64";
type = "firmware";
description = "ARM Trusted Firmware";
+ hash {
+ algo = "sha256";
+ value = <...hash of first segment...>;
+ };
};
atf-2 {
data = <...contents of second segment...>;
@@ -809,6 +830,10 @@
arch = "arm64";
type = "firmware";
description = "ARM Trusted Firmware";
+ hash {
+ algo = "sha256";
+ value = <...hash of second segment...>;
+ };
};
};
@@ -827,15 +852,15 @@
configurations {
default = "config-1";
config-1 {
- loadables = "atf-1", "atf-2", "atf-3", "tee-1", "tee-2";
+ loadables = "u-boot", "atf-2", "atf-3", "tee-1", "tee-2";
description = "rk3399-firefly.dtb";
fdt = "fdt-1";
- firmware = "u-boot";
+ firmware = "atf-1";
};
};
-U-Boot SPL can then load the firmware (U-Boot proper) and all the loadables
-(ATF and TEE), then proceed with the boot.
+U-Boot SPL can then load the firmware (ATF) and all the loadables (U-Boot
+proper, ATF and TEE), then proceed with the boot.
@@ -1178,11 +1203,13 @@
- multiple-data-files: boolean to tell binman to pass all files as
datafiles to mkimage instead of creating a temporary file the result
of datafiles concatenation
+ - filename: filename of output binary generated by mkimage
The data passed to mkimage via the -d flag is collected from subnodes of the
mkimage node, e.g.::
mkimage {
+ filename = "imximage.bin";
args = "-n test -T imximage";
u-boot-spl {
@@ -1190,13 +1217,14 @@
};
This calls mkimage to create an imximage with `u-boot-spl.bin` as the data
-file, which mkimage being called like this::
+file, with mkimage being called like this::
mkimage -d <data_file> -n test -T imximage <output_file>
The output from mkimage then becomes part of the image produced by
-binman. If you need to put mulitple things in the data file, you can use
-a section, or just multiple subnodes like this::
+binman but also is written into `imximage.bin` file. If you need to put
+multiple things in the data file, you can use a section, or just multiple
+subnodes like this::
mkimage {
args = "-n test -T imximage";
@@ -1208,17 +1236,20 @@
};
};
+Note that binman places the contents (here SPL and TPL) into a single file
+and passes that to mkimage using the -d option.
+
To pass all datafiles untouched to mkimage::
mkimage {
- args = "-n rk3399 -T rkspi";
- multiple-data-files;
+ args = "-n rk3399 -T rkspi";
+ multiple-data-files;
- u-boot-tpl {
- };
+ u-boot-tpl {
+ };
- u-boot-spl {
- };
+ u-boot-spl {
+ };
};
This calls mkimage to create a Rockchip RK3399-specific first stage
@@ -1242,17 +1273,17 @@
mkimage {
args = "-T imximage";
- data-to-imagename';
+ data-to-imagename;
u-boot-spl {
};
};
That will pass the data to mkimage both as the data file (with -d) and as
-the image name (with -n).
+the image name (with -n). In both cases, a filename is passed as the
+argument, with the actual data being in that file.
-
-If need to pass different data in with -n, then use an imagename subnode::
+If need to pass different data in with -n, then use an `imagename` subnode::
mkimage {
args = "-T imximage";
@@ -1271,6 +1302,20 @@
-n data.
+
+.. _etype_null:
+
+Entry: null: An entry which has no contents of its own
+------------------------------------------------------
+
+Note that the size property must be set since otherwise this entry does not
+know how large it should be.
+
+The contents are set by the containing section, e.g. the section's pad
+byte.
+
+
+
.. _etype_opensbi:
Entry: opensbi: RISC-V OpenSBI fw_dynamic blob
@@ -1478,6 +1523,10 @@
be written at offset 4 in the image file, since the first 16 bytes are
skipped when writing.
+filename
+ filename to write the unpadded section contents to within the output
+ directory (None to skip this).
+
Since a section is also an entry, it inherits all the properies of entries
too.
@@ -1497,12 +1546,47 @@
Properties / Entry arguments:
- tee-os-path: Filename of file to read into entry. This is typically
- called tee-pager.bin
+ called tee.bin or tee.elf
This entry holds the run-time firmware, typically started by U-Boot SPL.
See the U-Boot README for your architecture or board for how to use it. See
https://github.com/OP-TEE/optee_os for more information about OP-TEE.
+Note that if the file is in ELF format, it must go in a FIT. In that case,
+this entry will mark itself as absent, providing the data only through the
+read_elf_segments() method.
+
+Marking this entry as absent means that it if is used in the wrong context
+it can be automatically dropped. Thus it is possible to add an OP-TEE entry
+like this::
+
+ binman {
+ tee-os {
+ };
+ };
+
+and pass either an ELF or plain binary in with -a tee-os-path <filename>
+and have binman do the right thing:
+
+ - include the entry if tee.bin is provided and it does NOT have the v1
+ header
+ - drop it otherwise
+
+When used within a FIT, we can do::
+
+ binman {
+ fit {
+ tee-os {
+ };
+ };
+ };
+
+which will split the ELF into separate nodes for each segment, if an ELF
+file is provided (see :ref:`etype_fit`), or produce a single node if the
+OP-TEE binary v1 format is provided (see optee_doc_) .
+
+.. _optee_doc: https://optee.readthedocs.io/en/latest/architecture/core.html#partitioning-of-the-binary
+
.. _etype_text:
@@ -1567,11 +1651,7 @@
to relocate itself at runtime. The binary typically includes a device tree
blob at the end of it.
-U-Boot can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (fdt)'
-
-in the binman README for more information.
+U-Boot can access binman symbols at runtime. See :ref:`binman_fdt`.
Note that this entry is automatically replaced with u-boot-expanded unless
--no-expanded is used or the node has a 'no-expanded' property.
@@ -1701,9 +1781,7 @@
to run from the correct address if direct flash execution is possible (e.g.
on x86 devices).
-SPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
@@ -1806,9 +1884,7 @@
expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
u-boot-spl-dtb
-SPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
@@ -1844,9 +1920,7 @@
address in SRAM, or written to run from the correct address if direct
flash execution is possible (e.g. on x86 devices).
-SPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
@@ -1961,9 +2035,7 @@
expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
u-boot-tpl-dtb
-TPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+TPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
@@ -2034,6 +2106,128 @@
+.. _etype_u_boot_vpl:
+
+Entry: u-boot-vpl: U-Boot VPL binary
+------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot-vpl.bin (default 'vpl/u-boot-vpl.bin')
+
+This is the U-Boot VPL (Verifying Program Loader) binary. This is a small
+binary which loads before SPL, typically into on-chip SRAM. It is
+responsible for locating, loading and jumping to SPL, the next-stage
+loader. Note that VPL is not relocatable so must be loaded to the correct
+address in SRAM, or written to run from the correct address if direct
+flash execution is possible (e.g. on x86 devices).
+
+SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
+
+in the binman README for more information.
+
+The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
+binman uses that to look up symbols to write into the VPL binary.
+
+
+
+.. _etype_u_boot_vpl_bss_pad:
+
+Entry: u-boot-vpl-bss-pad: U-Boot VPL binary padded with a BSS region
+---------------------------------------------------------------------
+
+Properties / Entry arguments:
+ None
+
+This holds the padding added after the VPL binary to cover the BSS (Block
+Started by Symbol) region. This region holds the various variables used by
+VPL. It is set to 0 by VPL when it starts up. If you want to append data to
+the VPL image (such as a device tree file), you must pad out the BSS region
+to avoid the data overlapping with U-Boot variables. This entry is useful in
+that case. It automatically pads out the entry size to cover both the code,
+data and BSS.
+
+The contents of this entry will a certain number of zero bytes, determined
+by __bss_size
+
+The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
+binman uses that to look up the BSS address.
+
+
+
+.. _etype_u_boot_vpl_dtb:
+
+Entry: u-boot-vpl-dtb: U-Boot VPL device tree
+---------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of u-boot.dtb (default 'vpl/u-boot-vpl.dtb')
+
+This is the VPL device tree, containing configuration information for
+VPL. VPL needs this to know what devices are present and which drivers
+to activate.
+
+
+
+.. _etype_u_boot_vpl_elf:
+
+Entry: u-boot-vpl-elf: U-Boot VPL ELF image
+-------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename of VPL u-boot (default 'vpl/u-boot-vpl')
+
+This is the U-Boot VPL ELF image. It does not include a device tree but can
+be relocated to any address for execution.
+
+
+
+.. _etype_u_boot_vpl_expanded:
+
+Entry: u-boot-vpl-expanded: U-Boot VPL flat binary broken out into its component parts
+--------------------------------------------------------------------------------------
+
+Properties / Entry arguments:
+ - vpl-dtb: Controls whether this entry is selected (set to 'y' or '1' to
+ select)
+
+This is a section containing the U-Boot binary, BSS padding if needed and a
+devicetree. Using this entry type automatically creates this section, with
+the following entries in it:
+
+ u-boot-vpl-nodtb
+ u-boot-vpl-bss-pad
+ u-boot-dtb
+
+Having the devicetree separate allows binman to update it in the final
+image, so that the entries positions are provided to the running U-Boot.
+
+This entry is selected based on the value of the 'vpl-dtb' entryarg. If
+this is non-empty (and not 'n' or '0') then this expanded entry is selected.
+
+
+
+.. _etype_u_boot_vpl_nodtb:
+
+Entry: u-boot-vpl-nodtb: VPL binary without device tree appended
+----------------------------------------------------------------
+
+Properties / Entry arguments:
+ - filename: Filename to include (default 'vpl/u-boot-vpl-nodtb.bin')
+
+This is the U-Boot VPL binary, It does not include a device tree blob at
+the end of it so may not be able to work without it, assuming VPL needs
+a device tree to operate on your platform. You can add a u_boot_vpl_dtb
+entry after this one, or use a u_boot_vpl entry instead, which normally
+expands to a section containing u-boot-vpl-dtb, u-boot-vpl-bss-pad and
+u-boot-vpl-dtb
+
+VPL can access binman symbols at runtime. See :ref:`binman_fdt`.
+
+The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
+binman uses that to look up symbols to write into the VPL binary.
+
+
+
.. _etype_u_boot_with_ucode_ptr:
Entry: u-boot-with-ucode-ptr: U-Boot with embedded microcode pointer
diff --git a/tools/binman/entry.py b/tools/binman/entry.py
index 1be31a0..5eacc5f 100644
--- a/tools/binman/entry.py
+++ b/tools/binman/entry.py
@@ -49,6 +49,7 @@
offset: Offset of entry within the section, None if not known yet (in
which case it will be calculated by Pack())
size: Entry size in bytes, None if not known
+ min_size: Minimum entry size in bytes
pre_reset_size: size as it was before ResetForPack(). This allows us to
keep track of the size we started with and detect size changes
uncomp_size: Size of uncompressed data in bytes, if the entry is
@@ -73,7 +74,9 @@
compress: Compression algoithm used (e.g. 'lz4'), 'none' if none
orig_offset: Original offset value read from node
orig_size: Original size value read from node
- missing: True if this entry is missing its contents
+ missing: True if this entry is missing its contents. Note that if it is
+ optional, this entry will not appear in the list generated by
+ entry.CheckMissing() since it is considered OK for it to be missing.
allow_missing: Allow children of this entry to be missing (used by
subclasses such as Entry_section)
allow_fake: Allow creating a dummy fake file if the blob file is not
@@ -91,6 +94,12 @@
file, or is a binary file produced from an ELF file
auto_write_symbols (bool): True to write ELF symbols into this entry's
contents
+ absent (bool): True if this entry is absent. This can be controlled by
+ the entry itself, allowing it to vanish in certain circumstances.
+ An absent entry is removed during processing so that it does not
+ appear in the map
+ optional (bool): True if this entry contains an optional external blob
+ overlap (bool): True if this entry overlaps with others
"""
fake_dir = None
@@ -106,6 +115,7 @@
self.name = node and (name_prefix + node.name) or 'none'
self.offset = None
self.size = None
+ self.min_size = 0
self.pre_reset_size = None
self.uncomp_size = None
self.data = None
@@ -133,6 +143,11 @@
self.comp_bintool = None
self.elf_fname = None
self.auto_write_symbols = auto_write_symbols
+ self.absent = False
+ self.optional = False
+ self.overlap = False
+ self.elf_base_sym = None
+ self.offset_from_elf = None
@staticmethod
def FindEntryClass(etype, expanded):
@@ -257,6 +272,7 @@
self.Raise("Please use 'extend-size' instead of 'expand-size'")
self.offset = fdt_util.GetInt(self._node, 'offset')
self.size = fdt_util.GetInt(self._node, 'size')
+ self.min_size = fdt_util.GetInt(self._node, 'min-size', 0)
self.orig_offset = fdt_util.GetInt(self._node, 'orig-offset')
self.orig_size = fdt_util.GetInt(self._node, 'orig-size')
if self.GetImage().copy_to_orig:
@@ -284,9 +300,15 @@
self.offset_unset = fdt_util.GetBool(self._node, 'offset-unset')
self.extend_size = fdt_util.GetBool(self._node, 'extend-size')
self.missing_msg = fdt_util.GetString(self._node, 'missing-msg')
+ self.optional = fdt_util.GetBool(self._node, 'optional')
+ self.overlap = fdt_util.GetBool(self._node, 'overlap')
+ if self.overlap:
+ self.required_props += ['offset', 'size']
# This is only supported by blobs and sections at present
self.compress = fdt_util.GetString(self._node, 'compress', 'none')
+ self.offset_from_elf = fdt_util.GetPhandleNameOffset(self._node,
+ 'offset-from-elf')
def GetDefaultFilename(self):
return None
@@ -444,7 +466,7 @@
Returns:
True if the contents were found, False if another call is needed
- after the other entries are processed.
+ after the other entries are processed, None if there is no contents
"""
# No contents by default: subclasses can implement this
return True
@@ -483,8 +505,12 @@
if self.offset_unset:
self.Raise('No offset set with offset-unset: should another '
'entry provide this correct offset?')
- self.offset = tools.align(offset, self.align)
+ elif self.offset_from_elf:
+ self.offset = self.lookup_offset()
+ else:
+ self.offset = tools.align(offset, self.align)
needed = self.pad_before + self.contents_size + self.pad_after
+ needed = max(needed, self.min_size)
needed = tools.align(needed, self.align_size)
size = self.size
if not size:
@@ -572,7 +598,9 @@
Returns:
bytes content of the entry, excluding any padding. If the entry is
- compressed, the compressed data is returned
+ compressed, the compressed data is returned. If the entry data
+ is not yet available, False can be returned. If the entry data
+ is null, then None is returned.
"""
self.Detail('GetData: size %s' % to_hex_size(self.data))
return self.data
@@ -659,7 +687,7 @@
# Check if we are writing symbols into an ELF file
is_elf = self.GetDefaultFilename() == self.elf_fname
elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage(),
- is_elf)
+ is_elf, self.elf_base_sym)
def CheckEntries(self):
"""Check that the entry offsets are correct
@@ -1034,14 +1062,15 @@
self.allow_fake = allow_fake
def CheckMissing(self, missing_list):
- """Check if any entries in this section have missing external blobs
+ """Check if the entry has missing external blobs
- If there are missing blobs, the entries are added to the list
+ If there are missing (non-optional) blobs, the entries are added to the
+ list
Args:
missing_list: List of Entry objects to be added to
"""
- if self.missing:
+ if self.missing and not self.optional:
missing_list.append(self)
def check_fake_fname(self, fname, size=0):
@@ -1080,6 +1109,17 @@
# This is meaningless for anything other than blobs
pass
+ def CheckOptional(self, optional_list):
+ """Check if the entry has missing but optional external blobs
+
+ If there are missing (optional) blobs, the entries are added to the list
+
+ Args:
+ optional_list (list): List of Entry objects to be added to
+ """
+ if self.missing and self.optional:
+ optional_list.append(self)
+
def GetAllowMissing(self):
"""Get whether a section allows missing external blobs
@@ -1281,3 +1321,31 @@
not_present.append(prop)
if not_present:
self.Raise(f"'{self.etype}' entry is missing properties: {' '.join(not_present)}")
+
+ def mark_absent(self, msg):
+ tout.info("Entry '%s' marked absent: %s" % (self._node.path, msg))
+ self.absent = True
+
+ def read_elf_segments(self):
+ """Read segments from an entry that can generate an ELF file
+
+ Returns:
+ tuple:
+ list of segments, each:
+ int: Segment number (0 = first)
+ int: Start address of segment in memory
+ bytes: Contents of segment
+ int: entry address of ELF file
+ """
+ return None
+
+ def lookup_offset(self):
+ node, sym_name, offset = self.offset_from_elf
+ entry = self.section.FindEntryByNode(node)
+ if not entry:
+ self.Raise("Cannot find entry for node '%s'" % node.name)
+ if not entry.elf_fname:
+ entry.Raise("Need elf-fname property '%s'" % node.name)
+ val = elf.GetSymbolOffset(entry.elf_fname, sym_name,
+ entry.elf_base_sym)
+ return val + offset
diff --git a/tools/binman/entry_test.py b/tools/binman/entry_test.py
index aa470c5..a6fbf62 100644
--- a/tools/binman/entry_test.py
+++ b/tools/binman/entry_test.py
@@ -114,6 +114,25 @@
self.assertEquals(tools.get_bytes(0, 1024), base.CompressData(b'abc'))
self.assertEquals(tools.get_bytes(0, 1024), base.DecompressData(b'abc'))
+ def testLookupOffset(self):
+ """Test the lookup_offset() method of the base class"""
+ def MyFindEntryByNode(node):
+ return self.found
+
+ base = entry.Entry.Create(None, self.GetNode(), 'blob-dtb')
+ base.FindEntryByNode = MyFindEntryByNode
+ base.section = base
+ self.found = None
+ base.offset_from_elf = [self.GetNode(), 'start', 0]
+ with self.assertRaises(ValueError) as e:
+ base.lookup_offset()
+ self.assertIn("Cannot find entry for node 'u-boot'", str(e.exception))
+
+ self.found = base
+ with self.assertRaises(ValueError) as e:
+ base.lookup_offset()
+ self.assertIn("Need elf-fname property 'u-boot'", str(e.exception))
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/etype/_testing.py b/tools/binman/etype/_testing.py
index 6960048..1c1efb2 100644
--- a/tools/binman/etype/_testing.py
+++ b/tools/binman/etype/_testing.py
@@ -63,6 +63,7 @@
'bad-update-contents-twice')
self.return_contents_later = fdt_util.GetBool(self._node,
'return-contents-later')
+ self.set_to_absent = fdt_util.GetBool(self._node, 'set-to-absent')
# Set to True when the entry is ready to process the FDT.
self.process_fdt_ready = False
@@ -119,6 +120,8 @@
if self.require_bintool_for_contents:
if self.bintool_for_contents is None:
self.Raise("Required bintool unusable in ObtainContents()")
+ if self.set_to_absent:
+ self.mark_absent('for testing purposes')
return True
def GetOffsets(self):
diff --git a/tools/binman/etype/blob.py b/tools/binman/etype/blob.py
index a50a806..c7ddced 100644
--- a/tools/binman/etype/blob.py
+++ b/tools/binman/etype/blob.py
@@ -35,11 +35,17 @@
super().__init__(section, etype, node,
auto_write_symbols=auto_write_symbols)
self._filename = fdt_util.GetString(self._node, 'filename', self.etype)
+ self.elf_fname = fdt_util.GetString(self._node, 'elf-filename',
+ self.elf_fname)
+ self.elf_base_sym = fdt_util.GetString(self._node, 'elf-base-sym')
+ if not self.auto_write_symbols:
+ if fdt_util.GetBool(self._node, 'write-symbols'):
+ self.auto_write_symbols = True
def ObtainContents(self, fake_size=0):
self._filename = self.GetDefaultFilename()
self._pathname = tools.get_input_filename(self._filename,
- self.external and self.section.GetAllowMissing())
+ self.external and (self.optional or self.section.GetAllowMissing()))
# Allow the file to be missing
if not self._pathname:
self._pathname, faked = self.check_fake_fname(self._filename,
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
index 7860e2a..cd29435 100644
--- a/tools/binman/etype/fit.py
+++ b/tools/binman/etype/fit.py
@@ -70,6 +70,11 @@
Indicates that the contents of the FIT are external and provides the
external offset. This is passed to mkimage via the -E and -p flags.
+ fit,align
+ Indicates what alignment to use for the FIT and its external data,
+ and provides the alignment to use. This is passed to mkimage via
+ the -B flag.
+
fit,fdt-list
Indicates the entry argument which provides the list of device tree
files for the gen-fdt-nodes operation (as below). This is often
@@ -182,6 +187,12 @@
fit,data
Generates a `data = <...>` property with the contents of the segment
+ fit,firmware
+ Generates a `firmware = <...>` property. Provides a list of possible
+ nodes to be used as the `firmware` property value. The first valid
+ node is picked as the firmware. Any remaining valid nodes is
+ prepended to the `loadable` property generated by `fit,loadables`
+
fit,loadables
Generates a `loadable = <...>` property with a list of the generated
nodes (including all nodes if this operation is used multiple times)
@@ -223,6 +234,9 @@
atf-bl31 {
};
+ hash {
+ algo = "sha256";
+ };
};
@tee-SEQ {
@@ -238,6 +252,9 @@
tee-os {
};
+ hash {
+ algo = "sha256";
+ };
};
};
@@ -246,7 +263,7 @@
@config-SEQ {
description = "conf-NAME.dtb";
fdt = "fdt-SEQ";
- firmware = "u-boot";
+ fit,firmware = "atf-1", "u-boot";
fit,loadables;
};
};
@@ -266,6 +283,10 @@
arch = "arm64";
type = "firmware";
description = "ARM Trusted Firmware";
+ hash {
+ algo = "sha256";
+ value = <...hash of first segment...>;
+ };
};
atf-2 {
data = <...contents of second segment...>;
@@ -275,6 +296,10 @@
arch = "arm64";
type = "firmware";
description = "ARM Trusted Firmware";
+ hash {
+ algo = "sha256";
+ value = <...hash of second segment...>;
+ };
};
};
@@ -293,15 +318,15 @@
configurations {
default = "config-1";
config-1 {
- loadables = "atf-1", "atf-2", "atf-3", "tee-1", "tee-2";
+ loadables = "u-boot", "atf-2", "atf-3", "tee-1", "tee-2";
description = "rk3399-firefly.dtb";
fdt = "fdt-1";
- firmware = "u-boot";
+ firmware = "atf-1";
};
};
- U-Boot SPL can then load the firmware (U-Boot proper) and all the loadables
- (ATF and TEE), then proceed with the boot.
+ U-Boot SPL can then load the firmware (ATF) and all the loadables (U-Boot
+ proper, ATF and TEE), then proceed with the boot.
"""
def __init__(self, section, etype, node):
"""
@@ -392,8 +417,8 @@
_add_entries(self._node, 0, self._node)
- # Keep a copy of all entries, including generator entries, since these
- # removed from self._entries later.
+ # Keep a copy of all entries, including generator entries, since those
+ # are removed from self._entries later.
self._priv_entries = dict(self._entries)
def BuildSectionData(self, required):
@@ -423,6 +448,9 @@
'external': True,
'pad': fdt_util.fdt32_to_cpu(ext_offset.value)
}
+ align = self._fit_props.get('fit,align')
+ if align is not None:
+ args.update({'align': fdt_util.fdt32_to_cpu(align.value)})
if self.mkimage.run(reset_timestamp=True, output_fname=output_fname,
**args) is None:
# Bintool is missing; just use empty data as the output
@@ -488,6 +516,42 @@
return
fsw.property(pname, prop.bytes)
+ def _process_firmware_prop(node):
+ """Process optional fit,firmware property
+
+ Picks the first valid entry for use as the firmware, remaining valid
+ entries is prepended to loadables
+
+ Args:
+ node (Node): Generator node to process
+
+ Returns:
+ firmware (str): Firmware or None
+ result (list): List of remaining loadables
+ """
+ val = fdt_util.GetStringList(node, 'fit,firmware')
+ if val is None:
+ return None, self._loadables
+ valid_entries = list(self._loadables)
+ for name, entry in self.GetEntries().items():
+ missing = []
+ entry.CheckMissing(missing)
+ entry.CheckOptional(missing)
+ if not missing:
+ valid_entries.append(name)
+ firmware = None
+ result = []
+ for name in val:
+ if name in valid_entries:
+ if not firmware:
+ firmware = name
+ elif name not in result:
+ result.append(name)
+ for name in self._loadables:
+ if name != firmware and name not in result:
+ result.append(name)
+ return firmware, result
+
def _gen_fdt_nodes(base_node, node, depth, in_images):
"""Generate FDT nodes
@@ -498,20 +562,24 @@
first.
Args:
- node (None): Generator node to process
+ node (Node): Generator node to process
depth: Current node depth (0 is the base 'fit' node)
in_images: True if this is inside the 'images' node, so that
'data' properties should be generated
"""
if self._fdts:
+ firmware, fit_loadables = _process_firmware_prop(node)
# Generate nodes for each FDT
for seq, fdt_fname in enumerate(self._fdts):
node_name = node.name[1:].replace('SEQ', str(seq + 1))
fname = tools.get_input_filename(fdt_fname + '.dtb')
with fsw.add_node(node_name):
for pname, prop in node.props.items():
- if pname == 'fit,loadables':
- val = '\0'.join(self._loadables) + '\0'
+ if pname == 'fit,firmware':
+ if firmware:
+ fsw.property_string('firmware', firmware)
+ elif pname == 'fit,loadables':
+ val = '\0'.join(fit_loadables) + '\0'
fsw.property('loadables', val.encode('utf-8'))
elif pname == 'fit,operation':
pass
@@ -540,50 +608,55 @@
else:
self.Raise("Generator node requires 'fit,fdt-list' property")
- def _gen_split_elf(base_node, node, elf_data, missing):
+ def _gen_split_elf(base_node, node, depth, segments, entry_addr):
"""Add nodes for the ELF file, one per group of contiguous segments
Args:
base_node (Node): Template node from the binman definition
node (Node): Node to replace (in the FIT being built)
- data (bytes): ELF-format data to process (may be empty)
- missing (bool): True if any of the data is missing
-
+ depth: Current node depth (0 is the base 'fit' node)
+ segments (list): list of segments, each:
+ int: Segment number (0 = first)
+ int: Start address of segment in memory
+ bytes: Contents of segment
+ entry_addr (int): entry address of ELF file
"""
- # If any pieces are missing, skip this. The missing entries will
- # show an error
- if not missing:
- try:
- segments, entry = elf.read_loadable_segments(elf_data)
- except ValueError as exc:
- self._raise_subnode(node,
- f'Failed to read ELF file: {str(exc)}')
- for (seq, start, data) in segments:
- node_name = node.name[1:].replace('SEQ', str(seq + 1))
- with fsw.add_node(node_name):
- loadables.append(node_name)
- for pname, prop in node.props.items():
- if not pname.startswith('fit,'):
- fsw.property(pname, prop.bytes)
- elif pname == 'fit,load':
- fsw.property_u32('load', start)
- elif pname == 'fit,entry':
- if seq == 0:
- fsw.property_u32('entry', entry)
- elif pname == 'fit,data':
- fsw.property('data', bytes(data))
- elif pname != 'fit,operation':
- self._raise_subnode(
- node, f"Unknown directive '{pname}'")
+ for (seq, start, data) in segments:
+ node_name = node.name[1:].replace('SEQ', str(seq + 1))
+ with fsw.add_node(node_name):
+ loadables.append(node_name)
+ for pname, prop in node.props.items():
+ if not pname.startswith('fit,'):
+ fsw.property(pname, prop.bytes)
+ elif pname == 'fit,load':
+ fsw.property_u32('load', start)
+ elif pname == 'fit,entry':
+ if seq == 0:
+ fsw.property_u32('entry', entry_addr)
+ elif pname == 'fit,data':
+ fsw.property('data', bytes(data))
+ elif pname != 'fit,operation':
+ self._raise_subnode(
+ node, f"Unknown directive '{pname}'")
+
+ for subnode in node.subnodes:
+ with fsw.add_node(subnode.name):
+ _add_node(node, depth + 1, subnode)
def _gen_node(base_node, node, depth, in_images, entry):
"""Generate nodes from a template
- This creates one node for each member of self._fdts using the
- provided template. If a property value contains 'NAME' it is
- replaced with the filename of the FDT. If a property value contains
- SEQ it is replaced with the node sequence number, where 1 is the
- first.
+ This creates one or more nodes depending on the fit,operation being
+ used.
+
+ For OP_GEN_FDT_NODES it creates one node for each member of
+ self._fdts using the provided template. If a property value contains
+ 'NAME' it is replaced with the filename of the FDT. If a property
+ value contains SEQ it is replaced with the node sequence number,
+ where 1 is the first.
+
+ For OP_SPLIT_ELF it emits one node for each section in the ELF file.
+ If the file is missing, nothing is generated.
Args:
base_node (Node): Base Node of the FIT (with 'description'
@@ -592,6 +665,8 @@
depth (int): Current node depth (0 is the base 'fit' node)
in_images (bool): True if this is inside the 'images' node, so
that 'data' properties should be generated
+ entry (entry_Section): Entry for the section containing the
+ contents of this node
"""
oper = self._get_operation(base_node, node)
if oper == OP_GEN_FDT_NODES:
@@ -600,13 +675,28 @@
# Entry_section.ObtainContents() either returns True or
# raises an exception.
data = None
- missing_list = []
+ missing_opt_list = []
entry.ObtainContents()
entry.Pack(0)
- data = entry.GetData()
- entry.CheckMissing(missing_list)
+ entry.CheckMissing(missing_opt_list)
+ entry.CheckOptional(missing_opt_list)
- _gen_split_elf(base_node, node, data, bool(missing_list))
+ # If any pieces are missing, skip this. The missing entries will
+ # show an error
+ if not missing_opt_list:
+ segs = entry.read_elf_segments()
+ if segs:
+ segments, entry_addr = segs
+ else:
+ elf_data = entry.GetData()
+ try:
+ segments, entry_addr = (
+ elf.read_loadable_segments(elf_data))
+ except ValueError as exc:
+ self._raise_subnode(
+ node, f'Failed to read ELF file: {str(exc)}')
+
+ _gen_split_elf(base_node, node, depth, segments, entry_addr)
def _add_node(base_node, depth, node):
"""Add nodes to the output FIT
@@ -638,8 +728,7 @@
for subnode in node.subnodes:
subnode_path = f'{rel_path}/{subnode.name}'
- if has_images and not (subnode.name.startswith('hash') or
- subnode.name.startswith('signature')):
+ if has_images and not self.IsSpecialSubnode(subnode):
# This subnode is a content node not meant to appear in
# the FIT (e.g. "/images/kernel/u-boot"), so don't call
# fsw.add_node() or _add_node() for it.
diff --git a/tools/binman/etype/mkimage.py b/tools/binman/etype/mkimage.py
index c2288c4..cb264c3c 100644
--- a/tools/binman/etype/mkimage.py
+++ b/tools/binman/etype/mkimage.py
@@ -57,24 +57,24 @@
Note that binman places the contents (here SPL and TPL) into a single file
and passes that to mkimage using the -d option.
- To pass all datafiles untouched to mkimage::
+ To pass all datafiles untouched to mkimage::
- mkimage {
- args = "-n rk3399 -T rkspi";
- multiple-data-files;
+ mkimage {
+ args = "-n rk3399 -T rkspi";
+ multiple-data-files;
- u-boot-tpl {
- };
+ u-boot-tpl {
+ };
- u-boot-spl {
- };
- };
+ u-boot-spl {
+ };
+ };
- This calls mkimage to create a Rockchip RK3399-specific first stage
- bootloader, made of TPL+SPL. Since this first stage bootloader requires to
- align the TPL and SPL but also some weird hacks that is handled by mkimage
- directly, binman is told to not perform the concatenation of datafiles prior
- to passing the data to mkimage.
+ This calls mkimage to create a Rockchip RK3399-specific first stage
+ bootloader, made of TPL+SPL. Since this first stage bootloader requires to
+ align the TPL and SPL but also some weird hacks that is handled by mkimage
+ directly, binman is told to not perform the concatenation of datafiles prior
+ to passing the data to mkimage.
To use CONFIG options in the arguments, use a string list instead, as in
this example which also produces four arguments::
diff --git a/tools/binman/etype/null.py b/tools/binman/etype/null.py
new file mode 100644
index 0000000..c10d482
--- /dev/null
+++ b/tools/binman/etype/null.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2023 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+#
+
+from binman.entry import Entry
+from dtoc import fdt_util
+from patman import tools
+
+class Entry_null(Entry):
+ """An entry which has no contents of its own
+
+ Note that the size property must be set since otherwise this entry does not
+ know how large it should be.
+
+ The contents are set by the containing section, e.g. the section's pad
+ byte.
+ """
+ def __init__(self, section, etype, node):
+ super().__init__(section, etype, node)
+ self.required_props = ['size']
+
+ def ObtainContents(self):
+ # null contents
+ return None
diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py
index da561e2..57b91ff 100644
--- a/tools/binman/etype/section.py
+++ b/tools/binman/etype/section.py
@@ -144,6 +144,10 @@
be written at offset 4 in the image file, since the first 16 bytes are
skipped when writing.
+ filename
+ filename to write the unpadded section contents to within the output
+ directory (None to skip this).
+
Since a section is also an entry, it inherits all the properies of entries
too.
@@ -163,6 +167,18 @@
self._skip_at_start = None
self._end_4gb = False
self._ignore_missing = False
+ self._filename = None
+
+ def IsSpecialSubnode(self, node):
+ """Check if a node is a special one used by the section itself
+
+ Some notes are used for hashing / signatures and do not add entries to
+ the actual section.
+
+ Returns:
+ bool: True if the node is a special one, else False
+ """
+ return node.name.startswith('hash') or node.name.startswith('signature')
def ReadNode(self):
"""Read properties from the section node"""
@@ -183,12 +199,14 @@
self._skip_at_start = 0
self._name_prefix = fdt_util.GetString(self._node, 'name-prefix')
self.align_default = fdt_util.GetInt(self._node, 'align-default', 0)
+ self._filename = fdt_util.GetString(self._node, 'filename',
+ self._filename)
self.ReadEntries()
def ReadEntries(self):
for node in self._node.subnodes:
- if node.name.startswith('hash') or node.name.startswith('signature'):
+ if self.IsSpecialSubnode(node):
continue
entry = Entry.Create(self, node,
expanded=self.GetImage().use_expanded,
@@ -258,6 +276,7 @@
Args:
entry: Entry to check
+ entry_data: Data for the entry, False if is null
Returns:
Contents of the entry along with any pad bytes before and
@@ -312,14 +331,32 @@
# earlier in the image description. See testCollectionSection().
if not required and entry_data is None:
return None
- data = self.GetPaddedDataForEntry(entry, entry_data)
+
+ entry_data_final = entry_data
+ if entry_data is None:
+ pad_byte = (entry._pad_byte if isinstance(entry, Entry_section)
+ else self._pad_byte)
+ entry_data_final = tools.get_bytes(self._pad_byte, entry.size)
+
+ data = self.GetPaddedDataForEntry(entry, entry_data_final)
# Handle empty space before the entry
pad = (entry.offset or 0) - self._skip_at_start - len(section_data)
if pad > 0:
section_data += tools.get_bytes(self._pad_byte, pad)
# Add in the actual entry data
- section_data += data
+ if entry.overlap:
+ end_offset = entry.offset + entry.size
+ if end_offset > len(section_data):
+ entry.Raise("Offset %#x (%d) ending at %#x (%d) must overlap with existing entries" %
+ (entry.offset, entry.offset, end_offset,
+ end_offset))
+ # Don't write anything for null entries'
+ if entry_data is not None:
+ section_data = (section_data[:entry.offset] + data +
+ section_data[entry.offset + entry.size:])
+ else:
+ section_data += data
self.Detail('GetData: %d entries, total size %#x' %
(len(self._entries), len(section_data)))
@@ -348,7 +385,8 @@
"""Get the contents of an entry
This builds the contents of the section, stores this as the contents of
- the section and returns it
+ the section and returns it. If the section has a filename, the data is
+ written there also.
Args:
required: True if the data must be present, False if it is OK to
@@ -363,6 +401,8 @@
if data is None:
return None
self.SetContents(data)
+ if self._filename:
+ tools.write_file(tools.get_output_filename(self._filename), data)
return data
def GetOffsets(self):
@@ -439,12 +479,13 @@
(entry.offset, entry.offset, entry.size, entry.size,
self._node.path, self._skip_at_start,
self._skip_at_start, max_size, max_size))
- if entry.offset < offset and entry.size:
- entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' "
- "ending at %#x (%d)" %
- (entry.offset, entry.offset, prev_name, offset, offset))
- offset = entry.offset + entry.size
- prev_name = entry.GetPath()
+ if not entry.overlap:
+ if entry.offset < offset and entry.size:
+ entry.Raise("Offset %#x (%d) overlaps with previous entry '%s' ending at %#x (%d)" %
+ (entry.offset, entry.offset, prev_name, offset,
+ offset))
+ offset = entry.offset + entry.size
+ prev_name = entry.GetPath()
def WriteSymbols(self, section):
"""Write symbol values into binary files for access at run time"""
@@ -662,10 +703,13 @@
def GetEntryContents(self, skip_entry=None):
"""Call ObtainContents() for each entry in the section
+
+ Note that this may set entry.absent to True if the entry is not
+ actually needed
"""
def _CheckDone(entry):
if entry != skip_entry:
- if not entry.ObtainContents():
+ if entry.ObtainContents() is False:
next_todo.append(entry)
return entry
@@ -706,6 +750,10 @@
todo)
return True
+ def drop_absent(self):
+ """Drop entries which are absent"""
+ self._entries = {n: e for n, e in self._entries.items() if not e.absent}
+
def _SetEntryOffsetSize(self, name, offset, size):
"""Set the offset and size of an entry
@@ -846,7 +894,8 @@
def CheckMissing(self, missing_list):
"""Check if any entries in this section have missing external blobs
- If there are missing blobs, the entries are added to the list
+ If there are missing (non-optional) blobs, the entries are added to the
+ list
Args:
missing_list: List of Entry objects to be added to
@@ -865,6 +914,17 @@
for entry in self._entries.values():
entry.CheckFakedBlobs(faked_blobs_list)
+ def CheckOptional(self, optional_list):
+ """Check the section for missing but optional external blobs
+
+ If there are missing (optional) blobs, the entries are added to the list
+
+ Args:
+ optional_list (list): List of Entry objects to be added to
+ """
+ for entry in self._entries.values():
+ entry.CheckOptional(optional_list)
+
def check_missing_bintools(self, missing_list):
"""Check if any entries in this section have missing bintools
@@ -931,3 +991,12 @@
super().AddBintools(btools)
for entry in self._entries.values():
entry.AddBintools(btools)
+
+ def read_elf_segments(self):
+ entries = self.GetEntries()
+
+ # If the section only has one entry, see if it can provide ELF segments
+ if len(entries) == 1:
+ for entry in entries.values():
+ return entry.read_elf_segments()
+ return None
diff --git a/tools/binman/etype/tee_os.py b/tools/binman/etype/tee_os.py
index 6ce4b67..5529727 100644
--- a/tools/binman/etype/tee_os.py
+++ b/tools/binman/etype/tee_os.py
@@ -4,19 +4,93 @@
# Entry-type module for OP-TEE Trusted OS firmware blob
#
+import struct
+
from binman.etype.blob_named_by_arg import Entry_blob_named_by_arg
+from binman import elf
class Entry_tee_os(Entry_blob_named_by_arg):
"""Entry containing an OP-TEE Trusted OS (TEE) blob
Properties / Entry arguments:
- tee-os-path: Filename of file to read into entry. This is typically
- called tee-pager.bin
+ called tee.bin or tee.elf
This entry holds the run-time firmware, typically started by U-Boot SPL.
See the U-Boot README for your architecture or board for how to use it. See
https://github.com/OP-TEE/optee_os for more information about OP-TEE.
+
+ Note that if the file is in ELF format, it must go in a FIT. In that case,
+ this entry will mark itself as absent, providing the data only through the
+ read_elf_segments() method.
+
+ Marking this entry as absent means that it if is used in the wrong context
+ it can be automatically dropped. Thus it is possible to add an OP-TEE entry
+ like this::
+
+ binman {
+ tee-os {
+ };
+ };
+
+ and pass either an ELF or plain binary in with -a tee-os-path <filename>
+ and have binman do the right thing:
+
+ - include the entry if tee.bin is provided and it does NOT have the v1
+ header
+ - drop it otherwise
+
+ When used within a FIT, we can do::
+
+ binman {
+ fit {
+ tee-os {
+ };
+ };
+ };
+
+ which will split the ELF into separate nodes for each segment, if an ELF
+ file is provided (see :ref:`etype_fit`), or produce a single node if the
+ OP-TEE binary v1 format is provided (see optee_doc_) .
+
+ .. _optee_doc: https://optee.readthedocs.io/en/latest/architecture/core.html#partitioning-of-the-binary
"""
def __init__(self, section, etype, node):
super().__init__(section, etype, node, 'tee-os')
self.external = True
+
+ @staticmethod
+ def is_optee_bin_v1(data):
+ return len(data) >= 8 and data[0:5] == b'OPTE\x01'
+
+ def ObtainContents(self, fake_size=0):
+ result = super().ObtainContents(fake_size)
+ if not self.missing:
+ # If using the flat binary (without the OP-TEE header), then it is
+ # just included as a blob. But if it is an ELF or usees the v1
+ # binary header, then the FIT implementation will call
+ # read_elf_segments() to get the segment information
+ if elf.is_valid(self.data):
+ self.mark_absent('uses Elf format which must be in a FIT')
+ elif self.is_optee_bin_v1(self.data):
+ # The FIT implementation will call read_elf_segments() to get
+ # the segment information
+ self.mark_absent('uses v1 format which must be in a FIT')
+ return result
+
+ def read_elf_segments(self):
+ data = self.GetData()
+ if self.is_optee_bin_v1(data):
+ # OP-TEE v1 format (tee.bin)
+ init_sz, start_hi, start_lo, _, paged_sz = (
+ struct.unpack_from('<5I', data, 0x8))
+ if paged_sz != 0:
+ self.Raise("OP-TEE paged mode not supported")
+ e_entry = (start_hi << 32) + start_lo
+ p_addr = e_entry
+ p_data = data[0x1c:]
+ if len(p_data) != init_sz:
+ self.Raise("Invalid OP-TEE file: size mismatch (expected %#x, have %#x)" %
+ (init_sz, len(p_data)))
+ return [[0, p_addr, p_data]], e_entry
+ return None
diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py
index e8d180a..d5639ee 100644
--- a/tools/binman/etype/u_boot.py
+++ b/tools/binman/etype/u_boot.py
@@ -18,11 +18,7 @@
to relocate itself at runtime. The binary typically includes a device tree
blob at the end of it.
- U-Boot can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (fdt)'
-
- in the binman README for more information.
+ U-Boot can access binman symbols at runtime. See :ref:`binman_fdt`.
Note that this entry is automatically replaced with u-boot-expanded unless
--no-expanded is used or the node has a 'no-expanded' property.
diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py
index d1aa3b4..7f710c8 100644
--- a/tools/binman/etype/u_boot_spl.py
+++ b/tools/binman/etype/u_boot_spl.py
@@ -21,9 +21,7 @@
to run from the correct address if direct flash execution is possible (e.g.
on x86 devices).
- SPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+ SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
@@ -36,7 +34,6 @@
def __init__(self, section, etype, node):
super().__init__(section, etype, node, auto_write_symbols=True)
self.elf_fname = 'spl/u-boot-spl'
- self.auto_write_symbols = True
def GetDefaultFilename(self):
return 'spl/u-boot-spl.bin'
diff --git a/tools/binman/etype/u_boot_spl_nodtb.py b/tools/binman/etype/u_boot_spl_nodtb.py
index 50a126d..e7ec329 100644
--- a/tools/binman/etype/u_boot_spl_nodtb.py
+++ b/tools/binman/etype/u_boot_spl_nodtb.py
@@ -21,9 +21,7 @@
expands to a section containing u-boot-spl-dtb, u-boot-spl-bss-pad and
u-boot-spl-dtb
- SPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+ SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py
index 1883a2b..397b9f8 100644
--- a/tools/binman/etype/u_boot_tpl.py
+++ b/tools/binman/etype/u_boot_tpl.py
@@ -21,9 +21,7 @@
address in SRAM, or written to run from the correct address if direct
flash execution is possible (e.g. on x86 devices).
- SPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+ SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
diff --git a/tools/binman/etype/u_boot_tpl_nodtb.py b/tools/binman/etype/u_boot_tpl_nodtb.py
index 7e08e58..9bb2b5d 100644
--- a/tools/binman/etype/u_boot_tpl_nodtb.py
+++ b/tools/binman/etype/u_boot_tpl_nodtb.py
@@ -21,9 +21,7 @@
expands to a section containing u-boot-tpl-dtb, u-boot-tpl-bss-pad and
u-boot-tpl-dtb
- TPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+ TPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
diff --git a/tools/binman/etype/u_boot_vpl.py b/tools/binman/etype/u_boot_vpl.py
index 62e5969..31d7e83 100644
--- a/tools/binman/etype/u_boot_vpl.py
+++ b/tools/binman/etype/u_boot_vpl.py
@@ -21,9 +21,7 @@
address in SRAM, or written to run from the correct address if direct
flash execution is possible (e.g. on x86 devices).
- SPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
+ SPL can access binman symbols at runtime. See :ref:`binman_fdt`.
in the binman README for more information.
diff --git a/tools/binman/etype/u_boot_vpl_nodtb.py b/tools/binman/etype/u_boot_vpl_nodtb.py
index db3d8a9..64c2767 100644
--- a/tools/binman/etype/u_boot_vpl_nodtb.py
+++ b/tools/binman/etype/u_boot_vpl_nodtb.py
@@ -21,11 +21,7 @@
expands to a section containing u-boot-vpl-dtb, u-boot-vpl-bss-pad and
u-boot-vpl-dtb
- VPL can access binman symbols at runtime. See:
-
- 'Access to binman entry offsets at run time (symbols)'
-
- in the binman README for more information.
+ VPL can access binman symbols at runtime. See :ref:`binman_fdt`.
The ELF file 'vpl/u-boot-vpl' must also be available for this to work, since
binman uses that to look up symbols to write into the VPL binary.
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 62ee86b..6b203df 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -112,6 +112,8 @@
# Supported compression bintools
COMP_BINTOOLS = ['bzip2', 'gzip', 'lz4', 'lzma_alone', 'lzop', 'xz', 'zstd']
+TEE_ADDR = 0x5678
+
class TestFunctional(unittest.TestCase):
"""Functional tests for binman
@@ -219,6 +221,9 @@
TestFunctional._MakeInputFile('tee.elf',
tools.read_file(cls.ElfTestFile('elf_sections')))
+ # Newer OP_TEE file in v1 binary format
+ cls.make_tee_bin('tee.bin')
+
cls.comp_bintools = {}
for name in COMP_BINTOOLS:
cls.comp_bintools[name] = bintool.Bintool.create(name)
@@ -644,6 +649,14 @@
def ElfTestFile(cls, fname):
return os.path.join(cls._elf_testdir, fname)
+ @classmethod
+ def make_tee_bin(cls, fname, paged_sz=0, extra_data=b''):
+ init_sz, start_hi, start_lo, dummy = (len(U_BOOT_DATA), 0, TEE_ADDR, 0)
+ data = b'OPTE\x01xxx' + struct.pack('<5I', init_sz, start_hi, start_lo,
+ dummy, paged_sz) + U_BOOT_DATA
+ data += extra_data
+ TestFunctional._MakeInputFile(fname, data)
+
def AssertInList(self, grep_list, target):
"""Assert that at least one of a list of things is in a target
@@ -870,9 +883,9 @@
self.assertIn('image', control.images)
image = control.images['image']
entries = image.GetEntries()
- self.assertEqual(5, len(entries))
+ self.assertEqual(6, len(entries))
- # First u-boot with padding before and after
+ # First u-boot with padding before and after (included in minimum size)
self.assertIn('u-boot', entries)
entry = entries['u-boot']
self.assertEqual(0, entry.offset)
@@ -921,8 +934,17 @@
self.assertEqual(U_BOOT_DATA + tools.get_bytes(0, 64 - len(U_BOOT_DATA)),
data[pos:pos + entry.size])
+ # Sixth u-boot with both minimum size and aligned size
+ self.assertIn('u-boot-min-size', entries)
+ entry = entries['u-boot-min-size']
+ self.assertEqual(128, entry.offset)
+ self.assertEqual(32, entry.size)
+ self.assertEqual(U_BOOT_DATA, entry.data[:len(U_BOOT_DATA)])
+ self.assertEqual(U_BOOT_DATA + tools.get_bytes(0, 32 - len(U_BOOT_DATA)),
+ data[pos:pos + entry.size])
+
self.CheckNoGaps(entries)
- self.assertEqual(128, image.size)
+ self.assertEqual(160, image.size)
dtb = fdt.Fdt(out_dtb_fname)
dtb.Scan()
@@ -930,7 +952,7 @@
expected = {
'image-pos': 0,
'offset': 0,
- 'size': 128,
+ 'size': 160,
'u-boot:image-pos': 0,
'u-boot:offset': 0,
@@ -951,6 +973,10 @@
'u-boot-align-both:image-pos': 64,
'u-boot-align-both:offset': 64,
'u-boot-align-both:size': 64,
+
+ 'u-boot-min-size:image-pos': 128,
+ 'u-boot-min-size:offset': 128,
+ 'u-boot-min-size:size': 32,
}
self.assertEqual(expected, props)
@@ -5426,6 +5452,10 @@
fdt_util.fdt32_to_cpu(atf1.props['load'].value))
self.assertEqual(data, atf1.props['data'].bytes)
+ hash_node = atf1.FindNode('hash')
+ self.assertIsNotNone(hash_node)
+ self.assertEqual({'algo', 'value'}, hash_node.props.keys())
+
atf2 = dtb.GetNode('/images/atf-2')
self.assertEqual(base_keys, atf2.props.keys())
_, start, data = segments[1]
@@ -5433,6 +5463,14 @@
fdt_util.fdt32_to_cpu(atf2.props['load'].value))
self.assertEqual(data, atf2.props['data'].bytes)
+ hash_node = atf2.FindNode('hash')
+ self.assertIsNotNone(hash_node)
+ self.assertEqual({'algo', 'value'}, hash_node.props.keys())
+
+ hash_node = dtb.GetNode('/images/tee-1/hash-1')
+ self.assertIsNotNone(hash_node)
+ self.assertEqual({'algo', 'value'}, hash_node.props.keys())
+
conf = dtb.GetNode('/configurations')
self.assertEqual({'default'}, conf.props.keys())
@@ -6077,5 +6115,285 @@
'Cannot write symbols to an ELF file without Python elftools',
str(exc.exception))
+ def testSectionFilename(self):
+ """Check writing of section contents to a file"""
+ data = self._DoReadFile('261_section_fname.dts')
+ expected = (b'&&' + U_BOOT_DATA + b'&&&' +
+ tools.get_bytes(ord('!'), 7) +
+ U_BOOT_DATA + tools.get_bytes(ord('&'), 12))
+ self.assertEqual(expected, data)
+
+ sect_fname = tools.get_output_filename('outfile.bin')
+ self.assertTrue(os.path.exists(sect_fname))
+ sect_data = tools.read_file(sect_fname)
+ self.assertEqual(U_BOOT_DATA, sect_data)
+
+ def testAbsent(self):
+ """Check handling of absent entries"""
+ data = self._DoReadFile('262_absent.dts')
+ self.assertEqual(U_BOOT_DATA + U_BOOT_IMG_DATA, data)
+
+ def testPackTeeOsOptional(self):
+ """Test that an image with an optional TEE binary can be created"""
+ entry_args = {
+ 'tee-os-path': 'tee.elf',
+ }
+ data = self._DoReadFileDtb('263_tee_os_opt.dts',
+ entry_args=entry_args)[0]
+ self.assertEqual(U_BOOT_DATA + U_BOOT_IMG_DATA, data)
+
+ def checkFitTee(self, dts, tee_fname):
+ """Check that a tee-os entry works and returns data
+
+ Args:
+ dts (str): Device tree filename to use
+ tee_fname (str): filename containing tee-os
+
+ Returns:
+ bytes: Image contents
+ """
+ if not elf.ELF_TOOLS:
+ self.skipTest('Python elftools not available')
+ entry_args = {
+ 'of-list': 'test-fdt1 test-fdt2',
+ 'default-dt': 'test-fdt2',
+ 'tee-os-path': tee_fname,
+ }
+ test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
+ data = self._DoReadFileDtb(dts, entry_args=entry_args,
+ extra_indirs=[test_subdir])[0]
+ return data
+
+ def testFitTeeOsOptionalFit(self):
+ """Test an image with a FIT with an optional OP-TEE binary"""
+ data = self.checkFitTee('264_tee_os_opt_fit.dts', 'tee.bin')
+
+ # There should be only one node, holding the data set up in SetUpClass()
+ # for tee.bin
+ dtb = fdt.Fdt.FromData(data)
+ dtb.Scan()
+ node = dtb.GetNode('/images/tee-1')
+ self.assertEqual(TEE_ADDR,
+ fdt_util.fdt32_to_cpu(node.props['load'].value))
+ self.assertEqual(TEE_ADDR,
+ fdt_util.fdt32_to_cpu(node.props['entry'].value))
+ self.assertEqual(U_BOOT_DATA, node.props['data'].bytes)
+
+ def testFitTeeOsOptionalFitBad(self):
+ """Test an image with a FIT with an optional OP-TEE binary"""
+ with self.assertRaises(ValueError) as exc:
+ self.checkFitTee('265_tee_os_opt_fit_bad.dts', 'tee.bin')
+ self.assertIn(
+ "Node '/binman/fit': subnode 'images/@tee-SEQ': Failed to read ELF file: Magic number does not match",
+ str(exc.exception))
+
+ def testFitTeeOsBad(self):
+ """Test an OP-TEE binary with wrong formats"""
+ self.make_tee_bin('tee.bad1', 123)
+ with self.assertRaises(ValueError) as exc:
+ self.checkFitTee('264_tee_os_opt_fit.dts', 'tee.bad1')
+ self.assertIn(
+ "Node '/binman/fit/images/@tee-SEQ/tee-os': OP-TEE paged mode not supported",
+ str(exc.exception))
+
+ self.make_tee_bin('tee.bad2', 0, b'extra data')
+ with self.assertRaises(ValueError) as exc:
+ self.checkFitTee('264_tee_os_opt_fit.dts', 'tee.bad2')
+ self.assertIn(
+ "Node '/binman/fit/images/@tee-SEQ/tee-os': Invalid OP-TEE file: size mismatch (expected 0x4, have 0xe)",
+ str(exc.exception))
+
+ def testExtblobOptional(self):
+ """Test an image with an external blob that is optional"""
+ with test_util.capture_sys_output() as (stdout, stderr):
+ data = self._DoReadFile('266_blob_ext_opt.dts')
+ self.assertEqual(REFCODE_DATA, data)
+ err = stderr.getvalue()
+ self.assertRegex(
+ err,
+ "Image '.*' is missing external blobs but is still functional: missing")
+
+ def testSectionInner(self):
+ """Test an inner section with a size"""
+ data = self._DoReadFile('267_section_inner.dts')
+ expected = U_BOOT_DATA + tools.get_bytes(0, 12)
+ self.assertEqual(expected, data)
+
+ def testNull(self):
+ """Test an image with a null entry"""
+ data = self._DoReadFile('268_null.dts')
+ self.assertEqual(U_BOOT_DATA + b'\xff\xff\xff\xff' + U_BOOT_IMG_DATA, data)
+
+ def testOverlap(self):
+ """Test an image with a overlapping entry"""
+ data = self._DoReadFile('269_overlap.dts')
+ self.assertEqual(U_BOOT_DATA[:1] + b'aa' + U_BOOT_DATA[3:], data)
+
+ image = control.images['image']
+ entries = image.GetEntries()
+
+ self.assertIn('inset', entries)
+ inset = entries['inset']
+ self.assertEqual(1, inset.offset);
+ self.assertEqual(1, inset.image_pos);
+ self.assertEqual(2, inset.size);
+
+ def testOverlapNull(self):
+ """Test an image with a null overlap"""
+ data = self._DoReadFile('270_overlap_null.dts')
+ self.assertEqual(U_BOOT_DATA, data[:len(U_BOOT_DATA)])
+
+ # Check the FMAP
+ fhdr, fentries = fmap_util.DecodeFmap(data[len(U_BOOT_DATA):])
+ self.assertEqual(4, fhdr.nareas)
+ fiter = iter(fentries)
+
+ fentry = next(fiter)
+ self.assertEqual(b'SECTION', fentry.name)
+ self.assertEqual(0, fentry.offset)
+ self.assertEqual(len(U_BOOT_DATA), fentry.size)
+ self.assertEqual(0, fentry.flags)
+
+ fentry = next(fiter)
+ self.assertEqual(b'U_BOOT', fentry.name)
+ self.assertEqual(0, fentry.offset)
+ self.assertEqual(len(U_BOOT_DATA), fentry.size)
+ self.assertEqual(0, fentry.flags)
+
+ # Make sure that the NULL entry appears in the FMAP
+ fentry = next(fiter)
+ self.assertEqual(b'NULL', fentry.name)
+ self.assertEqual(1, fentry.offset)
+ self.assertEqual(2, fentry.size)
+ self.assertEqual(0, fentry.flags)
+
+ fentry = next(fiter)
+ self.assertEqual(b'FMAP', fentry.name)
+ self.assertEqual(len(U_BOOT_DATA), fentry.offset)
+
+ def testOverlapBad(self):
+ """Test an image with a bad overlapping entry"""
+ with self.assertRaises(ValueError) as exc:
+ self._DoReadFile('271_overlap_bad.dts')
+ self.assertIn(
+ "Node '/binman/inset': Offset 0x10 (16) ending at 0x12 (18) must overlap with existing entries",
+ str(exc.exception))
+
+ def testOverlapNoOffset(self):
+ """Test an image with a bad overlapping entry"""
+ with self.assertRaises(ValueError) as exc:
+ self._DoReadFile('272_overlap_no_size.dts')
+ self.assertIn(
+ "Node '/binman/inset': 'fill' entry is missing properties: size",
+ str(exc.exception))
+
+ def testBlobSymbol(self):
+ """Test a blob with symbols read from an ELF file"""
+ elf_fname = self.ElfTestFile('blob_syms')
+ TestFunctional._MakeInputFile('blob_syms', tools.read_file(elf_fname))
+ TestFunctional._MakeInputFile('blob_syms.bin',
+ tools.read_file(self.ElfTestFile('blob_syms.bin')))
+
+ data = self._DoReadFile('273_blob_symbol.dts')
+
+ syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
+ addr = elf.GetSymbolAddress(elf_fname, '__my_start_sym')
+ self.assertEqual(syms['_binman_sym_magic'].address, addr)
+ self.assertEqual(syms['_binman_inset_prop_offset'].address, addr + 4)
+ self.assertEqual(syms['_binman_inset_prop_size'].address, addr + 8)
+
+ sym_values = struct.pack('<LLL', elf.BINMAN_SYM_MAGIC_VALUE, 4, 8)
+ expected = sym_values
+ self.assertEqual(expected, data[:len(expected)])
+
+ def testOffsetFromElf(self):
+ """Test a blob with symbols read from an ELF file"""
+ elf_fname = self.ElfTestFile('blob_syms')
+ TestFunctional._MakeInputFile('blob_syms', tools.read_file(elf_fname))
+ TestFunctional._MakeInputFile('blob_syms.bin',
+ tools.read_file(self.ElfTestFile('blob_syms.bin')))
+
+ data = self._DoReadFile('274_offset_from_elf.dts')
+
+ syms = elf.GetSymbols(elf_fname, ['binman', 'image'])
+ base = elf.GetSymbolAddress(elf_fname, '__my_start_sym')
+
+ image = control.images['image']
+ entries = image.GetEntries()
+
+ self.assertIn('inset', entries)
+ inset = entries['inset']
+
+ self.assertEqual(base + 4, inset.offset);
+ self.assertEqual(base + 4, inset.image_pos);
+ self.assertEqual(4, inset.size);
+
+ self.assertIn('inset2', entries)
+ inset = entries['inset2']
+ self.assertEqual(base + 8, inset.offset);
+ self.assertEqual(base + 8, inset.image_pos);
+ self.assertEqual(4, inset.size);
+
+ def testFitAlign(self):
+ """Test an image with an FIT with aligned external data"""
+ data = self._DoReadFile('275_fit_align.dts')
+ self.assertEqual(4096, len(data))
+
+ dtb = fdt.Fdt.FromData(data)
+ dtb.Scan()
+
+ props = self._GetPropTree(dtb, ['data-position'])
+ expected = {
+ 'u-boot:data-position': 1024,
+ 'fdt-1:data-position': 2048,
+ 'fdt-2:data-position': 3072,
+ }
+ self.assertEqual(expected, props)
+
+ def testFitFirmwareLoadables(self):
+ """Test an image with an FIT that use fit,firmware"""
+ if not elf.ELF_TOOLS:
+ self.skipTest('Python elftools not available')
+ entry_args = {
+ 'of-list': 'test-fdt1',
+ 'default-dt': 'test-fdt1',
+ 'atf-bl31-path': 'bl31.elf',
+ 'tee-os-path': 'missing.bin',
+ }
+ test_subdir = os.path.join(self._indir, TEST_FDT_SUBDIR)
+ data = self._DoReadFileDtb(
+ '276_fit_firmware_loadables.dts',
+ entry_args=entry_args,
+ extra_indirs=[test_subdir])[0]
+
+ dtb = fdt.Fdt.FromData(data)
+ dtb.Scan()
+
+ node = dtb.GetNode('/configurations/conf-uboot-1')
+ self.assertEqual('u-boot', node.props['firmware'].value)
+ self.assertEqual(['atf-1', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-atf-1')
+ self.assertEqual('atf-1', node.props['firmware'].value)
+ self.assertEqual(['u-boot', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-missing-uboot-1')
+ self.assertEqual('u-boot', node.props['firmware'].value)
+ self.assertEqual(['atf-1', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-missing-atf-1')
+ self.assertEqual('atf-1', node.props['firmware'].value)
+ self.assertEqual(['u-boot', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+ node = dtb.GetNode('/configurations/conf-missing-tee-1')
+ self.assertEqual('atf-1', node.props['firmware'].value)
+ self.assertEqual(['u-boot', 'atf-2'],
+ fdt_util.GetStringList(node, 'loadables'))
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/tools/binman/image.py b/tools/binman/image.py
index 6d4bff5..b84dd21 100644
--- a/tools/binman/image.py
+++ b/tools/binman/image.py
@@ -94,9 +94,6 @@
def ReadNode(self):
super().ReadNode()
- filename = fdt_util.GetString(self._node, 'filename')
- if filename:
- self._filename = filename
self.allow_repack = fdt_util.GetBool(self._node, 'allow-repack')
self._symlink = fdt_util.GetString(self._node, 'symlink')
diff --git a/tools/binman/test/009_pack_extra.dts b/tools/binman/test/009_pack_extra.dts
index 1b31555..8d6f491 100644
--- a/tools/binman/test/009_pack_extra.dts
+++ b/tools/binman/test/009_pack_extra.dts
@@ -6,6 +6,7 @@
binman {
u-boot {
+ min-size = <12>;
pad-before = <3>;
pad-after = <5>;
};
@@ -31,5 +32,11 @@
align = <64>;
align-end = <128>;
};
+
+ u-boot-min-size {
+ type = "u-boot";
+ min-size = <24>;
+ align-size = <16>;
+ };
};
};
diff --git a/tools/binman/test/226_fit_split_elf.dts b/tools/binman/test/226_fit_split_elf.dts
index fab1533..22c453e 100644
--- a/tools/binman/test/226_fit_split_elf.dts
+++ b/tools/binman/test/226_fit_split_elf.dts
@@ -33,6 +33,9 @@
atf-bl31 {
};
+ hash {
+ algo = "sha256";
+ };
};
@tee-SEQ {
@@ -48,6 +51,9 @@
tee-os {
};
+ hash-1 {
+ algo = "sha256";
+ };
};
};
diff --git a/tools/binman/test/261_section_fname.dts b/tools/binman/test/261_section_fname.dts
new file mode 100644
index 0000000..790381e
--- /dev/null
+++ b/tools/binman/test/261_section_fname.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pad-byte = <0x26>;
+ size = <0x20>;
+ section@0 {
+ size = <0x10>;
+ pad-byte = <0x21>;
+ pad-before = <2>;
+ pad-after = <3>;
+
+ section {
+ filename = "outfile.bin";
+ u-boot {
+ };
+ };
+ };
+ section@1 {
+ u-boot {
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/262_absent.dts b/tools/binman/test/262_absent.dts
new file mode 100644
index 0000000..2ab8766
--- /dev/null
+++ b/tools/binman/test/262_absent.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ _testing {
+ set-to-absent;
+ };
+
+ u-boot-img {
+ };
+ };
+};
diff --git a/tools/binman/test/263_tee_os_opt.dts b/tools/binman/test/263_tee_os_opt.dts
new file mode 100644
index 0000000..2e4ec24
--- /dev/null
+++ b/tools/binman/test/263_tee_os_opt.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+ tee-os {
+ /*
+ * this results in nothing being added since only the
+ * .bin format is supported by this etype, unless it is
+ * part of a FIT
+ */
+ };
+ u-boot-img {
+ };
+ };
+};
diff --git a/tools/binman/test/264_tee_os_opt_fit.dts b/tools/binman/test/264_tee_os_opt_fit.dts
new file mode 100644
index 0000000..ae44b43
--- /dev/null
+++ b/tools/binman/test/264_tee_os_opt_fit.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ fit {
+ description = "test-desc";
+ #address-cells = <1>;
+ fit,fdt-list = "of-list";
+
+ images {
+ @tee-SEQ {
+ fit,operation = "split-elf";
+ description = "TEE";
+ type = "tee";
+ arch = "arm64";
+ os = "tee";
+ compression = "none";
+ fit,load;
+ fit,entry;
+ fit,data;
+
+ tee-os {
+ };
+ };
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/265_tee_os_opt_fit_bad.dts b/tools/binman/test/265_tee_os_opt_fit_bad.dts
new file mode 100644
index 0000000..7fa363c
--- /dev/null
+++ b/tools/binman/test/265_tee_os_opt_fit_bad.dts
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ fit {
+ description = "test-desc";
+ #address-cells = <1>;
+ fit,fdt-list = "of-list";
+
+ images {
+ @tee-SEQ {
+ fit,operation = "split-elf";
+ description = "TEE";
+ type = "tee";
+ arch = "arm64";
+ os = "tee";
+ compression = "none";
+ fit,load;
+ fit,entry;
+ fit,data;
+
+ tee-os {
+ };
+
+ /*
+ * mess up the ELF data by adding
+ * another bit of data at the end
+ */
+ u-boot {
+ };
+ };
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/266_blob_ext_opt.dts b/tools/binman/test/266_blob_ext_opt.dts
new file mode 100644
index 0000000..7171531
--- /dev/null
+++ b/tools/binman/test/266_blob_ext_opt.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ ok {
+ type = "blob-ext";
+ filename = "refcode.bin";
+ };
+
+ missing {
+ type = "blob-ext";
+ filename = "missing.bin";
+ optional;
+ };
+ };
+};
diff --git a/tools/binman/test/267_section_inner.dts b/tools/binman/test/267_section_inner.dts
new file mode 100644
index 0000000..f6faab3
--- /dev/null
+++ b/tools/binman/test/267_section_inner.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ section {
+ size = <0x10>;
+ u-boot {
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/268_null.dts b/tools/binman/test/268_null.dts
new file mode 100644
index 0000000..3824ba8
--- /dev/null
+++ b/tools/binman/test/268_null.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ pad-byte = <0xff>;
+ u-boot {
+ };
+ null {
+ size = <4>;
+ };
+ u-boot-img {
+ };
+ };
+};
diff --git a/tools/binman/test/269_overlap.dts b/tools/binman/test/269_overlap.dts
new file mode 100644
index 0000000..f949b8b
--- /dev/null
+++ b/tools/binman/test/269_overlap.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ inset {
+ type = "fill";
+ fill-byte = [61];
+ offset = <1>;
+ size = <2>;
+ overlap;
+ };
+ };
+};
diff --git a/tools/binman/test/270_overlap_null.dts b/tools/binman/test/270_overlap_null.dts
new file mode 100644
index 0000000..feed9ec
--- /dev/null
+++ b/tools/binman/test/270_overlap_null.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ section {
+ u-boot {
+ };
+
+ null {
+ offset = <1>;
+ size = <2>;
+ overlap;
+ };
+ };
+
+ fmap {
+ };
+ };
+};
diff --git a/tools/binman/test/271_overlap_bad.dts b/tools/binman/test/271_overlap_bad.dts
new file mode 100644
index 0000000..f281802
--- /dev/null
+++ b/tools/binman/test/271_overlap_bad.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ inset {
+ type = "fill";
+ fill-byte = [61];
+ offset = <0x10>;
+ size = <2>;
+ overlap;
+ };
+ };
+};
diff --git a/tools/binman/test/272_overlap_no_size.dts b/tools/binman/test/272_overlap_no_size.dts
new file mode 100644
index 0000000..4517536
--- /dev/null
+++ b/tools/binman/test/272_overlap_no_size.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ u-boot {
+ };
+
+ inset {
+ type = "fill";
+ fill-byte = [61];
+ overlap;
+ };
+ };
+};
diff --git a/tools/binman/test/273_blob_symbol.dts b/tools/binman/test/273_blob_symbol.dts
new file mode 100644
index 0000000..87b0aba
--- /dev/null
+++ b/tools/binman/test/273_blob_symbol.dts
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ blob {
+ filename = "blob_syms.bin";
+ write-symbols;
+ elf-filename = "blob_syms";
+ elf-base-sym = "__my_start_sym";
+ };
+
+ inset {
+ type = "null";
+ offset = <4>;
+ size = <8>;
+ overlap;
+ };
+ };
+};
diff --git a/tools/binman/test/274_offset_from_elf.dts b/tools/binman/test/274_offset_from_elf.dts
new file mode 100644
index 0000000..e3372fc
--- /dev/null
+++ b/tools/binman/test/274_offset_from_elf.dts
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ blob: blob {
+ filename = "blob_syms.bin";
+ elf-filename = "blob_syms";
+ elf-base-sym = "__my_start_sym";
+ };
+
+ inset {
+ type = "null";
+ offset-from-elf = <&blob>, "val3", <0>;
+ size = <4>;
+ overlap;
+ };
+
+ inset2 {
+ type = "null";
+ offset-from-elf = <&blob>, "val3", <4>;
+ size = <4>;
+ overlap;
+ };
+ };
+};
diff --git a/tools/binman/test/275_fit_align.dts b/tools/binman/test/275_fit_align.dts
new file mode 100644
index 0000000..c7b06e3
--- /dev/null
+++ b/tools/binman/test/275_fit_align.dts
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ fit {
+ description = "test desc";
+ #address-cells = <1>;
+ fit,external-offset = <1024>;
+ fit,align = <1024>;
+
+ images {
+ u-boot {
+ description = "test u-boot";
+ type = "standalone";
+ arch = "arm64";
+ os = "u-boot";
+ compression = "none";
+ load = <00000000>;
+ entry = <00000000>;
+
+ u-boot-nodtb {
+ };
+ };
+
+ fdt-1 {
+ description = "test fdt";
+ type = "flat_dt";
+ compression = "none";
+
+ u-boot-dtb {
+ };
+ };
+
+ fdt-2 {
+ description = "test fdt";
+ type = "flat_dt";
+ compression = "none";
+
+ u-boot-dtb {
+ };
+ };
+ };
+
+ configurations {
+ default = "config-1";
+ config-1 {
+ description = "test config";
+ fdt = "fdt-1";
+ firmware = "u-boot";
+ };
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/276_fit_firmware_loadables.dts b/tools/binman/test/276_fit_firmware_loadables.dts
new file mode 100644
index 0000000..2f79cdc
--- /dev/null
+++ b/tools/binman/test/276_fit_firmware_loadables.dts
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ binman {
+ fit {
+ description = "test desc";
+ #address-cells = <1>;
+ fit,fdt-list = "of-list";
+
+ images {
+ u-boot {
+ description = "test u-boot";
+ type = "standalone";
+ arch = "arm64";
+ os = "u-boot";
+ compression = "none";
+ load = <0x00000000>;
+ entry = <0x00000000>;
+
+ u-boot-nodtb {
+ };
+ };
+ tee {
+ description = "test tee";
+ type = "tee";
+ arch = "arm64";
+ os = "tee";
+ compression = "none";
+ load = <0x00200000>;
+
+ tee-os {
+ optional;
+ };
+ };
+ @atf-SEQ {
+ fit,operation = "split-elf";
+ description = "test tf-a";
+ type = "firmware";
+ arch = "arm64";
+ os = "arm-trusted-firmware";
+ compression = "none";
+ fit,load;
+ fit,entry;
+ fit,data;
+
+ atf-bl31 {
+ };
+ };
+ @fdt-SEQ {
+ description = "test fdt";
+ type = "flat_dt";
+ compression = "none";
+ };
+ };
+
+ configurations {
+ default = "@conf-uboot-DEFAULT-SEQ";
+ @conf-uboot-SEQ {
+ description = "uboot config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "u-boot";
+ fit,loadables;
+ };
+ @conf-atf-SEQ {
+ description = "atf config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "atf-1", "u-boot";
+ fit,loadables;
+ };
+ @conf-missing-uboot-SEQ {
+ description = "missing uboot config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "missing-1", "u-boot";
+ fit,loadables;
+ };
+ @conf-missing-atf-SEQ {
+ description = "missing atf config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "missing-1", "atf-1", "u-boot";
+ fit,loadables;
+ };
+ @conf-missing-tee-SEQ {
+ description = "missing tee config";
+ fdt = "fdt-SEQ";
+ fit,firmware = "atf-1", "u-boot", "tee";
+ fit,loadables;
+ };
+ };
+ };
+ };
+};
diff --git a/tools/binman/test/Makefile b/tools/binman/test/Makefile
index bea8567..cd66a30 100644
--- a/tools/binman/test/Makefile
+++ b/tools/binman/test/Makefile
@@ -30,11 +30,12 @@
LDS_BINMAN_X86 := -T $(SRC)u_boot_binman_syms_x86.lds
LDS_BINMAN_EMBED := -T $(SRC)u_boot_binman_embed.lds
LDS_EFL_SECTIONS := -T $(SRC)elf_sections.lds
+LDS_BLOB := -T $(SRC)blob_syms.lds
TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data \
u_boot_binman_syms u_boot_binman_syms.bin u_boot_binman_syms_bad \
u_boot_binman_syms_size u_boot_binman_syms_x86 embed_data \
- u_boot_binman_embed u_boot_binman_embed_sm elf_sections
+ u_boot_binman_embed u_boot_binman_embed_sm elf_sections blob_syms.bin
all: $(TARGETS)
@@ -71,6 +72,12 @@
u_boot_binman_embed_sm: CFLAGS += $(LDS_BINMAN_EMBED)
u_boot_binman_embed_sm: u_boot_binman_embed_sm.c
+blob_syms.bin: blob_syms
+ $(OBJCOPY) -O binary $< -R .note.gnu.build-id $@
+
+blob_syms: CFLAGS += $(LDS_BLOB)
+blob_syms: blob_syms.c
+
elf_sections: CFLAGS += $(LDS_EFL_SECTIONS)
elf_sections: elf_sections.c
diff --git a/tools/binman/test/blob_syms.c b/tools/binman/test/blob_syms.c
new file mode 100644
index 0000000..d652c79
--- /dev/null
+++ b/tools/binman/test/blob_syms.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2017 Google, Inc
+ *
+ * Simple program to create some binman symbols. This is used by binman tests.
+ */
+
+typedef unsigned long ulong;
+
+#include <linux/kconfig.h>
+#include <binman_sym.h>
+
+DECLARE_BINMAN_MAGIC_SYM;
+
+unsigned long val1 = 123;
+unsigned long val2 = 456;
+binman_sym_declare(unsigned long, inset, offset);
+unsigned long val3 = 789;
+unsigned long val4 = 999;
+binman_sym_declare(unsigned long, inset, size);
diff --git a/tools/binman/test/blob_syms.lds b/tools/binman/test/blob_syms.lds
new file mode 100644
index 0000000..787e38d
--- /dev/null
+++ b/tools/binman/test/blob_syms.lds
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2016 Google, Inc
+ */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = 0x00000010;
+ _start = .;
+
+ . = ALIGN(4);
+ .text :
+ {
+ __my_start_sym = .;
+ *(.text*)
+ }
+
+ . = ALIGN(4);
+ .binman_sym_table : {
+ __binman_sym_start = .;
+ KEEP(*(SORT(.binman_sym*)));
+ __binman_sym_end = .;
+ }
+ .interp : { *(.interp*) }
+
+}
diff --git a/tools/binman/test/embed_data.c b/tools/binman/test/embed_data.c
index 47d8c38..08b68c5 100644
--- a/tools/binman/test/embed_data.c
+++ b/tools/binman/test/embed_data.c
@@ -7,6 +7,7 @@
*/
int first[10] = {1};
+int before[2] __attribute__((section(".embed"))) = {2, 3};
int embed[3] __attribute__((section(".embed"))) = {0x1234, 0x5678};
int second[10] = {1};
diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile
index 2408788..202a814 100644
--- a/tools/docker/Dockerfile
+++ b/tools/docker/Dockerfile
@@ -2,7 +2,7 @@
# This Dockerfile is used to build an image containing basic stuff to be used
# to build U-Boot and run our test suites.
-FROM ubuntu:jammy-20221101
+FROM ubuntu:jammy-20221130
MAINTAINER Tom Rini <trini@konsulko.com>
LABEL Description=" This image is for building U-Boot inside a container"
@@ -64,6 +64,7 @@
iasl \
imagemagick \
iputils-ping \
+ libc6-i386 \
libconfuse-dev \
libgit2-dev \
libjson-glib-dev \
@@ -109,6 +110,7 @@
srecord \
sudo \
swig \
+ texinfo \
util-linux \
uuid-dev \
virtualenv \
diff --git a/tools/dtoc/fdt_util.py b/tools/dtoc/fdt_util.py
index d7c38ad..f343166 100644
--- a/tools/dtoc/fdt_util.py
+++ b/tools/dtoc/fdt_util.py
@@ -281,6 +281,34 @@
value = [value]
return [fdt32_to_cpu(v) for v in value]
+def GetPhandleNameOffset(node, propname):
+ """Get a <&phandle>, "string", <offset> value from a property
+
+ Args:
+ node: Node object to read from
+ propname: property name to read
+
+ Returns:
+ tuple:
+ Node object
+ str
+ int
+ or None if the property does not exist
+ """
+ prop = node.props.get(propname)
+ if not prop:
+ return None
+ value = prop.bytes
+ phandle = fdt32_to_cpu(value[:4])
+ node = node.GetFdt().LookupPhandle(phandle)
+ name = ''
+ for byte in value[4:]:
+ if not byte:
+ break
+ name += chr(byte)
+ val = fdt32_to_cpu(value[4 + len(name) + 1:])
+ return node, name, val
+
def GetDatatype(node, propname, datatype):
"""Get a value of a given type from a property
diff --git a/tools/dtoc/test/dtoc_test_phandle.dts b/tools/dtoc/test/dtoc_test_phandle.dts
index a71acff..d9aa433 100644
--- a/tools/dtoc/test/dtoc_test_phandle.dts
+++ b/tools/dtoc/test/dtoc_test_phandle.dts
@@ -32,6 +32,7 @@
u-boot,dm-pre-reloc;
compatible = "source";
clocks = <&phandle &phandle_1 11 &phandle_2 12 13 &phandle>;
+ phandle-name-offset = <&phandle_2>, "fred", <123>;
};
phandle-source2 {
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index 879ca2a..c62fcba 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -929,6 +929,7 @@
self._check_strings(HEADER + '''
struct dtd_source {
\tstruct phandle_2_arg clocks[4];
+\tunsigned char phandle_name_offset[13];
};
struct dtd_target {
\tfdt32_t\t\tintval;
@@ -981,6 +982,8 @@
\t\t\t{0, {11}},
\t\t\t{1, {12, 13}},
\t\t\t{4, {}},},
+\t.phandle_name_offset = {0x0, 0x0, 0x0, 0x3, 0x66, 0x72, 0x65, 0x64,
+\t\t0x0, 0x0, 0x0, 0x0, 0x7b},
};
U_BOOT_DRVINFO(phandle_source) = {
\t.name\t\t= "source",
diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py
index a3e36ea..3b8ee00 100755
--- a/tools/dtoc/test_fdt.py
+++ b/tools/dtoc/test_fdt.py
@@ -795,6 +795,17 @@
finally:
tools.outdir= old_outdir
+ def test_get_phandle_name_offset(self):
+ val = fdt_util.GetPhandleNameOffset(self.node, 'missing')
+ self.assertIsNone(val)
+
+ dtb = fdt.FdtScan(find_dtb_file('dtoc_test_phandle.dts'))
+ node = dtb.GetNode('/phandle-source')
+ node, name, offset = fdt_util.GetPhandleNameOffset(node,
+ 'phandle-name-offset')
+ self.assertEqual('phandle3-target', node.name)
+ self.assertEqual('fred', name)
+ self.assertEqual(123, offset)
def run_test_coverage(build_dir):
"""Run the tests and check that we get 100% coverage
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 923a975..8a18b1b 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -36,8 +36,10 @@
tfd = mmap_fdt(params->cmdname, tmpfile, size_inc, &ptr, &sbuf, true,
false);
- if (tfd < 0)
+ if (tfd < 0) {
+ fprintf(stderr, "Cannot map FDT file '%s'\n", tmpfile);
return -EIO;
+ }
if (params->keydest) {
struct stat dest_sbuf;
diff --git a/tools/image-host.c b/tools/image-host.c
index 4e0512b..4a24dee 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -1292,8 +1292,12 @@
ret = fit_image_add_verification_data(keydir, keyfile, keydest,
fit, noffset, comment, require_keys, engine_id,
cmdname, algo_name);
- if (ret)
+ if (ret) {
+ printf("Can't add verification data for node '%s' (%s)\n",
+ fdt_get_name(fit, noffset, NULL),
+ fdt_strerror(ret));
return ret;
+ }
}
/* If there are no keys, we can't sign configurations */
diff --git a/tools/patman/.checkpatch.conf b/tools/patman/.checkpatch.conf
new file mode 120000
index 0000000..c0e2020
--- /dev/null
+++ b/tools/patman/.checkpatch.conf
@@ -0,0 +1 @@
+../../.checkpatch.conf
\ No newline at end of file
diff --git a/tools/patman/checkpatch.py b/tools/patman/checkpatch.py
index 012c0d8..d1b902d 100644
--- a/tools/patman/checkpatch.py
+++ b/tools/patman/checkpatch.py
@@ -211,7 +211,7 @@
stdout: Full output of checkpatch
"""
chk = find_check_patch()
- args = [chk, '--u-boot', '--strict']
+ args = [chk]
if not use_tree:
args.append('--no-tree')
if show_types:
diff --git a/tools/proftool.c b/tools/proftool.c
index ea7d07a..b66ea55 100644
--- a/tools/proftool.c
+++ b/tools/proftool.c
@@ -81,14 +81,15 @@
static void usage(void)
{
fprintf(stderr,
- "Usage: proftool -cds -v3 <cmd> <profdata>\n"
+ "Usage: proftool [-cmtv] <cmd> <profdata>\n"
"\n"
"Commands\n"
" dump-ftrace\t\tDump out textual data in ftrace format\n"
"\n"
"Options:\n"
+ " -c <cfg>\tSpecific config file\n"
" -m <map>\tSpecify Systen.map file\n"
- " -t <trace>\tSpecific trace data file (from U-Boot)\n"
+ " -t <fname>\tSpecify trace data file (from U-Boot 'trace calls')\n"
" -v <0-4>\tSpecify verbosity\n");
exit(EXIT_FAILURE);
}
@@ -162,7 +163,7 @@
if (!err)
return 1;
if (err != size) {
- error("Cannot read profile file at pos %ld\n", ftell(fin));
+ error("Cannot read profile file at pos %lx\n", ftell(fin));
return -1;
}
return 0;
@@ -495,10 +496,17 @@
int missing_count = 0, skip_count = 0;
int i;
- printf("# tracer: ftrace\n"
- "#\n"
- "# TASK-PID CPU# TIMESTAMP FUNCTION\n"
- "# | | | | |\n");
+ printf("# tracer: function\n"
+ "#\n"
+ "# entries-in-buffer/entries-written: 140080/250280 #P:4\n"
+ "#\n"
+ "# _-----=> irqs-off\n"
+ "# / _----=> need-resched\n"
+ "# | / _---=> hardirq/softirq\n"
+ "# || / _--=> preempt-depth\n"
+ "# ||| / delay\n"
+ "# TASK-PID CPU# |||| TIMESTAMP FUNCTION\n"
+ "# | | | |||| | |\n");
for (i = 0, call = call_list; i < call_count; i++, call++) {
struct func_info *func = find_func_by_offset(call->func);
ulong time = call->flags & FUNCF_TIMESTAMP_MASK;
@@ -520,7 +528,7 @@
continue;
}
- printf("%16s-%-5d [01] %lu.%06lu: ", "uboot", 1,
+ printf("%16s-%-5d [000] .... %lu.%06lu: ", "uboot", 1,
time / 1000000, time % 1000000);
out_func(call->func, 0, " <- ");
@@ -562,23 +570,23 @@
int main(int argc, char *argv[])
{
const char *map_fname = "System.map";
- const char *prof_fname = NULL;
- const char *trace_config_fname = NULL;
+ const char *trace_fname = NULL;
+ const char *config_fname = NULL;
int opt;
verbose = 2;
- while ((opt = getopt(argc, argv, "m:p:t:v:")) != -1) {
+ while ((opt = getopt(argc, argv, "c:m:t:v:")) != -1) {
switch (opt) {
+ case 'c':
+ config_fname = optarg;
+ break;
+
case 'm':
map_fname = optarg;
break;
- case 'p':
- prof_fname = optarg;
- break;
-
case 't':
- trace_config_fname = optarg;
+ trace_fname = optarg;
break;
case 'v':
@@ -594,6 +602,5 @@
usage();
debug("Debug enabled\n");
- return prof_tool(argc, argv, prof_fname, map_fname,
- trace_config_fname);
+ return prof_tool(argc, argv, trace_fname, map_fname, config_fname);
}
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
index 0db45c2..1f1eaa1 100644
--- a/tools/rkcommon.c
+++ b/tools/rkcommon.c
@@ -133,6 +133,7 @@
{ "rk3368", "RK33", 0x8000 - 0x1000, false, RK_HEADER_V1 },
{ "rk3399", "RK33", 0x30000 - 0x2000, false, RK_HEADER_V1 },
{ "rv1108", "RK11", 0x1800, false, RK_HEADER_V1 },
+ { "rv1126", "110B", 0x10000 - 0x1000, false, RK_HEADER_V1 },
{ "rk3568", "RK35", 0x14000 - 0x1000, false, RK_HEADER_V2 },
};
@@ -154,7 +155,7 @@
static struct spl_params spl_params = { 0 };
-static unsigned char rc4_key[16] = {
+static const unsigned char rc4_key[16] = {
124, 78, 3, 4, 85, 5, 9, 7,
45, 44, 123, 56, 23, 13, 23, 17
};