summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.azure-pipelines.yml6
-rw-r--r--.gitlab-ci.yml9
-rw-r--r--MAINTAINERS2
-rw-r--r--Makefile8
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/cpu/armv7/Kconfig3
-rw-r--r--arch/arm/cpu/armv7/sunxi/psci.c190
-rw-r--r--arch/arm/cpu/armv7/sunxi/sram.c1
-rw-r--r--arch/arm/cpu/armv8/fel_utils.S1
-rw-r--r--arch/arm/dts/Makefile5
-rw-r--r--arch/arm/dts/at91-kstr-sama5d27-u-boot.dtsi42
-rw-r--r--arch/arm/dts/at91-kstr-sama5d27.dts127
-rw-r--r--arch/arm/dts/axp209.dtsi7
-rw-r--r--arch/arm/dts/meson-a1.dtsi356
-rw-r--r--arch/arm/dts/sama5d2.dtsi20
-rw-r--r--arch/arm/dts/sun50i-a64.dtsi3
-rw-r--r--arch/arm/dts/sun50i-h6-pine-h64-model-b.dts2
-rw-r--r--arch/arm/dts/sun50i-h616-orangepi-zero.dtsi134
-rw-r--r--arch/arm/dts/sun50i-h616-orangepi-zero2.dts121
-rw-r--r--arch/arm/dts/sun50i-h616-x96-mate.dts2
-rw-r--r--arch/arm/dts/sun50i-h618-orangepi-zero3.dts94
-rw-r--r--arch/arm/dts/sun5i-r8-chip.dts6
-rw-r--r--arch/arm/dts/sun5i.dtsi11
-rw-r--r--arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts137
-rw-r--r--arch/arm/dts/sun7i-a20-icnova-a20.dtsi62
-rw-r--r--arch/arm/dts/sun8i-a23-a33.dtsi2
-rw-r--r--arch/arm/dts/sun8i-a83t.dtsi2
-rw-r--r--arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts35
-rw-r--r--arch/arm/dts/sun8i-t113s.dtsi59
-rw-r--r--arch/arm/dts/sun8i-v3s.dtsi2
-rw-r--r--arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi126
-rw-r--r--arch/arm/dts/sunxi-u-boot.dtsi7
-rw-r--r--arch/arm/include/asm/arch-sunxi/boot0.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock.h3
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h12
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun4i.h17
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h7
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun9i.h9
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h39
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpucfg.h67
-rw-r--r--arch/arm/include/asm/arch-sunxi/mmc.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/prcm.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/serial.h32
-rw-r--r--arch/arm/include/asm/arch-sunxi/timer.h2
-rw-r--r--arch/arm/include/asm/mach-imx/ahab.h2
-rw-r--r--arch/arm/mach-at91/Kconfig12
-rw-r--r--arch/arm/mach-imx/Kconfig13
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/cmd_dek.c4
-rw-r--r--arch/arm/mach-imx/ele_ahab.c4
-rw-r--r--arch/arm/mach-imx/image-container.c4
-rw-r--r--arch/arm/mach-imx/imx8/ahab.c4
-rw-r--r--arch/arm/mach-imx/spl_imx_romapi.c8
-rw-r--r--arch/arm/mach-rmobile/Kconfig1
-rw-r--r--arch/arm/mach-sunxi/Kconfig42
-rw-r--r--arch/arm/mach-sunxi/Makefile2
-rw-r--r--arch/arm/mach-sunxi/board.c31
-rw-r--r--arch/arm/mach-sunxi/clock_sun50i_h6.c45
-rw-r--r--arch/arm/mach-sunxi/cpu_info.c2
-rw-r--r--arch/arm/mach-sunxi/dram_suniv.c2
-rw-r--r--arch/arm/mach-sunxi/gtbus_sun9i.c1
-rw-r--r--arch/arm/mach-sunxi/pinmux.c78
-rw-r--r--arch/arm/mach-sunxi/spl_spi_sunxi.c1
-rw-r--r--arch/arm/mach-sunxi/timer.c1
-rw-r--r--arch/riscv/Kconfig99
-rw-r--r--arch/riscv/Makefile5
-rw-r--r--arch/riscv/cpu/generic/dram.c16
-rw-r--r--arch/riscv/dts/binman.dtsi38
-rw-r--r--arch/riscv/dts/sunxi-d1-t113.dtsi15
-rw-r--r--arch/riscv/dts/sunxi-d1s-t113.dtsi927
-rw-r--r--arch/riscv/include/asm/string.h18
-rw-r--r--arch/riscv/lib/Makefile3
-rw-r--r--arch/riscv/lib/andes_plicsw.c24
-rw-r--r--arch/riscv/lib/strcmp_zbb.S81
-rw-r--r--arch/riscv/lib/strlen_zbb.S101
-rw-r--r--arch/riscv/lib/strncmp_zbb.S94
-rw-r--r--arch/sandbox/cpu/spl.c4
-rw-r--r--arch/sandbox/cpu/start.c9
-rw-r--r--arch/sandbox/cpu/u-boot-spl.lds2
-rw-r--r--arch/sandbox/dts/test.dts2
-rw-r--r--arch/sandbox/include/asm/spl.h3
-rw-r--r--board/AndesTech/ae350/MAINTAINERS12
-rw-r--r--board/AndesTech/ae350/ae350.c25
-rw-r--r--board/conclusive/kstr-sama5d27/Kconfig15
-rw-r--r--board/conclusive/kstr-sama5d27/MAINTAINERS9
-rw-r--r--board/conclusive/kstr-sama5d27/Makefile5
-rw-r--r--board/conclusive/kstr-sama5d27/kstr-sama5d27.c239
-rw-r--r--board/sunxi/MAINTAINERS5
-rw-r--r--board/sunxi/board.c34
-rw-r--r--board/sunxi/chip.c2
-rw-r--r--boot/bootflow.c29
-rw-r--r--boot/bootmeth_script.c16
-rw-r--r--cmd/tlv_eeprom.c14
-rw-r--r--common/board_r.c1
-rw-r--r--common/event.c1
-rw-r--r--common/spl/Kconfig18
-rw-r--r--common/spl/Makefile1
-rw-r--r--common/spl/spl.c4
-rw-r--r--common/spl/spl_blk_fs.c6
-rw-r--r--common/spl/spl_ext.c4
-rw-r--r--common/spl/spl_fat.c16
-rw-r--r--common/spl/spl_fit.c42
-rw-r--r--common/spl/spl_imx_container.c (renamed from arch/arm/mach-imx/parse-container.c)13
-rw-r--r--common/spl/spl_legacy.c8
-rw-r--r--common/spl/spl_mmc.c18
-rw-r--r--common/spl/spl_nand.c4
-rw-r--r--common/spl/spl_net.c10
-rw-r--r--common/spl/spl_nor.c18
-rw-r--r--common/spl/spl_opensbi.c31
-rw-r--r--common/spl/spl_spi.c18
-rw-r--r--configs/A10-OLinuXino-Lime_defconfig1
-rw-r--r--configs/A20-OLinuXino-Lime2-eMMC_defconfig1
-rw-r--r--configs/A20-OLinuXino-Lime2_defconfig1
-rw-r--r--configs/A20-OLinuXino-Lime_defconfig1
-rw-r--r--configs/A20-OLinuXino_MICRO-eMMC_defconfig1
-rw-r--r--configs/A20-OLinuXino_MICRO_defconfig1
-rw-r--r--configs/A20-Olimex-SOM-EVB_defconfig1
-rw-r--r--configs/A20-Olimex-SOM204-EVB-eMMC_defconfig1
-rw-r--r--configs/A20-Olimex-SOM204-EVB_defconfig1
-rw-r--r--configs/Bananapi_M2_Ultra_defconfig1
-rw-r--r--configs/Bananapi_defconfig1
-rw-r--r--configs/Bananapro_defconfig1
-rw-r--r--configs/Cubieboard2_defconfig1
-rw-r--r--configs/Cubieboard4_defconfig1
-rw-r--r--configs/Cubieboard_defconfig1
-rw-r--r--configs/Cubietruck_defconfig1
-rw-r--r--configs/Itead_Ibox_A20_defconfig1
-rw-r--r--configs/Lamobo_R1_defconfig2
-rw-r--r--configs/Linksprite_pcDuino3_Nano_defconfig1
-rw-r--r--configs/Linksprite_pcDuino3_defconfig1
-rw-r--r--configs/Mele_A1000_defconfig1
-rw-r--r--configs/Merrii_A80_Optimus_defconfig1
-rw-r--r--configs/Orangepi_defconfig1
-rw-r--r--configs/Orangepi_mini_defconfig1
-rw-r--r--configs/Sinovoip_BPI_M3_defconfig1
-rw-r--r--configs/ae350_rv32_falcon_defconfig60
-rw-r--r--configs/ae350_rv32_falcon_xip_defconfig61
-rw-r--r--configs/ae350_rv64_falcon_defconfig60
-rw-r--r--configs/ae350_rv64_falcon_xip_defconfig61
-rw-r--r--configs/bananapi_m1_plus_defconfig1
-rw-r--r--configs/bananapi_m2_plus_h3_defconfig1
-rw-r--r--configs/bananapi_m2_plus_h5_defconfig1
-rw-r--r--configs/deneb_defconfig6
-rw-r--r--configs/giedi_defconfig6
-rw-r--r--configs/i12-tvbox_defconfig1
-rw-r--r--configs/imx8mp_dhcom_pdk3_defconfig2
-rw-r--r--configs/imx8mp_evk_defconfig1
-rw-r--r--configs/imx8qm_mek_defconfig6
-rw-r--r--configs/imx8qxp_mek_defconfig6
-rw-r--r--configs/imx8ulp_evk_defconfig2
-rw-r--r--configs/imx93_11x11_evk_defconfig2
-rw-r--r--configs/imx93_11x11_evk_ld_defconfig2
-rw-r--r--configs/jesurun_q5_defconfig1
-rw-r--r--configs/kstr_sama5d27_defconfig73
-rw-r--r--configs/mangopi_mq_r_defconfig15
-rw-r--r--configs/mixtile_loftq_defconfig1
-rw-r--r--configs/mx28evk_defconfig1
-rw-r--r--configs/nanopi_m1_plus_defconfig1
-rw-r--r--configs/nanopi_neo_plus2_defconfig1
-rw-r--r--configs/nanopi_r1s_h5_defconfig1
-rw-r--r--configs/nsa325_defconfig2
-rw-r--r--configs/orangepi_pc2_defconfig1
-rw-r--r--configs/orangepi_plus2e_defconfig1
-rw-r--r--configs/orangepi_plus_defconfig3
-rw-r--r--configs/orangepi_win_defconfig1
-rw-r--r--configs/pine_h64_defconfig1
-rw-r--r--configs/pinebook_defconfig1
-rw-r--r--configs/pogo_v4_defconfig1
-rw-r--r--configs/sandbox_noinst_defconfig31
-rw-r--r--configs/sandbox_spl_defconfig8
-rw-r--r--configs/sandbox_vpl_defconfig1
-rw-r--r--configs/starfive_visionfive2_defconfig2
-rw-r--r--configs/teres_i_defconfig1
-rw-r--r--configs/usbarmory_defconfig2
-rw-r--r--configs/zeropi_defconfig1
-rw-r--r--doc/develop/release_cycle.rst7
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/ata/Makefile2
-rw-r--r--drivers/ata/ahci_sunxi.c9
-rw-r--r--drivers/ata/sata.c38
-rw-r--r--drivers/ata/sata_bootdev.c62
-rw-r--r--drivers/clk/sunxi/Kconfig7
-rw-r--r--drivers/clk/sunxi/Makefile1
-rw-r--r--drivers/clk/sunxi/clk_d1.c84
-rw-r--r--drivers/clk/sunxi/clk_sunxi.c5
-rw-r--r--drivers/core/Makefile1
-rw-r--r--drivers/core/root.c2
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/axp_gpio.c1
-rw-r--r--drivers/gpio/sunxi_gpio.c189
-rw-r--r--drivers/i2c/Makefile2
-rw-r--r--drivers/i2c/i2c-emul-uclass.c2
-rw-r--r--drivers/i2c/mvtwsi.c3
-rw-r--r--drivers/i2c/sun6i_p2wi.c2
-rw-r--r--drivers/i2c/sun8i_rsb.c2
-rw-r--r--drivers/mmc/sunxi_mmc.c9
-rw-r--r--drivers/net/sun8i_emac.c7
-rw-r--r--drivers/net/sunxi_emac.c38
-rw-r--r--drivers/phy/meson-g12a-usb2.c6
-rw-r--r--drivers/pinctrl/sunxi/Kconfig5
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c47
-rw-r--r--drivers/ram/Kconfig3
-rw-r--r--drivers/ram/Makefile3
-rw-r--r--drivers/ram/sunxi/Kconfig60
-rw-r--r--drivers/ram/sunxi/Makefile3
-rw-r--r--drivers/ram/sunxi/dram_sun20i_d1.c1441
-rw-r--r--drivers/ram/sunxi/dram_sun20i_d1.h73
-rw-r--r--drivers/serial/sandbox.c2
-rw-r--r--drivers/serial/serial_meson.c1
-rw-r--r--drivers/serial/serial_sh.c31
-rw-r--r--drivers/serial/serial_sh.h19
-rw-r--r--drivers/sysreset/sysreset_sandbox.c2
-rw-r--r--drivers/usb/gadget/f_sdp.c4
-rw-r--r--drivers/video/hitachi_tx18d42vm_lcd.c1
-rw-r--r--drivers/video/pwm_backlight.c13
-rw-r--r--drivers/video/simple_panel.c10
-rw-r--r--drivers/video/ssd2828.c1
-rw-r--r--drivers/video/sunxi/sunxi_display.c1
-rw-r--r--drivers/video/sunxi/sunxi_lcd.c1
-rw-r--r--drivers/video/tegra20/tegra-dsi.c8
-rw-r--r--drivers/watchdog/npcm_wdt.c10
-rw-r--r--dts/Kconfig8
-rw-r--r--fs/ext4/ext4_common.c4
-rw-r--r--fs/fs.c2
-rw-r--r--include/configs/kstr-sama5d27.h15
-rw-r--r--include/configs/sandbox.h3
-rw-r--r--include/configs/sunxi-common.h2
-rw-r--r--include/dt-bindings/clock/sun20i-d1-ccu.h158
-rw-r--r--include/dt-bindings/clock/sun20i-d1-r-ccu.h19
-rw-r--r--include/dt-bindings/clock/sun50i-h6-ccu.h2
-rw-r--r--include/dt-bindings/clock/sun50i-h616-ccu.h2
-rw-r--r--include/dt-bindings/clock/sun6i-rtc.h2
-rw-r--r--include/dt-bindings/reset/sun20i-d1-ccu.h79
-rw-r--r--include/dt-bindings/reset/sun20i-d1-r-ccu.h16
-rw-r--r--include/dt-bindings/reset/sun50i-h6-ccu.h2
-rw-r--r--include/dt-bindings/reset/sun50i-h6-r-ccu.h2
-rw-r--r--include/dt-bindings/reset/sun50i-h616-ccu.h2
-rw-r--r--include/event.h9
-rw-r--r--include/ext4fs.h1
-rw-r--r--include/ext_common.h14
-rw-r--r--include/imx_container.h (renamed from arch/arm/include/asm/mach-imx/image.h)9
-rw-r--r--include/init.h14
-rw-r--r--include/sata.h6
-rw-r--r--include/spl.h36
-rw-r--r--include/sunxi_gpio.h (renamed from arch/arm/include/asm/arch-sunxi/gpio.h)83
-rw-r--r--include/test/spl.h155
-rw-r--r--lib/Kconfig6
-rw-r--r--lib/Makefile1
-rw-r--r--net/Makefile4
-rw-r--r--net/bootp.c9
-rw-r--r--net/bootp.h3
-rw-r--r--net/net.c4
-rw-r--r--test/Kconfig1
-rw-r--r--test/Makefile5
-rw-r--r--test/boot/bootdev.c54
-rw-r--r--test/dm/wdt.c4
-rw-r--r--test/image/Kconfig50
-rw-r--r--test/image/Makefile7
-rw-r--r--test/image/spl_load.c676
-rw-r--r--test/image/spl_load_fs.c428
-rw-r--r--test/image/spl_load_net.c252
-rw-r--r--test/image/spl_load_nor.c39
-rw-r--r--test/image/spl_load_os.c76
-rw-r--r--test/image/spl_load_spi.c41
-rw-r--r--test/py/tests/test_spl.py10
-rw-r--r--test/test-main.c2
267 files changed, 8202 insertions, 896 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml
index 7985ff5523c..eb9353fc3dc 100644
--- a/.azure-pipelines.yml
+++ b/.azure-pipelines.yml
@@ -91,7 +91,7 @@ stages:
options: $(container_option)
steps:
- script: |
- ./tools/buildman/buildman --maintainer-check || exit 0
+ ./tools/buildman/buildman --maintainer-check
- job: tools_only
displayName: 'Ensure host tools and env tools build'
@@ -299,6 +299,10 @@ stages:
sandbox_noinst:
TEST_PY_BD: "sandbox_noinst"
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
+ sandbox_noinst_load_fit_full:
+ TEST_PY_BD: "sandbox_noinst"
+ TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
+ OVERRIDE: "-a CONFIG_SPL_LOAD_FIT_FULL=y"
sandbox_flattree:
TEST_PY_BD: "sandbox_flattree"
sandbox_trace:
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 129234ba3db..1e11b5a6fea 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -177,7 +177,7 @@ docs:
Check for configs without MAINTAINERS entry:
extends: .testsuites
script:
- - ./tools/buildman/buildman --maintainer-check || exit 0
+ - ./tools/buildman/buildman --maintainer-check
# Ensure host tools build
Build tools-only and envtools:
@@ -293,6 +293,13 @@ sandbox_noinst_test.py:
TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
<<: *buildman_and_testpy_dfn
+sandbox_noinst with LOAD_FIT_FULL test.py:
+ variables:
+ TEST_PY_BD: "sandbox_noinst"
+ TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
+ OVERRIDE: "-a CONFIG_SPL_LOAD_FIT_FULL=y"
+ <<: *buildman_and_testpy_dfn
+
sandbox_vpl test.py:
variables:
TEST_PY_BD: "sandbox_vpl"
diff --git a/MAINTAINERS b/MAINTAINERS
index 16b17fdd96d..cde778bc4d3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -300,7 +300,9 @@ F: arch/arm/include/asm/arch-vf610/
F: arch/arm/include/asm/mach-imx/
F: board/freescale/*mx*/
F: board/freescale/common/
+F: common/spl/spl_imx_container.c
F: drivers/serial/serial_mxc.c
+F: include/imx_container.h
ARM HISILICON
M: Peter Griffin <peter.griffin@linaro.org>
diff --git a/Makefile b/Makefile
index b204a500438..aa054ff4761 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
# SPDX-License-Identifier: GPL-2.0+
-VERSION = 2023
-PATCHLEVEL = 10
+VERSION = 2024
+PATCHLEVEL = 01
SUBLEVEL =
-EXTRAVERSION =
+EXTRAVERSION = -rc1
NAME =
# *DOCUMENTATION*
@@ -2165,7 +2165,7 @@ CLEAN_FILES += include/bmp_logo.h include/bmp_logo_data.h \
mkimage-out.spl.mkimage mkimage.spl.mkimage imx-boot.map \
itb.fit.fit itb.fit.itb itb.map spl.map mkimage-out.rom.mkimage \
mkimage.rom.mkimage rom.map simple-bin.map simple-bin-spi.map \
- idbloader-spi.img lib/efi_loader/helloworld_efi.S
+ idbloader-spi.img lib/efi_loader/helloworld_efi.S *.itb
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS += include/config include/generated spl tpl vpl \
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 531b081de99..d812685c984 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1135,7 +1135,6 @@ config ARCH_SUNXI
select DM_MMC if MMC
select DM_SCSI if SCSI
select DM_SERIAL
- select GPIO_EXTRA_HEADER
select OF_BOARD_SETUP
select OF_CONTROL
select OF_SEPARATE
@@ -1159,6 +1158,8 @@ config ARCH_SUNXI
imply CMD_GPT
imply CMD_UBI if MTD_RAW_NAND
imply DISTRO_DEFAULTS
+ imply DM_REGULATOR
+ imply DM_REGULATOR_FIXED
imply FAT_WRITE
imply FIT
imply OF_LIBFDT_OVERLAY
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
index f015d133cb0..4eb34b7b449 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -61,8 +61,9 @@ config ARMV7_SECURE_MAX_SIZE
config ARM_GIC_BASE_ADDRESS
hex
depends on ARMV7_NONSEC
- depends on ARCH_EXYNOS5
+ depends on ARCH_EXYNOS5 || MACH_SUN8I_R528
default 0x10480000 if ARCH_EXYNOS5
+ default 0x03020000 if MACH_SUN8I_R528
help
Override the GIC base address if the Arm Cortex defined
CBAR/PERIPHBASE system register holds the wrong value.
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index e1d3638b5ca..5cb8cfa6cf3 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -11,8 +11,6 @@
#include <asm/cache.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/cpucfg.h>
-#include <asm/arch/prcm.h>
#include <asm/armv7.h>
#include <asm/gic.h>
#include <asm/io.h>
@@ -28,6 +26,17 @@
#define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
/*
+ * Offsets into the CPUCFG block applicable to most SUNXIs.
+ */
+#define SUNXI_CPU_RST(cpu) (0x40 + (cpu) * 0x40 + 0x0)
+#define SUNXI_CPU_STATUS(cpu) (0x40 + (cpu) * 0x40 + 0x8)
+#define SUNXI_GEN_CTRL (0x184)
+#define SUNXI_PRIV0 (0x1a4)
+#define SUN7I_CPU1_PWR_CLAMP (0x1b0)
+#define SUN7I_CPU1_PWROFF (0x1b4)
+#define SUNXI_DBG_CTRL1 (0x1e4)
+
+/*
* R40 is different from other single cluster SoCs.
*
* The power clamps are located in the unused space after the per-core
@@ -38,6 +47,24 @@
#define SUN8I_R40_PWR_CLAMP(cpu) (0x120 + (cpu) * 0x4)
#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc)
+/*
+ * R528 is also different, as it has both cores powered up (but held in reset
+ * state) after the SoC is reset. Like the R40, it uses a "soft" entry point
+ * address register, but unlike the R40, it uses a newer "CPUX" block to manage
+ * CPU state, rather than the older CPUCFG system.
+ */
+#define SUN8I_R528_SOFT_ENTRY (0x1c8)
+#define SUN8I_R528_C0_RST_CTRL (0x0000)
+#define SUN8I_R528_C0_CTRL_REG0 (0x0010)
+#define SUN8I_R528_C0_CPU_STATUS (0x0080)
+
+#define SUN8I_R528_C0_STATUS_STANDBYWFI (16)
+
+/* Only newer cores have this additional IP block. */
+#ifndef SUNXI_R_CPUCFG_BASE
+#define SUNXI_R_CPUCFG_BASE 0
+#endif
+
static void __secure cp15_write_cntp_tval(u32 tval)
{
asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
@@ -76,11 +103,8 @@ static void __secure __mdelay(u32 ms)
isb();
}
-static void __secure clamp_release(u32 __maybe_unused *clamp)
+static void __secure clamp_release(u32 *clamp)
{
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
- defined(CONFIG_MACH_SUN8I_H3) || \
- defined(CONFIG_MACH_SUN8I_R40)
u32 tmp = 0x1ff;
do {
tmp >>= 1;
@@ -88,24 +112,54 @@ static void __secure clamp_release(u32 __maybe_unused *clamp)
} while (tmp);
__mdelay(10);
-#endif
}
-static void __secure clamp_set(u32 __maybe_unused *clamp)
+static void __secure clamp_set(u32 *clamp)
{
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
- defined(CONFIG_MACH_SUN8I_H3) || \
- defined(CONFIG_MACH_SUN8I_R40)
writel(0xff, clamp);
-#endif
}
-static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
- int cpu)
+static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
+{
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
+ writel((u32)entry,
+ SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ writel((u32)entry,
+ SUNXI_R_CPUCFG_BASE + SUN8I_R528_SOFT_ENTRY);
+ } else {
+ writel((u32)entry, SUNXI_CPUCFG_BASE + SUNXI_PRIV0);
+ }
+}
+
+static void __secure sunxi_cpu_set_power(int cpu, bool on)
{
+ u32 *clamp = NULL;
+ u32 *pwroff;
+
+ /* sun7i (A20) is different from other single cluster SoCs */
+ if (IS_ENABLED(CONFIG_MACH_SUN7I)) {
+ clamp = (void *)SUNXI_CPUCFG_BASE + SUN7I_CPU1_PWR_CLAMP;
+ pwroff = (void *)SUNXI_CPUCFG_BASE + SUN7I_CPU1_PWROFF;
+ cpu = 0;
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
+ clamp = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWR_CLAMP(cpu);
+ pwroff = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWROFF;
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ /* R528 leaves both cores powered up, manages them via reset */
+ return;
+ } else {
+ if (IS_ENABLED(CONFIG_MACH_SUN6I) ||
+ IS_ENABLED(CONFIG_MACH_SUN8I_H3))
+ clamp = (void *)SUNXI_PRCM_BASE + 0x140 + cpu * 0x4;
+
+ pwroff = (void *)SUNXI_PRCM_BASE + 0x100;
+ }
+
if (on) {
/* Release power clamp */
- clamp_release(clamp);
+ if (clamp)
+ clamp_release(clamp);
/* Clear power gating */
clrbits_le32(pwroff, BIT(cpu));
@@ -114,82 +168,80 @@ static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
setbits_le32(pwroff, BIT(cpu));
/* Activate power clamp */
- clamp_set(clamp);
+ if (clamp)
+ clamp_set(clamp);
}
}
-#ifdef CONFIG_MACH_SUN8I_R40
-/* secondary core entry address is programmed differently on R40 */
-static void __secure sunxi_set_entry_address(void *entry)
+static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
{
- writel((u32)entry,
- SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
-}
-#else
-static void __secure sunxi_set_entry_address(void *entry)
-{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ if (reset)
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_RST_CTRL,
+ BIT(cpu));
+ else
+ setbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_RST_CTRL,
+ BIT(cpu));
+
+ return;
+ }
- writel((u32)entry, &cpucfg->priv0);
+ writel(reset ? 0b00 : 0b11, SUNXI_CPUCFG_BASE + SUNXI_CPU_RST(cpu));
}
-#endif
-#ifdef CONFIG_MACH_SUN7I
-/* sun7i (A20) is different from other single cluster SoCs */
-static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on)
+static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ /* Not required on R528 */
+ return;
+ }
- sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
- on, 0);
+ if (lock)
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_DBG_CTRL1, BIT(cpu));
+ else
+ setbits_le32(SUNXI_CPUCFG_BASE + SUNXI_DBG_CTRL1, BIT(cpu));
}
-#elif defined CONFIG_MACH_SUN8I_R40
-static void __secure sunxi_cpu_set_power(int cpu, bool on)
+
+static bool __secure sunxi_cpu_poll_wfi(int cpu)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ return !!(readl(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_CPU_STATUS) &
+ BIT(SUN8I_R528_C0_STATUS_STANDBYWFI + cpu));
+ }
- sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu),
- (void *)cpucfg + SUN8I_R40_PWROFF,
- on, cpu);
+ return !!(readl(SUNXI_CPUCFG_BASE + SUNXI_CPU_STATUS(cpu)) & BIT(2));
}
-#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
-static void __secure sunxi_cpu_set_power(int cpu, bool on)
+
+static void __secure sunxi_cpu_invalidate_cache(int cpu)
{
- struct sunxi_prcm_reg *prcm =
- (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_CTRL_REG0,
+ BIT(cpu));
+ return;
+ }
- sunxi_power_switch(&prcm->cpu_pwr_clamp[cpu], &prcm->cpu_pwroff,
- on, cpu);
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_GEN_CTRL, BIT(cpu));
}
-#endif /* CONFIG_MACH_SUN7I */
-void __secure sunxi_cpu_power_off(u32 cpuid)
+static void __secure sunxi_cpu_power_off(u32 cpuid)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
u32 cpu = cpuid & 0x3;
/* Wait for the core to enter WFI */
- while (1) {
- if (readl(&cpucfg->cpu[cpu].status) & BIT(2))
- break;
+ while (!sunxi_cpu_poll_wfi(cpu))
__mdelay(1);
- }
/* Assert reset on target CPU */
- writel(0, &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, true);
/* Lock CPU (Disable external debug access) */
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ sunxi_cpu_set_locking(cpu, true);
/* Power down CPU */
sunxi_cpu_set_power(cpuid, false);
- /* Unlock CPU (Disable external debug access) */
- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ /* Unlock CPU (Reenable external debug access) */
+ sunxi_cpu_set_locking(cpu, false);
}
static u32 __secure cp15_read_scr(void)
@@ -246,33 +298,31 @@ out:
int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
u32 context_id)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
u32 cpu = (mpidr & 0x3);
/* store target PC and context id */
psci_save(cpu, pc, context_id);
/* Set secondary core power on PC */
- sunxi_set_entry_address(&psci_cpu_entry);
+ sunxi_cpu_set_entry(cpu, &psci_cpu_entry);
/* Assert reset on target CPU */
- writel(0, &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, true);
/* Invalidate L1 cache */
- clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+ sunxi_cpu_invalidate_cache(cpu);
/* Lock CPU (Disable external debug access) */
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ sunxi_cpu_set_locking(cpu, true);
/* Power up target CPU */
sunxi_cpu_set_power(cpu, true);
/* De-assert reset on target CPU */
- writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, false);
- /* Unlock CPU (Disable external debug access) */
- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ /* Unlock CPU (Reenable external debug access) */
+ sunxi_cpu_set_locking(cpu, false);
return ARM_PSCI_RET_SUCCESS;
}
diff --git a/arch/arm/cpu/armv7/sunxi/sram.c b/arch/arm/cpu/armv7/sunxi/sram.c
index 28564c2846a..28ff6a1b7c2 100644
--- a/arch/arm/cpu/armv7/sunxi/sram.c
+++ b/arch/arm/cpu/armv7/sunxi/sram.c
@@ -12,6 +12,7 @@
#include <common.h>
#include <init.h>
#include <asm/io.h>
+#include <asm/arch/cpu.h>
void sunxi_sram_init(void)
{
diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 2fe38a1a047..939869b9ffa 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -10,6 +10,7 @@
#include <config.h>
#include <asm/system.h>
#include <linux/linkage.h>
+#include <asm/arch/cpu.h>
/*
* We don't overwrite save_boot_params() here, to save the FEL state upon
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 4569483d5fd..96066a2b6b8 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -776,6 +776,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
sun8i-s3-pinecube.dtb \
sun8i-v3-sl631-imx179.dtb \
sun8i-v3s-licheepi-zero.dtb
+dtb-$(CONFIG_MACH_SUN8I_R528) += \
+ sun8i-t113s-mangopi-mq-r-t113.dtb
dtb-$(CONFIG_MACH_SUN50I_H5) += \
sun50i-h5-bananapi-m2-plus.dtb \
sun50i-h5-emlid-neutis-n5-devboard.dtb \
@@ -1232,6 +1234,9 @@ dtb-$(CONFIG_TARGET_SAMA5D27_SOM1_EK) += \
dtb-$(CONFIG_TARGET_SAMA5D27_WLSOM1_EK) += \
at91-sama5d27_wlsom1_ek.dtb
+dtb-$(CONFIG_TARGET_KSTR_SAMA5D27) += \
+ at91-kstr-sama5d27.dtb
+
dtb-$(CONFIG_TARGET_SAMA5D2_ICP) += \
at91-sama5d2_icp.dtb
diff --git a/arch/arm/dts/at91-kstr-sama5d27-u-boot.dtsi b/arch/arm/dts/at91-kstr-sama5d27-u-boot.dtsi
new file mode 100644
index 00000000000..cec35ab621f
--- /dev/null
+++ b/arch/arm/dts/at91-kstr-sama5d27-u-boot.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * at91-kstr-sama5d27-u-boot.dtsi - Device Tree Include file w/ U-Boot specific
+ * properties for Conclusive KSTR-SAMA5D27 board
+ *
+ * Copyright (C) 2023 Conclusive Engineering Sp. z o. o.
+ *
+ */
+
+/ {
+ chosen {
+ bootph-all;
+ };
+};
+
+&sdmmc0 {
+ bootph-all;
+};
+
+&uart1 {
+ bootph-all;
+};
+
+&pinctrl_uart1_default {
+ bootph-all;
+};
+
+&pinctrl_macb0_phy_irq {
+ bootph-all;
+};
+
+&pinctrl_macb0_rmii {
+ bootph-all;
+};
+
+&pinctrl_sdmmc0_cmd_dat_default {
+ bootph-all;
+};
+
+&pinctrl_sdmmc0_ck_cd_default {
+ bootph-all;
+};
diff --git a/arch/arm/dts/at91-kstr-sama5d27.dts b/arch/arm/dts/at91-kstr-sama5d27.dts
new file mode 100644
index 00000000000..c226a214a55
--- /dev/null
+++ b/arch/arm/dts/at91-kstr-sama5d27.dts
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0+ OR X11
+/*
+ * at91-kstr-sama5d27.dts - Device Tree file for Conclusive KSTR-SAMA5D27 board
+ *
+ * Copyright (C) 2019-2023 Conclusive Engineering Sp. z o. o.
+ *
+ */
+/dts-v1/;
+
+#include "sama5d2.dtsi"
+#include "sama5d2-pinfunc.h"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/mfd/atmel-flexcom.h>
+
+/ {
+ model = "Conclusive KSTR-SAMA5D27";
+ compatible = "conclusive,kstr-sama5d27", "atmel,sama5d2", "atmel,sama5";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ aliases {
+ i2c2 = &i2c6;
+ };
+};
+
+&main_xtal {
+ clock-frequency = <12000000>;
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sdmmc0_cmd_dat_default &pinctrl_sdmmc0_ck_cd_default>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1_default>;
+ status = "okay";
+};
+
+&macb0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_macb0_rmii &pinctrl_macb0_phy_irq>;
+ phy-mode = "rmii";
+ status = "okay";
+
+ ethernet-phy@0 {
+ reg = <0x0>;
+ reset-gpios = <&pioA 44 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&flx4 {
+ atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+ status = "okay";
+};
+
+&i2c6 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flx4_i2c>;
+ status = "okay";
+
+ eeprom: eeprom@50 {
+ compatible = "microchip,24c32", "atmel,24c32";
+ reg = <0x50>;
+ read-only;
+ pagesize = <32>;
+ status = "okay";
+ };
+};
+
+&pioA {
+ pinctrl {
+ pinctrl_uart1_default: uart1_default {
+ pinmux = <PIN_PD2__URXD1>,
+ <PIN_PD3__UTXD1>;
+ bias-disable;
+ };
+
+ pinctrl_macb0_phy_irq: macb0_phy_irq {
+ pinmux = <PIN_PB13__GPIO>;
+ bias-disable;
+ };
+
+ pinctrl_macb0_rmii: macb0_rmii {
+ pinmux = <PIN_PB14__GTXCK>,
+ <PIN_PB15__GTXEN>,
+ <PIN_PB16__GRXDV>,
+ <PIN_PB17__GRXER>,
+ <PIN_PB18__GRX0>,
+ <PIN_PB19__GRX1>,
+ <PIN_PB20__GTX0>,
+ <PIN_PB21__GTX1>,
+ <PIN_PB22__GMDC>,
+ <PIN_PB23__GMDIO>;
+ bias-disable;
+ };
+
+ pinctrl_sdmmc0_cmd_dat_default: sdmmc0_cmd_dat_default {
+ pinmux = <PIN_PA1__SDMMC0_CMD>,
+ <PIN_PA2__SDMMC0_DAT0>,
+ <PIN_PA3__SDMMC0_DAT1>,
+ <PIN_PA4__SDMMC0_DAT2>,
+ <PIN_PA5__SDMMC0_DAT3>;
+ bias-pull-up;
+ };
+
+ pinctrl_sdmmc0_ck_cd_default: sdmmc0_ck_cd_default {
+ pinmux = <PIN_PA0__SDMMC0_CK>,
+ <PIN_PA11__SDMMC0_VDDSEL>,
+ <PIN_PA13__SDMMC0_CD>;
+ bias-disable;
+ };
+
+ pinctrl_flx4_i2c: flx4_i2c {
+ pinmux = <PIN_PC28__FLEXCOM4_IO0>,
+ <PIN_PC29__FLEXCOM4_IO1>;
+ bias-disable;
+ };
+ };
+};
diff --git a/arch/arm/dts/axp209.dtsi b/arch/arm/dts/axp209.dtsi
index ca240cd6f6c..469d0f7d518 100644
--- a/arch/arm/dts/axp209.dtsi
+++ b/arch/arm/dts/axp209.dtsi
@@ -48,6 +48,13 @@
* http://dl.linux-sunxi.org/AXP/AXP209%20Datasheet%20v1.0_cn.pdf
*/
+/ {
+ pmic-temp {
+ compatible = "iio-hwmon";
+ io-channels = <&axp_adc 4>; /* Internal temperature */
+ };
+};
+
&axp209 {
compatible = "x-powers,axp209";
interrupt-controller;
diff --git a/arch/arm/dts/meson-a1.dtsi b/arch/arm/dts/meson-a1.dtsi
index e3a42c5b248..648e7f49424 100644
--- a/arch/arm/dts/meson-a1.dtsi
+++ b/arch/arm/dts/meson-a1.dtsi
@@ -3,9 +3,13 @@
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/amlogic,a1-pll-clkc.h>
+#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
#include <dt-bindings/gpio/meson-a1-gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/meson-a1-power.h>
+#include <dt-bindings/reset/amlogic,meson-a1-reset.h>
/ {
compatible = "amlogic,a1";
@@ -37,9 +41,19 @@
l2: l2-cache0 {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
};
};
+ efuse: efuse {
+ compatible = "amlogic,meson-gxbb-efuse";
+ clocks = <&clkc_periphs CLKID_OTP>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ secure-monitor = <&sm>;
+ power-domains = <&pwrc PWRC_OTP_ID>;
+ };
+
psci {
compatible = "arm,psci-1.0";
method = "smc";
@@ -65,7 +79,6 @@
pwrc: power-controller {
compatible = "amlogic,meson-a1-pwrc";
#power-domain-cells = <1>;
- status = "okay";
};
};
@@ -75,6 +88,16 @@
#size-cells = <2>;
ranges;
+ spifc: spi@fd000400 {
+ compatible = "amlogic,a1-spifc";
+ reg = <0x0 0xfd000400 0x0 0x290>;
+ clocks = <&clkc_periphs CLKID_SPIFC>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&pwrc PWRC_SPIFC_ID>;
+ status = "disabled";
+ };
+
apb: bus@fe000000 {
compatible = "simple-bus";
reg = <0x0 0xfe000000 0x0 0x1000000>;
@@ -103,10 +126,200 @@
gpio-ranges = <&periphs_pinctrl 0 0 62>;
};
+ i2c0_f11_pins: i2c0-f11 {
+ mux {
+ groups = "i2c0_sck_f11",
+ "i2c0_sda_f12";
+ function = "i2c0";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c0_f9_pins: i2c0-f9 {
+ mux {
+ groups = "i2c0_sck_f9",
+ "i2c0_sda_f10";
+ function = "i2c0";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_x_pins: i2c1-x {
+ mux {
+ groups = "i2c1_sck_x",
+ "i2c1_sda_x";
+ function = "i2c1";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c1_a_pins: i2c1-a {
+ mux {
+ groups = "i2c1_sck_a",
+ "i2c1_sda_a";
+ function = "i2c1";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_x0_pins: i2c2-x0 {
+ mux {
+ groups = "i2c2_sck_x0",
+ "i2c2_sda_x1";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_x15_pins: i2c2-x15 {
+ mux {
+ groups = "i2c2_sck_x15",
+ "i2c2_sda_x16";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_a4_pins: i2c2-a4 {
+ mux {
+ groups = "i2c2_sck_a4",
+ "i2c2_sda_a5";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c2_a8_pins: i2c2-a8 {
+ mux {
+ groups = "i2c2_sck_a8",
+ "i2c2_sda_a9";
+ function = "i2c2";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_x_pins: i2c3-x {
+ mux {
+ groups = "i2c3_sck_x",
+ "i2c3_sda_x";
+ function = "i2c3";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ i2c3_f_pins: i2c3-f {
+ mux {
+ groups = "i2c3_sck_f",
+ "i2c3_sda_f";
+ function = "i2c3";
+ bias-pull-up;
+ drive-strength-microamp = <3000>;
+ };
+ };
+
+ uart_a_pins: uart-a {
+ mux {
+ groups = "uart_a_tx",
+ "uart_a_rx";
+ function = "uart_a";
+ };
+ };
+
+ uart_a_cts_rts_pins: uart-a-cts-rts {
+ mux {
+ groups = "uart_a_cts",
+ "uart_a_rts";
+ function = "uart_a";
+ bias-pull-down;
+ };
+ };
+
+ sdio_pins: sdio {
+ mux0 {
+ groups = "sdcard_d0_x",
+ "sdcard_d1_x",
+ "sdcard_d2_x",
+ "sdcard_d3_x",
+ "sdcard_cmd_x";
+ function = "sdcard";
+ bias-pull-up;
+ };
+
+ mux1 {
+ groups = "sdcard_clk_x";
+ function = "sdcard";
+ bias-disable;
+ };
+ };
+
+ sdio_clk_gate_pins: sdio-clk-gate {
+ mux {
+ groups = "sdcard_clk_x";
+ function = "sdcard";
+ bias-pull-down;
+ };
+ };
+
+ spifc_pins: spifc {
+ mux {
+ groups = "spif_mo",
+ "spif_mi",
+ "spif_clk",
+ "spif_cs",
+ "spif_hold_n",
+ "spif_wp_n";
+ function = "spif";
+ };
+ };
+ };
+
+ gpio_intc: interrupt-controller@440 {
+ compatible = "amlogic,meson-a1-gpio-intc",
+ "amlogic,meson-gpio-intc";
+ reg = <0x0 0x0440 0x0 0x14>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ amlogic,channel-interrupts =
+ <49 50 51 52 53 54 55 56>;
+ };
+
+ clkc_periphs: clock-controller@800 {
+ compatible = "amlogic,a1-peripherals-clkc";
+ reg = <0 0x800 0 0x104>;
+ #clock-cells = <1>;
+ clocks = <&clkc_pll CLKID_FCLK_DIV2>,
+ <&clkc_pll CLKID_FCLK_DIV3>,
+ <&clkc_pll CLKID_FCLK_DIV5>,
+ <&clkc_pll CLKID_FCLK_DIV7>,
+ <&clkc_pll CLKID_HIFI_PLL>,
+ <&xtal>;
+ clock-names = "fclk_div2", "fclk_div3",
+ "fclk_div5", "fclk_div7",
+ "hifi_pll", "xtal";
+ };
+
+ i2c0: i2c@1400 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x1400 0x0 0x20>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_A>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
};
uart_AO: serial@1c00 {
- compatible = "amlogic,meson-gx-uart",
+ compatible = "amlogic,meson-a1-uart",
"amlogic,meson-ao-uart";
reg = <0x0 0x1c00 0x0 0x18>;
interrupts = <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>;
@@ -116,7 +329,7 @@
};
uart_AO_B: serial@2000 {
- compatible = "amlogic,meson-gx-uart",
+ compatible = "amlogic,meson-a1-uart",
"amlogic,meson-ao-uart";
reg = <0x0 0x2000 0x0 0x18>;
interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
@@ -125,9 +338,70 @@
status = "disabled";
};
+ saradc: adc@2c00 {
+ compatible = "amlogic,meson-g12a-saradc",
+ "amlogic,meson-saradc";
+ reg = <0x0 0x2c00 0x0 0x48>;
+ #io-channel-cells = <1>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&xtal>,
+ <&clkc_periphs CLKID_SARADC_EN>,
+ <&clkc_periphs CLKID_SARADC>,
+ <&clkc_periphs CLKID_SARADC_SEL>;
+ clock-names = "clkin", "core",
+ "adc_clk", "adc_sel";
+ status = "disabled";
+ };
+
+ i2c1: i2c@5c00 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x5c00 0x0 0x20>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_B>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ };
+
+ i2c2: i2c@6800 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x6800 0x0 0x20>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_C>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ };
+
+ i2c3: i2c@6c00 {
+ compatible = "amlogic,meson-axg-i2c";
+ status = "disabled";
+ reg = <0x0 0x6c00 0x0 0x20>;
+ interrupts = <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&clkc_periphs CLKID_I2C_M_D>;
+ power-domains = <&pwrc PWRC_I2C_ID>;
+ };
+
+ usb2_phy1: phy@4000 {
+ compatible = "amlogic,a1-usb2-phy";
+ clocks = <&clkc_periphs CLKID_USB_PHY_IN>;
+ clock-names = "xtal";
+ reg = <0x0 0x4000 0x0 0x60>;
+ resets = <&reset RESET_USBPHY>;
+ reset-names = "phy";
+ #phy-cells = <0>;
+ power-domains = <&pwrc PWRC_USB_ID>;
+ };
+
hwrng: rng@5118 {
compatible = "amlogic,meson-rng";
reg = <0x0 0x5118 0x0 0x4>;
+ power-domains = <&pwrc PWRC_OTP_ID>;
};
sec_AO: ao-secure@5a20 {
@@ -135,6 +409,78 @@
reg = <0x0 0x5a20 0x0 0x140>;
amlogic,has-chip-id;
};
+
+ clkc_pll: pll-clock-controller@7c80 {
+ compatible = "amlogic,a1-pll-clkc";
+ reg = <0 0x7c80 0 0x18c>;
+ #clock-cells = <1>;
+ clocks = <&clkc_periphs CLKID_FIXPLL_IN>,
+ <&clkc_periphs CLKID_HIFIPLL_IN>;
+ clock-names = "fixpll_in", "hifipll_in";
+ };
+
+ sd_emmc: sd@10000 {
+ compatible = "amlogic,meson-axg-mmc";
+ reg = <0x0 0x10000 0x0 0x800>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc_periphs CLKID_SD_EMMC_A>,
+ <&clkc_periphs CLKID_SD_EMMC>,
+ <&clkc_pll CLKID_FCLK_DIV2>;
+ clock-names = "core",
+ "clkin0",
+ "clkin1";
+ assigned-clocks = <&clkc_periphs CLKID_SD_EMMC_SEL2>;
+ assigned-clock-parents = <&xtal>;
+ resets = <&reset RESET_SD_EMMC_A>;
+ power-domains = <&pwrc PWRC_SD_EMMC_ID>;
+ status = "disabled";
+ };
+ };
+
+ usb: usb@fe004400 {
+ status = "disabled";
+ compatible = "amlogic,meson-a1-usb-ctrl";
+ reg = <0x0 0xfe004400 0x0 0xa0>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&clkc_periphs CLKID_USB_CTRL>,
+ <&clkc_periphs CLKID_USB_BUS>,
+ <&clkc_periphs CLKID_USB_CTRL_IN>;
+ clock-names = "usb_ctrl", "usb_bus", "xtal_usb_ctrl";
+ resets = <&reset RESET_USBCTRL>;
+ reset-name = "usb_ctrl";
+
+ dr_mode = "otg";
+
+ phys = <&usb2_phy1>;
+ phy-names = "usb2-phy1";
+
+ dwc3: usb@ff400000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0xff400000 0x0 0x100000>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+ dr_mode = "host";
+ snps,dis_u2_susphy_quirk;
+ snps,quirk-frame-length-adjustment = <0x20>;
+ snps,parkmode-disable-ss-quirk;
+ };
+
+ dwc2: usb@ff500000 {
+ compatible = "amlogic,meson-a1-usb", "snps,dwc2";
+ reg = <0x0 0xff500000 0x0 0x40000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usb2_phy1>;
+ phy-names = "usb2-phy";
+ clocks = <&clkc_periphs CLKID_USB_PHY>;
+ clock-names = "otg";
+ dr_mode = "peripheral";
+ g-rx-fifo-size = <192>;
+ g-np-tx-fifo-size = <128>;
+ g-tx-fifo-size = <128 128 16 16 16>;
+ };
};
gic: interrupt-controller@ff901000 {
diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi
index dd6468ed96a..819564fdd5b 100644
--- a/arch/arm/dts/sama5d2.dtsi
+++ b/arch/arm/dts/sama5d2.dtsi
@@ -781,6 +781,26 @@
status = "disabled";
};
+ flx4: flexcom@fc018000 {
+ compatible = "atmel,sama5d2-flexcom";
+ reg = <0xfc018000 0x200>;
+ clocks = <&flx4_clk>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0xfc018000 0x800>;
+ status = "disabled";
+
+ i2c6: i2c@600 {
+ compatible = "atmel,sama5d2-i2c";
+ reg = <0x600 0x200>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&flx4_clk>;
+ clock-names = "i2c6_clk";
+ status = "disabled";
+ };
+ };
+
aic: interrupt-controller@fc020000 {
#interrupt-cells = <3>;
compatible = "atmel,sama5d2-aic";
diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi
index 135762b34fd..2240eaec5dd 100644
--- a/arch/arm/dts/sun50i-a64.dtsi
+++ b/arch/arm/dts/sun50i-a64.dtsi
@@ -93,6 +93,7 @@
L2: l2-cache {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
};
};
@@ -407,7 +408,7 @@
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
clock-names = "ahb", "tcon-ch0";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
reset-names = "lcd", "lvds";
diff --git a/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts b/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts
index 686f58e7700..b710f1a0f53 100644
--- a/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts
+++ b/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2019 Corentin LABBE <clabbe@baylibre.com>
*/
diff --git a/arch/arm/dts/sun50i-h616-orangepi-zero.dtsi b/arch/arm/dts/sun50i-h616-orangepi-zero.dtsi
new file mode 100644
index 00000000000..15290e6892f
--- /dev/null
+++ b/arch/arm/dts/sun50i-h616-orangepi-zero.dtsi
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ *
+ * DT nodes common between Orange Pi Zero 2 and Orange Pi Zero 3.
+ * Excludes PMIC nodes and properties, since they are different between the two.
+ */
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ ethernet0 = &emac0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
+ default-state = "on";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
+ };
+ };
+
+ reg_vcc5v: vcc5v {
+ /* board wide 5V supply directly from the USB-C socket */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_usb1_vbus: regulator-usb1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&reg_vcc5v>;
+ enable-active-high;
+ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+/* USB 2 & 3 are on headers only. */
+
+&emac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ allwinner,rx-delay-ps = <3100>;
+ allwinner,tx-delay-ps = <700>;
+ status = "okay";
+};
+
+&mdio0 {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&mmc0 {
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>;
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&usbotg {
+ /*
+ * PHY0 pins are connected to a USB-C socket, but a role switch
+ * is not implemented: both CC pins are pulled to GND.
+ * The VBUS pins power the device, so a fixed peripheral mode
+ * is the best choice.
+ * The board can be powered via GPIOs, in this case port0 *can*
+ * act as a host (with a cable/adapter ignoring CC), as VBUS is
+ * then provided by the GPIOs. Any user of this setup would
+ * need to adjust the DT accordingly: dr_mode set to "host",
+ * enabling OHCI0 and EHCI0.
+ */
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h616-orangepi-zero2.dts b/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
index cb8600d0ea1..d83852e72f0 100644
--- a/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
+++ b/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
@@ -1,99 +1,23 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2020 Arm Ltd.
*/
/dts-v1/;
-#include "sun50i-h616.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/leds/common.h>
+#include "sun50i-h616-orangepi-zero.dtsi"
/ {
model = "OrangePi Zero2";
compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616";
-
- aliases {
- ethernet0 = &emac0;
- serial0 = &uart0;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- leds {
- compatible = "gpio-leds";
-
- led-0 {
- function = LED_FUNCTION_POWER;
- color = <LED_COLOR_ID_RED>;
- gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
- default-state = "on";
- };
-
- led-1 {
- function = LED_FUNCTION_STATUS;
- color = <LED_COLOR_ID_GREEN>;
- gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
- };
- };
-
- reg_vcc5v: vcc5v {
- /* board wide 5V supply directly from the USB-C socket */
- compatible = "regulator-fixed";
- regulator-name = "vcc-5v";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- regulator-always-on;
- };
-
- reg_usb1_vbus: regulator-usb1-vbus {
- compatible = "regulator-fixed";
- regulator-name = "usb1-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- vin-supply = <&reg_vcc5v>;
- enable-active-high;
- gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */
- };
};
-&ehci1 {
- status = "okay";
-};
-
-/* USB 2 & 3 are on headers only. */
-
&emac0 {
- pinctrl-names = "default";
- pinctrl-0 = <&ext_rgmii_pins>;
- phy-mode = "rgmii";
- phy-handle = <&ext_rgmii_phy>;
phy-supply = <&reg_dcdce>;
- allwinner,rx-delay-ps = <3100>;
- allwinner,tx-delay-ps = <700>;
- status = "okay";
-};
-
-&mdio0 {
- ext_rgmii_phy: ethernet-phy@1 {
- compatible = "ethernet-phy-ieee802.3-c22";
- reg = <1>;
- };
};
&mmc0 {
vmmc-supply = <&reg_dcdce>;
- cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
- bus-width = <4>;
- status = "okay";
-};
-
-&ohci1 {
- status = "okay";
};
&r_rsb {
@@ -211,44 +135,3 @@
vcc-ph-supply = <&reg_aldo1>;
vcc-pi-supply = <&reg_aldo1>;
};
-
-&spi0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>;
-
- flash@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "jedec,spi-nor";
- reg = <0>;
- spi-max-frequency = <40000000>;
- };
-};
-
-&uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_ph_pins>;
- status = "okay";
-};
-
-&usbotg {
- /*
- * PHY0 pins are connected to a USB-C socket, but a role switch
- * is not implemented: both CC pins are pulled to GND.
- * The VBUS pins power the device, so a fixed peripheral mode
- * is the best choice.
- * The board can be powered via GPIOs, in this case port0 *can*
- * act as a host (with a cable/adapter ignoring CC), as VBUS is
- * then provided by the GPIOs. Any user of this setup would
- * need to adjust the DT accordingly: dr_mode set to "host",
- * enabling OHCI0 and EHCI0.
- */
- dr_mode = "peripheral";
- status = "okay";
-};
-
-&usbphy {
- usb1_vbus-supply = <&reg_usb1_vbus>;
- status = "okay";
-};
diff --git a/arch/arm/dts/sun50i-h616-x96-mate.dts b/arch/arm/dts/sun50i-h616-x96-mate.dts
index 07424c28b69..959b6fd1848 100644
--- a/arch/arm/dts/sun50i-h616-x96-mate.dts
+++ b/arch/arm/dts/sun50i-h616-x96-mate.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2021 Arm Ltd.
*/
diff --git a/arch/arm/dts/sun50i-h618-orangepi-zero3.dts b/arch/arm/dts/sun50i-h618-orangepi-zero3.dts
new file mode 100644
index 00000000000..00fe28caac9
--- /dev/null
+++ b/arch/arm/dts/sun50i-h618-orangepi-zero3.dts
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616-orangepi-zero.dtsi"
+
+/ {
+ model = "OrangePi Zero3";
+ compatible = "xunlong,orangepi-zero3", "allwinner,sun50i-h618";
+};
+
+&emac0 {
+ phy-supply = <&reg_dldo1>;
+};
+
+&ext_rgmii_phy {
+ motorcomm,clk-out-frequency-hz = <125000000>;
+};
+
+&mmc0 {
+ /*
+ * The schematic shows the card detect pin wired up to PF6, via an
+ * inverter, but it just doesn't work.
+ */
+ broken-cd;
+ vmmc-supply = <&reg_dldo1>;
+};
+
+&r_i2c {
+ status = "okay";
+
+ axp313: pmic@36 {
+ compatible = "x-powers,axp313a";
+ reg = <0x36>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ interrupt-parent = <&pio>;
+ interrupts = <2 9 IRQ_TYPE_LEVEL_LOW>; /* PC9 */
+
+ vin1-supply = <&reg_vcc5v>;
+ vin2-supply = <&reg_vcc5v>;
+ vin3-supply = <&reg_vcc5v>;
+
+ regulators {
+ /* Supplies VCC-PLL, so needs to be always on. */
+ reg_aldo1: aldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc1v8";
+ };
+
+ /* Supplies VCC-IO, so needs to be always on. */
+ reg_dldo1: dldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc3v3";
+ };
+
+ reg_dcdc1: dcdc1 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <990000>;
+ regulator-name = "vdd-gpu-sys";
+ };
+
+ reg_dcdc2: dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-cpu";
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-dram";
+ };
+ };
+ };
+};
+
+&pio {
+ vcc-pc-supply = <&reg_dldo1>;
+ vcc-pf-supply = <&reg_dldo1>;
+ vcc-pg-supply = <&reg_aldo1>;
+ vcc-ph-supply = <&reg_dldo1>;
+ vcc-pi-supply = <&reg_dldo1>;
+};
diff --git a/arch/arm/dts/sun5i-r8-chip.dts b/arch/arm/dts/sun5i-r8-chip.dts
index fd37bd1f392..4192c23848c 100644
--- a/arch/arm/dts/sun5i-r8-chip.dts
+++ b/arch/arm/dts/sun5i-r8-chip.dts
@@ -255,6 +255,12 @@
pinctrl-0 = <&uart3_pg_pins>,
<&uart3_cts_rts_pg_pins>;
status = "okay";
+
+ bluetooth {
+ compatible = "realtek,rtl8723bs-bt";
+ device-wake-gpios = <&axp_gpio 3 GPIO_ACTIVE_HIGH>;
+ host-wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
+ };
};
&usb_otg {
diff --git a/arch/arm/dts/sun5i.dtsi b/arch/arm/dts/sun5i.dtsi
index 250d6b87ab4..d7c7b454a11 100644
--- a/arch/arm/dts/sun5i.dtsi
+++ b/arch/arm/dts/sun5i.dtsi
@@ -286,7 +286,7 @@
clock-names = "ahb",
"tcon-ch0",
"tcon-ch1";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
status = "disabled";
@@ -517,6 +517,15 @@
bias-pull-up;
};
+ /omit-if-no-ref/
+ mmc2_4bit_pe_pins: mmc2-4bit-pe-pins {
+ pins = "PE4", "PE5", "PE6", "PE7",
+ "PE8", "PE9";
+ function = "mmc2";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
mmc2_8bit_pins: mmc2-8bit-pins {
pins = "PC6", "PC7", "PC8", "PC9",
"PC10", "PC11", "PC12", "PC13",
diff --git a/arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts b/arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts
new file mode 100644
index 00000000000..577ead1d02a
--- /dev/null
+++ b/arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+// Copyright (C) 2023 In-Circuit GmbH
+
+/dts-v1/;
+
+#include "sun7i-a20-icnova-a20.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "In-Circuit ICnova A20 ADB4006";
+ compatible = "incircuit,icnova-a20-adb4006", "incircuit,icnova-a20",
+ "allwinner,sun7i-a20";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_YELLOW>;
+ gpios = <&pio 7 21 GPIO_ACTIVE_HIGH>; /* PH21 */
+ default-state = "on";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_HEARTBEAT;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>; /* PH20 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
+
+&ahci {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+};
+
+&codec {
+ status = "okay";
+};
+
+&de {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>; /* PH1 */
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&otg_sram {
+ status = "okay";
+};
+
+&reg_ahci_5v {
+ status = "okay";
+};
+
+&ac_power_supply {
+ status = "okay";
+};
+
+&reg_usb1_vbus {
+ status = "okay";
+};
+
+&reg_usb2_vbus {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pb_pins>;
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+ usb0_vbus_det-gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun7i-a20-icnova-a20.dtsi b/arch/arm/dts/sun7i-a20-icnova-a20.dtsi
new file mode 100644
index 00000000000..46616c6bc89
--- /dev/null
+++ b/arch/arm/dts/sun7i-a20-icnova-a20.dtsi
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+// Copyright (C) 2023 In-Circuit GmbH
+
+#include "sun7i-a20.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&cpu0 {
+ cpu-supply = <&reg_dcdc2>;
+};
+
+&gmac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_mii_pins>;
+ phy-handle = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ axp209: pmic@34 {
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+#include "axp209.dtsi"
+
+&reg_dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo1 {
+ regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-name = "avcc";
+};
diff --git a/arch/arm/dts/sun8i-a23-a33.dtsi b/arch/arm/dts/sun8i-a23-a33.dtsi
index 84c6d9379a3..a0cac966af3 100644
--- a/arch/arm/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/dts/sun8i-a23-a33.dtsi
@@ -190,7 +190,7 @@
clock-names = "ahb",
"tcon-ch0",
"lvds-alt";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_LCD>,
<&ccu RST_BUS_LVDS>;
diff --git a/arch/arm/dts/sun8i-a83t.dtsi b/arch/arm/dts/sun8i-a83t.dtsi
index 9c07660080d..cc40622466a 100644
--- a/arch/arm/dts/sun8i-a83t.dtsi
+++ b/arch/arm/dts/sun8i-a83t.dtsi
@@ -456,7 +456,7 @@
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
clock-names = "ahb", "tcon-ch0";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
reset-names = "lcd", "lvds";
diff --git a/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
new file mode 100644
index 00000000000..8b3a7538381
--- /dev/null
+++ b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/dts-v1/;
+
+#include "sun8i-t113s.dtsi"
+#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
+
+/ {
+ model = "MangoPi MQ-R-T113";
+ compatible = "widora,mangopi-mq-r-t113", "allwinner,sun8i-t113s";
+
+ aliases {
+ ethernet0 = &rtl8189ftv;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vcc_core>;
+};
+
+&cpu1 {
+ cpu-supply = <&reg_vcc_core>;
+};
+
+&mmc1 {
+ rtl8189ftv: wifi@1 {
+ reg = <1>;
+ interrupt-parent = <&pio>;
+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 = WL_WAKE_AP */
+ interrupt-names = "host-wake";
+ };
+};
diff --git a/arch/arm/dts/sun8i-t113s.dtsi b/arch/arm/dts/sun8i-t113s.dtsi
new file mode 100644
index 00000000000..b94b69142af
--- /dev/null
+++ b/arch/arm/dts/sun8i-t113s.dtsi
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+
+#define SOC_PERIPHERAL_IRQ(nr) GIC_SPI nr
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <../../riscv/dts/sunxi-d1s-t113.dtsi>
+#include <../../riscv/dts/sunxi-d1-t113.dtsi>
+
+/ {
+ interrupt-parent = <&gic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0>;
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <1>;
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ };
+ };
+
+ gic: interrupt-controller@1c81000 {
+ compatible = "arm,gic-400";
+ reg = <0x03021000 0x1000>,
+ <0x03022000 0x2000>,
+ <0x03024000 0x2000>,
+ <0x03026000 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+};
diff --git a/arch/arm/dts/sun8i-v3s.dtsi b/arch/arm/dts/sun8i-v3s.dtsi
index b001251644f..3b9a282c274 100644
--- a/arch/arm/dts/sun8i-v3s.dtsi
+++ b/arch/arm/dts/sun8i-v3s.dtsi
@@ -191,7 +191,7 @@
<&ccu CLK_TCON0>;
clock-names = "ahb",
"tcon-ch0";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_TCON0>;
reset-names = "lcd";
diff --git a/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
new file mode 100644
index 00000000000..a415c4a78a7
--- /dev/null
+++ b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+/*
+ * Common peripherals and configurations for MangoPi MQ-R boards.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ serial3 = &uart3;
+ };
+
+ chosen {
+ stdout-path = "serial3:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&pio 3 22 GPIO_ACTIVE_LOW>; /* PD22 */
+ };
+ };
+
+ /* board wide 5V supply directly from the USB-C socket */
+ reg_vcc5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ /* SY8008 DC/DC regulator on the board */
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&reg_vcc5v>;
+ };
+
+ /* SY8008 DC/DC regulator on the board, also supplying VDD-SYS */
+ reg_vcc_core: regulator-core {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-core";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ vin-supply = <&reg_vcc5v>;
+ };
+
+ /* XC6206 LDO on the board */
+ reg_avdd2v8: regulator-avdd {
+ compatible = "regulator-fixed";
+ regulator-name = "avdd2v8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ vin-supply = <&reg_3v3>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
+ };
+};
+
+&dcxo {
+ clock-frequency = <24000000>;
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ vmmc-supply = <&reg_3v3>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ vmmc-supply = <&reg_3v3>;
+ non-removable;
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ vcc-pb-supply = <&reg_3v3>;
+ vcc-pd-supply = <&reg_3v3>;
+ vcc-pe-supply = <&reg_avdd2v8>;
+ vcc-pf-supply = <&reg_3v3>;
+ vcc-pg-supply = <&reg_3v3>;
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pb_pins>;
+ status = "okay";
+};
+
+/* The USB-C socket has its CC pins pulled to GND, so is hardwired as a UFP. */
+&usb_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_vcc5v>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index af419c7e590..a0c8abb7033 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -23,6 +23,13 @@
};
};
+/* Let U-Boot be the firmware layer that controls the watchdog. */
+#ifdef CONFIG_MACH_SUN8I_R528
+&wdt {
+ status = "okay";
+};
+#endif
+
&binman {
u-boot-sunxi-with-spl {
filename = "u-boot-sunxi-with-spl.bin";
diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 30f5680757a..cad25c50bc6 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -3,6 +3,8 @@
* Configuration settings for the Allwinner A64 (sun50i) CPU
*/
+#include <asm/arch/cpu.h>
+
#if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
/* reserve space for BOOT0 header information */
b reset
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 2cfd5407423..fcc8966cb0b 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -9,6 +9,7 @@
#define _SUNXI_CLOCK_H
#include <linux/types.h>
+#include <asm/arch/cpu.h>
#define CLK_GATE_OPEN 0x1
#define CLK_GATE_CLOSE 0x0
@@ -16,7 +17,7 @@
/* clock control module regs definition */
#if defined(CONFIG_MACH_SUN8I_A83T)
#include <asm/arch/clock_sun8i_a83t.h>
-#elif defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
#include <asm/arch/clock_sun50i_h6.h>
#elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 37df4410eaa..a84a57e5b41 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -228,6 +228,7 @@ struct sunxi_ccm_reg {
/* pll1 bit field */
#define CCM_PLL1_CTRL_EN BIT(31)
+#define CCM_PLL1_LDO_EN BIT(30)
#define CCM_PLL1_LOCK_EN BIT(29)
#define CCM_PLL1_LOCK BIT(28)
#define CCM_PLL1_OUT_EN BIT(27)
@@ -248,6 +249,8 @@ struct sunxi_ccm_reg {
#define CCM_PLL6_CTRL_EN BIT(31)
#define CCM_PLL6_LOCK_EN BIT(29)
#define CCM_PLL6_LOCK BIT(28)
+#define CCM_PLL6_CTRL_P0_SHIFT 16
+#define CCM_PLL6_CTRL_P0_MASK (0x7 << CCM_PLL6_CTRL_P0_SHIFT)
#define CCM_PLL6_CTRL_N_SHIFT 8
#define CCM_PLL6_CTRL_N_MASK (0xff << CCM_PLL6_CTRL_N_SHIFT)
#define CCM_PLL6_CTRL_DIV1_SHIFT 0
@@ -263,7 +266,7 @@ struct sunxi_ccm_reg {
#define CCM_CPU_AXI_AXI_MASK 0x3
#define CCM_CPU_AXI_DEFAULT_FACTORS 0x301
-#ifdef CONFIG_MACH_SUN50I_H6
+#ifdef CONFIG_MACH_SUN50I_H6 /* H6 */
#define CCM_PLL6_DEFAULT 0xa0006300
/* psi_ahb1_ahb2 bit field */
@@ -274,7 +277,7 @@ struct sunxi_ccm_reg {
/* apb1 bit field */
#define CCM_APB1_DEFAULT 0x03000102
-#elif CONFIG_MACH_SUN50I_H616
+#elif CONFIG_MACH_SUN50I_H616 /* H616 */
#define CCM_PLL6_DEFAULT 0xa8003100
/* psi_ahb1_ahb2 bit field */
@@ -285,6 +288,11 @@ struct sunxi_ccm_reg {
/* apb1 bit field */
#define CCM_APB1_DEFAULT 0x03000102
+#elif CONFIG_MACH_SUN8I_R528 /* R528 */
+#define CCM_PLL6_DEFAULT 0xe8216300
+#define CCM_PSI_AHB1_AHB2_DEFAULT 0x03000002
+//#define CCM_AHB3_DEFAULT 0x03000002
+#define CCM_APB1_DEFAULT 0x03000102
#endif
/* apb2 bit field */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index b08f2023748..768c6572d6b 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -10,6 +10,8 @@
#include <asm/arch/cpu_sun9i.h>
#elif defined(CONFIG_SUN50I_GEN_H6)
#include <asm/arch/cpu_sun50i_h6.h>
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#include <asm/arch/cpu_sunxi_ncat2.h>
#else
#include <asm/arch/cpu_sun4i.h>
#endif
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index f7ecc790dbf..3daee2f574a 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -91,7 +91,6 @@
#define SUNXI_CCM_BASE 0x01c20000
#define SUNXI_INTC_BASE 0x01c20400
-#define SUNXI_PIO_BASE 0x01c20800
#define SUNXI_TIMER_BASE 0x01c20c00
#ifndef CONFIG_SUNXI_GEN_SUN6I
#define SUNXI_PWM_BASE 0x01c20e00
@@ -129,20 +128,6 @@ defined(CONFIG_MACH_SUN50I)
#define SUNXI_CPUCFG_BASE 0x01c25c00
#endif
-#ifdef CONFIG_MACH_SUNIV
-#define SUNXI_UART0_BASE 0x01c25000
-#define SUNXI_UART1_BASE 0x01c25400
-#define SUNXI_UART2_BASE 0x01c25800
-#else
-#define SUNXI_UART0_BASE 0x01c28000
-#define SUNXI_UART1_BASE 0x01c28400
-#define SUNXI_UART2_BASE 0x01c28800
-#endif
-#define SUNXI_UART3_BASE 0x01c28c00
-#define SUNXI_UART4_BASE 0x01c29000
-#define SUNXI_UART5_BASE 0x01c29400
-#define SUNXI_UART6_BASE 0x01c29800
-#define SUNXI_UART7_BASE 0x01c29c00
#define SUNXI_PS2_0_BASE 0x01c2a000
#define SUNXI_PS2_1_BASE 0x01c2a400
@@ -209,8 +194,6 @@ defined(CONFIG_MACH_SUN50I)
#endif
#define SUNXI_R_TWI_BASE 0x01f02400
-#define SUNXI_R_UART_BASE 0x01f02800
-#define SUNXI_R_PIO_BASE 0x01f02c00
#define SUN6I_P2WI_BASE 0x01f03400
#define SUNXI_RSB_BASE 0x01f03400
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index d9cf8ae0428..15ee092d358 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -22,7 +22,6 @@
#define SUNXI_SIDC_BASE 0x03006000
#define SUNXI_SID_BASE 0x03006200
#define SUNXI_TIMER_BASE 0x03009000
-#define SUNXI_PIO_BASE 0x0300B000
#define SUNXI_PSI_BASE 0x0300C000
#define SUNXI_GIC400_BASE 0x03020000
@@ -43,10 +42,6 @@
#define SUNXI_DRAM_PHY0_BASE 0x04800000
#endif
-#define SUNXI_UART0_BASE 0x05000000
-#define SUNXI_UART1_BASE 0x05000400
-#define SUNXI_UART2_BASE 0x05000800
-#define SUNXI_UART3_BASE 0x05000C00
#define SUNXI_TWI0_BASE 0x05002000
#define SUNXI_TWI1_BASE 0x05002400
#define SUNXI_TWI2_BASE 0x05002800
@@ -68,8 +63,6 @@
#define SUNXI_R_CPUCFG_BASE 0x07000400
#define SUNXI_PRCM_BASE 0x07010000
#define SUNXI_R_WDOG_BASE 0x07020400
-#define SUNXI_R_PIO_BASE 0x07022000
-#define SUNXI_R_UART_BASE 0x07080000
#define SUNXI_R_TWI_BASE 0x07081400
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
index 9c2d11b5901..2bf2675d5c1 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
@@ -81,18 +81,11 @@
/* APB0 Module */
#define SUNXI_CCM_BASE (REGS_APB0_BASE + 0x0000)
#define SUNXI_CCMMODULE_BASE (REGS_APB0_BASE + 0x0400)
-#define SUNXI_PIO_BASE (REGS_APB0_BASE + 0x0800)
#define SUNXI_TIMER_BASE (REGS_APB0_BASE + 0x0C00)
#define SUNXI_PWM_BASE (REGS_APB0_BASE + 0x1400)
#define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800)
/* APB1 Module */
-#define SUNXI_UART0_BASE (REGS_APB1_BASE + 0x0000)
-#define SUNXI_UART1_BASE (REGS_APB1_BASE + 0x0400)
-#define SUNXI_UART2_BASE (REGS_APB1_BASE + 0x0800)
-#define SUNXI_UART3_BASE (REGS_APB1_BASE + 0x0C00)
-#define SUNXI_UART4_BASE (REGS_APB1_BASE + 0x1000)
-#define SUNXI_UART5_BASE (REGS_APB1_BASE + 0x1400)
#define SUNXI_TWI0_BASE (REGS_APB1_BASE + 0x2800)
#define SUNXI_TWI1_BASE (REGS_APB1_BASE + 0x2C00)
#define SUNXI_TWI2_BASE (REGS_APB1_BASE + 0x3000)
@@ -101,8 +94,6 @@
/* RCPUS Module */
#define SUNXI_PRCM_BASE (REGS_RCPUS_BASE + 0x1400)
-#define SUNXI_R_UART_BASE (REGS_RCPUS_BASE + 0x2800)
-#define SUNXI_R_PIO_BASE (REGS_RCPUS_BASE + 0x2c00)
#define SUNXI_RSB_BASE (REGS_RCPUS_BASE + 0x3400)
/* Misc. */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
new file mode 100644
index 00000000000..908a582ae0f
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2022 Arm Limited
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_CPU_SUNXI_NCAT2_H
+#define _SUNXI_CPU_SUNXI_NCAT2_H
+
+#define SUNXI_CCM_BASE 0x02001000
+#define SUNXI_TIMER_BASE 0x02050000
+
+#define SUNXI_TWI0_BASE 0x02502000
+#define SUNXI_TWI1_BASE 0x02502400
+#define SUNXI_TWI2_BASE 0x02502800
+#define SUNXI_TWI3_BASE 0x02502C00
+
+#define SUNXI_SRAMC_BASE 0x03000000
+/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
+#define SUNXI_SIDC_BASE 0x03006000
+#define SUNXI_SID_BASE 0x03006200
+#define SUNXI_GIC400_BASE 0x03020000
+
+#define SUNXI_MMC0_BASE 0x04020000
+#define SUNXI_MMC1_BASE 0x04021000
+#define SUNXI_MMC2_BASE 0x04022000
+
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_PRCM_BASE 0x07010000
+
+#define SUNXI_CPUCFG_BASE 0x09010000
+
+#ifndef __ASSEMBLY__
+void sunxi_board_init(void);
+void sunxi_reset(void);
+int sunxi_get_sid(unsigned int *sid);
+#endif
+
+#endif /* _SUNXI_CPU_SUNXI_NCAT2_H */
diff --git a/arch/arm/include/asm/arch-sunxi/cpucfg.h b/arch/arm/include/asm/arch-sunxi/cpucfg.h
deleted file mode 100644
index 4aaebe0a976..00000000000
--- a/arch/arm/include/asm/arch-sunxi/cpucfg.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Sunxi A31 CPUCFG register definition.
- *
- * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com
- */
-
-#ifndef _SUNXI_CPUCFG_H
-#define _SUNXI_CPUCFG_H
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-
-#ifndef __ASSEMBLY__
-
-struct __packed sunxi_cpucfg_cpu {
- u32 rst; /* base + 0x0 */
- u32 ctrl; /* base + 0x4 */
- u32 status; /* base + 0x8 */
- u8 res[0x34]; /* base + 0xc */
-};
-
-struct __packed sunxi_cpucfg_reg {
- u8 res0[0x40]; /* 0x000 */
- struct sunxi_cpucfg_cpu cpu[4]; /* 0x040 */
- u8 res1[0x44]; /* 0x140 */
- u32 gen_ctrl; /* 0x184 */
- u32 l2_status; /* 0x188 */
- u8 res2[0x4]; /* 0x18c */
- u32 event_in; /* 0x190 */
- u8 res3[0xc]; /* 0x194 */
- u32 super_standy_flag; /* 0x1a0 */
- u32 priv0; /* 0x1a4 */
- u32 priv1; /* 0x1a8 */
- u8 res4[0x4]; /* 0x1ac */
- u32 cpu1_pwr_clamp; /* 0x1b0 sun7i only */
- u32 cpu1_pwroff; /* 0x1b4 sun7i only */
- u8 res5[0x2c]; /* 0x1b8 */
- u32 dbg_ctrl1; /* 0x1e4 */
- u8 res6[0x18]; /* 0x1e8 */
- u32 idle_cnt0_low; /* 0x200 */
- u32 idle_cnt0_high; /* 0x204 */
- u32 idle_cnt0_ctrl; /* 0x208 */
- u8 res8[0x4]; /* 0x20c */
- u32 idle_cnt1_low; /* 0x210 */
- u32 idle_cnt1_high; /* 0x214 */
- u32 idle_cnt1_ctrl; /* 0x218 */
- u8 res9[0x4]; /* 0x21c */
- u32 idle_cnt2_low; /* 0x220 */
- u32 idle_cnt2_high; /* 0x224 */
- u32 idle_cnt2_ctrl; /* 0x228 */
- u8 res10[0x4]; /* 0x22c */
- u32 idle_cnt3_low; /* 0x230 */
- u32 idle_cnt3_high; /* 0x234 */
- u32 idle_cnt3_ctrl; /* 0x238 */
- u8 res11[0x4]; /* 0x23c */
- u32 idle_cnt4_low; /* 0x240 */
- u32 idle_cnt4_high; /* 0x244 */
- u32 idle_cnt4_ctrl; /* 0x248 */
- u8 res12[0x34]; /* 0x24c */
- u32 cnt64_ctrl; /* 0x280 */
- u32 cnt64_low; /* 0x284 */
- u32 cnt64_high; /* 0x288 */
-};
-
-#endif /* __ASSEMBLY__ */
-#endif /* _SUNXI_CPUCFG_H */
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
index 5daacf10eb1..8ed3e0459c9 100644
--- a/arch/arm/include/asm/arch-sunxi/mmc.h
+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
@@ -45,7 +45,7 @@ struct sunxi_mmc {
u32 chda; /* 0x90 */
u32 cbda; /* 0x94 */
u32 res2[26];
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
u32 res3[17];
u32 samp_dl;
u32 res4[46];
diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
index 5106076f5e9..c5418cfd28d 100644
--- a/arch/arm/include/asm/arch-sunxi/prcm.h
+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
@@ -9,7 +9,7 @@
#define _SUNXI_PRCM_H
/* prcm regs definition */
-#if defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
#include <asm/arch/prcm_sun50i.h>
#else
#include <asm/arch/prcm_sun6i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/serial.h b/arch/arm/include/asm/arch-sunxi/serial.h
new file mode 100644
index 00000000000..9386287b65e
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/serial.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * hardcoded UART base addresses for early SPL use
+ *
+ * Copyright (c) 2022 Arm Ltd.
+ */
+
+#ifndef SUNXI_SERIAL_MEMMAP_H
+#define SUNXI_SERIAL_MEMMAP_H
+
+#if defined(CONFIG_MACH_SUN9I)
+#define SUNXI_UART0_BASE 0x07000000
+#define SUNXI_R_UART_BASE 0x08002800
+#elif defined(CONFIG_SUN50I_GEN_H6)
+#define SUNXI_UART0_BASE 0x05000000
+#define SUNXI_R_UART_BASE 0x07080000
+#elif defined(CONFIG_MACH_SUNIV)
+#define SUNXI_UART0_BASE 0x01c25000
+#define SUNXI_R_UART_BASE 0
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#define SUNXI_UART0_BASE 0x02500000
+#define SUNXI_R_UART_BASE 0 // 0x07080000 (?>
+#else
+#define SUNXI_UART0_BASE 0x01c28000
+#define SUNXI_R_UART_BASE 0x01f02800
+#endif
+
+#define SUNXI_UART1_BASE (SUNXI_UART0_BASE + 0x400)
+#define SUNXI_UART2_BASE (SUNXI_UART0_BASE + 0x800)
+#define SUNXI_UART3_BASE (SUNXI_UART0_BASE + 0xc00)
+
+#endif /* SUNXI_SERIAL_MEMMAP_H */
diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
index bb5626d893b..e17db8588e2 100644
--- a/arch/arm/include/asm/arch-sunxi/timer.h
+++ b/arch/arm/include/asm/arch-sunxi/timer.h
@@ -76,7 +76,7 @@ struct sunxi_timer_reg {
struct sunxi_tgp tgp[4];
u8 res5[8];
u32 cpu_cfg;
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
u8 res3[16];
struct sunxi_wdog wdog[5]; /* We have 5 watchdogs */
#endif
diff --git a/arch/arm/include/asm/mach-imx/ahab.h b/arch/arm/include/asm/mach-imx/ahab.h
index 4222e3db278..4884f056251 100644
--- a/arch/arm/include/asm/mach-imx/ahab.h
+++ b/arch/arm/include/asm/mach-imx/ahab.h
@@ -6,7 +6,7 @@
#ifndef __IMX_AHAB_H__
#define __IMX_AHAB_H__
-#include <asm/mach-imx/image.h>
+#include <imx_container.h>
int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length);
int ahab_auth_release(void);
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 4c65fc0dbd2..37ef2d691d6 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -204,6 +204,17 @@ config TARGET_SAMA5D27_WLSOM1_EK
processor-based SAMA5D2 MPU with 2 Gbit LPDDR2-SDRAM
in a single package.
+config TARGET_KSTR_SAMA5D27
+ bool "Conclusive KSTR-SAMA5D27 board"
+ select BOARD_EARLY_INIT_F
+ select SAMA5D2
+ help
+ The KSTR-SAMA5D27 embeds SAMA5D27 SoC, together with
+ 256 MiB SDRAM, 10/100 Mbit/s Ethernet, 96 Mbit/s Wi-Fi b/g/n,
+ Bluetooth 4.1 LE, USB OTG controller w/ type-C USB connector
+ and stackable GPIO headers in an all-in-one SBC form factor:
+ https://conclusive.pl/products/kstr-sama5d27-sbc/
+
config TARGET_SAMA5D2_ICP
bool "SAMA5D2 Industrial Connectivity Platform (ICP)"
select SAMA5D2
@@ -364,6 +375,7 @@ source "board/atmel/sama5d4_xplained/Kconfig"
source "board/atmel/sama5d4ek/Kconfig"
source "board/bluewater/gurnard/Kconfig"
source "board/calao/usb_a9263/Kconfig"
+source "board/conclusive/kstr-sama5d27/Kconfig"
source "board/egnite/ethernut5/Kconfig"
source "board/esd/meesc/Kconfig"
source "board/gardena/smart-gateway-at91sam/Kconfig"
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 44e1e1628ba..abd48d42583 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -194,19 +194,6 @@ config IMX_DCD_ADDR
This information is shared with the user via mkimage -l just so the
image can be signed.
-config SPL_LOAD_IMX_CONTAINER
- bool "Enable SPL loading U-Boot as a i.MX Container image"
- depends on SPL
- help
- This is to let SPL could load i.MX Container image
-
-config IMX_CONTAINER_CFG
- string "i.MX Container config file"
- depends on SPL
- help
- This is to specific the cfg file for generating container
- image which will be loaded by SPL.
-
config IOMUX_LPSR
bool
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 6904cf38802..a3b44c93e3d 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -79,7 +79,7 @@ obj-$(CONFIG_CMD_NANDBCB) += cmd_nandbcb.o
endif
ifeq ($(CONFIG_SPL_BUILD),y)
-obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image-container.o parse-container.o
+obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image-container.o
endif
ifeq ($(SOC),$(filter $(SOC),imx8ulp imx9))
diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c
index 6fa5b41fcd3..2f389dbe8df 100644
--- a/arch/arm/mach-imx/cmd_dek.c
+++ b/arch/arm/mach-imx/cmd_dek.c
@@ -18,12 +18,12 @@
#include <mapmem.h>
#include <tee.h>
#ifdef CONFIG_IMX_SECO_DEK_ENCAP
+#include <imx_container.h>
#include <firmware/imx/sci/sci.h>
-#include <asm/mach-imx/image.h>
#endif
#ifdef CONFIG_IMX_ELE_DEK_ENCAP
+#include <imx_container.h>
#include <asm/mach-imx/ele_api.h>
-#include <asm/mach-imx/image.h>
#endif
#include <cpu_func.h>
diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c
index 785b0d6ec3c..295c055ad0a 100644
--- a/arch/arm/mach-imx/ele_ahab.c
+++ b/arch/arm/mach-imx/ele_ahab.c
@@ -6,12 +6,12 @@
#include <common.h>
#include <command.h>
#include <errno.h>
+#include <imx_container.h>
#include <asm/io.h>
#include <asm/mach-imx/ele_api.h>
#include <asm/mach-imx/sys_proto.h>
#include <asm/arch-imx/cpu.h>
#include <asm/arch/sys_proto.h>
-#include <asm/mach-imx/image.h>
#include <console.h>
#include <cpu_func.h>
#include <asm/global_data.h>
@@ -343,7 +343,7 @@ int authenticate_os_container(ulong addr)
}
phdr = (struct container_hdr *)addr;
- if (phdr->tag != 0x87 || phdr->version != 0x0) {
+ if (!valid_container_hdr(phdr)) {
printf("Error: Wrong container header\n");
return -EFAULT;
}
diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c
index 0285bbdaf20..c9455fe222a 100644
--- a/arch/arm/mach-imx/image-container.c
+++ b/arch/arm/mach-imx/image-container.c
@@ -5,6 +5,7 @@
#include <common.h>
#include <errno.h>
+#include <imx_container.h>
#include <log.h>
#include <malloc.h>
#include <asm/io.h>
@@ -12,7 +13,6 @@
#include <spi_flash.h>
#include <spl.h>
#include <nand.h>
-#include <asm/mach-imx/image.h>
#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/boot_mode.h>
@@ -50,7 +50,7 @@ int get_container_size(ulong addr, u16 *header_length)
u32 max_offset = 0, img_end;
phdr = (struct container_hdr *)addr;
- if (phdr->tag != 0x87 || phdr->version != 0x0) {
+ if (!valid_container_hdr(phdr)) {
debug("Wrong container header\n");
return -EFAULT;
}
diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c
index b58b14ca9b4..994becccefd 100644
--- a/arch/arm/mach-imx/imx8/ahab.c
+++ b/arch/arm/mach-imx/imx8/ahab.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <command.h>
#include <errno.h>
+#include <imx_container.h>
#include <log.h>
#include <asm/global_data.h>
#include <asm/io.h>
@@ -13,7 +14,6 @@
#include <asm/mach-imx/sys_proto.h>
#include <asm/arch-imx/cpu.h>
#include <asm/arch/sys_proto.h>
-#include <asm/mach-imx/image.h>
#include <console.h>
#include <cpu_func.h>
#include "u-boot/sha256.h"
@@ -146,7 +146,7 @@ int authenticate_os_container(ulong addr)
}
phdr = (struct container_hdr *)addr;
- if (phdr->tag != 0x87 && phdr->version != 0x0) {
+ if (!valid_container_hdr(phdr)) {
printf("Error: Wrong container header\n");
return -EFAULT;
}
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c
index c4a4185eed1..93d48e56aca 100644
--- a/arch/arm/mach-imx/spl_imx_romapi.c
+++ b/arch/arm/mach-imx/spl_imx_romapi.c
@@ -6,11 +6,11 @@
#include <common.h>
#include <errno.h>
#include <image.h>
+#include <imx_container.h>
#include <log.h>
#include <asm/global_data.h>
#include <linux/libfdt.h>
#include <spl.h>
-#include <asm/mach-imx/image.h>
#include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -111,7 +111,8 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image,
load.read = spl_romapi_read_seekable;
load.priv = &pagesize;
return spl_load_simple_fit(spl_image, &load, offset / pagesize, header);
- } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
+ } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
+ valid_container_hdr((void *)header)) {
struct spl_load_info load;
memset(&load, 0, sizeof(load));
@@ -202,7 +203,8 @@ static u8 *search_container_header(u8 *p, int size)
for (i = 0; i < size; i += 4) {
hdr = p + i;
- if (*(hdr + 3) == 0x87 && *hdr == 0 && (*(hdr + 1) != 0 || *(hdr + 2) != 0))
+ if (valid_container_hdr((void *)hdr) &&
+ (*(hdr + 1) != 0 || *(hdr + 2) != 0))
return p + i;
}
diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig
index 714eb4405bc..2bb96749fc0 100644
--- a/arch/arm/mach-rmobile/Kconfig
+++ b/arch/arm/mach-rmobile/Kconfig
@@ -77,6 +77,7 @@ config RZG2L
imply PINCTRL_RZG2L
imply RENESAS_SDHI
imply RZG2L_GPIO
+ imply SCIF_CONSOLE
imply SYS_MALLOC_F
help
Enable support for the Renesas RZ/G2L family of SoCs. Currently
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 9d5df2c1027..40ca7d7b3a9 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -121,7 +121,7 @@ config AXP_PMIC_BUS
config SUNXI_SRAM_ADDRESS
hex
default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
- default 0x20000 if SUN50I_GEN_H6
+ default 0x20000 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
default 0x0
---help---
Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
@@ -183,6 +183,14 @@ config SUN50I_GEN_H6
Select this for sunxi SoCs which have H6 like peripherals, clocks
and memory map.
+config SUNXI_GEN_NCAT2
+ bool
+ select MMC_SUNXI_HAS_NEW_MODE
+ select SUPPORT_SPL
+ ---help---
+ Select this for sunxi SoCs which have D1 like peripherals, clocks
+ and memory map.
+
config SUNXI_DRAM_DW
bool
---help---
@@ -338,6 +346,19 @@ config MACH_SUN8I_R40
select SUNXI_DRAM_DW_32BIT
imply SPL_SYS_I2C_LEGACY
+config MACH_SUN8I_R528
+ bool "sun8i (Allwinner R528)"
+ select CPU_V7A
+ select CPU_V7_HAS_NONSEC
+ select CPU_V7_HAS_VIRT
+ select ARCH_SUPPORT_PSCI
+ select SPL_ARMV7_SET_CORTEX_SMPEN
+ select SUNXI_GEN_NCAT2
+ select SUNXI_NEW_PINCTRL
+ select MMC_SUNXI_HAS_NEW_MODE
+ select SUPPORT_SPL
+ select DRAM_SUN20I_D1
+
config MACH_SUN8I_V3S
bool "sun8i (Allwinner V3/V3s/S3/S3L)"
select CPU_V7A
@@ -648,6 +669,7 @@ config SYS_CLK_FREQ
default 1008000000 if MACH_SUN9I
default 888000000 if MACH_SUN50I_H6
default 1008000000 if MACH_SUN50I_H616
+ default 1008000000 if MACH_SUN8I_R528
config SYS_CONFIG_NAME
default "suniv" if MACH_SUNIV
@@ -656,6 +678,7 @@ config SYS_CONFIG_NAME
default "sun6i" if MACH_SUN6I
default "sun7i" if MACH_SUN7I
default "sun8i" if MACH_SUN8I
+ default "sun8i" if MACH_SUN8I_R528
default "sun9i" if MACH_SUN9I
default "sun50i" if MACH_SUN50I
default "sun50i" if MACH_SUN50I_H6
@@ -695,13 +718,6 @@ config OLD_SUNXI_KERNEL_COMPAT
Set this to enable various workarounds for old kernels, this results in
sub-optimal settings for newer kernels, only enable if needed.
-config MACPWR
- string "MAC power pin"
- default ""
- help
- 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 MMC1_PINS_PH
bool "Pins for mmc1 are on Port H"
depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40
@@ -811,6 +827,7 @@ config VIDEO_SUNXI
depends on !MACH_SUN9I
depends on !MACH_SUN50I
depends on !SUN50I_GEN_H6
+ depends on !SUNXI_GEN_NCAT2
select VIDEO
select DISPLAY
imply VIDEO_DT_SIMPLEFB
@@ -1008,14 +1025,6 @@ config VIDEO_LCD_TL059WV5C0
endchoice
-config SATAPWR
- string "SATA power pin"
- default ""
- help
- Set the pins used to power the SATA. This takes a string in the
- format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of
- port H.
-
config GMAC_TX_DELAY
int "GMAC Transmit Clock Delay Chain"
default 0
@@ -1032,6 +1041,7 @@ config SPL_STACK_R_ADDR
default 0x2fe00000 if MACH_SUN9I
default 0x4fe00000 if MACH_SUN50I
default 0x4fe00000 if SUN50I_GEN_H6
+ default 0x4fe00000 if SUNXI_GEN_NCAT2
config SPL_SPI_SUNXI
bool "Support for SPI Flash on Allwinner SoCs in SPL"
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 58f807cb82d..1d4c70ec352 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -10,7 +10,6 @@ obj-y += board.o
obj-y += clock.o
obj-y += cpu_info.o
obj-y += dram_helpers.o
-obj-y += pinmux.o
obj-$(CONFIG_SUN6I_PRCM) += prcm.o
obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o
obj-$(CONFIG_MACH_SUNIV) += clock_sun6i.o
@@ -26,6 +25,7 @@ obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o
endif
obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o gtbus_sun9i.o
obj-$(CONFIG_SUN50I_GEN_H6) += clock_sun50i_h6.o
+obj-$(CONFIG_SUNXI_GEN_NCAT2) += clock_sun50i_h6.o
ifndef CONFIG_ARM64
obj-y += timer.o
endif
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 61a4245c499..11a49418225 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -17,6 +17,7 @@
#include <i2c.h>
#include <serial.h>
#include <spl.h>
+#include <sunxi_gpio.h>
#include <asm/cache.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -146,6 +147,10 @@ static int gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPH(12), SUN9I_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(13), SUN9I_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(13), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_R528)
+ sunxi_gpio_set_cfgpin(SUNXI_GPE(2), 6);
+ sunxi_gpio_set_cfgpin(SUNXI_GPE(3), 6);
+ sunxi_gpio_set_pull(SUNXI_GPE(3), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUNIV)
sunxi_gpio_set_cfgpin(SUNXI_GPA(2), SUNIV_GPE_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPA(3), SUNIV_GPE_UART0);
@@ -162,6 +167,10 @@ static int gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_GPB_UART2);
sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 4 && defined(CONFIG_MACH_SUN8I_R528)
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(6), 7);
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(7), 7);
+ sunxi_gpio_set_pull(SUNXI_GPB(7), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
@@ -175,13 +184,19 @@ static int gpio_init(void)
#error Unsupported console port number. Please fix pin mux settings in board.c
#endif
-#ifdef CONFIG_SUN50I_GEN_H6
- /* Update PIO power bias configuration by copy hardware detected value */
- val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
- writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
- val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
- writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
-#endif
+ /*
+ * Update PIO power bias configuration by copying the hardware
+ * detected value.
+ */
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+ IS_ENABLED(CONFIG_SUN50I_GEN_NCAT2)) {
+ val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+ writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+ }
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6)) {
+ val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+ writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+ }
return 0;
}
@@ -480,7 +495,7 @@ void reset_cpu(void)
/* sun5i sometimes gets stuck without this */
writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
}
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
#if defined(CONFIG_MACH_SUN50I_H6)
/* WDOG is broken for some H6 rev. use the R_WDOG instead */
static const struct sunxi_wdog *wdog =
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index 7926394cf76..bea91c78bc5 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -18,8 +18,11 @@ void clock_init_safe(void)
setbits_le32(&prcm->res_cal_ctrl, 2);
}
- clrbits_le32(&prcm->res_cal_ctrl, 1);
- setbits_le32(&prcm->res_cal_ctrl, 1);
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
+ IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
+ clrbits_le32(&prcm->res_cal_ctrl, 1);
+ setbits_le32(&prcm->res_cal_ctrl, 1);
+ }
if (IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
/* set key field for ldo enable */
@@ -38,7 +41,9 @@ void clock_init_safe(void)
CCM_CPU_AXI_DEFAULT_FACTORS);
writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
+#ifdef CCM_AHB3_DEFAULT
writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
+#endif
writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
/*
@@ -86,11 +91,13 @@ void clock_set_pll1(unsigned int clk)
writel(val, &ccm->cpu_axi_cfg);
/* clk = 24*n/p, p is ignored if clock is >288MHz */
- writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
-#ifdef CONFIG_MACH_SUN50I_H616
- CCM_PLL1_OUT_EN |
-#endif
- CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
+ val = CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2;
+ val |= CCM_PLL1_CTRL_N(clk / 24000000);
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
+ val |= CCM_PLL1_OUT_EN;
+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+ val |= CCM_PLL1_OUT_EN | CCM_PLL1_LDO_EN;
+ writel(val, &ccm->pll1_cfg);
while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
/* Switch CPU to PLL1 */
@@ -105,16 +112,26 @@ unsigned int clock_get_pll6(void)
{
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- int m = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ? 4 : 2;
-
uint32_t rval = readl(&ccm->pll6_cfg);
int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
- int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
- CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
- CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
- /* The register defines PLL6-2X or PLL6-4X, not plain PLL6 */
- return 24000000 / m * n / div1 / div2;
+ CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
+ int div1, m;
+
+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
+ div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
+ CCM_PLL6_CTRL_P0_SHIFT) + 1;
+ m = 1;
+ } else {
+ div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
+ CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+ m = 4;
+ else
+ m = 2;
+ }
+
+ return 24000000U * n / m / div1 / div2;
}
int clock_twi_onoff(int port, int state)
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index 7eef178859b..7fecc3b88dd 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -93,6 +93,8 @@ int print_cpuinfo(void)
printf("CPU: Allwinner R40 (SUN8I %04x)\n", sunxi_get_sram_id());
#elif defined CONFIG_MACH_SUN8I_V3S
printf("CPU: Allwinner V3s (SUN8I %04x)\n", sunxi_get_sram_id());
+#elif defined CONFIG_MACH_SUN8I_R528
+ puts("CPU: Allwinner R528 (SUN8I)\n");
#elif defined CONFIG_MACH_SUN9I
puts("CPU: Allwinner A80 (SUN9I)\n");
#elif defined CONFIG_MACH_SUN50I
diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c
index 3aa3ce76272..9e583e18553 100644
--- a/arch/arm/mach-sunxi/dram_suniv.c
+++ b/arch/arm/mach-sunxi/dram_suniv.c
@@ -13,10 +13,10 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/dram.h>
-#include <asm/arch/gpio.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <hang.h>
+#include <sunxi_gpio.h>
#define SDR_T_CAS (0x2)
#define SDR_T_RAS (0x8)
diff --git a/arch/arm/mach-sunxi/gtbus_sun9i.c b/arch/arm/mach-sunxi/gtbus_sun9i.c
index cf011c4cfa7..5624621b500 100644
--- a/arch/arm/mach-sunxi/gtbus_sun9i.c
+++ b/arch/arm/mach-sunxi/gtbus_sun9i.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <asm/io.h>
+#include <asm/arch/cpu.h>
#include <asm/arch/gtbus_sun9i.h>
#include <asm/arch/sys_proto.h>
diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
deleted file mode 100644
index c95fcee9f6c..00000000000
--- a/arch/arm/mach-sunxi/pinmux.c
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2007-2011
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Tom Cubie <tangliang@allwinnertech.com>
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/gpio.h>
-
-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-{
- u32 index = GPIO_CFG_INDEX(bank_offset);
- u32 offset = GPIO_CFG_OFFSET(bank_offset);
-
- clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
-}
-
-void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- sunxi_gpio_set_cfgbank(pio, pin, val);
-}
-
-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
-{
- u32 index = GPIO_CFG_INDEX(bank_offset);
- u32 offset = GPIO_CFG_OFFSET(bank_offset);
- u32 cfg;
-
- cfg = readl(&pio->cfg[index]);
- cfg >>= offset;
-
- return cfg & 0xf;
-}
-
-int sunxi_gpio_get_cfgpin(u32 pin)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- return sunxi_gpio_get_cfgbank(pio, pin);
-}
-
-void sunxi_gpio_set_drv(u32 pin, u32 val)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- sunxi_gpio_set_drv_bank(pio, pin, val);
-}
-
-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
-{
- u32 index = GPIO_DRV_INDEX(bank_offset);
- u32 offset = GPIO_DRV_OFFSET(bank_offset);
-
- clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
-}
-
-void sunxi_gpio_set_pull(u32 pin, u32 val)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- sunxi_gpio_set_pull_bank(pio, pin, val);
-}
-
-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-{
- u32 index = GPIO_PULL_INDEX(bank_offset);
- u32 offset = GPIO_PULL_OFFSET(bank_offset);
-
- clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
-}
diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
index 81159cfee61..c2410dd7bb1 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -13,6 +13,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/libfdt.h>
+#include <sunxi_gpio.h>
#ifdef CONFIG_SPL_OS_BOOT
#error CONFIG_SPL_OS_BOOT is not supported yet
diff --git a/arch/arm/mach-sunxi/timer.c b/arch/arm/mach-sunxi/timer.c
index fc9d419a25e..9a6f6c06d8c 100644
--- a/arch/arm/mach-sunxi/timer.c
+++ b/arch/arm/mach-sunxi/timer.c
@@ -10,6 +10,7 @@
#include <time.h>
#include <asm/global_data.h>
#include <asm/io.h>
+#include <asm/arch/cpu.h>
#include <asm/arch/timer.h>
#include <linux/delay.h>
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 183885ebe7d..e291456530b 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -187,6 +187,97 @@ config RISCV_ISA_D
riscv32 ABI from ilp32 to ilp32d and the riscv64 ABI from lp64 to
lp64d.
+config RISCV_ISA_ZBB
+ bool "Zbb extension support for bit manipulation instructions"
+ help
+ Adds ZBB extension (basic bit manipulation) to the ISA subsets
+ that the toolchain is allowed to emit when building U-Boot.
+ The Zbb extension provides instructions to accelerate a number
+ of bit-specific operations (count bit population, sign extending,
+ bitrotation, etc) and enables optimized string routines.
+
+menu "Use assembly optimized implementation of string routines"
+
+config USE_ARCH_STRLEN
+ bool "Use an assembly optimized implementation of strlen"
+ default y
+ depends on RISCV_ISA_ZBB
+ help
+ Enable the generation of an optimized version of strlen using
+ Zbb extension.
+
+config SPL_USE_ARCH_STRLEN
+ bool "Use an assembly optimized implementation of strlen for SPL"
+ default y if USE_ARCH_STRLEN
+ depends on RISCV_ISA_ZBB
+ depends on SPL
+ help
+ Enable the generation of an optimized version of strlen using
+ Zbb extension.
+
+config TPL_USE_ARCH_STRLEN
+ bool "Use an assembly optimized implementation of strlen for TPL"
+ default y if USE_ARCH_STRLEN
+ depends on RISCV_ISA_ZBB
+ depends on TPL
+ help
+ Enable the generation of an optimized version of strlen using
+ Zbb extension.
+
+config USE_ARCH_STRCMP
+ bool "Use an assembly optimized implementation of strcmp"
+ default y
+ depends on RISCV_ISA_ZBB
+ help
+ Enable the generation of an optimized version of strcmp using
+ Zbb extension.
+
+config SPL_USE_ARCH_STRCMP
+ bool "Use an assembly optimized implementation of strcmp for SPL"
+ default y if USE_ARCH_STRCMP
+ depends on RISCV_ISA_ZBB
+ depends on SPL
+ help
+ Enable the generation of an optimized version of strcmp using
+ Zbb extension.
+
+config TPL_USE_ARCH_STRCMP
+ bool "Use an assembly optimized implementation of strcmp for TPL"
+ default y if USE_ARCH_STRCMP
+ depends on RISCV_ISA_ZBB
+ depends on TPL
+ help
+ Enable the generation of an optimized version of strcmp using
+ Zbb extension.
+
+config USE_ARCH_STRNCMP
+ bool "Use an assembly optimized implementation of strncmp"
+ default y
+ depends on RISCV_ISA_ZBB
+ help
+ Enable the generation of an optimized version of strncmp using
+ Zbb extension.
+
+config SPL_USE_ARCH_STRNCMP
+ bool "Use an assembly optimized implementation of strncmp for SPL"
+ default y if USE_ARCH_STRNCMP
+ depends on RISCV_ISA_ZBB
+ depends on SPL
+ help
+ Enable the generation of an optimized version of strncmp using
+ Zbb extension.
+
+config TPL_USE_ARCH_STRNCMP
+ bool "Use an assembly optimized implementation of strncmp for TPL"
+ default y if USE_ARCH_STRNCMP
+ depends on RISCV_ISA_ZBB
+ depends on TPL
+ help
+ Enable the generation of an optimized version of strncmp using
+ Zbb extension.
+
+endmenu
+
config RISCV_ISA_A
def_bool y
@@ -424,4 +515,12 @@ config TPL_USE_ARCH_MEMSET
endmenu
+config SPL_LOAD_FIT_OPENSBI_OS_BOOT
+ bool "Enable SPL (OpenSBI OS boot mode) applying linux from FIT"
+ depends on SPL_LOAD_FIT
+ help
+ Use fw_dynamic from the FIT image, and u-boot SPL will invoke it directly.
+ This is a shortcut boot flow, from u-boot SPL -> OpenSBI -> u-boot proper
+ -> linux to u-boot SPL -> OpenSBI -> linux.
+
endmenu
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 4963b5109b2..b3ef87078b5 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -24,6 +24,9 @@ endif
ifeq ($(CONFIG_RISCV_ISA_C),y)
ARCH_C = c
endif
+ifeq ($(CONFIG_RISCV_ISA_ZBB),y)
+ ARCH_ZBB = _zbb
+endif
ifeq ($(CONFIG_CMODEL_MEDLOW),y)
CMODEL = medlow
endif
@@ -32,7 +35,7 @@ ifeq ($(CONFIG_CMODEL_MEDANY),y)
endif
-RISCV_MARCH = $(ARCH_BASE)$(ARCH_A)$(ARCH_F)$(ARCH_D)$(ARCH_C)
+RISCV_MARCH = $(ARCH_BASE)$(ARCH_A)$(ARCH_F)$(ARCH_D)$(ARCH_C)$(ARCH_ZBB)
ABI = $(ABI_BASE)$(ABI_D)
# Newer binutils versions default to ISA spec version 20191213 which moves some
diff --git a/arch/riscv/cpu/generic/dram.c b/arch/riscv/cpu/generic/dram.c
index 94d8018407e..1b51bae9b66 100644
--- a/arch/riscv/cpu/generic/dram.c
+++ b/arch/riscv/cpu/generic/dram.c
@@ -20,19 +20,3 @@ int dram_init_banksize(void)
{
return fdtdec_setup_memory_banksize();
}
-
-phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
-{
- /*
- * Ensure that we run from first 4GB so that all
- * addresses used by U-Boot are 32bit addresses.
- *
- * This in-turn ensures that 32bit DMA capable
- * devices work fine because DMA mapping APIs will
- * provide 32bit DMA addresses only.
- */
- if (gd->ram_top >= SZ_4G)
- return SZ_4G - 1;
-
- return gd->ram_top;
-}
diff --git a/arch/riscv/dts/binman.dtsi b/arch/riscv/dts/binman.dtsi
index 156cb00971e..6b4eb8dc7b9 100644
--- a/arch/riscv/dts/binman.dtsi
+++ b/arch/riscv/dts/binman.dtsi
@@ -5,6 +5,9 @@
#include <config.h>
+#define U64_TO_U32_H(addr) (((addr) >> 32) & 0xffffffff)
+#define U64_TO_U32_L(addr) ((addr) & 0xffffffff)
+
/ {
binman: binman {
multiple-images;
@@ -13,26 +16,47 @@
&binman {
itb {
+
+#ifndef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT
filename = "u-boot.itb";
+#else
+ filename = "linux.itb";
+#endif
fit {
description = "Configuration to load OpenSBI before U-Boot";
- #address-cells = <1>;
+ #address-cells = <2>;
fit,fdt-list = "of-list";
images {
+#ifndef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT
uboot {
description = "U-Boot";
type = "standalone";
os = "U-Boot";
arch = "riscv";
compression = "none";
- load = <CONFIG_TEXT_BASE>;
+ load = <U64_TO_U32_H(CONFIG_TEXT_BASE)
+ U64_TO_U32_L(CONFIG_TEXT_BASE)>;
uboot_blob: blob-ext {
filename = "u-boot-nodtb.bin";
};
};
+#else
+ linux {
+ description = "Linux";
+ type = "standalone";
+ os = "Linux";
+ arch = "riscv";
+ compression = "none";
+ load = <CONFIG_TEXT_BASE>;
+
+ linux_blob: blob-ext {
+ filename = "Image";
+ };
+ };
+#endif
opensbi {
description = "OpenSBI fw_dynamic Firmware";
@@ -40,8 +64,10 @@
os = "opensbi";
arch = "riscv";
compression = "none";
- load = <CONFIG_SPL_OPENSBI_LOAD_ADDR>;
- entry = <CONFIG_SPL_OPENSBI_LOAD_ADDR>;
+ load = <U64_TO_U32_H(CONFIG_SPL_OPENSBI_LOAD_ADDR)
+ U64_TO_U32_L(CONFIG_SPL_OPENSBI_LOAD_ADDR)>;
+ entry = <U64_TO_U32_H(CONFIG_SPL_OPENSBI_LOAD_ADDR)
+ U64_TO_U32_L(CONFIG_SPL_OPENSBI_LOAD_ADDR)>;
opensbi_blob: opensbi {
filename = "fw_dynamic.bin";
@@ -68,7 +94,11 @@
#endif
description = "NAME";
firmware = "opensbi";
+#ifndef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT
loadables = "uboot";
+#else
+ loadables = "linux";
+#endif
#ifndef CONFIG_OF_BOARD
fdt = "fdt-SEQ";
#endif
diff --git a/arch/riscv/dts/sunxi-d1-t113.dtsi b/arch/riscv/dts/sunxi-d1-t113.dtsi
new file mode 100644
index 00000000000..b7156123df5
--- /dev/null
+++ b/arch/riscv/dts/sunxi-d1-t113.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+/ {
+ soc {
+ dsp_wdt: watchdog@1700400 {
+ compatible = "allwinner,sun20i-d1-wdt";
+ reg = <0x1700400 0x20>;
+ interrupts = <SOC_PERIPHERAL_IRQ(122) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ status = "reserved";
+ };
+ };
+};
diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
new file mode 100644
index 00000000000..822f022eec2
--- /dev/null
+++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
@@ -0,0 +1,927 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
+#include <dt-bindings/clock/sun20i-d1-ccu.h>
+#include <dt-bindings/clock/sun20i-d1-r-ccu.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+#include <dt-bindings/reset/sun20i-d1-ccu.h>
+#include <dt-bindings/reset/sun20i-d1-r-ccu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ dcxo: dcxo-clk {
+ compatible = "fixed-clock";
+ clock-output-names = "dcxo";
+ #clock-cells = <0>;
+ };
+
+ de: display-engine {
+ compatible = "allwinner,sun20i-d1-display-engine";
+ allwinner,pipelines = <&mixer0>, <&mixer1>;
+ status = "disabled";
+ };
+
+ soc {
+ compatible = "simple-bus";
+ ranges;
+ dma-noncoherent;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pio: pinctrl@2000000 {
+ compatible = "allwinner,sun20i-d1-pinctrl";
+ reg = <0x2000000 0x800>;
+ interrupts = <SOC_PERIPHERAL_IRQ(69) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(71) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(73) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(75) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(77) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(79) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_APB0>,
+ <&dcxo>,
+ <&rtc CLK_OSC32K>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ interrupt-controller;
+ #gpio-cells = <3>;
+ #interrupt-cells = <3>;
+
+ /omit-if-no-ref/
+ can0_pins: can0-pins {
+ pins = "PB2", "PB3";
+ function = "can0";
+ };
+
+ /omit-if-no-ref/
+ can1_pins: can1-pins {
+ pins = "PB4", "PB5";
+ function = "can1";
+ };
+
+ /omit-if-no-ref/
+ clk_pg11_pin: clk-pg11-pin {
+ pins = "PG11";
+ function = "clk";
+ };
+
+ /omit-if-no-ref/
+ dsi_4lane_pins: dsi-4lane-pins {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+ "PD6", "PD7", "PD8", "PD9";
+ drive-strength = <30>;
+ function = "dsi";
+ };
+
+ /omit-if-no-ref/
+ lcd_rgb666_pins: lcd-rgb666-pins {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+ "PD6", "PD7", "PD8", "PD9", "PD10", "PD11",
+ "PD12", "PD13", "PD14", "PD15", "PD16", "PD17",
+ "PD18", "PD19", "PD20", "PD21";
+ function = "lcd0";
+ };
+
+ /omit-if-no-ref/
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
+ function = "mmc0";
+ };
+
+ /omit-if-no-ref/
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5";
+ function = "mmc1";
+ };
+
+ /omit-if-no-ref/
+ mmc2_pins: mmc2-pins {
+ pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7";
+ function = "mmc2";
+ };
+
+ /omit-if-no-ref/
+ rgmii_pe_pins: rgmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9",
+ "PE11", "PE12", "PE13", "PE14", "PE15";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ rmii_pe_pins: rmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ spi0_pins: spi0-pins {
+ pins = "PC2", "PC3", "PC4", "PC5";
+ function = "spi0";
+ };
+
+ /omit-if-no-ref/
+ uart1_pg6_pins: uart1-pg6-pins {
+ pins = "PG6", "PG7";
+ function = "uart1";
+ };
+
+ /omit-if-no-ref/
+ uart1_pg8_rts_cts_pins: uart1-pg8-rts-cts-pins {
+ pins = "PG8", "PG9";
+ function = "uart1";
+ };
+
+ /omit-if-no-ref/
+ uart3_pb_pins: uart3-pb-pins {
+ pins = "PB6", "PB7";
+ function = "uart3";
+ };
+ };
+
+ ccu: clock-controller@2001000 {
+ compatible = "allwinner,sun20i-d1-ccu";
+ reg = <0x2001000 0x1000>;
+ clocks = <&dcxo>,
+ <&rtc CLK_OSC32K>,
+ <&rtc CLK_IOSC>;
+ clock-names = "hosc", "losc", "iosc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ gpadc: adc@2009000 {
+ compatible = "allwinner,sun20i-d1-gpadc";
+ reg = <0x2009000 0x400>;
+ clocks = <&ccu CLK_BUS_GPADC>;
+ resets = <&ccu RST_BUS_GPADC>;
+ interrupts = <SOC_PERIPHERAL_IRQ(57) IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ #io-channel-cells = <1>;
+ };
+
+ dmic: dmic@2031000 {
+ compatible = "allwinner,sun20i-d1-dmic",
+ "allwinner,sun50i-h6-dmic";
+ reg = <0x2031000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(24) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMIC>,
+ <&ccu CLK_DMIC>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_DMIC>;
+ dmas = <&dma 8>;
+ dma-names = "rx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ i2s1: i2s@2033000 {
+ compatible = "allwinner,sun20i-d1-i2s",
+ "allwinner,sun50i-r329-i2s";
+ reg = <0x2033000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(27) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S1>,
+ <&ccu CLK_I2S1>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S1>;
+ dmas = <&dma 4>, <&dma 4>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ i2s2: i2s@2034000 {
+ compatible = "allwinner,sun20i-d1-i2s",
+ "allwinner,sun50i-r329-i2s";
+ reg = <0x2034000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(28) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S2>,
+ <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S2>;
+ dmas = <&dma 5>, <&dma 5>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ timer: timer@2050000 {
+ compatible = "allwinner,sun20i-d1-timer",
+ "allwinner,sun8i-a23-timer";
+ reg = <0x2050000 0xa0>;
+ interrupts = <SOC_PERIPHERAL_IRQ(59) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(60) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo>;
+ };
+
+ wdt: watchdog@20500a0 {
+ compatible = "allwinner,sun20i-d1-wdt-reset",
+ "allwinner,sun20i-d1-wdt";
+ reg = <0x20500a0 0x20>;
+ interrupts = <SOC_PERIPHERAL_IRQ(63) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ status = "reserved";
+ };
+
+ uart0: serial@2500000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500000 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(2) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART0>;
+ resets = <&ccu RST_BUS_UART0>;
+ dmas = <&dma 14>, <&dma 14>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart1: serial@2500400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500400 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(3) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART1>;
+ resets = <&ccu RST_BUS_UART1>;
+ dmas = <&dma 15>, <&dma 15>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart2: serial@2500800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500800 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(4) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART2>;
+ resets = <&ccu RST_BUS_UART2>;
+ dmas = <&dma 16>, <&dma 16>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart3: serial@2500c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500c00 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(5) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART3>;
+ resets = <&ccu RST_BUS_UART3>;
+ dmas = <&dma 17>, <&dma 17>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart4: serial@2501000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2501000 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(6) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART4>;
+ resets = <&ccu RST_BUS_UART4>;
+ dmas = <&dma 18>, <&dma 18>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart5: serial@2501400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2501400 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(7) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART5>;
+ resets = <&ccu RST_BUS_UART5>;
+ dmas = <&dma 19>, <&dma 19>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c0: i2c@2502000 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(9) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ dmas = <&dma 43>, <&dma 43>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@2502400 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502400 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ dmas = <&dma 44>, <&dma 44>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@2502800 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502800 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(11) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ dmas = <&dma 45>, <&dma 45>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c@2502c00 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502c00 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(12) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C3>;
+ resets = <&ccu RST_BUS_I2C3>;
+ dmas = <&dma 46>, <&dma 46>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ can0: can@2504000 {
+ compatible = "allwinner,sun20i-d1-can";
+ reg = <0x02504000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(21) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CAN0>;
+ resets = <&ccu RST_BUS_CAN0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&can0_pins>;
+ status = "disabled";
+ };
+
+ can1: can@2504400 {
+ compatible = "allwinner,sun20i-d1-can";
+ reg = <0x02504400 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(22) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CAN1>;
+ resets = <&ccu RST_BUS_CAN1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&can1_pins>;
+ status = "disabled";
+ };
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun20i-d1-system-control";
+ reg = <0x3000000 0x1000>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ dma: dma-controller@3002000 {
+ compatible = "allwinner,sun20i-d1-dma";
+ reg = <0x3002000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(50) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+ clock-names = "bus", "mbus";
+ resets = <&ccu RST_BUS_DMA>;
+ dma-channels = <16>;
+ dma-requests = <48>;
+ #dma-cells = <1>;
+ };
+
+ sid: efuse@3006000 {
+ compatible = "allwinner,sun20i-d1-sid";
+ reg = <0x3006000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ crypto: crypto@3040000 {
+ compatible = "allwinner,sun20i-d1-crypto";
+ reg = <0x3040000 0x800>;
+ interrupts = <SOC_PERIPHERAL_IRQ(52) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CE>,
+ <&ccu CLK_CE>,
+ <&ccu CLK_MBUS_CE>,
+ <&rtc CLK_IOSC>;
+ clock-names = "bus", "mod", "ram", "trng";
+ resets = <&ccu RST_BUS_CE>;
+ };
+
+ mbus: dram-controller@3102000 {
+ compatible = "allwinner,sun20i-d1-mbus";
+ reg = <0x3102000 0x1000>,
+ <0x3103000 0x1000>;
+ reg-names = "mbus", "dram";
+ interrupts = <SOC_PERIPHERAL_IRQ(43) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_MBUS>,
+ <&ccu CLK_DRAM>,
+ <&ccu CLK_BUS_DRAM>;
+ clock-names = "mbus", "dram", "bus";
+ dma-ranges = <0 0x40000000 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interconnect-cells = <1>;
+ };
+
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4020000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(40) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ cap-sd-highspeed;
+ max-frequency = <150000000>;
+ no-mmc;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4021000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(41) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ cap-sd-highspeed;
+ max-frequency = <150000000>;
+ no-mmc;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun20i-d1-emmc",
+ "allwinner,sun50i-a100-emmc";
+ reg = <0x4022000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(42) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ cap-mmc-highspeed;
+ max-frequency = <150000000>;
+ mmc-ddr-1_8v;
+ mmc-ddr-3_3v;
+ no-sd;
+ no-sdio;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi0: spi@4025000 {
+ compatible = "allwinner,sun20i-d1-spi",
+ "allwinner,sun50i-r329-spi";
+ reg = <0x04025000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(15) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 22>, <&dma 22>;
+ dma-names = "rx", "tx";
+ resets = <&ccu RST_BUS_SPI0>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@4026000 {
+ compatible = "allwinner,sun20i-d1-spi-dbi",
+ "allwinner,sun50i-r329-spi-dbi",
+ "allwinner,sun50i-r329-spi";
+ reg = <0x04026000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(16) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 23>, <&dma 23>;
+ dma-names = "rx", "tx";
+ resets = <&ccu RST_BUS_SPI1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ usb_otg: usb@4100000 {
+ compatible = "allwinner,sun20i-d1-musb",
+ "allwinner,sun8i-a33-musb";
+ reg = <0x4100000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(29) IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ extcon = <&usbphy 0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ usbphy: phy@4100400 {
+ compatible = "allwinner,sun20i-d1-usb-phy";
+ reg = <0x4100400 0x100>,
+ <0x4101800 0x100>,
+ <0x4200800 0x100>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1";
+ clocks = <&dcxo>,
+ <&dcxo>;
+ clock-names = "usb0_phy",
+ "usb1_phy";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>;
+ reset-names = "usb0_reset",
+ "usb1_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@4101000 {
+ compatible = "allwinner,sun20i-d1-ehci",
+ "generic-ehci";
+ reg = <0x4101000 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(30) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_BUS_EHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>,
+ <&ccu RST_BUS_EHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@4101400 {
+ compatible = "allwinner,sun20i-d1-ohci",
+ "generic-ohci";
+ reg = <0x4101400 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(31) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci1: usb@4200000 {
+ compatible = "allwinner,sun20i-d1-ehci",
+ "generic-ehci";
+ reg = <0x4200000 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(33) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_BUS_EHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>,
+ <&ccu RST_BUS_EHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@4200400 {
+ compatible = "allwinner,sun20i-d1-ohci",
+ "generic-ohci";
+ reg = <0x4200400 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(34) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ emac: ethernet@4500000 {
+ compatible = "allwinner,sun20i-d1-emac",
+ "allwinner,sun50i-a64-emac";
+ reg = <0x4500000 0x10000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(46) IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ syscon = <&syscon>;
+ status = "disabled";
+
+ mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ display_clocks: clock-controller@5000000 {
+ compatible = "allwinner,sun20i-d1-de2-clk",
+ "allwinner,sun50i-h5-de2-clk";
+ reg = <0x5000000 0x10000>;
+ clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ mixer0: mixer@5100000 {
+ compatible = "allwinner,sun20i-d1-de2-mixer-0";
+ reg = <0x5100000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER0>,
+ <&display_clocks CLK_MIXER0>;
+ clock-names = "bus", "mod";
+ resets = <&display_clocks RST_MIXER0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port@1 {
+ reg = <1>;
+
+ mixer0_out_tcon_top_mixer0: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+ };
+ };
+ };
+ };
+
+ mixer1: mixer@5200000 {
+ compatible = "allwinner,sun20i-d1-de2-mixer-1";
+ reg = <0x5200000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER1>,
+ <&display_clocks CLK_MIXER1>;
+ clock-names = "bus", "mod";
+ resets = <&display_clocks RST_MIXER1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer1_out: port@1 {
+ reg = <1>;
+
+ mixer1_out_tcon_top_mixer1: endpoint {
+ remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
+ };
+ };
+ };
+ };
+
+ dsi: dsi@5450000 {
+ compatible = "allwinner,sun20i-d1-mipi-dsi",
+ "allwinner,sun50i-a100-mipi-dsi";
+ reg = <0x5450000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&tcon_top CLK_TCON_TOP_DSI>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ phys = <&dphy>;
+ phy-names = "dphy";
+ status = "disabled";
+
+ port {
+ dsi_in_tcon_lcd0: endpoint {
+ remote-endpoint = <&tcon_lcd0_out_dsi>;
+ };
+ };
+ };
+
+ dphy: phy@5451000 {
+ compatible = "allwinner,sun20i-d1-mipi-dphy",
+ "allwinner,sun50i-a100-mipi-dphy";
+ reg = <0x5451000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_MIPI_DSI>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ #phy-cells = <0>;
+ };
+
+ tcon_top: tcon-top@5460000 {
+ compatible = "allwinner,sun20i-d1-tcon-top";
+ reg = <0x5460000 0x1000>;
+ clocks = <&ccu CLK_BUS_DPSS_TOP>,
+ <&ccu CLK_TCON_TV>,
+ <&ccu CLK_TVE>,
+ <&ccu CLK_TCON_LCD0>;
+ clock-names = "bus", "tcon-tv0", "tve0", "dsi";
+ clock-output-names = "tcon-top-tv0", "tcon-top-dsi";
+ resets = <&ccu RST_BUS_DPSS_TOP>;
+ #clock-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_in: port@0 {
+ reg = <0>;
+
+ tcon_top_mixer0_in_mixer0: endpoint {
+ remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer0_out: port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer0>;
+ };
+
+ tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer1_in: port@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer1_in_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&mixer1_out_tcon_top_mixer1>;
+ };
+ };
+
+ tcon_top_mixer1_out: port@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer1>;
+ };
+
+ tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
+ };
+ };
+
+ tcon_top_hdmi_in: port@4 {
+ reg = <4>;
+
+ tcon_top_hdmi_in_tcon_tv0: endpoint {
+ remote-endpoint = <&tcon_tv0_out_tcon_top_hdmi>;
+ };
+ };
+
+ tcon_top_hdmi_out: port@5 {
+ reg = <5>;
+ };
+ };
+ };
+
+ tcon_lcd0: lcd-controller@5461000 {
+ compatible = "allwinner,sun20i-d1-tcon-lcd";
+ reg = <0x5461000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(90) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_LCD0>,
+ <&ccu CLK_TCON_LCD0>;
+ clock-names = "ahb", "tcon-ch0";
+ clock-output-names = "tcon-pixel-clock";
+ resets = <&ccu RST_BUS_TCON_LCD0>,
+ <&ccu RST_BUS_LVDS0>;
+ reset-names = "lcd", "lvds";
+ #clock-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_in: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_lcd0>;
+ };
+
+ tcon_lcd0_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_lcd0>;
+ };
+ };
+
+ tcon_lcd0_out: port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_tcon_lcd0>;
+ };
+ };
+ };
+ };
+
+ tcon_tv0: lcd-controller@5470000 {
+ compatible = "allwinner,sun20i-d1-tcon-tv";
+ reg = <0x5470000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(91) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_TV>,
+ <&tcon_top CLK_TCON_TOP_TV0>;
+ clock-names = "ahb", "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON_TV>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv0_in: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
+ };
+
+ tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
+ };
+ };
+
+ tcon_tv0_out: port@1 {
+ reg = <1>;
+
+ tcon_tv0_out_tcon_top_hdmi: endpoint {
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
+ };
+ };
+ };
+ };
+
+ ppu: power-controller@7001000 {
+ compatible = "allwinner,sun20i-d1-ppu";
+ reg = <0x7001000 0x1000>;
+ clocks = <&r_ccu CLK_BUS_R_PPU>;
+ resets = <&r_ccu RST_BUS_R_PPU>;
+ #power-domain-cells = <1>;
+ };
+
+ r_ccu: clock-controller@7010000 {
+ compatible = "allwinner,sun20i-d1-r-ccu";
+ reg = <0x7010000 0x400>;
+ clocks = <&dcxo>,
+ <&rtc CLK_OSC32K>,
+ <&rtc CLK_IOSC>,
+ <&ccu CLK_PLL_PERIPH0_DIV3>;
+ clock-names = "hosc", "losc", "iosc", "pll-periph";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ rtc: rtc@7090000 {
+ compatible = "allwinner,sun20i-d1-rtc",
+ "allwinner,sun50i-r329-rtc";
+ reg = <0x7090000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(144) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_BUS_R_RTC>,
+ <&dcxo>,
+ <&r_ccu CLK_R_AHB>;
+ clock-names = "bus", "hosc", "ahb";
+ #clock-cells = <1>;
+ };
+ };
+};
diff --git a/arch/riscv/include/asm/string.h b/arch/riscv/include/asm/string.h
index 7dee3e4c9f6..38ad85fe3bb 100644
--- a/arch/riscv/include/asm/string.h
+++ b/arch/riscv/include/asm/string.h
@@ -40,4 +40,22 @@ extern void *memmove(void *, const void *, __kernel_size_t);
#endif
extern void *memset(void *, int, __kernel_size_t);
+#undef __HAVE_ARCH_STRLEN
+#if CONFIG_IS_ENABLED(USE_ARCH_STRLEN)
+#define __HAVE_ARCH_STRLEN
+#endif
+extern __kernel_size_t strlen(const char *);
+
+#undef __HAVE_ARCH_STRCMP
+#if CONFIG_IS_ENABLED(USE_ARCH_STRCMP)
+#define __HAVE_ARCH_STRCMP
+#endif
+extern int strcmp(const char *, const char *);
+
+#undef __HAVE_ARCH_STRNCMP
+#if CONFIG_IS_ENABLED(USE_ARCH_STRNCMP)
+#define __HAVE_ARCH_STRNCMP
+#endif
+extern int strncmp(const char *, const char *, size_t __kernel_size_t);
+
#endif /* __ASM_RISCV_STRING_H */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 02c4d8fcc6c..9a05b662fd6 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -42,5 +42,8 @@ extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC)
obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o
obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMMOVE) += memmove.o
obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o
+obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_STRLEN) += strlen_zbb.o
+obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_STRCMP) += strcmp_zbb.o
+obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_STRNCMP) += strncmp_zbb.o
obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
diff --git a/arch/riscv/lib/andes_plicsw.c b/arch/riscv/lib/andes_plicsw.c
index 75184080890..6fd49e873b1 100644
--- a/arch/riscv/lib/andes_plicsw.c
+++ b/arch/riscv/lib/andes_plicsw.c
@@ -22,7 +22,7 @@
#include <linux/err.h>
/* pending register */
-#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + ((hart) / 4) * 4)
+#define PENDING_REG(base) ((ulong)(base) + 0x1000)
/* enable register */
#define ENABLE_REG(base, hart) ((ulong)(base) + 0x2000 + (hart) * 0x80)
/* claim register */
@@ -30,10 +30,11 @@
/* priority register */
#define PRIORITY_REG(base) ((ulong)(base) + PLICSW_PRIORITY_BASE)
-#define ENABLE_HART_IPI (0x01010101)
-#define SEND_IPI_TO_HART(hart) (0x1 << (hart))
+/* Bit 0 of PLIC-SW pending array is hardwired to zero, so we start from bit 1 */
+#define FIRST_AVAILABLE_BIT 0x2
+#define SEND_IPI_TO_HART(hart) (FIRST_AVAILABLE_BIT << (hart))
#define PLICSW_PRIORITY_BASE 0x4
-#define PLICSW_INTERRUPT_PER_HART 0x8
+#define PLICSW_INTERRUPT_PER_HART 0x1
DECLARE_GLOBAL_DATA_PTR;
@@ -41,9 +42,8 @@ static int enable_ipi(int hart)
{
unsigned int en;
- en = ENABLE_HART_IPI << hart;
+ en = FIRST_AVAILABLE_BIT << hart;
writel(en, (void __iomem *)ENABLE_REG(gd->arch.plicsw, hart));
- writel(en, (void __iomem *)ENABLE_REG(gd->arch.plicsw + 0x4, hart));
return 0;
}
@@ -75,7 +75,7 @@ int riscv_init_ipi(void)
ret = uclass_find_first_device(UCLASS_CPU, &dev);
if (ret)
return ret;
- else if (!dev)
+ if (!dev)
return -ENODEV;
ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
@@ -105,10 +105,9 @@ int riscv_init_ipi(void)
int riscv_send_ipi(int hart)
{
- unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
+ unsigned int ipi = SEND_IPI_TO_HART(hart);
- writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plicsw,
- gd->arch.boot_hart));
+ writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plicsw));
return 0;
}
@@ -125,10 +124,9 @@ int riscv_clear_ipi(int hart)
int riscv_get_ipi(int hart, int *pending)
{
- unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
+ unsigned int ipi = SEND_IPI_TO_HART(hart);
- *pending = readl((void __iomem *)PENDING_REG(gd->arch.plicsw,
- gd->arch.boot_hart));
+ *pending = readl((void __iomem *)PENDING_REG(gd->arch.plicsw));
*pending = !!(*pending & ipi);
return 0;
diff --git a/arch/riscv/lib/strcmp_zbb.S b/arch/riscv/lib/strcmp_zbb.S
new file mode 100644
index 00000000000..e5a367c0e5c
--- /dev/null
+++ b/arch/riscv/lib/strcmp_zbb.S
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Taken from Linux arch/riscv/lib/strcmp.S
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+ENTRY(__strcmp)
+WEAK(strcmp)
+.option push
+.option arch,+zbb
+ /*
+ * Returns
+ * a0 - comparison result, value like strcmp
+ *
+ * Parameters
+ * a0 - string1
+ * a1 - string2
+ *
+ * Clobbers
+ * t0, t1, t2, t3, t4
+ */
+
+ or t2, a0, a1
+ li t4, -1
+ and t2, t2, SZREG-1
+ bnez t2, 3f
+
+ /* Main loop for aligned string. */
+ .p2align 3
+1:
+ REG_L t0, 0(a0)
+ REG_L t1, 0(a1)
+ orc.b t3, t0
+ bne t3, t4, 2f
+ addi a0, a0, SZREG
+ addi a1, a1, SZREG
+ beq t0, t1, 1b
+
+ /*
+ * Words don't match, and no null byte in the first
+ * word. Get bytes in big-endian order and compare.
+ */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ rev8 t0, t0
+ rev8 t1, t1
+#endif
+
+ /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */
+ sltu a0, t0, t1
+ neg a0, a0
+ ori a0, a0, 1
+ ret
+
+2:
+ /*
+ * Found a null byte.
+ * If words don't match, fall back to simple loop.
+ */
+ bne t0, t1, 3f
+
+ /* Otherwise, strings are equal. */
+ li a0, 0
+ ret
+
+ /* Simple loop for misaligned strings. */
+ .p2align 3
+3:
+ lbu t0, 0(a0)
+ lbu t1, 0(a1)
+ addi a0, a0, 1
+ addi a1, a1, 1
+ bne t0, t1, 4f
+ bnez t0, 3b
+
+4:
+ sub a0, t0, t1
+ ret
+.option pop
+END(__strcmp)
diff --git a/arch/riscv/lib/strlen_zbb.S b/arch/riscv/lib/strlen_zbb.S
new file mode 100644
index 00000000000..bd8fa4c0bd0
--- /dev/null
+++ b/arch/riscv/lib/strlen_zbb.S
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Taken from Linux arch/riscv/lib/strlen.S
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define CZ ctz
+# define SHIFT srl
+#else
+# define CZ clz
+# define SHIFT sll
+#endif
+
+ENTRY(__strlen)
+WEAK(strlen)
+.option push
+.option arch,+zbb
+ /*
+ * Returns
+ * a0 - string length
+ *
+ * Parameters
+ * a0 - String to measure
+ *
+ * Clobbers
+ * t0, t1, t2, t3
+ */
+
+ /* Number of irrelevant bytes in the first word. */
+ andi t2, a0, SZREG-1
+
+ /* Align pointer. */
+ andi t0, a0, -SZREG
+
+ li t3, SZREG
+ sub t3, t3, t2
+ slli t2, t2, 3
+
+ /* Get the first word. */
+ REG_L t1, 0(t0)
+
+ /*
+ * Shift away the partial data we loaded to remove the irrelevant bytes
+ * preceding the string with the effect of adding NUL bytes at the
+ * end of the string's first word.
+ */
+ SHIFT t1, t1, t2
+
+ /* Convert non-NUL into 0xff and NUL into 0x00. */
+ orc.b t1, t1
+
+ /* Convert non-NUL into 0x00 and NUL into 0xff. */
+ not t1, t1
+
+ /*
+ * Search for the first set bit (corresponding to a NUL byte in the
+ * original chunk).
+ */
+ CZ t1, t1
+
+ /*
+ * The first chunk is special: compare against the number
+ * of valid bytes in this chunk.
+ */
+ srli a0, t1, 3
+ bgtu t3, a0, 2f
+
+ /* Prepare for the word comparison loop. */
+ addi t2, t0, SZREG
+ li t3, -1
+
+ /*
+ * Our critical loop is 4 instructions and processes data in
+ * 4 byte or 8 byte chunks.
+ */
+ .p2align 3
+1:
+ REG_L t1, SZREG(t0)
+ addi t0, t0, SZREG
+ orc.b t1, t1
+ beq t1, t3, 1b
+
+ not t1, t1
+ CZ t1, t1
+ srli t1, t1, 3
+
+ /* Get number of processed bytes. */
+ sub t2, t0, t2
+
+ /* Add number of characters in the first word. */
+ add a0, a0, t2
+
+ /* Add number of characters in the last word. */
+ add a0, a0, t1
+2:
+ ret
+.option pop
+END(__strlen)
diff --git a/arch/riscv/lib/strncmp_zbb.S b/arch/riscv/lib/strncmp_zbb.S
new file mode 100644
index 00000000000..00e0fec3a66
--- /dev/null
+++ b/arch/riscv/lib/strncmp_zbb.S
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Taken from Linux arch/riscv/lib/strncmp.S
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+ENTRY(__strncmp)
+WEAK(strncmp)
+.option push
+.option arch,+zbb
+ /*
+ * Returns
+ * a0 - comparison result, like strncmp
+ *
+ * Parameters
+ * a0 - string1
+ * a1 - string2
+ * a2 - number of characters to compare
+ *
+ * Clobbers
+ * t0, t1, t2, t3, t4, t5, t6
+ */
+
+ or t2, a0, a1
+ li t5, -1
+ and t2, t2, SZREG-1
+ add t4, a0, a2
+ bnez t2, 3f
+
+ /* Adjust limit for fast-path. */
+ andi t6, t4, -SZREG
+
+ /* Main loop for aligned string. */
+ .p2align 3
+1:
+ bge a0, t6, 3f
+ REG_L t0, 0(a0)
+ REG_L t1, 0(a1)
+ orc.b t3, t0
+ bne t3, t5, 2f
+ orc.b t3, t1
+ bne t3, t5, 2f
+ addi a0, a0, SZREG
+ addi a1, a1, SZREG
+ beq t0, t1, 1b
+
+ /*
+ * Words don't match, and no null byte in the first
+ * word. Get bytes in big-endian order and compare.
+ */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ rev8 t0, t0
+ rev8 t1, t1
+#endif
+
+ /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */
+ sltu a0, t0, t1
+ neg a0, a0
+ ori a0, a0, 1
+ ret
+
+2:
+ /*
+ * Found a null byte.
+ * If words don't match, fall back to simple loop.
+ */
+ bne t0, t1, 3f
+
+ /* Otherwise, strings are equal. */
+ li a0, 0
+ ret
+
+ /* Simple loop for misaligned strings. */
+ .p2align 3
+3:
+ bge a0, t4, 5f
+ lbu t0, 0(a0)
+ lbu t1, 0(a1)
+ addi a0, a0, 1
+ addi a1, a1, 1
+ bne t0, t1, 4f
+ bnez t0, 3b
+
+4:
+ sub a0, t0, t1
+ ret
+
+5:
+ li a0, 0
+ ret
+.option pop
+END(__strncmp)
diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
index 7590f1b80a6..16b76627983 100644
--- a/arch/sandbox/cpu/spl.c
+++ b/arch/sandbox/cpu/spl.c
@@ -129,6 +129,10 @@ void spl_board_init(void)
if (!CONFIG_IS_ENABLED(UNIT_TEST))
return;
+ /* These are necessary so TFTP can use LMBs to check its load address */
+ gd->bd->bi_dram[0].start = gd->ram_base;
+ gd->bd->bi_dram[0].size = get_effective_memsize();
+
if (state->run_unittests) {
struct unit_test *tests = UNIT_TEST_ALL_START();
const int count = UNIT_TEST_ALL_COUNT();
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 2c8a72590b5..2589c2eba73 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -13,6 +13,7 @@
#include <log.h>
#include <os.h>
#include <sort.h>
+#include <spl.h>
#include <asm/getopt.h>
#include <asm/global_data.h>
#include <asm/io.h>
@@ -202,10 +203,14 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state,
{
char buf[256];
char *fname;
+ char *relname;
int len;
- len = state_get_rel_filename("arch/sandbox/dts/test.dtb", buf,
- sizeof(buf));
+ if (spl_phase() <= PHASE_SPL)
+ relname = "../arch/sandbox/dts/test.dtb";
+ else
+ relname = "arch/sandbox/dts/test.dtb";
+ len = state_get_rel_filename(relname, buf, sizeof(buf));
if (len < 0)
return len;
diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds
index ef885fd0cb0..a81d66a6f2e 100644
--- a/arch/sandbox/cpu/u-boot-spl.lds
+++ b/arch/sandbox/cpu/u-boot-spl.lds
@@ -26,6 +26,8 @@ SECTIONS
KEEP(*(_u_boot_sandbox_getopt))
*(_u_boot_sandbox_getopt_end)
}
+
+ _image_binary_end = .;
}
INSERT AFTER .data;
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index e88c267620a..e4303473563 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -975,7 +975,7 @@
};
wdt-gpio-toggle {
- gpios = <&gpio_a 7 0>;
+ gpios = <&gpio_a 8 0>;
compatible = "linux,wdt-gpio";
hw_margin_ms = <100>;
hw_algo = "toggle";
diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h
index 2f8b5fcfcfe..f349ea19971 100644
--- a/arch/sandbox/include/asm/spl.h
+++ b/arch/sandbox/include/asm/spl.h
@@ -12,6 +12,9 @@ enum {
BOOT_DEVICE_MMC2_2,
BOOT_DEVICE_BOARD,
BOOT_DEVICE_VBE,
+ BOOT_DEVICE_CPGMAC,
+ BOOT_DEVICE_NOR,
+ BOOT_DEVICE_SPI,
};
/**
diff --git a/board/AndesTech/ae350/MAINTAINERS b/board/AndesTech/ae350/MAINTAINERS
index ead8e0e2afb..a6bc90baf88 100644
--- a/board/AndesTech/ae350/MAINTAINERS
+++ b/board/AndesTech/ae350/MAINTAINERS
@@ -4,10 +4,14 @@ S: Maintained
F: board/AndesTech/ae350/
F: include/configs/ae350.h
F: configs/ae350_rv32_defconfig
-F: configs/ae350_rv64_defconfig
-F: configs/ae350_rv32_xip_defconfig
-F: configs/ae350_rv64_xip_defconfig
+F: configs/ae350_rv32_falcon_defconfig
+F: configs/ae350_rv32_falcon_xip_defconfig
F: configs/ae350_rv32_spl_defconfig
-F: configs/ae350_rv64_spl_defconfig
F: configs/ae350_rv32_spl_xip_defconfig
+F: configs/ae350_rv32_xip_defconfig
+F: configs/ae350_rv64_defconfig
+F: configs/ae350_rv64_falcon_defconfig
+F: configs/ae350_rv64_falcon_xip_defconfig
+F: configs/ae350_rv64_spl_defconfig
F: configs/ae350_rv64_spl_xip_defconfig
+F: configs/ae350_rv64_xip_defconfig
diff --git a/board/AndesTech/ae350/ae350.c b/board/AndesTech/ae350/ae350.c
index 1c2288b6ce9..d78ee403e6c 100644
--- a/board/AndesTech/ae350/ae350.c
+++ b/board/AndesTech/ae350/ae350.c
@@ -19,6 +19,8 @@
#include <fdtdec.h>
#include <dm.h>
#include <spl.h>
+#include <mapmem.h>
+#include <hang.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -26,6 +28,29 @@ DECLARE_GLOBAL_DATA_PTR;
* Miscellaneous platform dependent initializations
*/
+#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL)
+#define ANDES_SPL_FDT_ADDR (CONFIG_TEXT_BASE - 0x100000)
+void spl_perform_fixups(struct spl_image_info *spl_image)
+{
+ /*
+ * Originally, u-boot-spl will place DTB directly after the kernel,
+ * but the size of the kernel did not include the BSS section, which
+ * means u-boot-spl will place the DTB in the kernel BSS section
+ * causing the DTB to be cleared by kernel BSS initializtion.
+ * Moving DTB in front of the kernel can avoid the error.
+ */
+ if (ANDES_SPL_FDT_ADDR < 0) {
+ printf("%s: CONFIG_TEXT_BASE needs to be larger than 0x100000\n",
+ __func__);
+ hang();
+ }
+
+ memcpy((void *)ANDES_SPL_FDT_ADDR, spl_image->fdt_addr,
+ fdt_totalsize(spl_image->fdt_addr));
+ spl_image->fdt_addr = map_sysmem(ANDES_SPL_FDT_ADDR, 0);
+}
+#endif
+
int board_init(void)
{
gd->bd->bi_boot_params = PHYS_SDRAM_0 + 0x400;
diff --git a/board/conclusive/kstr-sama5d27/Kconfig b/board/conclusive/kstr-sama5d27/Kconfig
new file mode 100644
index 00000000000..572551cfda9
--- /dev/null
+++ b/board/conclusive/kstr-sama5d27/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_KSTR_SAMA5D27
+
+config SYS_BOARD
+ default "kstr-sama5d27"
+
+config SYS_VENDOR
+ default "conclusive"
+
+config SYS_SOC
+ default "at91"
+
+config SYS_CONFIG_NAME
+ default "kstr-sama5d27"
+
+endif
diff --git a/board/conclusive/kstr-sama5d27/MAINTAINERS b/board/conclusive/kstr-sama5d27/MAINTAINERS
new file mode 100644
index 00000000000..b7882284880
--- /dev/null
+++ b/board/conclusive/kstr-sama5d27/MAINTAINERS
@@ -0,0 +1,9 @@
+CONCLUSIVE KSTR-SAMA5D27 BOARD
+M: Jakub Klama <jakub@conclusive.pl>
+M: Artur Rojek <artur@conclusive.pl>
+S: Maintained
+F: board/conclusive/kstr-sama5d27
+F: include/configs/kstr-sama5d27.h
+F: configs/kstr_sama5d27_defconfig
+F: arch/arm/dts/at91-kstr-sama5d27.dts
+F: arch/arm/dts/at91-kstr-sama5d27-u-boot.dtsi
diff --git a/board/conclusive/kstr-sama5d27/Makefile b/board/conclusive/kstr-sama5d27/Makefile
new file mode 100644
index 00000000000..edf7d1c9344
--- /dev/null
+++ b/board/conclusive/kstr-sama5d27/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (C) 2019-2023 Conclusive Engineering Sp. z o. o.
+
+obj-y += kstr-sama5d27.o
diff --git a/board/conclusive/kstr-sama5d27/kstr-sama5d27.c b/board/conclusive/kstr-sama5d27/kstr-sama5d27.c
new file mode 100644
index 00000000000..1b765b11374
--- /dev/null
+++ b/board/conclusive/kstr-sama5d27/kstr-sama5d27.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * kstr-sama5d27.c - Board init file for Conclusive KSTR-SAMA5D27 board
+ * Copyright (C) 2021-2023 Conclusive Engineering Sp. z o. o.
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <init.h>
+#include <env.h>
+#include <fdt_support.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/at91_common.h>
+#include <asm/arch/atmel_pio4.h>
+#include <asm/arch/atmel_mpddrc.h>
+#include <asm/arch/atmel_sdhci.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/sama5d2.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+#include <asm/arch/atmel_usba_udc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+static void board_uart1_hw_init(void)
+{
+ /* URXD1 */
+ atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, ATMEL_PIO_PUEN_MASK);
+ /* UTXD1 */
+ atmel_pio4_set_a_periph(AT91_PIO_PORTD, 3, 0);
+ at91_periph_clk_enable(ATMEL_ID_UART1);
+}
+
+void board_debug_uart_init(void)
+{
+ board_uart1_hw_init();
+}
+#endif
+
+void board_lan8720a_init(void)
+{
+ /* LAN8720A_nRST */
+ atmel_pio4_set_pio_output(AT91_PIO_PORTB, 12, 0);
+ /*
+ * Force 0 on RXER/PHYAD0. LAN8720A chipset will latch with address 0 on
+ * MDIO bus.
+ */
+ atmel_pio4_set_pio_output(AT91_PIO_PORTB, 17, 0);
+ /* Minimal delay of reset signal is 25 ms */
+ mdelay(30);
+ /* LAN8720A_nRST */
+ atmel_pio4_set_pio_output(AT91_PIO_PORTB, 12, 1);
+}
+
+void board_usba_init(void)
+{
+#ifdef CONFIG_USB_GADGET_ATMEL_USBA
+ /* USB device peripheral initialization: sama5d2_devices.c */
+ at91_udp_hw_init();
+ /* USB device controller drivers/usb/gadget/atmel_usba_udc.c */
+ usba_udc_probe(&pdata);
+#endif
+}
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+#ifdef CONFIG_DEBUG_UART
+ debug_uart_init();
+#endif
+
+ return 0;
+}
+#endif
+
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+ char *wlanaddr = env_get("eth1addr");
+
+ if (wlanaddr)
+ do_fixup_by_compat(blob, "brcm,bcm4329-fmac", "local-mac-address",
+ wlanaddr, strlen(wlanaddr), 1);
+ else
+ printf("Not setting WIFI mac address. Check if EEPROM TLV is correctly set up.\n");
+
+ return 0;
+}
+
+int board_init(void)
+{
+ /* address of boot parameters */
+ gd->bd->bi_boot_params = CFG_SYS_SDRAM_BASE + 0x100;
+
+ board_usba_init();
+ board_lan8720a_init();
+
+ return 0;
+}
+
+static int settings_r(void)
+{
+ mac_read_from_eeprom();
+ serial_read_from_eeprom(0);
+
+ return 0;
+}
+EVENT_SPY_SIMPLE(EVT_SETTINGS_R, settings_r);
+
+#if defined(CONFIG_DISPLAY_BOARDINFO_LATE)
+int checkboard(void)
+{
+ const char *serial_number;
+
+ serial_number = env_get("serial#");
+ if (!serial_number)
+ printf("Warning: unknown serial number.\n");
+ else
+ printf("S/N: %s\n", serial_number);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_MISC_INIT_R
+int misc_init_r(void)
+{
+ return 0;
+}
+#endif
+
+int dram_init(void)
+{
+ gd->ram_size = get_ram_size((void *)CFG_SYS_SDRAM_BASE,
+ CFG_SYS_SDRAM_SIZE);
+ return 0;
+}
+
+/* SPL */
+#ifdef CONFIG_SPL_BUILD
+void spl_board_init(void)
+{
+}
+
+static void ddrc_conf(struct atmel_mpddrc_config *ddrc)
+{
+ ddrc->md = (ATMEL_MPDDRC_MD_DBW_16_BITS | ATMEL_MPDDRC_MD_DDR2_SDRAM);
+
+ ddrc->cr = (ATMEL_MPDDRC_CR_NC_COL_10 |
+ ATMEL_MPDDRC_CR_NR_ROW_13 |
+ ATMEL_MPDDRC_CR_CAS_DDR_CAS3 |
+ ATMEL_MPDDRC_CR_DIC_DS |
+ ATMEL_MPDDRC_CR_ZQ_LONG |
+ ATMEL_MPDDRC_CR_NB_8BANKS |
+ ATMEL_MPDDRC_CR_DECOD_INTERLEAVED |
+ ATMEL_MPDDRC_CR_UNAL_SUPPORTED);
+
+ ddrc->rtr = 0x511;
+
+ ddrc->tpr0 = ((7 << ATMEL_MPDDRC_TPR0_TRAS_OFFSET) |
+ (3 << ATMEL_MPDDRC_TPR0_TRCD_OFFSET) |
+ (3 << ATMEL_MPDDRC_TPR0_TWR_OFFSET) |
+ (9 << ATMEL_MPDDRC_TPR0_TRC_OFFSET) |
+ (3 << ATMEL_MPDDRC_TPR0_TRP_OFFSET) |
+ (4 << ATMEL_MPDDRC_TPR0_TRRD_OFFSET) |
+ (4 << ATMEL_MPDDRC_TPR0_TWTR_OFFSET) |
+ (2 << ATMEL_MPDDRC_TPR0_TMRD_OFFSET));
+
+ ddrc->tpr1 = ((22 << ATMEL_MPDDRC_TPR1_TRFC_OFFSET) |
+ (23 << ATMEL_MPDDRC_TPR1_TXSNR_OFFSET) |
+ (200 << ATMEL_MPDDRC_TPR1_TXSRD_OFFSET) |
+ (3 << ATMEL_MPDDRC_TPR1_TXP_OFFSET));
+
+ ddrc->tpr2 = ((2 << ATMEL_MPDDRC_TPR2_TXARD_OFFSET) |
+ (8 << ATMEL_MPDDRC_TPR2_TXARDS_OFFSET) |
+ (4 << ATMEL_MPDDRC_TPR2_TRPA_OFFSET) |
+ (4 << ATMEL_MPDDRC_TPR2_TRTP_OFFSET) |
+ (8 << ATMEL_MPDDRC_TPR2_TFAW_OFFSET));
+}
+
+void mem_init(void)
+{
+ struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
+ struct atmel_mpddr *mpddrc = (struct atmel_mpddr *)ATMEL_BASE_MPDDRC;
+ struct atmel_mpddrc_config ddrc_config;
+ u32 reg;
+
+ ddrc_conf(&ddrc_config);
+
+ at91_periph_clk_enable(ATMEL_ID_MPDDRC);
+ writel(AT91_PMC_DDR, &pmc->scer);
+
+ reg = readl(&mpddrc->io_calibr);
+ reg &= ~ATMEL_MPDDRC_IO_CALIBR_RDIV;
+ reg |= ATMEL_MPDDRC_IO_CALIBR_DDR3_RZQ_55;
+ reg &= ~ATMEL_MPDDRC_IO_CALIBR_TZQIO;
+ reg |= ATMEL_MPDDRC_IO_CALIBR_TZQIO_(101);
+ writel(reg, &mpddrc->io_calibr);
+
+ writel(ATMEL_MPDDRC_RD_DATA_PATH_SHIFT_ONE_CYCLE,
+ &mpddrc->rd_data_path);
+
+ ddr3_init(ATMEL_BASE_MPDDRC, ATMEL_BASE_DDRCS, &ddrc_config);
+
+ writel(0x3, &mpddrc->cal_mr4);
+ writel(64, &mpddrc->tim_cal);
+}
+
+void at91_pmc_init(void)
+{
+ u32 tmp;
+
+ /*
+ * While coming from the ROM code, we run on PLLA @ 492 MHz / 164 MHz,
+ * so we need to slow down and configure MCKR accordingly.
+ * This is why we have a special flavor of the switching function.
+ */
+ tmp = AT91_PMC_MCKR_PLLADIV_2 |
+ AT91_PMC_MCKR_MDIV_3 |
+ AT91_PMC_MCKR_CSS_MAIN;
+ at91_mck_init_down(tmp);
+
+ tmp = AT91_PMC_PLLAR_29 |
+ AT91_PMC_PLLXR_PLLCOUNT(0x3f) |
+ AT91_PMC_PLLXR_MUL(40) |
+ AT91_PMC_PLLXR_DIV(1);
+ at91_plla_init(tmp);
+
+ tmp = AT91_PMC_MCKR_H32MXDIV |
+ AT91_PMC_MCKR_PLLADIV_2 |
+ AT91_PMC_MCKR_MDIV_3 |
+ AT91_PMC_MCKR_CSS_PLLA;
+ at91_mck_init(tmp);
+}
+#endif
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 98bbd2dd25d..4bbe3f62fa6 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -291,6 +291,11 @@ M: Aleksei Mamlin <mamlinav@gmail.com>
S: Maintained
F: configs/Marsboard_A10_defconfig
+MANGOPI MQ-R BOARD
+M: Andre Przywara <andre.przywara@arm.com>
+S: Maintained
+F: configs/mangopi_mq_r_defconfig
+
MELE I7 BOARD
M: Marcus Cooper <codekipper@gmail.com>
S: Maintained
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index ebaa9431984..39ecbe988f7 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -38,6 +38,7 @@
#include <asm/armv7.h>
#endif
#include <asm/gpio.h>
+#include <sunxi_gpio.h>
#include <asm/io.h>
#include <u-boot/crc.h>
#include <env_internal.h>
@@ -187,7 +188,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
/* add board specific code here */
int board_init(void)
{
- __maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
+ __maybe_unused int id_pfr1, ret;
gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
@@ -224,29 +225,6 @@ int board_init(void)
if (ret)
return ret;
- /* strcmp() would look better, but doesn't get optimised away. */
- if (CONFIG_SATAPWR[0]) {
- satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
- if (satapwr_pin >= 0) {
- gpio_request(satapwr_pin, "satapwr");
- gpio_direction_output(satapwr_pin, 1);
-
- /*
- * Give the attached SATA device time to power-up
- * to avoid link timeouts
- */
- mdelay(500);
- }
- }
-
- if (CONFIG_MACPWR[0]) {
- macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
- if (macpwr_pin >= 0) {
- gpio_request(macpwr_pin, "macpwr");
- gpio_direction_output(macpwr_pin, 1);
- }
- }
-
#if CONFIG_IS_ENABLED(DM_I2C)
/*
* Temporary workaround for enabling I2C clocks until proper sunxi DM
@@ -254,7 +232,6 @@ int board_init(void)
*/
i2c_init_board();
#endif
-
eth_init_board();
return 0;
@@ -482,6 +459,13 @@ static void mmc_pinmux_setup(int sdc)
sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
sunxi_gpio_set_drv(pin, 2);
}
+#elif defined(CONFIG_MACH_SUN8I_R528)
+ /* SDC2: PC2-PC7 */
+ for (pin = SUNXI_GPC(2); pin <= SUNXI_GPC(7); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
#else
puts("ERROR: No pinmux setup defined for MMC2!\n");
#endif
diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c
index cde04bebe96..eeee6319e79 100644
--- a/board/sunxi/chip.c
+++ b/board/sunxi/chip.c
@@ -12,7 +12,7 @@
#include <w1-eeprom.h>
#include <dm/device-internal.h>
-#include <asm/arch/gpio.h>
+#include <sunxi_gpio.h>
#include <extension_board.h>
diff --git a/boot/bootflow.c b/boot/bootflow.c
index e03932e65a7..be543c8588c 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -156,6 +156,27 @@ static void bootflow_iter_set_dev(struct bootflow_iter *iter,
}
/**
+ * scan_next_in_uclass() - Scan for the next bootdev in the same media uclass
+ *
+ * Move through the following bootdevs until we find another in this media
+ * uclass, or run out
+ *
+ * @devp: On entry, the device to check, on exit the new device, or NULL if
+ * there is none
+ */
+static void scan_next_in_uclass(struct udevice **devp)
+{
+ struct udevice *dev = *devp;
+ enum uclass_id cur_id = device_get_uclass_id(dev->parent);
+
+ do {
+ uclass_find_next_device(&dev);
+ } while (dev && cur_id != device_get_uclass_id(dev->parent));
+
+ *devp = dev;
+}
+
+/**
* iter_incr() - Move to the next item (method, part, bootdev)
*
* Return: 0 if OK, BF_NO_MORE_DEVICES if there are no more bootdevs
@@ -230,8 +251,7 @@ static int iter_incr(struct bootflow_iter *iter)
&method_flags);
} else if (IS_ENABLED(CONFIG_BOOTSTD_FULL) &&
(iter->flags & BOOTFLOWIF_SINGLE_UCLASS)) {
- /* Move to the next bootdev in this uclass */
- uclass_find_next_device(&dev);
+ scan_next_in_uclass(&dev);
if (!dev) {
log_debug("finished uclass %s\n",
dev_get_uclass_name(dev));
@@ -266,8 +286,9 @@ static int iter_incr(struct bootflow_iter *iter)
* bootdev_find_by_label() where this flag is
* set up
*/
- if (iter->method_flags & BOOTFLOW_METHF_SINGLE_UCLASS) {
- uclass_next_device(&dev);
+ if (iter->method_flags &
+ BOOTFLOW_METHF_SINGLE_UCLASS) {
+ scan_next_in_uclass(&dev);
log_debug("looking for next device %s: %s\n",
iter->dev->name,
dev ? dev->name : "<none>");
diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c
index 345114dabf7..06340e43d2d 100644
--- a/boot/bootmeth_script.c
+++ b/boot/bootmeth_script.c
@@ -188,12 +188,20 @@ static int script_boot(struct udevice *dev, struct bootflow *bflow)
{
struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
ulong addr;
- int ret;
+ int ret = 0;
- if (desc->uclass_id == UCLASS_USB)
+ if (desc->uclass_id == UCLASS_USB) {
ret = env_set("devtype", "usb");
- else
- ret = env_set("devtype", blk_get_devtype(bflow->blk));
+ } else {
+ /* If the uclass is AHCI, but the driver is ATA
+ * (not scsi), set devtype to sata
+ */
+ if (IS_ENABLED(CONFIG_SATA) &&
+ desc->uclass_id == UCLASS_AHCI)
+ ret = env_set("devtype", "sata");
+ else
+ ret = env_set("devtype", blk_get_devtype(bflow->blk));
+ }
if (!ret)
ret = env_set_hex("devnum", desc->devnum);
if (!ret)
diff --git a/cmd/tlv_eeprom.c b/cmd/tlv_eeprom.c
index 79796394c5c..57cfd355df1 100644
--- a/cmd/tlv_eeprom.c
+++ b/cmd/tlv_eeprom.c
@@ -1088,19 +1088,7 @@ int mac_read_from_eeprom(void)
return 0;
}
-/**
- * populate_serial_number - read the serial number from EEPROM
- *
- * This function reads the serial number from the EEPROM and sets the
- * appropriate environment variable.
- *
- * The environment variable is only set if it has not been set
- * already. This ensures that any user-saved variables are never
- * overwritten.
- *
- * This function must be called after relocation.
- */
-int populate_serial_number(int devnum)
+int serial_read_from_eeprom(int devnum)
{
char serialstr[257];
int eeprom_index;
diff --git a/common/board_r.c b/common/board_r.c
index 52786901be5..a7967849dc0 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -693,6 +693,7 @@ static init_fnc_t init_sequence_r[] = {
#if defined(CONFIG_ID_EEPROM)
mac_read_from_eeprom,
#endif
+ INITCALL_EVENT(EVT_SETTINGS_R),
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_PCI_INIT_R) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
/*
diff --git a/common/event.c b/common/event.c
index 3080d9ed754..dc61b9672f3 100644
--- a/common/event.c
+++ b/common/event.c
@@ -37,6 +37,7 @@ const char *const type_name[] = {
/* init hooks */
"misc_init_f",
"fsp_init_r",
+ "settings_r",
"last_stage_init",
/* Fpga load hook */
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 46323597942..25cd18afda7 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -265,7 +265,7 @@ config SPL_TEXT_BASE
default 0x402F0400 if AM33XX
default 0x40301350 if OMAP54XX
default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
- default 0x20060 if SUN50I_GEN_H6
+ default 0x20060 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
default 0x00060 if ARCH_SUNXI
default 0xfffc0000 if ARCH_ZYNQMP
default 0x0
@@ -330,6 +330,20 @@ config SPL_LEGACY_IMAGE_CRC_CHECK
If disabled, Legacy images are booted if the image magic and size
are correct, without further integrity checks.
+config SPL_LOAD_IMX_CONTAINER
+ bool "Enable SPL loading and booting of i.MX8 Containers"
+ depends on SPL
+ help
+ Support booting U-Boot from an i.MX8 container image. If you are not
+ using i.MX8, say 'n'.
+
+config IMX_CONTAINER_CFG
+ string "i.MX8 Container config file"
+ depends on SPL && SPL_LOAD_IMX_CONTAINER
+ help
+ Specify the cfg file for generating the container image which will be
+ loaded by SPL.
+
config SPL_SYS_MALLOC_SIMPLE
bool "Only use malloc_simple functions in the SPL"
help
@@ -357,6 +371,7 @@ config SPL_STACK
default 0x91ffb8 if ARCH_MX6 && !MX6_OCRAM_256KB
default 0x118000 if MACH_SUN50I_H6
default 0x58000 if MACH_SUN50I_H616
+ default 0x40000 if MACH_SUN8I_R528
default 0x54000 if MACH_SUN50I || MACH_SUN50I_H5
default 0x18000 if MACH_SUN9I
default 0x8000 if ARCH_SUNXI
@@ -643,6 +658,7 @@ config SPL_ETH
config SPL_FS_EXT4
bool "Support EXT filesystems"
+ select SPL_CRC16 if EXT4_WRITE
help
Enable support for EXT2/3/4 filesystems with SPL. This permits
U-Boot (or Linux in Falcon mode) to be loaded from an EXT
diff --git a/common/spl/Makefile b/common/spl/Makefile
index bad2bbf6cf1..4f8eb2ec0ca 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_$(SPL_TPL_)OPENSBI) += spl_opensbi.o
obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o
obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o
obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o
+obj-$(CONFIG_$(SPL_TPL_)LOAD_IMX_CONTAINER) += spl_imx_container.o
obj-$(CONFIG_$(SPL_TPL_)SATA) += spl_sata.o
obj-$(CONFIG_$(SPL_TPL_)NVME) += spl_nvme.o
obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += spl_semihosting.o
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 66eeea41a34..732d90d39e6 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -653,7 +653,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
spl_set_bd();
if (IS_ENABLED(CONFIG_SPL_SYS_MALLOC)) {
- mem_malloc_init(SPL_SYS_MALLOC_START, SPL_SYS_MALLOC_SIZE);
+ mem_malloc_init((ulong)map_sysmem(SPL_SYS_MALLOC_START,
+ SPL_SYS_MALLOC_SIZE),
+ SPL_SYS_MALLOC_SIZE);
gd->flags |= GD_FLG_FULL_MALLOC_INIT;
}
if (!(gd->flags & GD_FLG_SPL_INIT)) {
diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c
index ea5d1a51d9f..63825d620d1 100644
--- a/common/spl/spl_blk_fs.c
+++ b/common/spl/spl_blk_fs.c
@@ -9,6 +9,7 @@
#include <spl.h>
#include <image.h>
#include <fs.h>
+#include <asm/io.h>
struct blk_dev {
const char *ifname;
@@ -29,7 +30,8 @@ static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset,
return ret;
}
- ret = fs_read(load->filename, (ulong)buf, file_offset, size, &actlen);
+ ret = fs_read(load->filename, virt_to_phys(buf), file_offset, size,
+ &actlen);
if (ret < 0) {
printf("spl: error reading image %s. Err - %d\n",
load->filename, ret);
@@ -69,7 +71,7 @@ int spl_blk_load_image(struct spl_image_info *spl_image,
goto out;
}
- ret = fs_read(filename, (ulong)header, 0,
+ ret = fs_read(filename, virt_to_phys(header), 0,
sizeof(struct legacy_img_hdr), &actlen);
if (ret) {
printf("spl: unable to read file %s. Err - %d\n", filename,
diff --git a/common/spl/spl_ext.c b/common/spl/spl_ext.c
index 902564a6077..af836ca15b8 100644
--- a/common/spl/spl_ext.c
+++ b/common/spl/spl_ext.c
@@ -2,6 +2,7 @@
#include <common.h>
#include <env.h>
+#include <mapmem.h>
#include <part.h>
#include <spl.h>
#include <asm/u-boot.h>
@@ -53,7 +54,8 @@ int spl_load_image_ext(struct spl_image_info *spl_image,
goto end;
}
- err = ext4fs_read((char *)spl_image->load_addr, 0, filelen, &actlen);
+ err = ext4fs_read(map_sysmem(spl_image->load_addr, filelen), 0, filelen,
+ &actlen);
end:
#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT
diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c
index c6e2526ade1..014074f85be 100644
--- a/common/spl/spl_fat.c
+++ b/common/spl/spl_fat.c
@@ -11,6 +11,7 @@
#include <common.h>
#include <env.h>
#include <log.h>
+#include <mapmem.h>
#include <spl.h>
#include <asm/u-boot.h>
#include <fat.h>
@@ -20,6 +21,11 @@
static int fat_registered;
+void spl_fat_force_reregister(void)
+{
+ fat_registered = 0;
+}
+
static int spl_register_fat_device(struct blk_desc *block_dev, int partition)
{
int err = 0;
@@ -74,11 +80,13 @@ int spl_load_image_fat(struct spl_image_info *spl_image,
if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) &&
image_get_magic(header) == FDT_MAGIC) {
- err = file_fat_read(filename, (void *)CONFIG_SYS_LOAD_ADDR, 0);
+ err = file_fat_read(filename,
+ map_sysmem(CONFIG_SYS_LOAD_ADDR, 0), 0);
if (err <= 0)
goto end;
err = spl_parse_image_header(spl_image, bootdev,
- (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR);
+ map_sysmem(CONFIG_SYS_LOAD_ADDR,
+ err));
if (err == -EAGAIN)
return err;
if (err == 0)
@@ -99,8 +107,8 @@ int spl_load_image_fat(struct spl_image_info *spl_image,
if (err)
goto end;
- err = file_fat_read(filename,
- (u8 *)(uintptr_t)spl_image->load_addr, 0);
+ err = file_fat_read(filename, map_sysmem(spl_image->load_addr,
+ spl_image->size), 0);
}
end:
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index 1409b926372..70d8d5942d9 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -16,6 +16,7 @@
#include <sysinfo.h>
#include <asm/cache.h>
#include <asm/global_data.h>
+#include <asm/io.h>
#include <linux/libfdt.h>
#include <linux/printk.h>
@@ -366,7 +367,8 @@ static bool os_takes_devicetree(uint8_t os)
case IH_OS_U_BOOT:
return true;
case IH_OS_LINUX:
- return IS_ENABLED(CONFIG_SPL_OS_BOOT);
+ return IS_ENABLED(CONFIG_SPL_OS_BOOT) ||
+ IS_ENABLED(CONFIG_SPL_OPENSBI);
default:
return false;
}
@@ -393,25 +395,32 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image,
/* Figure out which device tree the board wants to use */
node = spl_fit_get_image_node(ctx, FIT_FDT_PROP, index++);
if (node < 0) {
+ size_t size;
+
debug("%s: cannot find FDT node\n", __func__);
/*
* U-Boot did not find a device tree inside the FIT image. Use
* the U-Boot device tree instead.
*/
- if (gd->fdt_blob)
- memcpy((void *)image_info.load_addr, gd->fdt_blob,
- fdt_totalsize(gd->fdt_blob));
- else
+ if (!gd->fdt_blob)
return node;
+
+ /*
+ * Make the load-address of the FDT available for the SPL
+ * framework
+ */
+ size = fdt_totalsize(gd->fdt_blob);
+ spl_image->fdt_addr = map_sysmem(image_info.load_addr, size);
+ memcpy(spl_image->fdt_addr, gd->fdt_blob, size);
} else {
ret = load_simple_fit(info, sector, ctx, node, &image_info);
if (ret < 0)
return ret;
+
+ spl_image->fdt_addr = phys_to_virt(image_info.load_addr);
}
- /* Make the load-address of the FDT available for the SPL framework */
- spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0);
if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY))
return 0;
@@ -876,7 +885,7 @@ int spl_load_fit_image(struct spl_image_info *spl_image,
#ifdef CONFIG_SPL_FIT_SIGNATURE
images.verify = 1;
#endif
- ret = fit_image_load(&images, (ulong)header,
+ ret = fit_image_load(&images, virt_to_phys((void *)header),
NULL, &fit_uname_config,
IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1,
FIT_LOAD_OPTIONAL, &fw_data, &fw_len);
@@ -884,15 +893,15 @@ int spl_load_fit_image(struct spl_image_info *spl_image,
printf("DEPRECATED: 'standalone = ' property.");
printf("Please use either 'firmware =' or 'kernel ='\n");
} else {
- ret = fit_image_load(&images, (ulong)header, NULL,
- &fit_uname_config, IH_ARCH_DEFAULT,
+ ret = fit_image_load(&images, virt_to_phys((void *)header),
+ NULL, &fit_uname_config, IH_ARCH_DEFAULT,
IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL,
&fw_data, &fw_len);
}
if (ret < 0) {
- ret = fit_image_load(&images, (ulong)header, NULL,
- &fit_uname_config, IH_ARCH_DEFAULT,
+ ret = fit_image_load(&images, virt_to_phys((void *)header),
+ NULL, &fit_uname_config, IH_ARCH_DEFAULT,
IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL,
&fw_data, &fw_len);
}
@@ -901,8 +910,9 @@ int spl_load_fit_image(struct spl_image_info *spl_image,
return ret;
spl_image->size = fw_len;
- spl_image->entry_point = fw_data;
spl_image->load_addr = fw_data;
+ if (fit_image_get_entry(header, ret, &spl_image->entry_point))
+ spl_image->entry_point = fw_data;
if (fit_image_get_os(header, ret, &spl_image->os))
spl_image->os = IH_OS_INVALID;
spl_image->name = genimg_get_os_name(spl_image->os);
@@ -913,9 +923,9 @@ int spl_load_fit_image(struct spl_image_info *spl_image,
#ifdef CONFIG_SPL_FIT_SIGNATURE
images.verify = 1;
#endif
- ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config,
- IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1,
- FIT_LOAD_OPTIONAL, &dt_data, &dt_len);
+ ret = fit_image_load(&images, virt_to_phys((void *)header), NULL,
+ &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_FLATDT,
+ -1, FIT_LOAD_OPTIONAL, &dt_data, &dt_len);
if (ret >= 0) {
spl_image->fdt_addr = (void *)dt_data;
diff --git a/arch/arm/mach-imx/parse-container.c b/common/spl/spl_imx_container.c
index e2a9e2b2732..127802f5cb7 100644
--- a/arch/arm/mach-imx/parse-container.c
+++ b/common/spl/spl_imx_container.c
@@ -3,12 +3,14 @@
* Copyright 2018-2021 NXP
*/
+#define LOG_CATEGORY LOGC_ARCH
#include <common.h>
#include <stdlib.h>
#include <errno.h>
+#include <imx_container.h>
#include <log.h>
+#include <mapmem.h>
#include <spl.h>
-#include <asm/mach-imx/image.h>
#ifdef CONFIG_AHAB_BOOT
#include <asm/mach-imx/ahab.h>
#endif
@@ -45,7 +47,8 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
debug("%s: container: %p sector: %lu sectors: %u\n", __func__,
container, sector, sectors);
if (info->read(info, sector, sectors,
- (void *)images[image_index].entry) != sectors) {
+ map_sysmem(images[image_index].dst,
+ images[image_index].size)) != sectors) {
printf("%s wrong\n", __func__);
return NULL;
}
@@ -84,14 +87,14 @@ static int read_auth_container(struct spl_image_info *spl_image,
goto end;
}
- if (container->tag != 0x87 && container->version != 0x0) {
- printf("Wrong container header");
+ if (!valid_container_hdr(container)) {
+ log_err("Wrong container header\n");
ret = -ENOENT;
goto end;
}
if (!container->num_images) {
- printf("Wrong container, no image found");
+ log_err("Wrong container, no image found\n");
ret = -ENOENT;
goto end;
}
diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c
index 095443c63d8..51656fb9617 100644
--- a/common/spl/spl_legacy.c
+++ b/common/spl/spl_legacy.c
@@ -7,6 +7,7 @@
#include <image.h>
#include <log.h>
#include <malloc.h>
+#include <mapmem.h>
#include <asm/sections.h>
#include <spl.h>
@@ -19,7 +20,7 @@
static void spl_parse_legacy_validate(uintptr_t start, uintptr_t size)
{
uintptr_t spl_start = (uintptr_t)_start;
- uintptr_t spl_end = (uintptr_t)_image_binary_end;
+ uintptr_t spl_end = (uintptr_t)&_image_binary_end;
uintptr_t end = start + size;
if ((start >= spl_start && start < spl_end) ||
@@ -129,7 +130,7 @@ int spl_load_legacy_img(struct spl_image_info *spl_image,
dataptr += sizeof(*hdr);
load->read(load, dataptr, spl_image->size,
- (void *)(unsigned long)spl_image->load_addr);
+ map_sysmem(spl_image->load_addr, spl_image->size));
break;
case IH_COMP_LZMA:
@@ -148,7 +149,8 @@ int spl_load_legacy_img(struct spl_image_info *spl_image,
}
load->read(load, dataptr, spl_image->size, src);
- ret = lzmaBuffToBuffDecompress((void *)spl_image->load_addr,
+ ret = lzmaBuffToBuffDecompress(map_sysmem(spl_image->load_addr,
+ spl_image->size),
&lzma_len, src, spl_image->size);
if (ret) {
printf("LZMA decompression error: %d\n", ret);
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 612b11ef5b9..82689da1401 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <dm.h>
#include <log.h>
+#include <mapmem.h>
#include <part.h>
#include <spl.h>
#include <linux/compiler.h>
@@ -16,6 +17,7 @@
#include <errno.h>
#include <mmc.h>
#include <image.h>
+#include <imx_container.h>
static int mmc_load_legacy(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
@@ -45,7 +47,8 @@ static int mmc_load_legacy(struct spl_image_info *spl_image,
count = blk_dread(mmc_get_blk_desc(mmc),
sector + image_offset_sectors,
image_size_sectors,
- (void *)(ulong)spl_image->load_addr);
+ map_sysmem(spl_image->load_addr,
+ image_size_sectors * mmc->read_bl_len));
debug("read %x sectors to %lx\n", image_size_sectors,
spl_image->load_addr);
if (count != image_size_sectors)
@@ -108,7 +111,8 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
load.bl_len = mmc->read_bl_len;
load.read = h_spl_load_read;
ret = spl_load_simple_fit(spl_image, &load, sector, header);
- } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
+ } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
+ valid_container_hdr((void *)header)) {
struct spl_load_info load;
load.dev = mmc;
@@ -408,18 +412,24 @@ static int spl_mmc_get_mmc_devnum(struct mmc *mmc)
#if !CONFIG_IS_ENABLED(BLK)
block_dev = &mmc->block_dev;
#else
- block_dev = dev_get_uclass_plat(mmc->dev);
+ block_dev = mmc_get_blk_desc(mmc);
#endif
return block_dev->devnum;
}
+static struct mmc *mmc;
+
+void spl_mmc_clear_cache(void)
+{
+ mmc = NULL;
+}
+
int spl_mmc_load(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
const char *filename,
int raw_part,
unsigned long raw_sect)
{
- static struct mmc *mmc;
u32 boot_mode;
int err = 0;
__maybe_unused int part = 0;
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
index 6cc34004f49..07916bedbb9 100644
--- a/common/spl/spl_nand.c
+++ b/common/spl/spl_nand.c
@@ -7,6 +7,7 @@
#include <config.h>
#include <fdt_support.h>
#include <image.h>
+#include <imx_container.h>
#include <log.h>
#include <spl.h>
#include <asm/io.h>
@@ -99,7 +100,8 @@ static int spl_nand_load_element(struct spl_image_info *spl_image,
load.bl_len = bl_len;
load.read = spl_nand_fit_read;
return spl_load_simple_fit(spl_image, &load, offset / bl_len, header);
- } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
+ } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
+ valid_container_hdr((void *)header)) {
struct spl_load_info load;
load.dev = NULL;
diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c
index b2c901b554b..f01d4df8bc6 100644
--- a/common/spl/spl_net.c
+++ b/common/spl/spl_net.c
@@ -11,6 +11,7 @@
#include <errno.h>
#include <image.h>
#include <log.h>
+#include <mapmem.h>
#include <spl.h>
#include <net.h>
#include <linux/libfdt.h>
@@ -21,14 +22,15 @@ static ulong spl_net_load_read(struct spl_load_info *load, ulong sector,
{
debug("%s: sector %lx, count %lx, buf %lx\n",
__func__, sector, count, (ulong)buf);
- memcpy(buf, (void *)(image_load_addr + sector), count);
+ memcpy(buf, map_sysmem(image_load_addr + sector, count), count);
return count;
}
static int spl_net_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
- struct legacy_img_hdr *header = (struct legacy_img_hdr *)image_load_addr;
+ struct legacy_img_hdr *header = map_sysmem(image_load_addr,
+ sizeof(*header));
int rv;
env_init();
@@ -62,7 +64,9 @@ static int spl_net_load_image(struct spl_image_info *spl_image,
if (rv)
return rv;
- memcpy((void *)spl_image->load_addr, header, spl_image->size);
+ memcpy(map_sysmem(spl_image->load_addr, spl_image->size),
+ map_sysmem(image_load_addr, spl_image->size),
+ spl_image->size);
}
return rv;
diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c
index 79d4f1d7aa8..236b0718283 100644
--- a/common/spl/spl_nor.c
+++ b/common/spl/spl_nor.c
@@ -5,7 +5,9 @@
#include <common.h>
#include <image.h>
+#include <imx_container.h>
#include <log.h>
+#include <mapmem.h>
#include <spl.h>
static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector,
@@ -13,7 +15,7 @@ static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector,
{
debug("%s: sector %lx, count %lx, buf %p\n",
__func__, sector, count, buf);
- memcpy(buf, (void *)sector, count);
+ memcpy(buf, map_sysmem(sector, count), count);
return count;
}
@@ -26,7 +28,7 @@ unsigned long __weak spl_nor_get_uboot_base(void)
static int spl_nor_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
- __maybe_unused const struct legacy_img_hdr *header;
+ struct legacy_img_hdr *header;
__maybe_unused struct spl_load_info load;
/*
@@ -41,7 +43,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image,
* Load Linux from its location in NOR flash to its defined
* location in SDRAM
*/
- header = (const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE;
+ header = (void *)CONFIG_SYS_OS_BASE;
#ifdef CONFIG_SPL_LOAD_FIT
if (image_get_magic(header) == FDT_MAGIC) {
int ret;
@@ -91,8 +93,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image,
* Load real U-Boot from its location in NOR flash to its
* defined location in SDRAM
*/
+ header = map_sysmem(spl_nor_get_uboot_base(), sizeof(*header));
#ifdef CONFIG_SPL_LOAD_FIT
- header = (const struct legacy_img_hdr *)spl_nor_get_uboot_base();
if (image_get_magic(header) == FDT_MAGIC) {
debug("Found FIT format U-Boot\n");
load.bl_len = 1;
@@ -102,7 +104,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image,
(void *)header);
}
#endif
- if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
+ if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
+ valid_container_hdr((void *)header)) {
load.bl_len = 1;
load.read = spl_nor_load_read;
return spl_load_imx_container(spl_image, &load,
@@ -111,14 +114,11 @@ static int spl_nor_load_image(struct spl_image_info *spl_image,
/* Legacy image handling */
if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT)) {
- struct legacy_img_hdr hdr;
-
load.bl_len = 1;
load.read = spl_nor_load_read;
- spl_nor_load_read(&load, spl_nor_get_uboot_base(), sizeof(hdr), &hdr);
return spl_load_legacy_img(spl_image, bootdev, &load,
spl_nor_get_uboot_base(),
- &hdr);
+ header);
}
return -EINVAL;
diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c
index 0df611623ae..9801d38c0b3 100644
--- a/common/spl/spl_opensbi.c
+++ b/common/spl/spl_opensbi.c
@@ -21,7 +21,7 @@ DECLARE_GLOBAL_DATA_PTR;
struct fw_dynamic_info opensbi_info;
-static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node)
+static int spl_opensbi_find_os_node(void *blob, int *uboot_node, int os_type)
{
int fit_images_node, node;
const char *fit_os;
@@ -35,7 +35,7 @@ static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node)
if (!fit_os)
continue;
- if (genimg_get_os_id(fit_os) == IH_OS_U_BOOT) {
+ if (genimg_get_os_id(fit_os) == os_type) {
*uboot_node = node;
return 0;
}
@@ -46,8 +46,9 @@ static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node)
void __noreturn spl_invoke_opensbi(struct spl_image_info *spl_image)
{
- int ret, uboot_node;
- ulong uboot_entry;
+ int ret, os_node;
+ ulong os_entry;
+ int os_type;
typedef void __noreturn (*opensbi_entry_t)(ulong hartid, ulong dtb, ulong info);
opensbi_entry_t opensbi_entry;
@@ -56,22 +57,32 @@ void __noreturn spl_invoke_opensbi(struct spl_image_info *spl_image)
hang();
}
- /* Find U-Boot image in /fit-images */
- ret = spl_opensbi_find_uboot_node(spl_image->fdt_addr, &uboot_node);
+ /*
+ * Find next os image in /fit-images
+ * The next os image default is u-boot proper, once enable
+ * OpenSBI OS boot mode, the OS image should be linux.
+ */
+ if (CONFIG_IS_ENABLED(LOAD_FIT_OPENSBI_OS_BOOT))
+ os_type = IH_OS_LINUX;
+ else
+ os_type = IH_OS_U_BOOT;
+
+ ret = spl_opensbi_find_os_node(spl_image->fdt_addr, &os_node, os_type);
if (ret) {
- pr_err("Can't find U-Boot node, %d\n", ret);
+ pr_err("Can't find %s node for opensbi, %d\n",
+ genimg_get_os_name(os_type), ret);
hang();
}
/* Get U-Boot entry point */
- ret = fit_image_get_entry(spl_image->fdt_addr, uboot_node, &uboot_entry);
+ ret = fit_image_get_entry(spl_image->fdt_addr, os_node, &os_entry);
if (ret)
- ret = fit_image_get_load(spl_image->fdt_addr, uboot_node, &uboot_entry);
+ ret = fit_image_get_load(spl_image->fdt_addr, os_node, &os_entry);
/* Prepare opensbi_info object */
opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE;
opensbi_info.version = FW_DYNAMIC_INFO_VERSION;
- opensbi_info.next_addr = uboot_entry;
+ opensbi_info.next_addr = os_entry;
opensbi_info.next_mode = FW_DYNAMIC_INFO_NEXT_MODE_S;
opensbi_info.options = CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS;
opensbi_info.boot_hart = gd->arch.boot_hart;
diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c
index d69069a75bf..3ac4b1b5091 100644
--- a/common/spl/spl_spi.c
+++ b/common/spl/spl_spi.c
@@ -10,12 +10,15 @@
#include <common.h>
#include <image.h>
+#include <imx_container.h>
#include <log.h>
+#include <mapmem.h>
#include <spi.h>
#include <spi_flash.h>
#include <errno.h>
#include <spl.h>
#include <asm/global_data.h>
+#include <asm/io.h>
#include <dm/ofnode.h>
#if CONFIG_IS_ENABLED(OS_BOOT)
@@ -133,13 +136,16 @@ static int spl_spi_load_image(struct spl_image_info *spl_image,
if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) &&
image_get_magic(header) == FDT_MAGIC) {
+ u32 size = roundup(fdt_totalsize(header), 4);
+
err = spi_flash_read(flash, payload_offs,
- roundup(fdt_totalsize(header), 4),
- (void *)CONFIG_SYS_LOAD_ADDR);
+ size,
+ map_sysmem(CONFIG_SYS_LOAD_ADDR,
+ size));
if (err)
return err;
err = spl_parse_image_header(spl_image, bootdev,
- (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR);
+ phys_to_virt(CONFIG_SYS_LOAD_ADDR));
} else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
image_get_magic(header) == FDT_MAGIC) {
struct spl_load_info load;
@@ -153,7 +159,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image,
err = spl_load_simple_fit(spl_image, &load,
payload_offs,
header);
- } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
+ } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
+ valid_container_hdr((void *)header)) {
struct spl_load_info load;
load.dev = flash;
@@ -170,7 +177,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image,
return err;
err = spi_flash_read(flash, payload_offs + spl_image->offset,
spl_image->size,
- (void *)spl_image->load_addr);
+ map_sysmem(spl_image->load_addr,
+ spl_image->size));
}
if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) {
err = spi_nor_remove(flash);
diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index df4fdfaba41..57e91d0f017 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=480
CONFIG_DRAM_EMR1=4
CONFIG_SYS_CLK_FREQ=912000000
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
index be49e9323a1..44770ffb048 100644
--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_SPL_SPI_SUNXI=y
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index 43cd28c3dd0..e10660c933c 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 7c77f38fba6..4ed666a034a 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
index 02116995a3e..ca5869f43d9 100644
--- a/configs/A20-OLinuXino_MICRO-eMMC_defconfig
+++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_I2C1_ENABLE=y
CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index 895e8dbcbd2..db4270f9b27 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_I2C1_ENABLE=y
CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig
index 5bcc9f9f3c0..ac900477d1e 100644
--- a/configs/A20-Olimex-SOM-EVB_defconfig
+++ b/configs/A20-Olimex-SOM-EVB_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="PH5"
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
index e5881090dda..00a98140b37 100644
--- a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_GMAC_TX_DELAY=4
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
index 592a79a6c7e..f4ae3ae6d8b 100644
--- a/configs/A20-Olimex-SOM204-EVB_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_GMAC_TX_DELAY=4
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig
index a5fe76af568..2cc7bbbd8b7 100644
--- a/configs/Bananapi_M2_Ultra_defconfig
+++ b/configs/Bananapi_M2_Ultra_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-r40-bananapi-m2-ultra"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_R40=y
CONFIG_DRAM_CLK=576
-CONFIG_MACPWR="PA17"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB1_VBUS_PIN="PH23"
CONFIG_USB2_VBUS_PIN="PH23"
diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
index 6c2a1f630e8..f4910ba13ac 100644
--- a/configs/Bananapi_defconfig
+++ b/configs/Bananapi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_VIDEO_COMPOSITE=y
CONFIG_GMAC_TX_DELAY=3
CONFIG_AHCI=y
diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
index 94fd74754ea..02be8971df9 100644
--- a/configs/Bananapro_defconfig
+++ b/configs/Bananapro_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapro"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_USB1_VBUS_PIN="PH0"
CONFIG_USB2_VBUS_PIN="PH1"
CONFIG_VIDEO_COMPOSITE=y
diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
index 0c233687413..ef4f11b7c62 100644
--- a/configs/Cubieboard2_defconfig
+++ b/configs/Cubieboard2_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-cubieboard2"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Cubieboard4_defconfig b/configs/Cubieboard4_defconfig
index 2f93a7b77c3..d3678ad5c75 100644
--- a/configs/Cubieboard4_defconfig
+++ b/configs/Cubieboard4_defconfig
@@ -11,6 +11,5 @@ CONFIG_USB1_VBUS_PIN="PH14"
CONFIG_USB3_VBUS_PIN="PH15"
CONFIG_AXP_GPIO=y
CONFIG_SYS_I2C_SUN8I_RSB=y
-CONFIG_DM_REGULATOR=y
CONFIG_REGULATOR_AXP_USB_POWER=y
CONFIG_AXP809_POWER=y
diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
index 71743f7b8a1..ab3f65ad667 100644
--- a/configs/Cubieboard_defconfig
+++ b/configs/Cubieboard_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-cubieboard"
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
index 184f305b19d..184143d7086 100644
--- a/configs/Cubietruck_defconfig
+++ b/configs/Cubietruck_defconfig
@@ -8,7 +8,6 @@ CONFIG_USB0_VBUS_PIN="PH17"
CONFIG_USB0_VBUS_DET="PH22"
CONFIG_USB0_ID_DET="PH19"
CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PH12"
CONFIG_GMAC_TX_DELAY=1
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
index 5d05f337982..d03fa62196b 100644
--- a/configs/Itead_Ibox_A20_defconfig
+++ b/configs/Itead_Ibox_A20_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-itead-ibox"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
index 5294608459b..66f57ab3c85 100644
--- a/configs/Lamobo_R1_defconfig
+++ b/configs/Lamobo_R1_defconfig
@@ -4,8 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-lamobo-r1"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
-CONFIG_SATAPWR="PB3"
CONFIG_GMAC_TX_DELAY=4
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
index e3e30a49490..9eb9a918aee 100644
--- a/configs/Linksprite_pcDuino3_Nano_defconfig
+++ b/configs/Linksprite_pcDuino3_Nano_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=408
CONFIG_DRAM_ZQ=122
CONFIG_USB1_VBUS_PIN="PH11"
-CONFIG_SATAPWR="PH2"
CONFIG_GMAC_TX_DELAY=3
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
index 1fda0db4c9d..7db10e685bc 100644
--- a/configs/Linksprite_pcDuino3_defconfig
+++ b/configs/Linksprite_pcDuino3_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
CONFIG_DRAM_ZQ=122
-CONFIG_SATAPWR="PH2"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig
index f5b6d908cdc..9ac2e4839d9 100644
--- a/configs/Mele_A1000_defconfig
+++ b/configs/Mele_A1000_defconfig
@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-a1000"
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
-CONFIG_MACPWR="PH15"
CONFIG_VIDEO_VGA=y
CONFIG_VIDEO_COMPOSITE=y
CONFIG_AHCI=y
diff --git a/configs/Merrii_A80_Optimus_defconfig b/configs/Merrii_A80_Optimus_defconfig
index f0c54e2af8e..a26677e1c05 100644
--- a/configs/Merrii_A80_Optimus_defconfig
+++ b/configs/Merrii_A80_Optimus_defconfig
@@ -11,6 +11,5 @@ CONFIG_USB1_VBUS_PIN="PH4"
CONFIG_USB3_VBUS_PIN="PH5"
CONFIG_AXP_GPIO=y
CONFIG_SYS_I2C_SUN8I_RSB=y
-CONFIG_DM_REGULATOR=y
CONFIG_REGULATOR_AXP_USB_POWER=y
CONFIG_AXP809_POWER=y
diff --git a/configs/Orangepi_defconfig b/configs/Orangepi_defconfig
index c89a9a1f9dd..53edf525ec0 100644
--- a/configs/Orangepi_defconfig
+++ b/configs/Orangepi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_USB1_VBUS_PIN="PH26"
CONFIG_USB2_VBUS_PIN="PH22"
CONFIG_VIDEO_VGA=y
diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
index fe9ce808a1e..ccf32670170 100644
--- a/configs/Orangepi_mini_defconfig
+++ b/configs/Orangepi_mini_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi-mini"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_USB1_VBUS_PIN="PH26"
CONFIG_USB2_VBUS_PIN="PH22"
diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
index 5642e52ec50..ad41dbd26a1 100644
--- a/configs/Sinovoip_BPI_M3_defconfig
+++ b/configs/Sinovoip_BPI_M3_defconfig
@@ -12,7 +12,6 @@ CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_ID_DET="PH11"
CONFIG_USB1_VBUS_PIN="PD24"
CONFIG_AXP_GPIO=y
-CONFIG_SATAPWR="PD25"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_CONSOLE_MUX=y
CONFIG_PHY_REALTEK=y
diff --git a/configs/ae350_rv32_falcon_defconfig b/configs/ae350_rv32_falcon_defconfig
new file mode 100644
index 00000000000..3f2993e371d
--- /dev/null
+++ b/configs/ae350_rv32_falcon_defconfig
@@ -0,0 +1,60 @@
+CONFIG_RISCV=y
+CONFIG_TEXT_BASE=0x01800000
+CONFIG_SYS_MALLOC_LEN=0x80000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_DEFAULT_DEVICE_TREE="ae350_32"
+CONFIG_SYS_MONITOR_LEN=786432
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000
+CONFIG_SPL=y
+CONFIG_SYS_LOAD_ADDR=0x100000
+CONFIG_TARGET_ANDES_AE350=y
+CONFIG_RISCV_SMODE=y
+# CONFIG_AVAILABLE_HARTS is not set
+CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
+CONFIG_SYS_MONITOR_BASE=0x88000000
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTDELAY=3
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL_MAX_SIZE=0x100000
+CONFIG_SPL_BSS_START_ADDR=0x400000
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_SYS_PBSIZE=1050
+CONFIG_SYS_BOOTM_LEN=0x4000000
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y
+CONFIG_FLASH_SHOW_PROGRESS=0
+CONFIG_SYS_CFI_FLASH_STATUS_POLL=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y
+# CONFIG_BINMAN_FDT is not set
diff --git a/configs/ae350_rv32_falcon_xip_defconfig b/configs/ae350_rv32_falcon_xip_defconfig
new file mode 100644
index 00000000000..e4f4c7807cc
--- /dev/null
+++ b/configs/ae350_rv32_falcon_xip_defconfig
@@ -0,0 +1,61 @@
+CONFIG_RISCV=y
+CONFIG_TEXT_BASE=0x01800000
+CONFIG_SYS_MALLOC_LEN=0x80000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_DEFAULT_DEVICE_TREE="ae350_32"
+CONFIG_SPL_TEXT_BASE=0x80000000
+CONFIG_SYS_MONITOR_LEN=786432
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000
+CONFIG_SPL=y
+CONFIG_SYS_LOAD_ADDR=0x100000
+CONFIG_TARGET_ANDES_AE350=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SPL_XIP=y
+CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
+CONFIG_SYS_MONITOR_BASE=0x88000000
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x80010000
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTDELAY=3
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL_MAX_SIZE=0x100000
+CONFIG_SPL_BSS_START_ADDR=0x400000
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_SYS_PBSIZE=1050
+CONFIG_SYS_BOOTM_LEN=0x4000000
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y
+CONFIG_FLASH_SHOW_PROGRESS=0
+CONFIG_SYS_CFI_FLASH_STATUS_POLL=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y
+# CONFIG_BINMAN_FDT is not set
diff --git a/configs/ae350_rv64_falcon_defconfig b/configs/ae350_rv64_falcon_defconfig
new file mode 100644
index 00000000000..4fb83d82404
--- /dev/null
+++ b/configs/ae350_rv64_falcon_defconfig
@@ -0,0 +1,60 @@
+CONFIG_RISCV=y
+CONFIG_TEXT_BASE=0x01800000
+CONFIG_SYS_MALLOC_LEN=0x80000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_DEFAULT_DEVICE_TREE="ae350_64"
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000
+CONFIG_SPL=y
+CONFIG_SYS_LOAD_ADDR=0x100000
+CONFIG_TARGET_ANDES_AE350=y
+CONFIG_ARCH_RV64I=y
+CONFIG_RISCV_SMODE=y
+# CONFIG_AVAILABLE_HARTS is not set
+CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
+CONFIG_SYS_MONITOR_BASE=0x88000000
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTDELAY=3
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL_MAX_SIZE=0x100000
+CONFIG_SPL_BSS_START_ADDR=0x400000
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_SYS_PBSIZE=1050
+CONFIG_SYS_BOOTM_LEN=0x4000000
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y
+CONFIG_FLASH_SHOW_PROGRESS=0
+CONFIG_SYS_CFI_FLASH_STATUS_POLL=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y
+# CONFIG_BINMAN_FDT is not set
diff --git a/configs/ae350_rv64_falcon_xip_defconfig b/configs/ae350_rv64_falcon_xip_defconfig
new file mode 100644
index 00000000000..45464260eee
--- /dev/null
+++ b/configs/ae350_rv64_falcon_xip_defconfig
@@ -0,0 +1,61 @@
+CONFIG_RISCV=y
+CONFIG_TEXT_BASE=0x01800000
+CONFIG_SYS_MALLOC_LEN=0x80000
+CONFIG_NR_DRAM_BANKS=2
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000
+CONFIG_ENV_SECT_SIZE=0x1000
+CONFIG_DEFAULT_DEVICE_TREE="ae350_64"
+CONFIG_SPL_TEXT_BASE=0x80000000
+CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000
+CONFIG_SPL=y
+CONFIG_SYS_LOAD_ADDR=0x100000
+CONFIG_TARGET_ANDES_AE350=y
+CONFIG_ARCH_RV64I=y
+CONFIG_RISCV_SMODE=y
+CONFIG_SPL_XIP=y
+CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
+CONFIG_SYS_MONITOR_BASE=0x88000000
+CONFIG_FIT=y
+CONFIG_SPL_LOAD_FIT_ADDRESS=0x80010000
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTDELAY=3
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_DISPLAY_BOARDINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SPL_MAX_SIZE=0x100000
+CONFIG_SPL_BSS_START_ADDR=0x400000
+CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_CACHE=y
+CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0
+CONFIG_SYS_PROMPT="RISC-V # "
+CONFIG_SYS_PBSIZE=1050
+CONFIG_SYS_BOOTM_LEN=0x4000000
+CONFIG_CMD_IMLS=y
+CONFIG_CMD_MMC=y
+CONFIG_CMD_SF_TEST=y
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_BOOTP_PREFER_SERVERIP=y
+CONFIG_CMD_CACHE=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_NET_RETRY_COUNT=50
+CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_MMC=y
+CONFIG_FTSDC010=y
+CONFIG_FTSDC010_SDIO=y
+CONFIG_MTD_NOR_FLASH=y
+CONFIG_FLASH_CFI_DRIVER=y
+CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y
+CONFIG_FLASH_SHOW_PROGRESS=0
+CONFIG_SYS_CFI_FLASH_STATUS_POLL=y
+CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
+CONFIG_SYS_FLASH_CFI=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_FTMAC100=y
+CONFIG_BAUDRATE=38400
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_ATCSPI200_SPI=y
+# CONFIG_BINMAN_FDT is not set
diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
index 0fbb619d623..a432a01f6b4 100644
--- a/configs/bananapi_m1_plus_defconfig
+++ b/configs/bananapi_m1_plus_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi-m1-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_VIDEO_COMPOSITE=y
CONFIG_GMAC_TX_DELAY=3
CONFIG_AHCI=y
diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig
index 26ced59fb02..a8f9b5044b0 100644
--- a/configs/bananapi_m2_plus_h3_defconfig
+++ b/configs/bananapi_m2_plus_h3_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig
index fb6c945919a..1634f626190 100644
--- a/configs/bananapi_m2_plus_h5_defconfig
+++ b/configs/bananapi_m2_plus_h5_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-bananapi-m2-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/deneb_defconfig b/configs/deneb_defconfig
index 82869e4e0f9..65b9809f467 100644
--- a/configs/deneb_defconfig
+++ b/configs/deneb_defconfig
@@ -22,8 +22,6 @@ CONFIG_SPL_STACK=0x13e000
CONFIG_SPL=y
CONFIG_ENV_OFFSET_REDUND=0x2000
CONFIG_IDENT_STRING=" ##v01.06"
-CONFIG_SPL_LOAD_IMX_CONTAINER=y
-CONFIG_IMX_CONTAINER_CFG="board/siemens/capricorn/uboot-container.cfg"
CONFIG_SYS_LOAD_ADDR=0x80280000
CONFIG_REMAKE_ELF=y
CONFIG_FIT=y
@@ -44,6 +42,10 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
CONFIG_SPL_BSS_START_ADDR=0x128000
CONFIG_SPL_BSS_MAX_SIZE=0x1000
CONFIG_SPL_BOARD_INIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
+CONFIG_IMX_CONTAINER_CFG="board/siemens/capricorn/uboot-container.cfg"
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
diff --git a/configs/giedi_defconfig b/configs/giedi_defconfig
index b56b736c436..3c3c7fbeb42 100644
--- a/configs/giedi_defconfig
+++ b/configs/giedi_defconfig
@@ -22,8 +22,6 @@ CONFIG_SPL_STACK=0x13e000
CONFIG_SPL=y
CONFIG_ENV_OFFSET_REDUND=0x2000
CONFIG_IDENT_STRING=" ##v01.07"
-CONFIG_SPL_LOAD_IMX_CONTAINER=y
-CONFIG_IMX_CONTAINER_CFG="board/siemens/capricorn/uboot-container.cfg"
CONFIG_SYS_LOAD_ADDR=0x80280000
CONFIG_REMAKE_ELF=y
CONFIG_FIT=y
@@ -44,6 +42,10 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
CONFIG_SPL_BSS_START_ADDR=0x128000
CONFIG_SPL_BSS_MAX_SIZE=0x1000
CONFIG_SPL_BOARD_INIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
+CONFIG_IMX_CONTAINER_CFG="board/siemens/capricorn/uboot-container.cfg"
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
index 257dd89af45..37f0f53ae7d 100644
--- a/configs/i12-tvbox_defconfig
+++ b/configs/i12-tvbox_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-i12-tvbox"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MACPWR="PH21"
CONFIG_VIDEO_COMPOSITE=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/imx8mp_dhcom_pdk3_defconfig b/configs/imx8mp_dhcom_pdk3_defconfig
index c20273ec944..c1f8fbd3ec3 100644
--- a/configs/imx8mp_dhcom_pdk3_defconfig
+++ b/configs/imx8mp_dhcom_pdk3_defconfig
@@ -175,6 +175,7 @@ CONFIG_FASTBOOT_FLASH_MMC_DEV=0
CONFIG_GPIO_HOG=y
CONFIG_SPL_GPIO_HOG=y
CONFIG_MXC_GPIO=y
+CONFIG_DM_PCA953X=y
CONFIG_DM_I2C=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA954x=y
@@ -262,4 +263,3 @@ CONFIG_USB_FUNCTION_ACM=y
CONFIG_USB_ETHER=y
CONFIG_USB_ETH_CDC=y
CONFIG_IMX_WATCHDOG=y
-CONFIG_DM_PCA953X=y
diff --git a/configs/imx8mp_evk_defconfig b/configs/imx8mp_evk_defconfig
index 820dc36e9cd..d538b85c1f8 100644
--- a/configs/imx8mp_evk_defconfig
+++ b/configs/imx8mp_evk_defconfig
@@ -139,5 +139,4 @@ CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="FSL"
CONFIG_USB_GADGET_VENDOR_NUM=0x0525
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
-CONFIG_SDP_LOADADDR=0x0
CONFIG_IMX_WATCHDOG=y
diff --git a/configs/imx8qm_mek_defconfig b/configs/imx8qm_mek_defconfig
index b9083b0453f..d7cf8699baf 100644
--- a/configs/imx8qm_mek_defconfig
+++ b/configs/imx8qm_mek_defconfig
@@ -20,8 +20,6 @@ CONFIG_SPL_SERIAL=y
CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK=0x13e000
CONFIG_SPL=y
-CONFIG_SPL_LOAD_IMX_CONTAINER=y
-CONFIG_IMX_CONTAINER_CFG="board/freescale/imx8qm_mek/uboot-container.cfg"
CONFIG_SYS_LOAD_ADDR=0x80280000
CONFIG_REMAKE_ELF=y
CONFIG_FIT=y
@@ -38,6 +36,10 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
CONFIG_SPL_BSS_START_ADDR=0x128000
CONFIG_SPL_BSS_MAX_SIZE=0x1000
CONFIG_SPL_BOARD_INIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
+CONFIG_IMX_CONTAINER_CFG="board/freescale/imx8qm_mek/uboot-container.cfg"
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
diff --git a/configs/imx8qxp_mek_defconfig b/configs/imx8qxp_mek_defconfig
index f516b0b5557..37c51474fc3 100644
--- a/configs/imx8qxp_mek_defconfig
+++ b/configs/imx8qxp_mek_defconfig
@@ -20,8 +20,6 @@ CONFIG_SPL_SERIAL=y
CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK=0x13e000
CONFIG_SPL=y
-CONFIG_SPL_LOAD_IMX_CONTAINER=y
-CONFIG_IMX_CONTAINER_CFG="board/freescale/imx8qxp_mek/uboot-container.cfg"
CONFIG_SYS_LOAD_ADDR=0x80280000
CONFIG_REMAKE_ELF=y
CONFIG_FIT=y
@@ -38,6 +36,10 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
CONFIG_SPL_BSS_START_ADDR=0x128000
CONFIG_SPL_BSS_MAX_SIZE=0x1000
CONFIG_SPL_BOARD_INIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
+CONFIG_IMX_CONTAINER_CFG="board/freescale/imx8qxp_mek/uboot-container.cfg"
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
diff --git a/configs/imx8ulp_evk_defconfig b/configs/imx8ulp_evk_defconfig
index 40a4dca250c..7a5147af377 100644
--- a/configs/imx8ulp_evk_defconfig
+++ b/configs/imx8ulp_evk_defconfig
@@ -19,7 +19,6 @@ CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK=0x22050000
CONFIG_SPL=y
CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x88000000
-CONFIG_SPL_LOAD_IMX_CONTAINER=y
CONFIG_SYS_LOAD_ADDR=0x80480000
CONFIG_REMAKE_ELF=y
CONFIG_FIT=y
@@ -36,6 +35,7 @@ CONFIG_SPL_BSS_START_ADDR=0x22048000
CONFIG_SPL_BSS_MAX_SIZE=0x2000
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_BOOTROM_SUPPORT=y
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
diff --git a/configs/imx93_11x11_evk_defconfig b/configs/imx93_11x11_evk_defconfig
index 1ea6524dbbf..9ced5ed0f65 100644
--- a/configs/imx93_11x11_evk_defconfig
+++ b/configs/imx93_11x11_evk_defconfig
@@ -18,7 +18,6 @@ CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK=0x20519dd0
CONFIG_SPL=y
CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x88000000
-CONFIG_SPL_LOAD_IMX_CONTAINER=y
CONFIG_SYS_LOAD_ADDR=0x80400000
CONFIG_SYS_MEMTEST_START=0x80000000
CONFIG_SYS_MEMTEST_END=0x90000000
@@ -33,6 +32,7 @@ CONFIG_SPL_BSS_START_ADDR=0x2051a000
CONFIG_SPL_BSS_MAX_SIZE=0x2000
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_BOOTROM_SUPPORT=y
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
diff --git a/configs/imx93_11x11_evk_ld_defconfig b/configs/imx93_11x11_evk_ld_defconfig
index 071f2fa3f31..abd646b6855 100644
--- a/configs/imx93_11x11_evk_ld_defconfig
+++ b/configs/imx93_11x11_evk_ld_defconfig
@@ -19,7 +19,6 @@ CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK=0x20519dd0
CONFIG_SPL=y
CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x88000000
-CONFIG_SPL_LOAD_IMX_CONTAINER=y
CONFIG_SYS_LOAD_ADDR=0x80400000
CONFIG_SYS_MEMTEST_START=0x80000000
CONFIG_SYS_MEMTEST_END=0x90000000
@@ -34,6 +33,7 @@ CONFIG_SPL_BSS_START_ADDR=0x2051a000
CONFIG_SPL_BSS_MAX_SIZE=0x2000
CONFIG_SPL_BOARD_INIT=y
CONFIG_SPL_BOOTROM_SUPPORT=y
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_SYS_MALLOC=y
CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
diff --git a/configs/jesurun_q5_defconfig b/configs/jesurun_q5_defconfig
index 0ff666b2ee5..c99be7cea4e 100644
--- a/configs/jesurun_q5_defconfig
+++ b/configs/jesurun_q5_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-jesurun-q5"
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
CONFIG_DRAM_CLK=312
-CONFIG_MACPWR="PH19"
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_VIDEO_COMPOSITE=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/kstr_sama5d27_defconfig b/configs/kstr_sama5d27_defconfig
new file mode 100644
index 00000000000..fa7a5495410
--- /dev/null
+++ b/configs/kstr_sama5d27_defconfig
@@ -0,0 +1,73 @@
+CONFIG_ARM=y
+CONFIG_ARCH_AT91=y
+CONFIG_TEXT_BASE=0x26f00000
+CONFIG_TARGET_KSTR_SAMA5D27=y
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20003ee0
+CONFIG_DM_GPIO=y
+CONFIG_DEFAULT_DEVICE_TREE="at91-kstr-sama5d27"
+CONFIG_OF_LIBFDT_OVERLAY=y
+CONFIG_DM_RESET=y
+CONFIG_SYS_MONITOR_LEN=524288
+CONFIG_SYS_LOAD_ADDR=0x24000000
+CONFIG_FIT=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_SD_BOOT=y
+CONFIG_BOOTDELAY=3
+CONFIG_OF_BOARD_SETUP=y
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rw rootwait"
+# CONFIG_USE_BOOTCOMMAND is not set
+# CONFIG_DISPLAY_BOARDINFO is not set
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_R=y
+CONFIG_CMD_TLV_EEPROM=y
+CONFIG_CMD_DM=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_I2C=y
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MMC=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_USB_MASS_STORAGE=y
+# CONFIG_ISO_PARTITION is not set
+CONFIG_OF_CONTROL=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_FAT=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_CLK=y
+CONFIG_CLK_AT91=y
+CONFIG_AT91_UTMI=y
+CONFIG_AT91_H32MX=y
+CONFIG_AT91_GENERIC_CLK=y
+CONFIG_ATMEL_PIO4=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_AT91=y
+CONFIG_I2C_EEPROM=y
+CONFIG_MICROCHIP_FLEXCOM=y
+CONFIG_MMC_IO_VOLTAGE=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
+CONFIG_MMC_SDHCI_ATMEL=y
+CONFIG_PHY_MICREL=y
+CONFIG_MACB=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_AT91PIO4=y
+CONFIG_RESET_AT91=y
+CONFIG_DM_SERIAL=y
+CONFIG_ATMEL_USART=y
+CONFIG_SYSRESET=y
+CONFIG_SYSRESET_AT91=y
+CONFIG_TEE=y
+CONFIG_OPTEE=y
+CONFIG_TIMER=y
+CONFIG_ATMEL_PIT_TIMER=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VENDOR_NUM=0x16c0
+CONFIG_USB_GADGET_PRODUCT_NUM=0x03e9
+CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+# CONFIG_EFI_LOADER is not set
diff --git a/configs/mangopi_mq_r_defconfig b/configs/mangopi_mq_r_defconfig
new file mode 100644
index 00000000000..66ae639326f
--- /dev/null
+++ b/configs/mangopi_mq_r_defconfig
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-mangopi-mq-r-t113"
+CONFIG_SPL=y
+CONFIG_MACH_SUN8I_R528=y
+CONFIG_DRAM_CLK=792
+CONFIG_DRAM_ZQ=8092667
+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_DRAM_SUNXI_ODT_EN=0
+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
+CONFIG_DRAM_SUNXI_TPR11=0x340000
+CONFIG_DRAM_SUNXI_TPR12=0x46
+CONFIG_DRAM_SUNXI_TPR13=0x34000100
+CONFIG_CONS_INDEX=4
diff --git a/configs/mixtile_loftq_defconfig b/configs/mixtile_loftq_defconfig
index 0e4cdc44670..2f92228eb7b 100644
--- a/configs/mixtile_loftq_defconfig
+++ b/configs/mixtile_loftq_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-mixtile-loftq"
CONFIG_SPL=y
CONFIG_MACH_SUN6I=y
CONFIG_DRAM_ZQ=251
-CONFIG_MACPWR="PA21"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB1_VBUS_PIN="PH24"
CONFIG_USB2_VBUS_PIN=""
diff --git a/configs/mx28evk_defconfig b/configs/mx28evk_defconfig
index 4058d08f961..905766b3b0c 100644
--- a/configs/mx28evk_defconfig
+++ b/configs/mx28evk_defconfig
@@ -67,7 +67,6 @@ CONFIG_DM_SERIAL=y
CONFIG_SPI=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_MAX_CONTROLLER_COUNT=2
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="FSL"
CONFIG_USB_GADGET_VENDOR_NUM=0x0525
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index 76655d79ae0..078e98b644d 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=408
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
index 924ff38f17c..85ff31c6fe5 100644
--- a/configs/nanopi_neo_plus2_defconfig
+++ b/configs/nanopi_neo_plus2_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=408
CONFIG_DRAM_ZQ=3881977
# CONFIG_DRAM_ODT_EN is not set
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/nanopi_r1s_h5_defconfig b/configs/nanopi_r1s_h5_defconfig
index 27cf172d72a..2a6f94afe40 100644
--- a/configs/nanopi_r1s_h5_defconfig
+++ b/configs/nanopi_r1s_h5_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=672
CONFIG_DRAM_ZQ=3881977
# CONFIG_DRAM_ODT_EN is not set
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/nsa325_defconfig b/configs/nsa325_defconfig
index d5fe9ca099c..539fcc4ac6c 100644
--- a/configs/nsa325_defconfig
+++ b/configs/nsa325_defconfig
@@ -14,7 +14,6 @@ CONFIG_TARGET_NSA325=y
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xC0000
CONFIG_DEFAULT_DEVICE_TREE="kirkwood-nsa325"
-CONFIG_SYS_PROMPT="NSA325> "
CONFIG_IDENT_STRING="\nZyXEL NSA325 2-Bay Power Media Server"
CONFIG_SYS_LOAD_ADDR=0x800000
CONFIG_PCI=y
@@ -28,6 +27,7 @@ CONFIG_SHOW_BOOT_PROGRESS=y
CONFIG_BOOTDELAY=10
CONFIG_USE_PREBOOT=y
CONFIG_BOARD_LATE_INIT=y
+CONFIG_SYS_PROMPT="NSA325> "
# CONFIG_BOOTM_PLAN9 is not set
# CONFIG_BOOTM_RTEMS is not set
# CONFIG_BOOTM_VXWORKS is not set
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
index 777af8c60ea..fb6fbaf787a 100644
--- a/configs/orangepi_pc2_defconfig
+++ b/configs/orangepi_pc2_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=672
CONFIG_DRAM_ZQ=3881977
-CONFIG_MACPWR="PD6"
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
index 138a6a72b8c..5e2cbc48ea2 100644
--- a/configs/orangepi_plus2e_defconfig
+++ b/configs/orangepi_plus2e_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus2e"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
index 76de72aa228..adffe389e9e 100644
--- a/configs/orangepi_plus_defconfig
+++ b/configs/orangepi_plus_defconfig
@@ -4,10 +4,9 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB1_VBUS_PIN="PG13"
-CONFIG_SATAPWR="PG11"
+CONFIG_USB3_VBUS_PIN="PG11"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
CONFIG_SPL_SYS_I2C_LEGACY=y
diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
index df11ad8c8fd..3ddaf050a48 100644
--- a/configs/orangepi_win_defconfig
+++ b/configs/orangepi_win_defconfig
@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win"
CONFIG_SPL=y
CONFIG_MACH_SUN50I=y
-CONFIG_MACPWR="PD14"
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPI_FLASH_WINBOND=y
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 6dac6098d04..4712b8e4694 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-pine-h64"
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_LPDDR3=y
-CONFIG_MACPWR="PC16"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB3_VBUS_PIN="PL5"
CONFIG_SPL_SPI_SUNXI=y
diff --git a/configs/pinebook_defconfig b/configs/pinebook_defconfig
index 26918dd3875..8d00a4f0a59 100644
--- a/configs/pinebook_defconfig
+++ b/configs/pinebook_defconfig
@@ -10,7 +10,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_R_I2C_ENABLE=y
CONFIG_SPL_SYS_I2C_LEGACY=y
CONFIG_SYS_I2C_MVTWSI=y
-CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_PWM=y
CONFIG_PWM_SUNXI=y
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/pogo_v4_defconfig b/configs/pogo_v4_defconfig
index cbbade3c0ca..2747c3c72d9 100644
--- a/configs/pogo_v4_defconfig
+++ b/configs/pogo_v4_defconfig
@@ -16,6 +16,7 @@ CONFIG_DEFAULT_DEVICE_TREE="kirkwood-pogoplug-series-4"
CONFIG_IDENT_STRING="\nPogoplug V4"
CONFIG_SYS_LOAD_ADDR=0x800000
CONFIG_PCI=y
+CONFIG_LTO=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_BOOTSTAGE=y
CONFIG_SHOW_BOOT_PROGRESS=y
diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig
index d39e54f98d2..db05e630832 100644
--- a/configs/sandbox_noinst_defconfig
+++ b/configs/sandbox_noinst_defconfig
@@ -4,13 +4,18 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x2000
+CONFIG_SPL_DM_SPI=y
CONFIG_DEFAULT_DEVICE_TREE="sandbox"
CONFIG_DM_RESET=y
+CONFIG_SPL_MMC=y
CONFIG_SPL_SERIAL=y
CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000
CONFIG_SPL=y
-CONFIG_SYS_LOAD_ADDR=0x0
+CONFIG_SPL_FS_FAT=y
+CONFIG_SPL_SPI_FLASH_SUPPORT=y
+CONFIG_SPL_SPI=y
+CONFIG_SYS_LOAD_ADDR=0x1000000
CONFIG_PCI=y
CONFIG_SANDBOX_SPL=y
CONFIG_DEBUG_UART=y
@@ -32,9 +37,26 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_SPL_NO_BSS_LIMIT=y
CONFIG_HANDOFF=y
CONFIG_SPL_BOARD_INIT=y
+# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
+CONFIG_SPL_LEGACY_IMAGE_FORMAT=y
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
+CONFIG_SPL_SYS_MALLOC=y
+CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
+CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000
+CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x0
CONFIG_SPL_ENV_SUPPORT=y
+CONFIG_SPL_ETH=y
+CONFIG_SPL_FS_EXT4=y
CONFIG_SPL_I2C=y
+CONFIG_SPL_MMC_WRITE=y
+CONFIG_SPL_DM_SPI_FLASH=y
+CONFIG_SPL_NET=y
+CONFIG_SPL_NOR_SUPPORT=y
CONFIG_SPL_RTC=y
+# CONFIG_SPL_SPI_FLASH_TINY is not set
+CONFIG_SPL_SPI_LOAD=y
CONFIG_CMD_CPU=y
CONFIG_CMD_LICENSE=y
CONFIG_CMD_BOOTZ=y
@@ -91,10 +113,13 @@ CONFIG_AMIGA_PARTITION=y
CONFIG_OF_CONTROL=y
CONFIG_SPL_OF_CONTROL=y
CONFIG_SPL_OF_PLATDATA=y
+CONFIG_SPL_OF_REAL=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_EXT4=y
CONFIG_ENV_EXT4_INTERFACE="host"
CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
+CONFIG_USE_BOOTFILE=y
+CONFIG_BOOTFILE="uImage"
CONFIG_BOOTP_SEND_HOSTNAME=y
CONFIG_NETCONSOLE=y
CONFIG_IP_DEFRAG=y
@@ -112,6 +137,7 @@ CONFIG_ADC=y
CONFIG_ADC_SANDBOX=y
CONFIG_AXI=y
CONFIG_AXI_SANDBOX=y
+CONFIG_SPL_BLK_FS=y
CONFIG_SYS_IDE_MAXBUS=1
CONFIG_SYS_ATA_BASE_ADDR=0x100
CONFIG_SYS_ATA_STRIDE=4
@@ -153,6 +179,7 @@ CONFIG_CROS_EC_SPI=y
CONFIG_P2SB=y
CONFIG_PWRSEQ=y
CONFIG_SPL_PWRSEQ=y
+CONFIG_FS_LOADER=y
CONFIG_MMC_SANDBOX=y
CONFIG_SPI_FLASH_SANDBOX=y
CONFIG_SPI_FLASH_ATMEL=y
@@ -214,6 +241,7 @@ CONFIG_SYSRESET=y
CONFIG_SPL_SYSRESET=y
CONFIG_DM_THERMAL=y
CONFIG_TIMER=y
+CONFIG_SPL_TIMER=y
CONFIG_TIMER_EARLY=y
CONFIG_SANDBOX_TIMER=y
CONFIG_USB=y
@@ -236,6 +264,7 @@ CONFIG_RSA_VERIFY_WITH_PKEY=y
CONFIG_TPM=y
CONFIG_LZ4=y
CONFIG_ZSTD=y
+CONFIG_SPL_LZMA=y
CONFIG_ERRNO_STR=y
CONFIG_EFI_CAPSULE_ON_DISK=y
CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index 4a67af2f088..56072b15ad2 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -32,9 +32,16 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_SPL_NO_BSS_LIMIT=y
CONFIG_HANDOFF=y
CONFIG_SPL_BOARD_INIT=y
+CONFIG_SPL_LEGACY_IMAGE_FORMAT=y
+CONFIG_SPL_LOAD_IMX_CONTAINER=y
+CONFIG_SPL_SYS_MALLOC=y
+CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y
+CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000
+CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000
CONFIG_SPL_ENV_SUPPORT=y
CONFIG_SPL_FPGA=y
CONFIG_SPL_I2C=y
+CONFIG_SPL_NOR_SUPPORT=y
CONFIG_SPL_RTC=y
CONFIG_CMD_CPU=y
CONFIG_CMD_LICENSE=y
@@ -243,6 +250,7 @@ CONFIG_TPM=y
CONFIG_SPL_CRC8=y
CONFIG_LZ4=y
CONFIG_ZSTD=y
+CONFIG_SPL_LZMA=y
CONFIG_ERRNO_STR=y
CONFIG_SPL_HEXDUMP=y
CONFIG_EFI_CAPSULE_ON_DISK=y
diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig
index 8d76f19729b..5bd0281796d 100644
--- a/configs/sandbox_vpl_defconfig
+++ b/configs/sandbox_vpl_defconfig
@@ -262,3 +262,4 @@ CONFIG_UNIT_TEST=y
CONFIG_SPL_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
+# CONFIG_SPL_UT_LOAD_OS is not set
diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig
index 6590727fe75..b21754feafc 100644
--- a/configs/starfive_visionfive2_defconfig
+++ b/configs/starfive_visionfive2_defconfig
@@ -31,6 +31,7 @@ CONFIG_RISCV_SMODE=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_FIT=y
CONFIG_DISTRO_DEFAULTS=y
+CONFIG_BOOTSTAGE=y
CONFIG_QSPI_BOOT=y
CONFIG_SD_BOOT=y
CONFIG_OF_BOARD_SETUP=y
@@ -72,6 +73,7 @@ CONFIG_CMD_I2C=y
CONFIG_CMD_PCI=y
CONFIG_CMD_USB=y
CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_BOOTSTAGE=y
CONFIG_OF_BOARD=y
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_NOWHERE=y
diff --git a/configs/teres_i_defconfig b/configs/teres_i_defconfig
index e7de85eb506..b9b22e77203 100644
--- a/configs/teres_i_defconfig
+++ b/configs/teres_i_defconfig
@@ -11,7 +11,6 @@ CONFIG_I2C0_ENABLE=y
CONFIG_PREBOOT="setenv usb_pgood_delay 2000; usb start"
CONFIG_SPL_SYS_I2C_LEGACY=y
CONFIG_SYS_I2C_MVTWSI=y
-CONFIG_DM_REGULATOR_FIXED=y
CONFIG_DM_PWM=y
CONFIG_PWM_SUNXI=y
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/usbarmory_defconfig b/configs/usbarmory_defconfig
index 277f055aef2..b717fc826ff 100644
--- a/configs/usbarmory_defconfig
+++ b/configs/usbarmory_defconfig
@@ -6,8 +6,6 @@ CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x2000
CONFIG_ENV_OFFSET=0x60000
CONFIG_TARGET_USBARMORY=y
-CONFIG_SYS_I2C_MXC_I2C1=y
-CONFIG_SYS_I2C_MXC_I2C2=y
CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="imx53-usbarmory"
# CONFIG_CMD_BMODE is not set
diff --git a/configs/zeropi_defconfig b/configs/zeropi_defconfig
index 11f3715e6dc..7901bffd159 100644
--- a/configs/zeropi_defconfig
+++ b/configs/zeropi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-zeropi"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=408
-CONFIG_MACPWR="PD6"
# CONFIG_VIDEO_DE2 is not set
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_CONSOLE_MUX=y
diff --git a/doc/develop/release_cycle.rst b/doc/develop/release_cycle.rst
index 72343386b50..29aff8df891 100644
--- a/doc/develop/release_cycle.rst
+++ b/doc/develop/release_cycle.rst
@@ -50,8 +50,7 @@ Current Status
* U-Boot v2023.10 was released on Mon 02 October 2023.
-* The Merge Window for the next release (v2024.01) is **open** until the -rc1
- release on Mon 23 October 2023.
+* The Merge Window for the next release (v2024.01) is **closed**.
* The next branch is now **closed**.
@@ -63,9 +62,9 @@ Future Releases
.. The following commented out dates are for when release candidates are
planned to be tagged.
-.. For the next scheduled release, release candidates were made on::
+For the next scheduled release, release candidates were made on::
-.. * U-Boot v2024.01-rc1 was released on Mon 23 October 2023.
+* U-Boot v2024.01-rc1 was released on Mon 23 October 2023.
.. * U-Boot v2024.01-rc2 was released on Mon 06 November 2023.
diff --git a/drivers/Makefile b/drivers/Makefile
index 74f940a57d3..bf73b7718ce 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
+obj-$(CONFIG_DRAM_SUN20I_D1) += ram/
obj-$(CONFIG_SPL_DM_RESET) += reset/
obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 6e30180b8b4..0b6f91098a3 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_SCSI_AHCI) += ahci.o
obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
obj-$(CONFIG_FSL_SATA) += fsl_sata.o
obj-$(CONFIG_LIBATA) += libata.o
-obj-$(CONFIG_SATA) += sata.o
+obj-$(CONFIG_SATA) += sata.o sata_bootdev.o
obj-$(CONFIG_SATA_CEVA) += sata_ceva.o
obj-$(CONFIG_SATA_MV) += sata_mv.o
obj-$(CONFIG_SATA_SIL) += sata_sil.o
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 94a3379c532..9064774e661 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -7,6 +7,7 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <linux/delay.h>
+#include <power/regulator.h>
#define AHCI_PHYCS0R 0x00c0
#define AHCI_PHYCS1R 0x00c4
@@ -74,6 +75,7 @@ static int sunxi_ahci_phy_init(u8 *reg_base)
static int sunxi_sata_probe(struct udevice *dev)
{
+ struct udevice *reg_dev;
ulong base;
u8 *reg;
int ret;
@@ -89,6 +91,13 @@ static int sunxi_sata_probe(struct udevice *dev)
debug("%s: Failed to init phy (err=%d)\n", __func__, ret);
return ret;
}
+
+ ret = device_get_supply_regulator(dev, "target-supply", &reg_dev);
+ if (ret == 0) {
+ regulator_set_enable(reg_dev, true);
+ mdelay(500);
+ }
+
ret = ahci_probe_scsi(dev, base);
if (ret) {
debug("%s: Failed to probe (err=%d)\n", __func__, ret);
diff --git a/drivers/ata/sata.c b/drivers/ata/sata.c
index ce3e9b5a400..dcb5fcf476b 100644
--- a/drivers/ata/sata.c
+++ b/drivers/ata/sata.c
@@ -15,6 +15,8 @@
#include <dm.h>
#include <part.h>
#include <sata.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
#ifndef CONFIG_AHCI
struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
@@ -50,6 +52,42 @@ int sata_scan(struct udevice *dev)
return ops->scan(dev);
}
+int sata_rescan(bool verbose)
+{
+ int ret;
+ struct udevice *dev;
+
+ if (verbose)
+ printf("Removing devices on SATA bus...\n");
+
+ blk_unbind_all(UCLASS_AHCI);
+
+ ret = uclass_find_first_device(UCLASS_AHCI, &dev);
+ if (ret || !dev) {
+ printf("Cannot find SATA device (err=%d)\n", ret);
+ return -ENOSYS;
+ }
+
+ ret = device_remove(dev, DM_REMOVE_NORMAL);
+ if (ret) {
+ printf("Cannot remove SATA device '%s' (err=%d)\n", dev->name, ret);
+ return -ENOSYS;
+ }
+
+ if (verbose)
+ printf("Rescanning SATA bus for devices...\n");
+
+ ret = uclass_probe_all(UCLASS_AHCI);
+
+ if (ret == -ENODEV) {
+ if (verbose)
+ printf("No SATA block device found\n");
+ return 0;
+ }
+
+ return ret;
+}
+
#ifndef CONFIG_AHCI
#ifdef CONFIG_PARTITIONS
struct blk_desc *sata_get_dev(int dev)
diff --git a/drivers/ata/sata_bootdev.c b/drivers/ata/sata_bootdev.c
new file mode 100644
index 00000000000..f638493ce04
--- /dev/null
+++ b/drivers/ata/sata_bootdev.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootdev for sata
+ *
+ * Copyright 2023 Tony Dinh <mibodhi@gmail.com>
+ */
+
+#include <common.h>
+#include <ahci.h>
+#include <bootdev.h>
+#include <dm.h>
+#include <init.h>
+#include <sata.h>
+
+static int sata_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 sata_bootdev_hunt(struct bootdev_hunter *info, bool show)
+{
+ int ret;
+
+ if (IS_ENABLED(CONFIG_PCI)) {
+ ret = pci_init();
+ if (ret)
+ return ret;
+ }
+
+ ret = sata_rescan(true);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+struct bootdev_ops sata_bootdev_ops = {
+};
+
+static const struct udevice_id sata_bootdev_ids[] = {
+ { .compatible = "u-boot,bootdev-sata" },
+ { }
+};
+
+U_BOOT_DRIVER(sata_bootdev) = {
+ .name = "sata_bootdev",
+ .id = UCLASS_BOOTDEV,
+ .ops = &sata_bootdev_ops,
+ .bind = sata_bootdev_bind,
+ .of_match = sata_bootdev_ids,
+};
+
+BOOTDEV_HUNTER(sata_bootdev_hunter) = {
+ .prio = BOOTDEVP_4_SCAN_FAST,
+ .uclass = UCLASS_AHCI,
+ .hunt = sata_bootdev_hunt,
+ .drv = DM_DRIVER_REF(sata_bootdev),
+};
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index bf11fad6eef..8bdc0944896 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -87,6 +87,13 @@ config CLK_SUN8I_H3
This enables common clock driver support for platforms based
on Allwinner H3/H5 SoC.
+config CLK_SUN20I_D1
+ bool "Clock driver for Allwinner D1"
+ default MACH_SUN8I_R528
+ help
+ This enables common clock driver support for platforms based
+ on Allwinner D1 SoC.
+
config CLK_SUN50I_H6
bool "Clock driver for Allwinner H6"
default MACH_SUN50I_H6
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 895da02ebea..90a277489dc 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
+obj-$(CONFIG_CLK_SUN20I_D1) += clk_d1.o
obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
obj-$(CONFIG_CLK_SUN50I_H6_R) += clk_h6_r.o
obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
diff --git a/drivers/clk/sunxi/clk_d1.c b/drivers/clk/sunxi/clk_d1.c
new file mode 100644
index 00000000000..9dae761de83
--- /dev/null
+++ b/drivers/clk/sunxi/clk_d1.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/sun20i-d1-ccu.h>
+#include <dt-bindings/reset/sun20i-d1-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate d1_gates[] = {
+ [CLK_APB0] = GATE_DUMMY,
+
+ [CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
+ [CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
+ [CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
+ [CLK_BUS_UART0] = GATE(0x90c, BIT(0)),
+ [CLK_BUS_UART1] = GATE(0x90c, BIT(1)),
+ [CLK_BUS_UART2] = GATE(0x90c, BIT(2)),
+ [CLK_BUS_UART3] = GATE(0x90c, BIT(3)),
+ [CLK_BUS_UART4] = GATE(0x90c, BIT(4)),
+ [CLK_BUS_UART5] = GATE(0x90c, BIT(5)),
+ [CLK_BUS_I2C0] = GATE(0x91c, BIT(0)),
+ [CLK_BUS_I2C1] = GATE(0x91c, BIT(1)),
+ [CLK_BUS_I2C2] = GATE(0x91c, BIT(2)),
+ [CLK_BUS_I2C3] = GATE(0x91c, BIT(3)),
+ [CLK_SPI0] = GATE(0x940, BIT(31)),
+ [CLK_SPI1] = GATE(0x944, BIT(31)),
+ [CLK_BUS_SPI0] = GATE(0x96c, BIT(0)),
+ [CLK_BUS_SPI1] = GATE(0x96c, BIT(1)),
+
+ [CLK_BUS_EMAC] = GATE(0x97c, BIT(0)),
+
+ [CLK_USB_OHCI0] = GATE(0xa70, BIT(31)),
+ [CLK_USB_OHCI1] = GATE(0xa74, BIT(31)),
+ [CLK_BUS_OHCI0] = GATE(0xa8c, BIT(0)),
+ [CLK_BUS_OHCI1] = GATE(0xa8c, BIT(1)),
+ [CLK_BUS_EHCI0] = GATE(0xa8c, BIT(4)),
+ [CLK_BUS_EHCI1] = GATE(0xa8c, BIT(5)),
+ [CLK_BUS_OTG] = GATE(0xa8c, BIT(8)),
+ [CLK_BUS_LRADC] = GATE(0xa9c, BIT(0)),
+
+ [CLK_RISCV] = GATE(0xd04, BIT(31)),
+};
+
+static struct ccu_reset d1_resets[] = {
+ [RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
+ [RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
+ [RST_BUS_MMC2] = RESET(0x84c, BIT(18)),
+ [RST_BUS_UART0] = RESET(0x90c, BIT(16)),
+ [RST_BUS_UART1] = RESET(0x90c, BIT(17)),
+ [RST_BUS_UART2] = RESET(0x90c, BIT(18)),
+ [RST_BUS_UART3] = RESET(0x90c, BIT(19)),
+ [RST_BUS_UART4] = RESET(0x90c, BIT(20)),
+ [RST_BUS_UART5] = RESET(0x90c, BIT(21)),
+ [RST_BUS_I2C0] = RESET(0x91c, BIT(16)),
+ [RST_BUS_I2C1] = RESET(0x91c, BIT(17)),
+ [RST_BUS_I2C2] = RESET(0x91c, BIT(18)),
+ [RST_BUS_I2C3] = RESET(0x91c, BIT(19)),
+ [RST_BUS_SPI0] = RESET(0x96c, BIT(16)),
+ [RST_BUS_SPI1] = RESET(0x96c, BIT(17)),
+
+ [RST_BUS_EMAC] = RESET(0x97c, BIT(16)),
+
+ [RST_USB_PHY0] = RESET(0xa70, BIT(30)),
+ [RST_USB_PHY1] = RESET(0xa74, BIT(30)),
+ [RST_BUS_OHCI0] = RESET(0xa8c, BIT(16)),
+ [RST_BUS_OHCI1] = RESET(0xa8c, BIT(17)),
+ [RST_BUS_EHCI0] = RESET(0xa8c, BIT(20)),
+ [RST_BUS_EHCI1] = RESET(0xa8c, BIT(21)),
+ [RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
+ [RST_BUS_LRADC] = RESET(0xa9c, BIT(16)),
+};
+
+const struct ccu_desc d1_ccu_desc = {
+ .gates = d1_gates,
+ .resets = d1_resets,
+ .num_gates = ARRAY_SIZE(d1_gates),
+ .num_resets = ARRAY_SIZE(d1_resets),
+};
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
index ec02a2d0370..1782cffc404 100644
--- a/drivers/clk/sunxi/clk_sunxi.c
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -118,6 +118,7 @@ extern const struct ccu_desc a64_ccu_desc;
extern const struct ccu_desc a80_ccu_desc;
extern const struct ccu_desc a80_mmc_clk_desc;
extern const struct ccu_desc a83t_ccu_desc;
+extern const struct ccu_desc d1_ccu_desc;
extern const struct ccu_desc f1c100s_ccu_desc;
extern const struct ccu_desc h3_ccu_desc;
extern const struct ccu_desc h6_ccu_desc;
@@ -195,6 +196,10 @@ static const struct udevice_id sunxi_clk_ids[] = {
{ .compatible = "allwinner,sun50i-h5-ccu",
.data = (ulong)&h3_ccu_desc },
#endif
+#ifdef CONFIG_CLK_SUN20I_D1
+ { .compatible = "allwinner,sun20i-d1-ccu",
+ .data = (ulong)&d1_ccu_desc },
+#endif
#ifdef CONFIG_CLK_SUN50I_H6
{ .compatible = "allwinner,sun50i-h6-ccu",
.data = (ulong)&h6_ccu_desc },
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index bce0a3f65cb..acbd2bf2cef 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)OF_LIVE) += of_access.o of_addr.o
ifndef CONFIG_DM_DEV_READ_INLINE
obj-$(CONFIG_OF_CONTROL) += read.o
endif
+obj-$(CONFIG_$(SPL_)OF_PLATDATA) += read.o
obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o
ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 126b3140666..d4ae652bcfb 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -426,7 +426,7 @@ void dm_get_mem(struct dm_stats *stats)
stats->tag_size;
}
-#ifdef CONFIG_ACPIGEN
+#if CONFIG_IS_ENABLED(ACPIGEN)
static int root_acpi_get_name(const struct udevice *dev, char *out_name)
{
return acpi_copy_name(out_name, "\\_SB");
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 74baa98d3c1..ba42b0768e1 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -372,6 +372,13 @@ config SUNXI_GPIO
help
Support the GPIO device in Allwinner SoCs.
+config SUNXI_NEW_PINCTRL
+ bool
+ depends on SUNXI_GPIO
+ ---help---
+ The Allwinner D1 and other new SoCs use a different register map
+ for the GPIO block, which we need to know about in the SPL.
+
config XILINX_GPIO
bool "Xilinx GPIO driver"
depends on DM_GPIO
diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c
index 49672193ffc..af6631697f5 100644
--- a/drivers/gpio/axp_gpio.c
+++ b/drivers/gpio/axp_gpio.c
@@ -14,6 +14,7 @@
#include <dm/lists.h>
#include <dm/root.h>
#include <errno.h>
+#include <sunxi_gpio.h>
static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val);
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index f0b42e4fdb7..e4463a223f7 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -17,37 +17,165 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <dt-bindings/gpio/gpio.h>
+#include <sunxi_gpio.h>
-#if !CONFIG_IS_ENABLED(DM_GPIO)
-static int sunxi_gpio_output(u32 pin, u32 val)
+/*
+ * =======================================================================
+ * Low level GPIO/pin controller access functions, to be shared by non-DM
+ * SPL code and the DM pinctrl/GPIO drivers.
+ * The functions ending in "bank" take a base pointer to a GPIO bank, and
+ * the pin offset is relative to that bank.
+ * The functions without "bank" in their name take a linear GPIO number,
+ * covering all ports, and starting at 0 for PortA.
+ * =======================================================================
+ */
+
+#define GPIO_BANK(pin) ((pin) >> 5)
+#define GPIO_NUM(pin) ((pin) & 0x1f)
+
+#define GPIO_CFG_REG_OFFSET 0x00
+#define GPIO_CFG_INDEX(pin) (((pin) & 0x1f) >> 3)
+#define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1f) & 0x7) << 2)
+
+#define GPIO_DAT_REG_OFFSET 0x10
+
+#define GPIO_DRV_REG_OFFSET 0x14
+
+/* Newer SoCs use a slightly different register layout */
+#ifdef CONFIG_SUNXI_NEW_PINCTRL
+/* pin drive strength: 4 bits per pin */
+#define GPIO_DRV_INDEX(pin) ((pin) / 8)
+#define GPIO_DRV_OFFSET(pin) (((pin) % 8) * 4)
+
+#define GPIO_PULL_REG_OFFSET 0x24
+
+#else /* older generation pin controllers */
+/* pin drive strength: 2 bits per pin */
+#define GPIO_DRV_INDEX(pin) ((pin) / 16)
+#define GPIO_DRV_OFFSET(pin) (((pin) % 16) * 2)
+
+#define GPIO_PULL_REG_OFFSET 0x1c
+#endif
+
+#define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
+#define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+
+static void* BANK_TO_GPIO(int bank)
+{
+ void *pio_base;
+
+ if (bank < SUNXI_GPIO_L) {
+ pio_base = (void *)(uintptr_t)SUNXI_PIO_BASE;
+ } else {
+ pio_base = (void *)(uintptr_t)SUNXI_R_PIO_BASE;
+ bank -= SUNXI_GPIO_L;
+ }
+
+ return pio_base + bank * SUNXI_PINCTRL_BANK_SIZE;
+}
+
+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
+{
+ u32 index = GPIO_CFG_INDEX(pin_offset);
+ u32 offset = GPIO_CFG_OFFSET(pin_offset);
+
+ clrsetbits_le32(bank_base + GPIO_CFG_REG_OFFSET + index * 4,
+ 0xfU << offset, val << offset);
+}
+
+void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
{
- u32 dat;
u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+ void *pio = BANK_TO_GPIO(bank);
- dat = readl(&pio->dat);
- if (val)
- dat |= 0x1 << num;
- else
- dat &= ~(0x1 << num);
+ sunxi_gpio_set_cfgbank(pio, GPIO_NUM(pin), val);
+}
+
+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset)
+{
+ u32 index = GPIO_CFG_INDEX(pin_offset);
+ u32 offset = GPIO_CFG_OFFSET(pin_offset);
+ u32 cfg;
- writel(dat, &pio->dat);
+ cfg = readl(bank_base + GPIO_CFG_REG_OFFSET + index * 4);
+ cfg >>= offset;
- return 0;
+ return cfg & 0xf;
+}
+
+int sunxi_gpio_get_cfgpin(u32 pin)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *bank_base = BANK_TO_GPIO(bank);
+
+ return sunxi_gpio_get_cfgbank(bank_base, GPIO_NUM(pin));
+}
+
+static void sunxi_gpio_set_value_bank(void *bank_base, int pin, bool set)
+{
+ u32 mask = 1U << pin;
+
+ clrsetbits_le32(bank_base + GPIO_DAT_REG_OFFSET,
+ set ? 0 : mask, set ? mask : 0);
+}
+
+static int sunxi_gpio_get_value_bank(void *bank_base, int pin)
+{
+ return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & (1U << pin));
+}
+
+void sunxi_gpio_set_drv(u32 pin, u32 val)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *bank_base = BANK_TO_GPIO(bank);
+
+ sunxi_gpio_set_drv_bank(bank_base, GPIO_NUM(pin), val);
+}
+
+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val)
+{
+ u32 index = GPIO_DRV_INDEX(pin_offset);
+ u32 offset = GPIO_DRV_OFFSET(pin_offset);
+
+ clrsetbits_le32(bank_base + GPIO_DRV_REG_OFFSET + index * 4,
+ 0x3U << offset, val << offset);
+}
+
+void sunxi_gpio_set_pull(u32 pin, u32 val)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *bank_base = BANK_TO_GPIO(bank);
+
+ sunxi_gpio_set_pull_bank(bank_base, GPIO_NUM(pin), val);
}
-static int sunxi_gpio_input(u32 pin)
+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val)
+{
+ u32 index = GPIO_PULL_INDEX(pin_offset);
+ u32 offset = GPIO_PULL_OFFSET(pin_offset);
+
+ clrsetbits_le32(bank_base + GPIO_PULL_REG_OFFSET + index * 4,
+ 0x3U << offset, val << offset);
+}
+
+
+/* =========== Non-DM code, used by the SPL. ============ */
+
+#if !CONFIG_IS_ENABLED(DM_GPIO)
+static void sunxi_gpio_set_value(u32 pin, bool set)
{
- u32 dat;
u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+ void *pio = BANK_TO_GPIO(bank);
+
+ sunxi_gpio_set_value_bank(pio, GPIO_NUM(pin), set);
+}
- dat = readl(&pio->dat);
- dat >>= num;
+static int sunxi_gpio_get_value(u32 pin)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *pio = BANK_TO_GPIO(bank);
- return dat & 0x1;
+ return sunxi_gpio_get_value_bank(pio, GPIO_NUM(pin));
}
int gpio_request(unsigned gpio, const char *label)
@@ -70,18 +198,21 @@ int gpio_direction_input(unsigned gpio)
int gpio_direction_output(unsigned gpio, int value)
{
sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
+ sunxi_gpio_set_value(gpio, value);
- return sunxi_gpio_output(gpio, value);
+ return 0;
}
int gpio_get_value(unsigned gpio)
{
- return sunxi_gpio_input(gpio);
+ return sunxi_gpio_get_value(gpio);
}
int gpio_set_value(unsigned gpio, int value)
{
- return sunxi_gpio_output(gpio, value);
+ sunxi_gpio_set_value(gpio, value);
+
+ return 0;
}
int sunxi_name_to_gpio(const char *name)
@@ -106,7 +237,9 @@ int sunxi_name_to_gpio(const char *name)
return -1;
return group * 32 + pin;
}
-#endif /* DM_GPIO */
+#endif /* !DM_GPIO */
+
+/* =========== DM code, used by U-Boot proper. ============ */
#if CONFIG_IS_ENABLED(DM_GPIO)
/* TODO(sjg@chromium.org): Remove this function and use device tree */
@@ -131,13 +264,8 @@ int sunxi_name_to_gpio(const char *name)
static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct sunxi_gpio_plat *plat = dev_get_plat(dev);
- u32 num = GPIO_NUM(offset);
- unsigned dat;
-
- dat = readl(&plat->regs->dat);
- dat >>= num;
- return dat & 0x1;
+ return sunxi_gpio_get_value_bank(plat->regs, offset);
}
static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
@@ -175,9 +303,8 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
if (flags & GPIOD_IS_OUT) {
u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
- u32 num = GPIO_NUM(offset);
- clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
+ sunxi_gpio_set_value_bank(plat->regs, offset, value);
sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
} else if (flags & GPIOD_IS_IN) {
u32 pull = 0;
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index d5b85f398db..a96a8c7e955 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -3,7 +3,7 @@
# (C) Copyright 2000-2007
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
obj-$(CONFIG_$(SPL_)DM_I2C) += i2c-uclass.o
-ifdef CONFIG_ACPIGEN
+ifdef CONFIG_$(SPL_)ACPIGEN
obj-$(CONFIG_$(SPL_)DM_I2C) += acpi_i2c.o
endif
obj-$(CONFIG_$(SPL_)DM_I2C_GPIO) += i2c-gpio.o
diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c
index 1107cf309fc..d421ddfcbe2 100644
--- a/drivers/i2c/i2c-emul-uclass.c
+++ b/drivers/i2c/i2c-emul-uclass.c
@@ -46,7 +46,7 @@ int i2c_emul_find(struct udevice *dev, struct udevice **emulp)
struct udevice *emul;
int ret;
- if (!CONFIG_IS_ENABLED(OF_PLATDATA)) {
+ if (CONFIG_IS_ENABLED(OF_REAL)) {
ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev,
"sandbox,emul", &emul);
} else {
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 14cdb0f6635..c38330f758a 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -124,7 +124,8 @@ enum mvtwsi_ctrl_register_fields {
* on other platforms, it is a normal r/w bit, which is cleared by writing 0.
*/
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || \
+ defined(CONFIG_SUNXI_GEN_NCAT2)
#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000008
#else
#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000000
diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c
index d221323295d..b8e07a533ca 100644
--- a/drivers/i2c/sun6i_p2wi.c
+++ b/drivers/i2c/sun6i_p2wi.c
@@ -20,10 +20,10 @@
#include <errno.h>
#include <i2c.h>
#include <reset.h>
+#include <sunxi_gpio.h>
#include <time.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/p2wi.h>
#include <asm/arch/prcm.h>
#include <asm/arch/sys_proto.h>
diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c
index 47fa05b6d1c..f36f2c7afac 100644
--- a/drivers/i2c/sun8i_rsb.c
+++ b/drivers/i2c/sun8i_rsb.c
@@ -14,10 +14,10 @@
#include <dm.h>
#include <errno.h>
#include <i2c.h>
+#include <sunxi_gpio.h>
#include <reset.h>
#include <time.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/prcm.h>
#include <asm/arch/rsb.h>
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 23bc7da917a..4d6351bf275 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -27,6 +27,7 @@
#include <asm/arch/cpu.h>
#include <asm/arch/mmc.h>
#include <linux/delay.h>
+#include <sunxi_gpio.h>
#ifndef CCM_MMC_CTRL_MODE_SEL_NEW
#define CCM_MMC_CTRL_MODE_SEL_NEW 0
@@ -56,6 +57,7 @@ static bool sunxi_mmc_can_calibrate(void)
return IS_ENABLED(CONFIG_MACH_SUN50I) ||
IS_ENABLED(CONFIG_MACH_SUN50I_H5) ||
IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
IS_ENABLED(CONFIG_MACH_SUN8I_R40);
}
@@ -190,7 +192,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc)
rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
writel(rval, &priv->reg->clkcr);
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
/* A64 supports calibration of delays on MMC controller and we
* have to set delay of zero before starting calibration.
* Allwinner BSP driver sets a delay only in the case of
@@ -543,7 +545,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
/* config ahb clock */
debug("init mmc %d clock and io\n", sdc_no);
-#if !defined(CONFIG_SUN50I_GEN_H6)
+#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
#ifdef CONFIG_SUNXI_GEN_SUN6I
@@ -618,7 +620,7 @@ static unsigned get_mclk_offset(void)
if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
return 0x410;
- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
return 0x830;
return 0x88;
@@ -705,6 +707,7 @@ static const struct udevice_id sunxi_mmc_ids[] = {
{ .compatible = "allwinner,sun50i-h6-emmc" },
{ .compatible = "allwinner,sun50i-a100-mmc" },
{ .compatible = "allwinner,sun50i-a100-emmc" },
+ { .compatible = "allwinner,sun20i-d1-mmc" },
{ /* sentinel */ }
};
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 04c3274fbe1..4ba9ee1529e 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -29,6 +29,7 @@
#include <net.h>
#include <reset.h>
#include <wait_bit.h>
+#include <power/regulator.h>
#define MDIO_CMD_MII_BUSY BIT(0)
#define MDIO_CMD_MII_WRITE BIT(1)
@@ -170,6 +171,7 @@ struct emac_eth_dev {
#if CONFIG_IS_ENABLED(DM_GPIO)
struct gpio_desc reset_gpio;
#endif
+ struct udevice *phy_reg;
};
@@ -720,6 +722,9 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
sun8i_emac_set_syscon(sun8i_pdata, priv);
+ if (priv->phy_reg)
+ regulator_set_enable(priv->phy_reg, true);
+
sun8i_mdio_init(dev->name, dev);
priv->bus = miiphy_get_dev_by_name(dev->name);
@@ -829,6 +834,8 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
+ device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
+
pdata->phy_interface = -1;
priv->phyaddr = -1;
priv->use_internal_phy = false;
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 4c90d4b4981..f546ad1fe8d 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -17,6 +17,7 @@
#include <net.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
+#include <power/regulator.h>
/* EMAC register */
struct emac_regs {
@@ -165,6 +166,7 @@ struct emac_eth_dev {
struct phy_device *phydev;
int link_printed;
uchar rx_buf[EMAC_RX_BUFSIZE];
+ struct udevice *phy_reg;
};
struct emac_rxhdr {
@@ -572,6 +574,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
if (ret)
return ret;
+ if (priv->phy_reg)
+ regulator_set_enable(priv->phy_reg, true);
+
return sunxi_emac_init_phy(priv, dev);
}
@@ -585,9 +590,42 @@ static const struct eth_ops sunxi_emac_eth_ops = {
static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
+ struct emac_eth_dev *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args args;
+ ofnode phy_node, mdio_node;
+ int ret;
pdata->iobase = dev_read_addr(dev);
+ phy_node = dev_get_phy_node(dev);
+ if (!ofnode_valid(phy_node)) {
+ dev_err(dev, "failed to get PHY node\n");
+ return -ENOENT;
+ }
+ /*
+ * The PHY regulator is in the MDIO node, not the EMAC or PHY node.
+ * U-Boot does not have (and does not need) a device driver for the
+ * MDIO device, so just "pass through" that DT node to get to the
+ * regulator phandle.
+ * The PHY regulator is optional, though: ignore if we cannot find
+ * a phy-supply property.
+ */
+ mdio_node = ofnode_get_parent(phy_node);
+ ret= ofnode_parse_phandle_with_args(mdio_node, "phy-supply", NULL, 0, 0,
+ &args);
+ if (ret && ret != -ENOENT) {
+ dev_err(dev, "failed to get PHY supply node\n");
+ return ret;
+ }
+ if (!ret) {
+ ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR, args.node,
+ &priv->phy_reg);
+ if (ret) {
+ dev_err(dev, "failed to get PHY regulator node\n");
+ return ret;
+ }
+ }
+
return 0;
}
diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c
index 4ba3992bda7..3958d2404b8 100644
--- a/drivers/phy/meson-g12a-usb2.c
+++ b/drivers/phy/meson-g12a-usb2.c
@@ -328,12 +328,12 @@ int meson_g12a_usb2_phy_probe(struct udevice *dev)
#if CONFIG_IS_ENABLED(POWER_DOMAIN)
ret = power_domain_get(dev, &priv->pwrdm);
- if (ret < 0 && ret != -ENODEV) {
- pr_err("failed to get power domain\n");
+ if (ret < 0 && ret != -ENODEV && ret != -ENOENT) {
+ pr_err("failed to get power domain : %d\n", ret);
return ret;
}
- if (ret != -ENODEV) {
+ if (ret != -ENODEV && ret != -ENOENT) {
ret = power_domain_on(&priv->pwrdm);
if (ret < 0) {
pr_err("failed to enable power domain\n");
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 77da90836b6..cbd61795986 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -124,4 +124,9 @@ config PINCTRL_SUN50I_H616_R
default MACH_SUN50I_H616
select PINCTRL_SUNXI
+config PINCTRL_SUN20I_D1
+ bool "Support for the Allwinner D1/R528 PIO"
+ default MACH_SUN8I_R528
+ select PINCTRL_SUNXI
+
endif
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index e5102180902..bdf6360f176 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -7,6 +7,7 @@
#include <dm/pinctrl.h>
#include <errno.h>
#include <malloc.h>
+#include <sunxi_gpio.h>
#include <asm/gpio.h>
@@ -35,7 +36,7 @@ struct sunxi_pinctrl_desc {
};
struct sunxi_pinctrl_plat {
- struct sunxi_gpio __iomem *base;
+ void __iomem *base;
};
static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
@@ -86,8 +87,8 @@ static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
sunxi_pinctrl_get_function_name(dev, func_selector),
desc->functions[func_selector].mux);
- sunxi_gpio_set_cfgbank(plat->base + bank, pin,
- desc->functions[func_selector].mux);
+ sunxi_gpio_set_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE,
+ pin, desc->functions[func_selector].mux);
return 0;
}
@@ -102,7 +103,7 @@ static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
uint bank, uint pin, uint bias)
{
- struct sunxi_gpio *regs = &plat->base[bank];
+ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
sunxi_gpio_set_pull_bank(regs, pin, bias);
@@ -112,7 +113,7 @@ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
uint bank, uint pin, uint drive)
{
- struct sunxi_gpio *regs = &plat->base[bank];
+ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
if (drive < 10 || drive > 40)
return -EINVAL;
@@ -148,7 +149,7 @@ static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
int pin = pin_selector % SUNXI_GPIOS_PER_BANK;
- int mux = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
+ int mux = sunxi_gpio_get_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE, pin);
switch (mux) {
case SUNXI_GPIO_INPUT:
@@ -206,7 +207,7 @@ static int sunxi_pinctrl_bind(struct udevice *dev)
if (!gpio_plat)
return -ENOMEM;
- gpio_plat->regs = plat->base + i;
+ gpio_plat->regs = plat->base + i * SUNXI_PINCTRL_BANK_SIZE;
gpio_plat->bank_name[0] = 'P';
gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
gpio_plat->bank_name[2] = '\0';
@@ -597,6 +598,32 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_r_pinctrl_desc =
.num_banks = 3,
};
+static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
+ { "emac", 8 }, /* PE0-PE15 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 4 }, /* PB10-PB11 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC2-PC7 */
+ { "spi0", 2 }, /* PC2-PC7 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2,PF4 */
+#else
+ { "uart0", 6 }, /* PB0-PB1, PB8-PB9, PE2-PE3 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 7 }, /* PB0-PB1 */
+ { "uart3", 7 }, /* PB6-PB7 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
+ .functions = sun20i_d1_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun20i_d1_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 7,
+};
+
static const struct sunxi_pinctrl_function sun50i_a64_pinctrl_functions[] = {
{ "emac", 4 }, /* PD8-PD23 */
{ "gpio_in", 0 },
@@ -862,6 +889,12 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
.data = (ulong)&sun9i_a80_r_pinctrl_desc,
},
#endif
+#ifdef CONFIG_PINCTRL_SUN20I_D1
+ {
+ .compatible = "allwinner,sun20i-d1-pinctrl",
+ .data = (ulong)&sun20i_d1_pinctrl_desc,
+ },
+#endif
#ifdef CONFIG_PINCTRL_SUN50I_A64
{
.compatible = "allwinner,sun50i-a64-pinctrl",
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index bf999645774..5b07e920301 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -109,8 +109,9 @@ config IMXRT_SDRAM
source "drivers/ram/aspeed/Kconfig"
source "drivers/ram/cadence/Kconfig"
+source "drivers/ram/octeon/Kconfig"
source "drivers/ram/rockchip/Kconfig"
source "drivers/ram/sifive/Kconfig"
source "drivers/ram/stm32mp1/Kconfig"
-source "drivers/ram/octeon/Kconfig"
source "drivers/ram/starfive/Kconfig"
+source "drivers/ram/sunxi/Kconfig"
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 6eb1a241359..985990ab5ac 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -23,6 +23,9 @@ obj-$(CONFIG_RAM_SIFIVE) += sifive/
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive/
endif
+
+obj-$(CONFIG_DRAM_SUN20I_D1) += sunxi/
+
obj-$(CONFIG_ARCH_OCTEON) += octeon/
obj-$(CONFIG_ARCH_RMOBILE) += renesas/
diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
new file mode 100644
index 00000000000..1775cb0d780
--- /dev/null
+++ b/drivers/ram/sunxi/Kconfig
@@ -0,0 +1,60 @@
+config DRAM_SUN20I_D1
+ bool
+ depends on ARCH_SUNXI
+ help
+ This enables support for the DRAM controller driver covering
+ the Allwinner D1/R528/T113s SoCs.
+
+if DRAM_SUN20I_D1
+
+config DRAM_SUNXI_ODT_EN
+ hex "DRAM ODT EN parameter"
+ help
+ ODT EN value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR0
+ hex "DRAM TPR0 parameter"
+ help
+ TPR0 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR11
+ hex "DRAM TPR11 parameter"
+ help
+ TPR11 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR12
+ hex "DRAM TPR12 parameter"
+ help
+ TPR12 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR13
+ hex "DRAM TPR13 parameter"
+ help
+ TPR13 value from vendor DRAM settings. It tells which features
+ should be configured.
+
+choice
+ prompt "DRAM chip type"
+ default SUNXI_DRAM_TYPE_DDR3 if DRAM_SUN20I_D1
+
+config SUNXI_DRAM_TYPE_DDR2
+ bool "DDR2 chips"
+
+config SUNXI_DRAM_TYPE_DDR3
+ bool "DDR3 chips"
+
+config SUNXI_DRAM_TYPE_LPDDR2
+ bool "LPDDR2 chips"
+
+config SUNXI_DRAM_TYPE_LPDDR3
+ bool "LPDDR3 chips"
+endchoice
+
+config SUNXI_DRAM_TYPE
+ int
+ default 2 if SUNXI_DRAM_TYPE_DDR2
+ default 3 if SUNXI_DRAM_TYPE_DDR3
+ default 6 if SUNXI_DRAM_TYPE_LPDDR2
+ default 7 if SUNXI_DRAM_TYPE_LPDDR3
+
+endif
diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
new file mode 100644
index 00000000000..86ea0b9ae98
--- /dev/null
+++ b/drivers/ram/sunxi/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
new file mode 100644
index 00000000000..38379281d73
--- /dev/null
+++ b/drivers/ram/sunxi/dram_sun20i_d1.c
@@ -0,0 +1,1441 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Allwinner D1/D1s/R528/T113-sx DRAM initialisation
+ *
+ * As usual there is no documentation for the memory controller or PHY IP
+ * used here. The baseline of this code was lifted from awboot[1], which
+ * seems to be based on some form of de-compilation of some original Allwinner
+ * code bits (with a GPL2 license tag from the very beginning).
+ * This version here is a reworked version, to match the U-Boot coding style
+ * and style of the other Allwinner DRAM drivers.
+ *
+ * [1] https://github.com/szemzoa/awboot.git
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#ifdef CONFIG_RAM
+ #include <dm.h>
+ #include <ram.h>
+#endif
+#include <linux/delay.h>
+
+#include "dram_sun20i_d1.h"
+
+#ifndef SUNXI_SID_BASE
+#define SUNXI_SID_BASE 0x3006200
+#endif
+
+#ifndef SUNXI_CCM_BASE
+#define SUNXI_CCM_BASE 0x2001000
+#endif
+
+static void sid_read_ldoB_cal(const dram_para_t *para)
+{
+ uint32_t reg;
+
+ reg = (readl(SUNXI_SID_BASE + 0x1c) & 0xff00) >> 8;
+
+ if (reg == 0)
+ return;
+
+ switch (para->dram_type) {
+ case SUNXI_DRAM_TYPE_DDR2:
+ break;
+ case SUNXI_DRAM_TYPE_DDR3:
+ if (reg > 0x20)
+ reg -= 0x16;
+ break;
+ default:
+ reg = 0;
+ break;
+ }
+
+ clrsetbits_le32(0x3000150, 0xff00, reg << 8);
+}
+
+static void dram_voltage_set(const dram_para_t *para)
+{
+ int vol;
+
+ switch (para->dram_type) {
+ case SUNXI_DRAM_TYPE_DDR2:
+ vol = 47;
+ break;
+ case SUNXI_DRAM_TYPE_DDR3:
+ vol = 25;
+ break;
+ default:
+ vol = 0;
+ break;
+ }
+
+ clrsetbits_le32(0x3000150, 0x20ff00, vol << 8);
+
+ udelay(1);
+
+ sid_read_ldoB_cal(para);
+}
+
+static void dram_enable_all_master(void)
+{
+ writel(~0, 0x3102020);
+ writel(0xff, 0x3102024);
+ writel(0xffff, 0x3102028);
+ udelay(10);
+}
+
+static void dram_disable_all_master(void)
+{
+ writel(1, 0x3102020);
+ writel(0, 0x3102024);
+ writel(0, 0x3102028);
+ udelay(10);
+}
+
+static void eye_delay_compensation(const dram_para_t *para)
+{
+ uint32_t delay;
+ unsigned long ptr;
+
+ // DATn0IOCR, n = 0...7
+ delay = (para->dram_tpr11 & 0xf) << 9;
+ delay |= (para->dram_tpr12 & 0xf) << 1;
+ for (ptr = 0x3103310; ptr < 0x3103334; ptr += 4)
+ setbits_le32(ptr, delay);
+
+ // DATn1IOCR, n = 0...7
+ delay = (para->dram_tpr11 & 0xf0) << 5;
+ delay |= (para->dram_tpr12 & 0xf0) >> 3;
+ for (ptr = 0x3103390; ptr != 0x31033b4; ptr += 4)
+ setbits_le32(ptr, delay);
+
+ // PGCR0: assert AC loopback FIFO reset
+ clrbits_le32(0x3103100, 0x04000000);
+
+ // ??
+
+ delay = (para->dram_tpr11 & 0xf0000) >> 7;
+ delay |= (para->dram_tpr12 & 0xf0000) >> 15;
+ setbits_le32(0x3103334, delay);
+ setbits_le32(0x3103338, delay);
+
+ delay = (para->dram_tpr11 & 0xf00000) >> 11;
+ delay |= (para->dram_tpr12 & 0xf00000) >> 19;
+ setbits_le32(0x31033b4, delay);
+ setbits_le32(0x31033b8, delay);
+
+ setbits_le32(0x310333c, (para->dram_tpr11 & 0xf0000) << 9);
+ setbits_le32(0x31033bc, (para->dram_tpr11 & 0xf00000) << 5);
+
+ // PGCR0: release AC loopback FIFO reset
+ setbits_le32(0x3103100, BIT(26));
+
+ udelay(1);
+
+ delay = (para->dram_tpr10 & 0xf0) << 4;
+ for (ptr = 0x3103240; ptr != 0x310327c; ptr += 4)
+ setbits_le32(ptr, delay);
+ for (ptr = 0x3103228; ptr != 0x3103240; ptr += 4)
+ setbits_le32(ptr, delay);
+
+ setbits_le32(0x3103218, (para->dram_tpr10 & 0x0f) << 8);
+ setbits_le32(0x310321c, (para->dram_tpr10 & 0x0f) << 8);
+
+ setbits_le32(0x3103280, (para->dram_tpr10 & 0xf00) >> 4);
+}
+
+/*
+ * Main purpose of the auto_set_timing routine seems to be to calculate all
+ * timing settings for the specific type of sdram used. Read together with
+ * an sdram datasheet for context on the various variables.
+ */
+static void mctl_set_timing_params(const dram_para_t *para,
+ const dram_config_t *config)
+{
+ /* DRAM_TPR0 */
+ u8 tccd = 2;
+ u8 tfaw;
+ u8 trrd;
+ u8 trcd;
+ u8 trc;
+
+ /* DRAM_TPR1 */
+ u8 txp;
+ u8 twtr;
+ u8 trtp = 4;
+ u8 twr;
+ u8 trp;
+ u8 tras;
+
+ /* DRAM_TPR2 */
+ u16 trefi;
+ u16 trfc;
+
+ u8 tcksrx;
+ u8 tckesr;
+ u8 trd2wr;
+ u8 twr2rd;
+ u8 trasmax;
+ u8 twtp;
+ u8 tcke;
+ u8 tmod;
+ u8 tmrd;
+ u8 tmrw;
+
+ u8 tcl;
+ u8 tcwl;
+ u8 t_rdata_en;
+ u8 wr_latency;
+
+ u32 mr0;
+ u32 mr1;
+ u32 mr2;
+ u32 mr3;
+
+ u32 tdinit0;
+ u32 tdinit1;
+ u32 tdinit2;
+ u32 tdinit3;
+
+ switch (para->dram_type) {
+ case SUNXI_DRAM_TYPE_DDR2:
+ /* DRAM_TPR0 */
+ tfaw = ns_to_t(50);
+ trrd = ns_to_t(10);
+ trcd = ns_to_t(20);
+ trc = ns_to_t(65);
+
+ /* DRAM_TPR1 */
+ txp = 2;
+ twtr = ns_to_t(8);
+ twr = ns_to_t(15);
+ trp = ns_to_t(15);
+ tras = ns_to_t(45);
+
+ /* DRAM_TRP2 */
+ trfc = ns_to_t(328);
+ trefi = ns_to_t(7800) / 32;
+
+ trasmax = CONFIG_DRAM_CLK / 30;
+ if (CONFIG_DRAM_CLK < 409) {
+ t_rdata_en = 1;
+ tcl = 3;
+ mr0 = 0x06a3;
+ } else {
+ t_rdata_en = 2;
+ tcl = 4;
+ mr0 = 0x0e73;
+ }
+ tmrd = 2;
+ twtp = twr + 5;
+ tcksrx = 5;
+ tckesr = 4;
+ trd2wr = 4;
+ tcke = 3;
+ tmod = 12;
+ wr_latency = 1;
+ tmrw = 0;
+ twr2rd = twtr + 5;
+ tcwl = 0;
+
+ mr1 = para->dram_mr1;
+ mr2 = 0;
+ mr3 = 0;
+
+ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
+ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
+ tdinit2 = 200 * CONFIG_DRAM_CLK + 1;
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
+
+ break;
+ case SUNXI_DRAM_TYPE_DDR3:
+ trfc = ns_to_t(350);
+ trefi = ns_to_t(7800) / 32 + 1; // XXX
+
+ twtr = ns_to_t(8) + 2; // + 2 ? XXX
+ /* Only used by trd2wr calculation, which gets discard below */
+// twr = max(ns_to_t(15), 2);
+ trrd = max(ns_to_t(10), 2);
+ txp = max(ns_to_t(10), 2);
+
+ if (CONFIG_DRAM_CLK <= 800) {
+ tfaw = ns_to_t(50);
+ trcd = ns_to_t(15);
+ trp = ns_to_t(15);
+ trc = ns_to_t(53);
+ tras = ns_to_t(38);
+
+ mr0 = 0x1c70;
+ mr2 = 0x18;
+ tcl = 6;
+ wr_latency = 2;
+ tcwl = 4;
+ t_rdata_en = 4;
+ } else {
+ tfaw = ns_to_t(35);
+ trcd = ns_to_t(14);
+ trp = ns_to_t(14);
+ trc = ns_to_t(48);
+ tras = ns_to_t(34);
+
+ mr0 = 0x1e14;
+ mr2 = 0x20;
+ tcl = 7;
+ wr_latency = 3;
+ tcwl = 5;
+ t_rdata_en = 5;
+ }
+
+ trasmax = CONFIG_DRAM_CLK / 30;
+ twtp = tcwl + 2 + twtr; // WL+BL/2+tWTR
+ /* Gets overwritten below */
+// trd2wr = tcwl + 2 + twr; // WL+BL/2+tWR
+ twr2rd = tcwl + twtr; // WL+tWTR
+
+ tdinit0 = 500 * CONFIG_DRAM_CLK + 1; // 500 us
+ tdinit1 = 360 * CONFIG_DRAM_CLK / 1000 + 1; // 360 ns
+ tdinit2 = 200 * CONFIG_DRAM_CLK + 1; // 200 us
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1; // 1 us
+
+ mr1 = para->dram_mr1;
+ mr3 = 0;
+ tcke = 3;
+ tcksrx = 5;
+ tckesr = 4;
+ if (((config->dram_tpr13 & 0xc) == 0x04) || CONFIG_DRAM_CLK < 912)
+ trd2wr = 5;
+ else
+ trd2wr = 6;
+
+ tmod = 12;
+ tmrd = 4;
+ tmrw = 0;
+
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR2:
+ tfaw = max(ns_to_t(50), 4);
+ trrd = max(ns_to_t(10), 1);
+ trcd = max(ns_to_t(24), 2);
+ trc = ns_to_t(70);
+ txp = ns_to_t(8);
+ if (txp < 2) {
+ txp++;
+ twtr = 2;
+ } else {
+ twtr = txp;
+ }
+ twr = max(ns_to_t(15), 2);
+ trp = ns_to_t(17);
+ tras = ns_to_t(42);
+ trefi = ns_to_t(3900) / 32;
+ trfc = ns_to_t(210);
+
+ trasmax = CONFIG_DRAM_CLK / 60;
+ mr3 = para->dram_mr3;
+ twtp = twr + 5;
+ mr2 = 6;
+ mr1 = 5;
+ tcksrx = 5;
+ tckesr = 5;
+ trd2wr = 10;
+ tcke = 2;
+ tmod = 5;
+ tmrd = 5;
+ tmrw = 3;
+ tcl = 4;
+ wr_latency = 1;
+ t_rdata_en = 1;
+
+ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
+ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
+ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
+ twr2rd = twtr + 5;
+ tcwl = 2;
+ mr1 = 195;
+ mr0 = 0;
+
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ tfaw = max(ns_to_t(50), 4);
+ trrd = max(ns_to_t(10), 1);
+ trcd = max(ns_to_t(24), 2);
+ trc = ns_to_t(70);
+ twtr = max(ns_to_t(8), 2);
+ twr = max(ns_to_t(15), 2);
+ trp = ns_to_t(17);
+ tras = ns_to_t(42);
+ trefi = ns_to_t(3900) / 32;
+ trfc = ns_to_t(210);
+ txp = twtr;
+
+ trasmax = CONFIG_DRAM_CLK / 60;
+ if (CONFIG_DRAM_CLK < 800) {
+ tcwl = 4;
+ wr_latency = 3;
+ t_rdata_en = 6;
+ mr2 = 12;
+ } else {
+ tcwl = 3;
+ tcke = 6;
+ wr_latency = 2;
+ t_rdata_en = 5;
+ mr2 = 10;
+ }
+ twtp = tcwl + 5;
+ tcl = 7;
+ mr3 = para->dram_mr3;
+ tcksrx = 5;
+ tckesr = 5;
+ trd2wr = 13;
+ tcke = 3;
+ tmod = 12;
+ tdinit0 = 400 * CONFIG_DRAM_CLK + 1;
+ tdinit1 = 500 * CONFIG_DRAM_CLK / 1000 + 1;
+ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
+ tmrd = 5;
+ tmrw = 5;
+ twr2rd = tcwl + twtr + 5;
+ mr1 = 195;
+ mr0 = 0;
+
+ break;
+ default:
+ trfc = 128;
+ trp = 6;
+ trefi = 98;
+ txp = 10;
+ twr = 8;
+ twtr = 3;
+ tras = 14;
+ tfaw = 16;
+ trc = 20;
+ trcd = 6;
+ trrd = 3;
+
+ twr2rd = 8;
+ tcksrx = 4;
+ tckesr = 3;
+ trd2wr = 4;
+ trasmax = 27;
+ twtp = 12;
+ tcke = 2;
+ tmod = 6;
+ tmrd = 2;
+ tmrw = 0;
+ tcwl = 3;
+ tcl = 3;
+ wr_latency = 1;
+ t_rdata_en = 1;
+ mr3 = 0;
+ mr2 = 0;
+ mr1 = 0;
+ mr0 = 0;
+ tdinit3 = 0;
+ tdinit2 = 0;
+ tdinit1 = 0;
+ tdinit0 = 0;
+
+ break;
+ }
+
+ /* Set mode registers */
+ writel(mr0, 0x3103030);
+ writel(mr1, 0x3103034);
+ writel(mr2, 0x3103038);
+ writel(mr3, 0x310303c);
+ /* TODO: dram_odt_en is either 0x0 or 0x1, so right shift looks weird */
+ writel((para->dram_odt_en >> 4) & 0x3, 0x310302c);
+
+ /* Set dram timing DRAMTMG0 - DRAMTMG5 */
+ writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0),
+ 0x3103058);
+ writel((txp << 16) | (trtp << 8) | (trc << 0),
+ 0x310305c);
+ writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0),
+ 0x3103060);
+ writel((tmrw << 16) | (tmrd << 12) | (tmod << 0),
+ 0x3103064);
+ writel((trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0),
+ 0x3103068);
+ writel((tcksrx << 24) | (tcksrx << 16) | (tckesr << 8) | (tcke << 0),
+ 0x310306c);
+
+ /* Set dual rank timing */
+ clrsetbits_le32(0x3103078, 0xf000ffff,
+ (CONFIG_DRAM_CLK < 800) ? 0xf0006610 : 0xf0007610);
+
+ /* Set phy interface time PITMG0, PTR3, PTR4 */
+ writel((0x2 << 24) | (t_rdata_en << 16) | BIT(8) | (wr_latency << 0),
+ 0x3103080);
+ writel(((tdinit0 << 0) | (tdinit1 << 20)), 0x3103050);
+ writel(((tdinit2 << 0) | (tdinit3 << 20)), 0x3103054);
+
+ /* Set refresh timing and mode */
+ writel((trefi << 16) | (trfc << 0), 0x3103090);
+ writel((trefi << 15) & 0x0fff0000, 0x3103094);
+}
+
+// Purpose of this routine seems to be to initialize the PLL driving
+// the MBUS and sdram.
+//
+static int ccu_set_pll_ddr_clk(int index, const dram_para_t *para,
+ const dram_config_t *config)
+{
+ unsigned int val, clk, n;
+
+ if (config->dram_tpr13 & BIT(6))
+ clk = para->dram_tpr9;
+ else
+ clk = para->dram_clk;
+
+ // set VCO clock divider
+ n = (clk * 2) / 24;
+
+ val = readl(SUNXI_CCM_BASE + 0x10);
+ val &= ~0x0007ff03; // clear dividers
+ val |= (n - 1) << 8; // set PLL division
+ val |= BIT(31) | BIT(30); // enable PLL and LDO
+ writel(val | BIT(29), SUNXI_CCM_BASE + 0x10);
+
+ // wait for PLL to lock
+ while ((readl(SUNXI_CCM_BASE + 0x10) & BIT(28)) == 0)
+ ;
+
+ udelay(20);
+
+ // enable PLL output
+ setbits_le32(SUNXI_CCM_BASE + 0x0, BIT(27));
+
+ // turn clock gate on
+ val = readl(SUNXI_CCM_BASE + 0x800);
+ val &= ~0x03000303; // select DDR clk source, n=1, m=1
+ val |= BIT(31); // turn clock on
+ writel(val, SUNXI_CCM_BASE + 0x800);
+
+ return n * 24;
+}
+
+/* Set up the PLL and clock gates for the DRAM controller and MBUS clocks. */
+static void mctl_sys_init(const dram_para_t *para, const dram_config_t *config)
+{
+ // assert MBUS reset
+ clrbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
+
+ // turn off sdram clock gate, assert sdram reset
+ clrbits_le32(SUNXI_CCM_BASE + 0x80c, 0x10001);
+ clrsetbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(30), BIT(27));
+ udelay(10);
+
+ // set ddr pll clock
+ ccu_set_pll_ddr_clk(0, para, config);
+ udelay(100);
+ dram_disable_all_master();
+
+ // release sdram reset
+ setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(16));
+
+ // release MBUS reset
+ setbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
+ setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(30));
+
+ udelay(5);
+
+ // turn on sdram clock gate
+ setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(0));
+
+ // turn dram clock gate on, trigger sdr clock update
+ setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(27));
+ udelay(5);
+
+ // mCTL clock enable
+ writel(0x8000, 0x310300c);
+ udelay(10);
+}
+
+// The main purpose of this routine seems to be to copy an address configuration
+// from the dram_para1 and dram_para2 fields to the PHY configuration registers
+// (0x3102000, 0x3102004).
+//
+static void mctl_com_init(const dram_para_t *para, const dram_config_t *config)
+{
+ uint32_t val, width;
+ unsigned long ptr;
+ int i;
+
+ // purpose ??
+ clrsetbits_le32(0x3102008, 0x3f00, 0x2000);
+
+ // set SDRAM type and word width
+ val = readl(0x3102000) & ~0x00fff000;
+ val |= (para->dram_type & 0x7) << 16; // DRAM type
+ val |= (~config->dram_para2 & 0x1) << 12; // DQ width
+ val |= BIT(22); // ??
+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
+ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
+ val |= BIT(19); // type 6 and 7 must use 1T
+ } else {
+ if (config->dram_tpr13 & BIT(5))
+ val |= BIT(19);
+ }
+ writel(val, 0x3102000);
+
+ // init rank / bank / row for single/dual or two different ranks
+ if ((config->dram_para2 & BIT(8)) &&
+ ((config->dram_para2 & 0xf000) != 0x1000))
+ width = 32;
+ else
+ width = 16;
+
+ ptr = 0x3102000;
+ for (i = 0; i < width; i += 16) {
+ val = readl(ptr) & 0xfffff000;
+
+ val |= (config->dram_para2 >> 12) & 0x3; // rank
+ val |= ((config->dram_para1 >> (i + 12)) << 2) & 0x4; // bank - 2
+ val |= (((config->dram_para1 >> (i + 4)) - 1) << 4) & 0xff; // row - 1
+
+ // convert from page size to column addr width - 3
+ switch ((config->dram_para1 >> i) & 0xf) {
+ case 8: val |= 0xa00; break;
+ case 4: val |= 0x900; break;
+ case 2: val |= 0x800; break;
+ case 1: val |= 0x700; break;
+ default: val |= 0x600; break;
+ }
+ writel(val, ptr);
+ ptr += 4;
+ }
+
+ // set ODTMAP based on number of ranks in use
+ val = (readl(0x3102000) & 0x1) ? 0x303 : 0x201;
+ writel(val, 0x3103120);
+
+ // set mctl reg 3c4 to zero when using half DQ
+ if (config->dram_para2 & BIT(0))
+ writel(0, 0x31033c4);
+
+ // purpose ??
+ if (para->dram_tpr4) {
+ setbits_le32(0x3102000, (para->dram_tpr4 & 0x3) << 25);
+ setbits_le32(0x3102004, (para->dram_tpr4 & 0x7fc) << 10);
+ }
+}
+
+static const uint8_t ac_remapping_tables[][22] = {
+ [0] = { 0 },
+ [1] = { 1, 9, 3, 7, 8, 18, 4, 13, 5, 6, 10,
+ 2, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [2] = { 4, 9, 3, 7, 8, 18, 1, 13, 2, 6, 10,
+ 5, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [3] = { 1, 7, 8, 12, 10, 18, 4, 13, 5, 6, 3,
+ 2, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [4] = { 4, 12, 10, 7, 8, 18, 1, 13, 2, 6, 3,
+ 5, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [5] = { 13, 2, 7, 9, 12, 19, 5, 1, 6, 3, 4,
+ 8, 10, 0, 0, 0, 21, 22, 18, 17, 11, 20 },
+ [6] = { 3, 10, 7, 13, 9, 11, 1, 2, 4, 6, 8,
+ 5, 12, 0, 0, 0, 20, 1, 0, 21, 22, 17 },
+ [7] = { 3, 2, 4, 7, 9, 1, 17, 12, 18, 14, 13,
+ 8, 15, 6, 10, 5, 19, 22, 16, 21, 20, 11 },
+};
+
+/*
+ * This routine chooses one of several remapping tables for 22 lines.
+ * It is unclear which lines are being remapped. It seems to pick
+ * table cfg7 for the Nezha board.
+ */
+static void mctl_phy_ac_remapping(const dram_para_t *para,
+ const dram_config_t *config)
+{
+ const uint8_t *cfg;
+ uint32_t fuse, val;
+
+ /*
+ * It is unclear whether the LPDDRx types don't need any remapping,
+ * or whether the original code just didn't provide tables.
+ */
+ if (para->dram_type != SUNXI_DRAM_TYPE_DDR2 &&
+ para->dram_type != SUNXI_DRAM_TYPE_DDR3)
+ return;
+
+ fuse = (readl(SUNXI_SID_BASE + 0x28) & 0xf00) >> 8;
+ debug("DDR efuse: 0x%x\n", fuse);
+
+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR2) {
+ if (fuse == 15)
+ return;
+ cfg = ac_remapping_tables[6];
+ } else {
+ if (config->dram_tpr13 & 0xc0000) {
+ cfg = ac_remapping_tables[7];
+ } else {
+ switch (fuse) {
+ case 8: cfg = ac_remapping_tables[2]; break;
+ case 9: cfg = ac_remapping_tables[3]; break;
+ case 10: cfg = ac_remapping_tables[5]; break;
+ case 11: cfg = ac_remapping_tables[4]; break;
+ default:
+ case 12: cfg = ac_remapping_tables[1]; break;
+ case 13:
+ case 14: cfg = ac_remapping_tables[0]; break;
+ }
+ }
+ }
+
+ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
+ (cfg[1] << 10) | (cfg[0] << 5);
+ writel(val, 0x3102500);
+
+ val = (cfg[10] << 25) | (cfg[9] << 20) | (cfg[8] << 15) |
+ (cfg[ 7] << 10) | (cfg[6] << 5) | cfg[5];
+ writel(val, 0x3102504);
+
+ val = (cfg[15] << 20) | (cfg[14] << 15) | (cfg[13] << 10) |
+ (cfg[12] << 5) | cfg[11];
+ writel(val, 0x3102508);
+
+ val = (cfg[21] << 25) | (cfg[20] << 20) | (cfg[19] << 15) |
+ (cfg[18] << 10) | (cfg[17] << 5) | cfg[16];
+ writel(val, 0x310250c);
+
+ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
+ (cfg[1] << 10) | (cfg[0] << 5) | 1;
+ writel(val, 0x3102500);
+}
+
+// Init the controller channel. The key part is placing commands in the main
+// command register (PIR, 0x3103000) and checking command status (PGSR0, 0x3103010).
+//
+static unsigned int mctl_channel_init(unsigned int ch_index,
+ const dram_para_t *para,
+ const dram_config_t *config)
+{
+ unsigned int val, dqs_gating_mode;
+
+ dqs_gating_mode = (config->dram_tpr13 & 0xc) >> 2;
+
+ // set DDR clock to half of CPU clock
+ clrsetbits_le32(0x310200c, 0xfff, (para->dram_clk / 2) - 1);
+
+ // MRCTRL0 nibble 3 undocumented
+ clrsetbits_le32(0x3103108, 0xf00, 0x300);
+
+ if (para->dram_odt_en)
+ val = 0;
+ else
+ val = BIT(5);
+
+ // DX0GCR0
+ if (para->dram_clk > 672)
+ clrsetbits_le32(0x3103344, 0xf63e, val);
+ else
+ clrsetbits_le32(0x3103344, 0xf03e, val);
+
+ // DX1GCR0
+ if (para->dram_clk > 672) {
+ setbits_le32(0x3103344, 0x400);
+ clrsetbits_le32(0x31033c4, 0xf63e, val);
+ } else {
+ clrsetbits_le32(0x31033c4, 0xf03e, val);
+ }
+
+ // 0x3103208 undocumented
+ setbits_le32(0x3103208, BIT(1));
+
+ eye_delay_compensation(para);
+
+ // set PLL SSCG ?
+ val = readl(0x3103108);
+ if (dqs_gating_mode == 1) {
+ clrsetbits_le32(0x3103108, 0xc0, 0);
+ clrbits_le32(0x31030bc, 0x107);
+ } else if (dqs_gating_mode == 2) {
+ clrsetbits_le32(0x3103108, 0xc0, 0x80);
+
+ clrsetbits_le32(0x31030bc, 0x107,
+ (((config->dram_tpr13 >> 16) & 0x1f) - 2) | 0x100);
+ clrsetbits_le32(0x310311c, BIT(31), BIT(27));
+ } else {
+ clrbits_le32(0x3103108, 0x40);
+ udelay(10);
+ setbits_le32(0x3103108, 0xc0);
+ }
+
+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
+ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
+ if (dqs_gating_mode == 1)
+ clrsetbits_le32(0x310311c, 0x080000c0, 0x80000000);
+ else
+ clrsetbits_le32(0x310311c, 0x77000000, 0x22000000);
+ }
+
+ clrsetbits_le32(0x31030c0, 0x0fffffff,
+ (config->dram_para2 & BIT(12)) ? 0x03000001 : 0x01000007);
+
+ if (readl(0x70005d4) & BIT(16)) {
+ clrbits_le32(0x7010250, 0x2);
+ udelay(10);
+ }
+
+ // Set ZQ config
+ clrsetbits_le32(0x3103140, 0x3ffffff,
+ (para->dram_zq & 0x00ffffff) | BIT(25));
+
+ // Initialise DRAM controller
+ if (dqs_gating_mode == 1) {
+ //writel(0x52, 0x3103000); // prep PHY reset + PLL init + z-cal
+ writel(0x53, 0x3103000); // Go
+
+ while ((readl(0x3103010) & 0x1) == 0) {
+ } // wait for IDONE
+ udelay(10);
+
+ // 0x520 = prep DQS gating + DRAM init + d-cal
+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
+ writel(0x5a0, 0x3103000); // + DRAM reset
+ else
+ writel(0x520, 0x3103000);
+ } else {
+ if ((readl(0x70005d4) & (1 << 16)) == 0) {
+ // prep DRAM init + PHY reset + d-cal + PLL init + z-cal
+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
+ writel(0x1f2, 0x3103000); // + DRAM reset
+ else
+ writel(0x172, 0x3103000);
+ } else {
+ // prep PHY reset + d-cal + z-cal
+ writel(0x62, 0x3103000);
+ }
+ }
+
+ setbits_le32(0x3103000, 0x1); // GO
+
+ udelay(10);
+ while ((readl(0x3103010) & 0x1) == 0) {
+ } // wait for IDONE
+
+ if (readl(0x70005d4) & BIT(16)) {
+ clrsetbits_le32(0x310310c, 0x06000000, 0x04000000);
+ udelay(10);
+
+ setbits_le32(0x3103004, 0x1);
+
+ while ((readl(0x3103018) & 0x7) != 0x3) {
+ }
+
+ clrbits_le32(0x7010250, 0x1);
+ udelay(10);
+
+ clrbits_le32(0x3103004, 0x1);
+
+ while ((readl(0x3103018) & 0x7) != 0x1) {
+ }
+
+ udelay(15);
+
+ if (dqs_gating_mode == 1) {
+ clrbits_le32(0x3103108, 0xc0);
+ clrsetbits_le32(0x310310c, 0x06000000, 0x02000000);
+ udelay(1);
+ writel(0x401, 0x3103000);
+
+ while ((readl(0x3103010) & 0x1) == 0) {
+ }
+ }
+ }
+
+ // Check for training error
+ if (readl(0x3103010) & BIT(20)) {
+ printf("ZQ calibration error, check external 240 ohm resistor\n");
+ return 0;
+ }
+
+ // STATR = Zynq STAT? Wait for status 'normal'?
+ while ((readl(0x3103018) & 0x1) == 0) {
+ }
+
+ setbits_le32(0x310308c, BIT(31));
+ udelay(10);
+ clrbits_le32(0x310308c, BIT(31));
+ udelay(10);
+ setbits_le32(0x3102014, BIT(31));
+ udelay(10);
+
+ clrbits_le32(0x310310c, 0x06000000);
+
+ if (dqs_gating_mode == 1)
+ clrsetbits_le32(0x310311c, 0xc0, 0x40);
+
+ return 1;
+}
+
+static unsigned int calculate_rank_size(uint32_t regval)
+{
+ unsigned int bits;
+
+ bits = (regval >> 8) & 0xf; /* page size - 3 */
+ bits += (regval >> 4) & 0xf; /* row width - 1 */
+ bits += (regval >> 2) & 0x3; /* bank count - 2 */
+ bits -= 14; /* 1MB = 20 bits, minus above 6 = 14 */
+
+ return 1U << bits;
+}
+
+/*
+ * The below routine reads the dram config registers and extracts
+ * the number of address bits in each rank available. It then calculates
+ * total memory size in MB.
+ */
+static unsigned int DRAMC_get_dram_size(void)
+{
+ uint32_t val;
+ unsigned int size;
+
+ val = readl(0x3102000); /* MC_WORK_MODE0 */
+ size = calculate_rank_size(val);
+ if ((val & 0x3) == 0) /* single rank? */
+ return size;
+
+ val = readl(0x3102004); /* MC_WORK_MODE1 */
+ if ((val & 0x3) == 0) /* two identical ranks? */
+ return size * 2;
+
+ /* add sizes of both ranks */
+ return size + calculate_rank_size(val);
+}
+
+/*
+ * The below routine reads the command status register to extract
+ * DQ width and rank count. This follows the DQS training command in
+ * channel_init. If error bit 22 is reset, we have two ranks and full DQ.
+ * If there was an error, figure out whether it was half DQ, single rank,
+ * or both. Set bit 12 and 0 in dram_para2 with the results.
+ */
+static int dqs_gate_detect(dram_config_t *config)
+{
+ uint32_t dx0, dx1;
+
+ if ((readl(0x3103010) & BIT(22)) == 0) {
+ config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
+ debug("dual rank and full DQ\n");
+
+ return 1;
+ }
+
+ dx0 = (readl(0x3103348) & 0x3000000) >> 24;
+ if (dx0 == 0) {
+ config->dram_para2 = (config->dram_para2 & ~0xf) | 0x1001;
+ debug("dual rank and half DQ\n");
+
+ return 1;
+ }
+
+ if (dx0 == 2) {
+ dx1 = (readl(0x31033c8) & 0x3000000) >> 24;
+ if (dx1 == 2) {
+ config->dram_para2 = config->dram_para2 & ~0xf00f;
+ debug("single rank and full DQ\n");
+ } else {
+ config->dram_para2 = (config->dram_para2 & ~0xf00f) | BIT(0);
+ debug("single rank and half DQ\n");
+ }
+
+ return 1;
+ }
+
+ if ((config->dram_tpr13 & BIT(29)) == 0)
+ return 0;
+
+ debug("DX0 state: %d\n", dx0);
+ debug("DX1 state: %d\n", dx1);
+
+ return 0;
+}
+
+static int dramc_simple_wr_test(unsigned int mem_mb, int len)
+{
+ unsigned int offs = (mem_mb / 2) << 18; // half of memory size
+ unsigned int patt1 = 0x01234567;
+ unsigned int patt2 = 0xfedcba98;
+ unsigned int *addr, v1, v2, i;
+
+ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i != len; i++, addr++) {
+ writel(patt1 + i, (unsigned long)addr);
+ writel(patt2 + i, (unsigned long)(addr + offs));
+ }
+
+ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i != len; i++) {
+ v1 = readl((unsigned long)(addr + i));
+ v2 = patt1 + i;
+ if (v1 != v2) {
+ printf("DRAM: simple test FAIL\n");
+ printf("%x != %x at address %p\n", v1, v2, addr + i);
+ return 1;
+ }
+ v1 = readl((unsigned long)(addr + offs + i));
+ v2 = patt2 + i;
+ if (v1 != v2) {
+ printf("DRAM: simple test FAIL\n");
+ printf("%x != %x at address %p\n", v1, v2, addr + offs + i);
+ return 1;
+ }
+ }
+
+ debug("DRAM: simple test OK\n");
+ return 0;
+}
+
+// Set the Vref mode for the controller
+//
+static void mctl_vrefzq_init(const dram_para_t *para, const dram_config_t *config)
+{
+ if (config->dram_tpr13 & BIT(17))
+ return;
+
+ clrsetbits_le32(0x3103110, 0x7f7f7f7f, para->dram_tpr5);
+
+ // IOCVR1
+ if ((config->dram_tpr13 & BIT(16)) == 0)
+ clrsetbits_le32(0x3103114, 0x7f, para->dram_tpr6 & 0x7f);
+}
+
+// Perform an init of the controller. This is actually done 3 times. The first
+// time to establish the number of ranks and DQ width. The second time to
+// establish the actual ram size. The third time is final one, with the final
+// settings.
+//
+static int mctl_core_init(const dram_para_t *para, const dram_config_t *config)
+{
+ mctl_sys_init(para, config);
+
+ mctl_vrefzq_init(para, config);
+
+ mctl_com_init(para, config);
+
+ mctl_phy_ac_remapping(para, config);
+
+ mctl_set_timing_params(para, config);
+
+ return mctl_channel_init(0, para, config);
+}
+
+/*
+ * This routine sizes a DRAM device by cycling through address lines and
+ * figuring out if they are connected to a real address line, or if the
+ * address is a mirror.
+ * First the column and bank bit allocations are set to low values (2 and 9
+ * address lines). Then a maximum allocation (16 lines) is set for rows and
+ * this is tested.
+ * Next the BA2 line is checked. This seems to be placed above the column,
+ * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
+ * and these are tested. The results are placed in dram_para1 and dram_para2.
+ */
+
+static uint32_t get_payload(bool odd, unsigned long int ptr)
+{
+ if (odd)
+ return (uint32_t)ptr;
+ else
+ return ~((uint32_t)ptr);
+}
+
+static int auto_scan_dram_size(const dram_para_t *para, dram_config_t *config)
+{
+ unsigned int rval, i, j, rank, maxrank, offs;
+ unsigned int shft;
+ unsigned long ptr, mc_work_mode, chk;
+
+ if (mctl_core_init(para, config) == 0) {
+ printf("DRAM initialisation error : 0\n");
+ return 0;
+ }
+
+ maxrank = (config->dram_para2 & 0xf000) ? 2 : 1;
+ mc_work_mode = 0x3102000;
+ offs = 0;
+
+ /* write test pattern */
+ for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
+ writel(get_payload(i & 0x1, ptr), ptr);
+
+ for (rank = 0; rank < maxrank;) {
+ /* set row mode */
+ clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
+ udelay(1);
+
+ // Scan per address line, until address wraps (i.e. see shadow)
+ for (i = 11; i < 17; i++) {
+ chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
+ ptr = CFG_SYS_SDRAM_BASE;
+ for (j = 0; j < 64; j++) {
+ if (readl(chk) != get_payload(j & 0x1, ptr))
+ break;
+ ptr += 4;
+ chk += 4;
+ }
+ if (j == 64)
+ break;
+ }
+ if (i > 16)
+ i = 16;
+ debug("rank %d row = %d\n", rank, i);
+
+ /* Store rows in para 1 */
+ shft = offs + 4;
+ rval = config->dram_para1;
+ rval &= ~(0xff << shft);
+ rval |= i << shft;
+ config->dram_para1 = rval;
+
+ if (rank == 1) /* Set bank mode for rank0 */
+ clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
+
+ /* Set bank mode for current rank */
+ clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
+ udelay(1);
+
+ // Test if bit A23 is BA2 or mirror XXX A22?
+ chk = CFG_SYS_SDRAM_BASE + (1U << 22);
+ ptr = CFG_SYS_SDRAM_BASE;
+ for (i = 0, j = 0; i < 64; i++) {
+ if (readl(chk) != get_payload(i & 1, ptr)) {
+ j = 1;
+ break;
+ }
+ ptr += 4;
+ chk += 4;
+ }
+
+ debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
+
+ /* Store banks in para 1 */
+ shft = 12 + offs;
+ rval = config->dram_para1;
+ rval &= ~(0xf << shft);
+ rval |= j << shft;
+ config->dram_para1 = rval;
+
+ if (rank == 1) /* Set page mode for rank0 */
+ clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
+
+ /* Set page mode for current rank */
+ clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
+ udelay(1);
+
+ // Scan per address line, until address wraps (i.e. see shadow)
+ for (i = 9; i < 14; i++) {
+ chk = CFG_SYS_SDRAM_BASE + (1U << i);
+ ptr = CFG_SYS_SDRAM_BASE;
+ for (j = 0; j < 64; j++) {
+ if (readl(chk) != get_payload(j & 1, ptr))
+ break;
+ ptr += 4;
+ chk += 4;
+ }
+ if (j == 64)
+ break;
+ }
+ if (i > 13)
+ i = 13;
+
+ unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
+ debug("rank %d page size = %d KB\n", rank, pgsize);
+
+ /* Store page size */
+ shft = offs;
+ rval = config->dram_para1;
+ rval &= ~(0xf << shft);
+ rval |= pgsize << shft;
+ config->dram_para1 = rval;
+
+ // Move to next rank
+ rank++;
+ if (rank != maxrank) {
+ if (rank == 1) {
+ /* MC_WORK_MODE */
+ clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
+
+ /* MC_WORK_MODE2 */
+ clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
+ }
+ /* store rank1 config in upper half of para1 */
+ offs += 16;
+ mc_work_mode += 4; /* move to MC_WORK_MODE2 */
+ }
+ }
+ if (maxrank == 2) {
+ config->dram_para2 &= 0xfffff0ff;
+ /* note: rval is equal to para->dram_para1 here */
+ if ((rval & 0xffff) == (rval >> 16)) {
+ debug("rank1 config same as rank0\n");
+ } else {
+ config->dram_para2 |= BIT(8);
+ debug("rank1 config different from rank0\n");
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * This routine sets up parameters with dqs_gating_mode equal to 1 and two
+ * ranks enabled. It then configures the core and tests for 1 or 2 ranks and
+ * full or half DQ width. It then resets the parameters to the original values.
+ * dram_para2 is updated with the rank and width findings.
+ */
+static int auto_scan_dram_rank_width(const dram_para_t *para,
+ dram_config_t *config)
+{
+ unsigned int s1 = config->dram_tpr13;
+ unsigned int s2 = config->dram_para1;
+
+ config->dram_para1 = 0x00b000b0;
+ config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
+
+ /* set DQS probe mode */
+ config->dram_tpr13 = (config->dram_tpr13 & ~0x8) | BIT(2) | BIT(0);
+
+ mctl_core_init(para, config);
+
+ if (readl(0x3103010) & BIT(20))
+ return 0;
+
+ if (dqs_gate_detect(config) == 0)
+ return 0;
+
+ config->dram_tpr13 = s1;
+ config->dram_para1 = s2;
+
+ return 1;
+}
+
+/*
+ * This routine determines the SDRAM topology. It first establishes the number
+ * of ranks and the DQ width. Then it scans the SDRAM address lines to establish
+ * the size of each rank. It then updates dram_tpr13 to reflect that the sizes
+ * are now known: a re-init will not repeat the autoscan.
+ */
+static int auto_scan_dram_config(const dram_para_t *para,
+ dram_config_t *config)
+{
+ if (((config->dram_tpr13 & BIT(14)) == 0) &&
+ (auto_scan_dram_rank_width(para, config) == 0)) {
+ printf("ERROR: auto scan dram rank & width failed\n");
+ return 0;
+ }
+
+ if (((config->dram_tpr13 & BIT(0)) == 0) &&
+ (auto_scan_dram_size(para, config) == 0)) {
+ printf("ERROR: auto scan dram size failed\n");
+ return 0;
+ }
+
+ if ((config->dram_tpr13 & BIT(15)) == 0)
+ config->dram_tpr13 |= BIT(14) | BIT(13) | BIT(1) | BIT(0);
+
+ return 1;
+}
+
+static int init_DRAM(int type, const dram_para_t *para)
+{
+ dram_config_t config = {
+ .dram_para1 = 0x000010d2,
+ .dram_para2 = 0,
+ .dram_tpr13 = CONFIG_DRAM_SUNXI_TPR13,
+ };
+ u32 rc, mem_size_mb;
+
+ debug("DRAM BOOT DRIVE INFO: %s\n", "V0.24");
+ debug("DRAM CLK = %d MHz\n", para->dram_clk);
+ debug("DRAM Type = %d (2:DDR2,3:DDR3)\n", para->dram_type);
+ if ((para->dram_odt_en & 0x1) == 0)
+ debug("DRAMC read ODT off\n");
+ else
+ debug("DRAMC ZQ value: 0x%x\n", para->dram_zq);
+
+ /* Test ZQ status */
+ if (config.dram_tpr13 & BIT(16)) {
+ debug("DRAM only have internal ZQ\n");
+ setbits_le32(0x3000160, BIT(8));
+ writel(0, 0x3000168);
+ udelay(10);
+ } else {
+ clrbits_le32(0x3000160, 0x3);
+ writel(config.dram_tpr13 & BIT(16), 0x7010254);
+ udelay(10);
+ clrsetbits_le32(0x3000160, 0x108, BIT(1));
+ udelay(10);
+ setbits_le32(0x3000160, BIT(0));
+ udelay(20);
+ debug("ZQ value = 0x%x\n", readl(0x300016c));
+ }
+
+ dram_voltage_set(para);
+
+ /* Set SDRAM controller auto config */
+ if ((config.dram_tpr13 & BIT(0)) == 0) {
+ if (auto_scan_dram_config(para, &config) == 0) {
+ printf("auto_scan_dram_config() FAILED\n");
+ return 0;
+ }
+ }
+
+ /* report ODT */
+ rc = para->dram_mr1;
+ if ((rc & 0x44) == 0)
+ debug("DRAM ODT off\n");
+ else
+ debug("DRAM ODT value: 0x%x\n", rc);
+
+ /* Init core, final run */
+ if (mctl_core_init(para, &config) == 0) {
+ printf("DRAM initialisation error: 1\n");
+ return 0;
+ }
+
+ /* Get SDRAM size */
+ /* TODO: who ever puts a negative number in the top half? */
+ rc = config.dram_para2;
+ if (rc & BIT(31)) {
+ rc = (rc >> 16) & ~BIT(15);
+ } else {
+ rc = DRAMC_get_dram_size();
+ debug("DRAM: size = %dMB\n", rc);
+ config.dram_para2 = (config.dram_para2 & 0xffffU) | rc << 16;
+ }
+ mem_size_mb = rc;
+
+ /* Purpose ?? */
+ if (config.dram_tpr13 & BIT(30)) {
+ rc = para->dram_tpr8;
+ if (rc == 0)
+ rc = 0x10000200;
+ writel(rc, 0x31030a0);
+ writel(0x40a, 0x310309c);
+ setbits_le32(0x3103004, BIT(0));
+ debug("Enable Auto SR\n");
+ } else {
+ clrbits_le32(0x31030a0, 0xffff);
+ clrbits_le32(0x3103004, 0x1);
+ }
+
+ /* Purpose ?? */
+ if (config.dram_tpr13 & BIT(9)) {
+ clrsetbits_le32(0x3103100, 0xf000, 0x5000);
+ } else {
+ if (para->dram_type != SUNXI_DRAM_TYPE_LPDDR2)
+ clrbits_le32(0x3103100, 0xf000);
+ }
+
+ setbits_le32(0x3103140, BIT(31));
+
+ /* CHECK: is that really writing to a different register? */
+ if (config.dram_tpr13 & BIT(8))
+ writel(readl(0x3103140) | 0x300, 0x31030b8);
+
+ if (config.dram_tpr13 & BIT(16))
+ clrbits_le32(0x3103108, BIT(13));
+ else
+ setbits_le32(0x3103108, BIT(13));
+
+ /* Purpose ?? */
+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR3)
+ clrsetbits_le32(0x310307c, 0xf0000, 0x1000);
+
+ dram_enable_all_master();
+ if (config.dram_tpr13 & BIT(28)) {
+ if ((readl(0x70005d4) & BIT(16)) ||
+ dramc_simple_wr_test(mem_size_mb, 4096))
+ return 0;
+ }
+
+ return mem_size_mb;
+}
+
+static const dram_para_t para = {
+ .dram_clk = CONFIG_DRAM_CLK,
+ .dram_type = CONFIG_SUNXI_DRAM_TYPE,
+ .dram_zq = CONFIG_DRAM_ZQ,
+ .dram_odt_en = CONFIG_DRAM_SUNXI_ODT_EN,
+ .dram_mr0 = 0x1c70,
+ .dram_mr1 = 0x42,
+ .dram_mr2 = 0x18,
+ .dram_mr3 = 0,
+ .dram_tpr0 = 0x004a2195,
+ .dram_tpr1 = 0x02423190,
+ .dram_tpr2 = 0x0008b061,
+ .dram_tpr3 = 0xb4787896, // unused
+ .dram_tpr4 = 0,
+ .dram_tpr5 = 0x48484848,
+ .dram_tpr6 = 0x00000048,
+ .dram_tpr7 = 0x1620121e, // unused
+ .dram_tpr8 = 0,
+ .dram_tpr9 = 0, // clock?
+ .dram_tpr10 = 0,
+ .dram_tpr11 = CONFIG_DRAM_SUNXI_TPR11,
+ .dram_tpr12 = CONFIG_DRAM_SUNXI_TPR12,
+};
+
+unsigned long sunxi_dram_init(void)
+{
+ return init_DRAM(0, &para) * 1024UL * 1024;
+};
+
+#ifdef CONFIG_RAM /* using the driver model */
+struct sunxi_ram_priv {
+ size_t size;
+};
+
+static int sunxi_ram_probe(struct udevice *dev)
+{
+ struct sunxi_ram_priv *priv = dev_get_priv(dev);
+ unsigned long dram_size;
+
+ debug("%s: %s: probing\n", __func__, dev->name);
+
+ dram_size = sunxi_dram_init();
+ if (!dram_size) {
+ printf("DRAM init failed\n");
+ return -ENODEV;
+ }
+
+ priv->size = dram_size;
+
+ return 0;
+}
+
+static int sunxi_ram_get_info(struct udevice *dev, struct ram_info *info)
+{
+ struct sunxi_ram_priv *priv = dev_get_priv(dev);
+
+ debug("%s: %s: getting info\n", __func__, dev->name);
+
+ info->base = CFG_SYS_SDRAM_BASE;
+ info->size = priv->size;
+
+ return 0;
+}
+
+static struct ram_ops sunxi_ram_ops = {
+ .get_info = sunxi_ram_get_info,
+};
+
+static const struct udevice_id sunxi_ram_ids[] = {
+ { .compatible = "allwinner,sun20i-d1-mbus" },
+ { }
+};
+
+U_BOOT_DRIVER(sunxi_ram) = {
+ .name = "sunxi_ram",
+ .id = UCLASS_RAM,
+ .of_match = sunxi_ram_ids,
+ .ops = &sunxi_ram_ops,
+ .probe = sunxi_ram_probe,
+ .priv_auto = sizeof(struct sunxi_ram_priv),
+};
+#endif /* CONFIG_RAM (using driver model) */
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.h b/drivers/ram/sunxi/dram_sun20i_d1.h
new file mode 100644
index 00000000000..91383f6cf10
--- /dev/null
+++ b/drivers/ram/sunxi/dram_sun20i_d1.h
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * D1/R528/T113 DRAM controller register and constant defines
+ *
+ * (C) Copyright 2022 Arm Ltd.
+ * Based on H6 and H616 header, which are:
+ * (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ */
+
+#ifndef _SUNXI_DRAM_SUN20I_D1_H
+#define _SUNXI_DRAM_SUN20I_D1_H
+
+enum sunxi_dram_type {
+ SUNXI_DRAM_TYPE_DDR2 = 2,
+ SUNXI_DRAM_TYPE_DDR3 = 3,
+ SUNXI_DRAM_TYPE_LPDDR2 = 6,
+ SUNXI_DRAM_TYPE_LPDDR3 = 7,
+};
+
+/*
+ * This structure contains a mixture of fixed configuration settings,
+ * variables that are used at runtime to communicate settings between
+ * different stages and functions, and unused values.
+ * This is copied from Allwinner's boot0 data structure, which can be
+ * found at offset 0x38 in any boot0 binary. To allow matching up some
+ * board specific settings, this struct is kept compatible, even though
+ * we don't need all members in our code.
+ */
+typedef struct dram_para {
+ /* normal configuration */
+ const u32 dram_clk;
+ const u32 dram_type;
+ const u32 dram_zq;
+ const u32 dram_odt_en;
+
+ /* timing configuration */
+ const u32 dram_mr0;
+ const u32 dram_mr1;
+ const u32 dram_mr2;
+ const u32 dram_mr3;
+ const u32 dram_tpr0; //DRAMTMG0
+ const u32 dram_tpr1; //DRAMTMG1
+ const u32 dram_tpr2; //DRAMTMG2
+ const u32 dram_tpr3; //DRAMTMG3
+ const u32 dram_tpr4; //DRAMTMG4
+ const u32 dram_tpr5; //DRAMTMG5
+ const u32 dram_tpr6; //DRAMTMG8
+ const u32 dram_tpr7;
+ const u32 dram_tpr8;
+ const u32 dram_tpr9;
+ const u32 dram_tpr10;
+ const u32 dram_tpr11;
+ const u32 dram_tpr12;
+} dram_para_t;
+
+typedef struct dram_config {
+ /* control configuration */
+ u32 dram_para1;
+ u32 dram_para2;
+ /* contains a bitfield of DRAM setup settings */
+ u32 dram_tpr13;
+} dram_config_t;
+
+static inline int ns_to_t(int nanoseconds)
+{
+ const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
+
+ return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
+}
+
+#endif /* _SUNXI_DRAM_SUN20I_D1_H */
diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c
index f4003811ee7..f6ac3d22852 100644
--- a/drivers/serial/sandbox.c
+++ b/drivers/serial/sandbox.c
@@ -280,7 +280,7 @@ U_BOOT_DRIVER(sandbox_serial) = {
.flags = DM_FLAG_PRE_RELOC,
};
-#if CONFIG_IS_ENABLED(OF_REAL)
+#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
static const struct sandbox_serial_plat platdata_non_fdt = {
.colour = -1,
};
diff --git a/drivers/serial/serial_meson.c b/drivers/serial/serial_meson.c
index 934de2ab235..be5f380f850 100644
--- a/drivers/serial/serial_meson.c
+++ b/drivers/serial/serial_meson.c
@@ -232,6 +232,7 @@ static const struct dm_serial_ops meson_serial_ops = {
static const struct udevice_id meson_serial_ids[] = {
{ .compatible = "amlogic,meson-uart" },
{ .compatible = "amlogic,meson-gx-uart" },
+ { .compatible = "amlogic,meson-a1-uart" },
{ }
};
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 36263109e6b..c034ab54e15 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -12,10 +12,12 @@
#include <asm/processor.h>
#include <clk.h>
#include <dm.h>
+#include <dm/device_compat.h>
#include <dm/platform_data/serial_sh.h>
#include <errno.h>
#include <linux/compiler.h>
#include <linux/delay.h>
+#include <reset.h>
#include <serial.h>
#include "serial_sh.h"
@@ -79,10 +81,22 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
static void handle_error(struct uart_port *port)
{
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ /*
+ * Most errors are cleared by resetting the relevant error bits to zero
+ * in the FSR & LSR registers. For each register, a read followed by a
+ * write is needed according to the relevant datasheets.
+ */
+ unsigned short status = sci_in(port, SCxSR);
+ sci_out(port, SCxSR, status & ~SCxSR_ERRORS(port));
sci_in(port, SCLSR);
sci_out(port, SCLSR, 0x00);
+
+ /*
+ * To clear framing errors, we also need to read and discard a
+ * character.
+ */
+ if ((port->type != PORT_SCI) && (status & SCIF_FER))
+ sci_in(port, SCxRDR);
}
static int serial_raw_putc(struct uart_port *port, const char c)
@@ -187,12 +201,24 @@ static int sh_serial_probe(struct udevice *dev)
{
struct sh_serial_plat *plat = dev_get_plat(dev);
struct uart_port *priv = dev_get_priv(dev);
+ struct reset_ctl rst;
+ int ret;
priv->membase = (unsigned char *)plat->base;
priv->mapbase = plat->base;
priv->type = plat->type;
priv->clk_mode = plat->clk_mode;
+ /* De-assert the module reset if it is defined. */
+ ret = reset_get_by_index(dev, 0, &rst);
+ if (!ret) {
+ ret = reset_deassert(&rst);
+ if (ret < 0) {
+ dev_err(dev, "failed to de-assert reset line\n");
+ return ret;
+ }
+ }
+
sh_serial_init_generic(priv);
return 0;
@@ -209,6 +235,7 @@ static const struct dm_serial_ops sh_serial_ops = {
static const struct udevice_id sh_serial_id[] ={
{.compatible = "renesas,sci", .data = PORT_SCI},
{.compatible = "renesas,scif", .data = PORT_SCIF},
+ {.compatible = "renesas,scif-r9a07g044", .data = PORT_SCIFA},
{.compatible = "renesas,scifa", .data = PORT_SCIFA},
{.compatible = "renesas,hscif", .data = PORT_HSCIF},
{}
diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h
index 149ec1fe739..58c2d22bc75 100644
--- a/drivers/serial/serial_sh.h
+++ b/drivers/serial/serial_sh.h
@@ -90,7 +90,7 @@ struct uart_port {
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_RCAR_GEN2) || defined(CONFIG_RCAR_64) || \
- defined(CONFIG_R7S72100)
+ defined(CONFIG_R7S72100) || defined(CONFIG_RZG2L)
# if defined(CFG_SCIF_A)
# define SCIF_ORER 0x0200
# else
@@ -312,6 +312,9 @@ static inline void sci_##name##_out(struct uart_port *port,\
sh4_scif_offset, sh4_scif_size)
#define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \
CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
+#elif defined(CONFIG_RZG2L)
+#define SCIF_FNS(reg_name, reg_offset, reg_size) \
+ CPU_SCIF_FNS(reg_name, reg_offset, reg_size)
#else
#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\
sh4_sci_offset, sh4_sci_size, \
@@ -387,6 +390,20 @@ SCIF_FNS(SCLSR, 0, 0, 0x14, 16)
#else
SCIF_FNS(SCLSR, 0, 0, 0x24, 16)
#endif
+#elif defined(CONFIG_RZG2L)
+SCIF_FNS(SCSMR, 0x00, 16)
+SCIF_FNS(SCBRR, 0x02, 8)
+SCIF_FNS(SCSCR, 0x04, 16)
+SCIF_FNS(SCxTDR, 0x06, 8)
+SCIF_FNS(SCxSR, 0x08, 16)
+SCIF_FNS(SCxRDR, 0x0A, 8)
+SCIF_FNS(SCFCR, 0x0C, 16)
+SCIF_FNS(SCFDR, 0x0E, 16)
+SCIF_FNS(SCSPTR, 0x10, 16)
+SCIF_FNS(SCLSR, 0x12, 16)
+SCIF_FNS(SCSEMR, 0x14, 8)
+SCIF_FNS(SCxTCR, 0x16, 16)
+SCIF_FNS(DL, 0x00, 0)
#else
/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/
/* name off sz off sz off sz off sz off sz*/
diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c
index 3750c60b9b9..f485a135299 100644
--- a/drivers/sysreset/sysreset_sandbox.c
+++ b/drivers/sysreset/sysreset_sandbox.c
@@ -132,7 +132,7 @@ U_BOOT_DRIVER(warm_sysreset_sandbox) = {
.ops = &sandbox_warm_sysreset_ops,
};
-#if CONFIG_IS_ENABLED(OF_REAL)
+#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
/* This is here in case we don't have a device tree */
U_BOOT_DRVINFO(sysreset_sandbox_non_fdt) = {
.name = "sysreset_sandbox",
diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
index 2b3a9c5fd4c..ee9384fb37e 100644
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -34,6 +34,7 @@
#include <spl.h>
#include <image.h>
#include <imximage.h>
+#include <imx_container.h>
#include <watchdog.h>
#define HID_REPORT_ID_MASK 0x000000ff
@@ -852,7 +853,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image,
return SDP_EXIT;
}
#endif
- if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
+ if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) &&
+ valid_container_hdr((void *)header)) {
struct spl_load_info load;
load.dev = header;
diff --git a/drivers/video/hitachi_tx18d42vm_lcd.c b/drivers/video/hitachi_tx18d42vm_lcd.c
index 87c4d27438a..95984fe3d3d 100644
--- a/drivers/video/hitachi_tx18d42vm_lcd.c
+++ b/drivers/video/hitachi_tx18d42vm_lcd.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <asm/gpio.h>
+#include <sunxi_gpio.h>
#include <errno.h>
/*
diff --git a/drivers/video/pwm_backlight.c b/drivers/video/pwm_backlight.c
index aa0e2928666..1c747d98d7a 100644
--- a/drivers/video/pwm_backlight.c
+++ b/drivers/video/pwm_backlight.c
@@ -100,8 +100,8 @@ static int enable_sequence(struct udevice *dev, int seq)
plat = dev_get_uclass_plat(priv->reg);
log_debug("Enable '%s', regulator '%s'/'%s'\n",
dev->name, priv->reg->name, plat->name);
- ret = regulator_set_enable(priv->reg, true);
- if (ret) {
+ ret = regulator_set_enable_if_allowed(priv->reg, true);
+ if (ret && ret != -ENOSYS) {
log_debug("Cannot enable regulator for PWM '%s'\n",
dev->name);
return log_ret(ret);
@@ -181,11 +181,10 @@ static int pwm_backlight_set_brightness(struct udevice *dev, int percent)
}
if (disable) {
dm_gpio_set_value(&priv->enable, 0);
- if (priv->reg) {
- ret = regulator_set_enable(priv->reg, false);
- if (ret)
- return log_ret(ret);
- }
+ ret = regulator_set_enable_if_allowed(priv->reg, false);
+ if (ret && ret != -ENOSYS)
+ return log_ret(ret);
+
priv->enabled = false;
}
diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c
index 6a6473eb0e5..efb122b534a 100644
--- a/drivers/video/simple_panel.c
+++ b/drivers/video/simple_panel.c
@@ -114,11 +114,11 @@ static int simple_panel_probe(struct udevice *dev)
const u32 dsi_data = dev_get_driver_data(dev);
int ret;
- if (CONFIG_IS_ENABLED(DM_REGULATOR) && priv->reg) {
- debug("%s: Enable regulator '%s'\n", __func__, priv->reg->name);
- ret = regulator_set_enable(priv->reg, true);
- if (ret)
- return ret;
+ ret = regulator_set_enable_if_allowed(priv->reg, true);
+ if (ret && ret != -ENOSYS) {
+ debug("%s: failed to enable regulator '%s' %d\n",
+ __func__, priv->reg->name, ret);
+ return ret;
}
switch (dsi_data) {
diff --git a/drivers/video/ssd2828.c b/drivers/video/ssd2828.c
index 4cdcbe7755a..948f5e74d0f 100644
--- a/drivers/video/ssd2828.c
+++ b/drivers/video/ssd2828.c
@@ -12,7 +12,6 @@
#include <common.h>
#include <malloc.h>
#include <mipi_display.h>
-#include <asm/arch/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index 9110a484821..8da44a1bb6d 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -31,6 +31,7 @@
#include <malloc.h>
#include <video.h>
#include <dm/uclass-internal.h>
+#include <sunxi_gpio.h>
#include "../videomodes.h"
#include "../anx9804.h"
#include "../hitachi_tx18d42vm_lcd.h"
diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c
index 8b9c3b2bfa9..7a01cc343ca 100644
--- a/drivers/video/sunxi/sunxi_lcd.c
+++ b/drivers/video/sunxi/sunxi_lcd.c
@@ -17,6 +17,7 @@
#include <asm/arch/lcdc.h>
#include <asm/global_data.h>
#include <asm/gpio.h>
+#include <sunxi_gpio.h>
struct sunxi_lcd_priv {
struct display_timing timing;
diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c
index 8c3404e085d..b4cf4fad5eb 100644
--- a/drivers/video/tegra20/tegra-dsi.c
+++ b/drivers/video/tegra20/tegra-dsi.c
@@ -831,11 +831,9 @@ static int tegra_dsi_bridge_probe(struct udevice *dev)
tegra_dsi_get_format(device->format, &priv->format);
- if (priv->avdd) {
- ret = regulator_set_enable(priv->avdd, true);
- if (ret)
- return ret;
- }
+ ret = regulator_set_enable_if_allowed(priv->avdd, true);
+ if (ret && ret != -ENOSYS)
+ return ret;
tegra_dsi_init_clocks(dev);
diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
index e56aa0ebe1d..57b61215a2a 100644
--- a/drivers/watchdog/npcm_wdt.c
+++ b/drivers/watchdog/npcm_wdt.c
@@ -69,15 +69,21 @@ static int npcm_wdt_stop(struct udevice *dev)
static int npcm_wdt_reset(struct udevice *dev)
{
struct npcm_wdt_priv *priv = dev_get_priv(dev);
+ u32 val;
- writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, priv->regs);
+ val = readl(priv->regs);
+ writel(val | NPCM_WTR, priv->regs);
return 0;
}
static int npcm_wdt_expire_now(struct udevice *dev, ulong flags)
{
- return npcm_wdt_reset(dev);
+ struct npcm_wdt_priv *priv = dev_get_priv(dev);
+
+ writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, priv->regs);
+
+ return 0;
}
static int npcm_wdt_of_to_plat(struct udevice *dev)
diff --git a/dts/Kconfig b/dts/Kconfig
index 9152f5885e9..00c0aeff893 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -410,12 +410,14 @@ config SPL_OF_PLATDATA
declarations for each node. See of-plat.txt for more information.
config SPL_OF_REAL
- bool
+ bool "Support a real devicetree in SPL" if SANDBOX
+ depends on SPL_OF_CONTROL
+ select SPL_OF_LIBFDT
help
Indicates that a real devicetree is available which can be accessed
at runtime. This means that dev_read_...() functions can be used to
- read data from the devicetree for each device. This is true if
- SPL_OF_CONTROL is enabled and not SPL_OF_PLATDATA
+ read data from the devicetree for each device. You do not need to
+ enable this option if you have enabled SPL_OF_PLATDATA.
if SPL_OF_PLATDATA
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index 9a9c520e22c..f50de7c089e 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -2373,10 +2373,6 @@ int ext4fs_mount(unsigned part_length)
struct ext2_data *data;
int status;
struct ext_filesystem *fs = get_fs();
-
- if (part_length < SUPERBLOCK_SIZE)
- return 0;
-
data = zalloc(SUPERBLOCK_SIZE);
if (!data)
return 0;
diff --git a/fs/fs.c b/fs/fs.c
index cfc781bbb8d..4cb4310c9cc 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -237,7 +237,7 @@ static struct fstype_info fstypes[] = {
.mkdir = fs_mkdir_unsupported,
},
#endif
-#ifdef CONFIG_SANDBOX
+#if IS_ENABLED(CONFIG_SANDBOX) && !IS_ENABLED(CONFIG_SPL_BUILD)
{
.fstype = FS_TYPE_SANDBOX,
.name = "sandbox",
diff --git a/include/configs/kstr-sama5d27.h b/include/configs/kstr-sama5d27.h
new file mode 100644
index 00000000000..772a073ba20
--- /dev/null
+++ b/include/configs/kstr-sama5d27.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2021-2023 Conclusive Engineering Sp. z o. o.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "at91-sama5_common.h"
+
+/* SDRAM */
+#define CFG_SYS_SDRAM_BASE 0x20000000
+#define CFG_SYS_SDRAM_SIZE 0x10000000
+
+#endif
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 4e5653dc886..2372485c84e 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -18,4 +18,7 @@
#define CFG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\
115200}
+/* Unused but necessary to build */
+#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE
+
#endif
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index d2d70f0fc23..b8ca77d031d 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -12,7 +12,6 @@
#ifndef _SUNXI_COMMON_CONFIG_H
#define _SUNXI_COMMON_CONFIG_H
-#include <asm/arch/cpu.h>
#include <linux/stringify.h>
/* Serial & console */
@@ -24,6 +23,7 @@
#define CFG_SYS_NS16550_CLK 24000000
#endif
#if !CONFIG_IS_ENABLED(DM_SERIAL)
+#include <asm/arch/serial.h>
# define CFG_SYS_NS16550_COM1 SUNXI_UART0_BASE
# define CFG_SYS_NS16550_COM2 SUNXI_UART1_BASE
# define CFG_SYS_NS16550_COM3 SUNXI_UART2_BASE
diff --git a/include/dt-bindings/clock/sun20i-d1-ccu.h b/include/dt-bindings/clock/sun20i-d1-ccu.h
new file mode 100644
index 00000000000..fdbfb404f92
--- /dev/null
+++ b/include/dt-bindings/clock/sun20i-d1-ccu.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
+#define _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
+
+#define CLK_PLL_CPUX 0
+#define CLK_PLL_DDR0 1
+#define CLK_PLL_PERIPH0_4X 2
+#define CLK_PLL_PERIPH0_2X 3
+#define CLK_PLL_PERIPH0_800M 4
+#define CLK_PLL_PERIPH0 5
+#define CLK_PLL_PERIPH0_DIV3 6
+#define CLK_PLL_VIDEO0_4X 7
+#define CLK_PLL_VIDEO0_2X 8
+#define CLK_PLL_VIDEO0 9
+#define CLK_PLL_VIDEO1_4X 10
+#define CLK_PLL_VIDEO1_2X 11
+#define CLK_PLL_VIDEO1 12
+#define CLK_PLL_VE 13
+#define CLK_PLL_AUDIO0_4X 14
+#define CLK_PLL_AUDIO0_2X 15
+#define CLK_PLL_AUDIO0 16
+#define CLK_PLL_AUDIO1 17
+#define CLK_PLL_AUDIO1_DIV2 18
+#define CLK_PLL_AUDIO1_DIV5 19
+#define CLK_CPUX 20
+#define CLK_CPUX_AXI 21
+#define CLK_CPUX_APB 22
+#define CLK_PSI_AHB 23
+#define CLK_APB0 24
+#define CLK_APB1 25
+#define CLK_MBUS 26
+#define CLK_DE 27
+#define CLK_BUS_DE 28
+#define CLK_DI 29
+#define CLK_BUS_DI 30
+#define CLK_G2D 31
+#define CLK_BUS_G2D 32
+#define CLK_CE 33
+#define CLK_BUS_CE 34
+#define CLK_VE 35
+#define CLK_BUS_VE 36
+#define CLK_BUS_DMA 37
+#define CLK_BUS_MSGBOX0 38
+#define CLK_BUS_MSGBOX1 39
+#define CLK_BUS_MSGBOX2 40
+#define CLK_BUS_SPINLOCK 41
+#define CLK_BUS_HSTIMER 42
+#define CLK_AVS 43
+#define CLK_BUS_DBG 44
+#define CLK_BUS_PWM 45
+#define CLK_BUS_IOMMU 46
+#define CLK_DRAM 47
+#define CLK_MBUS_DMA 48
+#define CLK_MBUS_VE 49
+#define CLK_MBUS_CE 50
+#define CLK_MBUS_TVIN 51
+#define CLK_MBUS_CSI 52
+#define CLK_MBUS_G2D 53
+#define CLK_MBUS_RISCV 54
+#define CLK_BUS_DRAM 55
+#define CLK_MMC0 56
+#define CLK_MMC1 57
+#define CLK_MMC2 58
+#define CLK_BUS_MMC0 59
+#define CLK_BUS_MMC1 60
+#define CLK_BUS_MMC2 61
+#define CLK_BUS_UART0 62
+#define CLK_BUS_UART1 63
+#define CLK_BUS_UART2 64
+#define CLK_BUS_UART3 65
+#define CLK_BUS_UART4 66
+#define CLK_BUS_UART5 67
+#define CLK_BUS_I2C0 68
+#define CLK_BUS_I2C1 69
+#define CLK_BUS_I2C2 70
+#define CLK_BUS_I2C3 71
+#define CLK_SPI0 72
+#define CLK_SPI1 73
+#define CLK_BUS_SPI0 74
+#define CLK_BUS_SPI1 75
+#define CLK_EMAC_25M 76
+#define CLK_BUS_EMAC 77
+#define CLK_IR_TX 78
+#define CLK_BUS_IR_TX 79
+#define CLK_BUS_GPADC 80
+#define CLK_BUS_THS 81
+#define CLK_I2S0 82
+#define CLK_I2S1 83
+#define CLK_I2S2 84
+#define CLK_I2S2_ASRC 85
+#define CLK_BUS_I2S0 86
+#define CLK_BUS_I2S1 87
+#define CLK_BUS_I2S2 88
+#define CLK_SPDIF_TX 89
+#define CLK_SPDIF_RX 90
+#define CLK_BUS_SPDIF 91
+#define CLK_DMIC 92
+#define CLK_BUS_DMIC 93
+#define CLK_AUDIO_DAC 94
+#define CLK_AUDIO_ADC 95
+#define CLK_BUS_AUDIO 96
+#define CLK_USB_OHCI0 97
+#define CLK_USB_OHCI1 98
+#define CLK_BUS_OHCI0 99
+#define CLK_BUS_OHCI1 100
+#define CLK_BUS_EHCI0 101
+#define CLK_BUS_EHCI1 102
+#define CLK_BUS_OTG 103
+#define CLK_BUS_LRADC 104
+#define CLK_BUS_DPSS_TOP 105
+#define CLK_HDMI_24M 106
+#define CLK_HDMI_CEC_32K 107
+#define CLK_HDMI_CEC 108
+#define CLK_BUS_HDMI 109
+#define CLK_MIPI_DSI 110
+#define CLK_BUS_MIPI_DSI 111
+#define CLK_TCON_LCD0 112
+#define CLK_BUS_TCON_LCD0 113
+#define CLK_TCON_TV 114
+#define CLK_BUS_TCON_TV 115
+#define CLK_TVE 116
+#define CLK_BUS_TVE_TOP 117
+#define CLK_BUS_TVE 118
+#define CLK_TVD 119
+#define CLK_BUS_TVD_TOP 120
+#define CLK_BUS_TVD 121
+#define CLK_LEDC 122
+#define CLK_BUS_LEDC 123
+#define CLK_CSI_TOP 124
+#define CLK_CSI_MCLK 125
+#define CLK_BUS_CSI 126
+#define CLK_TPADC 127
+#define CLK_BUS_TPADC 128
+#define CLK_BUS_TZMA 129
+#define CLK_DSP 130
+#define CLK_BUS_DSP_CFG 131
+#define CLK_RISCV 132
+#define CLK_RISCV_AXI 133
+#define CLK_BUS_RISCV_CFG 134
+#define CLK_FANOUT_24M 135
+#define CLK_FANOUT_12M 136
+#define CLK_FANOUT_16M 137
+#define CLK_FANOUT_25M 138
+#define CLK_FANOUT_32K 139
+#define CLK_FANOUT_27M 140
+#define CLK_FANOUT_PCLK 141
+#define CLK_FANOUT0 142
+#define CLK_FANOUT1 143
+#define CLK_FANOUT2 144
+#define CLK_BUS_CAN0 145
+#define CLK_BUS_CAN1 146
+
+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ */
diff --git a/include/dt-bindings/clock/sun20i-d1-r-ccu.h b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
new file mode 100644
index 00000000000..f95c170711e
--- /dev/null
+++ b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
+
+#define CLK_R_AHB 0
+
+#define CLK_BUS_R_TIMER 2
+#define CLK_BUS_R_TWD 3
+#define CLK_BUS_R_PPU 4
+#define CLK_R_IR_RX 5
+#define CLK_BUS_R_IR_RX 6
+#define CLK_BUS_R_RTC 7
+#define CLK_BUS_R_CPUCFG 8
+
+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ */
diff --git a/include/dt-bindings/clock/sun50i-h6-ccu.h b/include/dt-bindings/clock/sun50i-h6-ccu.h
index a1545cd60e7..ef9123d8193 100644
--- a/include/dt-bindings/clock/sun50i-h6-ccu.h
+++ b/include/dt-bindings/clock/sun50i-h6-ccu.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
*/
diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h
index 1191aca53ac..6f8f01e6762 100644
--- a/include/dt-bindings/clock/sun50i-h616-ccu.h
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2020 Arm Ltd.
*/
diff --git a/include/dt-bindings/clock/sun6i-rtc.h b/include/dt-bindings/clock/sun6i-rtc.h
index c845493e4d3..3bd3aa3d57c 100644
--- a/include/dt-bindings/clock/sun6i-rtc.h
+++ b/include/dt-bindings/clock/sun6i-rtc.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
#ifndef _DT_BINDINGS_CLK_SUN6I_RTC_H_
#define _DT_BINDINGS_CLK_SUN6I_RTC_H_
diff --git a/include/dt-bindings/reset/sun20i-d1-ccu.h b/include/dt-bindings/reset/sun20i-d1-ccu.h
new file mode 100644
index 00000000000..79e52aca591
--- /dev/null
+++ b/include/dt-bindings/reset/sun20i-d1-ccu.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
+#define _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
+
+#define RST_MBUS 0
+#define RST_BUS_DE 1
+#define RST_BUS_DI 2
+#define RST_BUS_G2D 3
+#define RST_BUS_CE 4
+#define RST_BUS_VE 5
+#define RST_BUS_DMA 6
+#define RST_BUS_MSGBOX0 7
+#define RST_BUS_MSGBOX1 8
+#define RST_BUS_MSGBOX2 9
+#define RST_BUS_SPINLOCK 10
+#define RST_BUS_HSTIMER 11
+#define RST_BUS_DBG 12
+#define RST_BUS_PWM 13
+#define RST_BUS_DRAM 14
+#define RST_BUS_MMC0 15
+#define RST_BUS_MMC1 16
+#define RST_BUS_MMC2 17
+#define RST_BUS_UART0 18
+#define RST_BUS_UART1 19
+#define RST_BUS_UART2 20
+#define RST_BUS_UART3 21
+#define RST_BUS_UART4 22
+#define RST_BUS_UART5 23
+#define RST_BUS_I2C0 24
+#define RST_BUS_I2C1 25
+#define RST_BUS_I2C2 26
+#define RST_BUS_I2C3 27
+#define RST_BUS_SPI0 28
+#define RST_BUS_SPI1 29
+#define RST_BUS_EMAC 30
+#define RST_BUS_IR_TX 31
+#define RST_BUS_GPADC 32
+#define RST_BUS_THS 33
+#define RST_BUS_I2S0 34
+#define RST_BUS_I2S1 35
+#define RST_BUS_I2S2 36
+#define RST_BUS_SPDIF 37
+#define RST_BUS_DMIC 38
+#define RST_BUS_AUDIO 39
+#define RST_USB_PHY0 40
+#define RST_USB_PHY1 41
+#define RST_BUS_OHCI0 42
+#define RST_BUS_OHCI1 43
+#define RST_BUS_EHCI0 44
+#define RST_BUS_EHCI1 45
+#define RST_BUS_OTG 46
+#define RST_BUS_LRADC 47
+#define RST_BUS_DPSS_TOP 48
+#define RST_BUS_HDMI_SUB 49
+#define RST_BUS_HDMI_MAIN 50
+#define RST_BUS_MIPI_DSI 51
+#define RST_BUS_TCON_LCD0 52
+#define RST_BUS_TCON_TV 53
+#define RST_BUS_LVDS0 54
+#define RST_BUS_TVE 55
+#define RST_BUS_TVE_TOP 56
+#define RST_BUS_TVD 57
+#define RST_BUS_TVD_TOP 58
+#define RST_BUS_LEDC 59
+#define RST_BUS_CSI 60
+#define RST_BUS_TPADC 61
+#define RST_DSP 62
+#define RST_BUS_DSP_CFG 63
+#define RST_BUS_DSP_DBG 64
+#define RST_BUS_RISCV_CFG 65
+#define RST_BUS_CAN0 66
+#define RST_BUS_CAN1 67
+
+#endif /* _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun20i-d1-r-ccu.h b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
new file mode 100644
index 00000000000..e20babc990a
--- /dev/null
+++ b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
+
+#define RST_BUS_R_TIMER 0
+#define RST_BUS_R_TWD 1
+#define RST_BUS_R_PPU 2
+#define RST_BUS_R_IR_RX 3
+#define RST_BUS_R_RTC 4
+#define RST_BUS_R_CPUCFG 5
+
+#endif /* _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h6-ccu.h b/include/dt-bindings/reset/sun50i-h6-ccu.h
index 81106f45509..d038ddfa481 100644
--- a/include/dt-bindings/reset/sun50i-h6-ccu.h
+++ b/include/dt-bindings/reset/sun50i-h6-ccu.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
*/
diff --git a/include/dt-bindings/reset/sun50i-h6-r-ccu.h b/include/dt-bindings/reset/sun50i-h6-r-ccu.h
index 7950e799c76..d541ade884f 100644
--- a/include/dt-bindings/reset/sun50i-h6-r-ccu.h
+++ b/include/dt-bindings/reset/sun50i-h6-r-ccu.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
*/
diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
index cb6285a8d12..1bd8bb0a11b 100644
--- a/include/dt-bindings/reset/sun50i-h616-ccu.h
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2020 Arm Ltd.
*/
diff --git a/include/event.h b/include/event.h
index c5646b713ad..a8f046da3c3 100644
--- a/include/event.h
+++ b/include/event.h
@@ -105,6 +105,15 @@ enum event_t {
EVT_FSP_INIT_F,
/**
+ * @EVT_SETTINGS_R:
+ * This event is triggered post-relocation and before console init.
+ * This gives an option to perform any platform-dependent setup, which
+ * needs to take place before show_board_info() (e.g. readout of EEPROM
+ * stored settings).
+ */
+ EVT_SETTINGS_R,
+
+ /**
* @EVT_LAST_STAGE_INIT:
* This event is triggered just before jumping to the main loop.
* Some boards need to perform initialisation immediately before control
diff --git a/include/ext4fs.h b/include/ext4fs.h
index cb5d9cc0a5c..dd66d27f776 100644
--- a/include/ext4fs.h
+++ b/include/ext4fs.h
@@ -31,6 +31,7 @@
struct disk_partition;
#define EXT4_INDEX_FL 0x00001000 /* Inode uses hash tree index */
+#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
#define EXT4_EXT_MAGIC 0xf30a
#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
diff --git a/include/ext_common.h b/include/ext_common.h
index 30a0c248414..b09bbde116a 100644
--- a/include/ext_common.h
+++ b/include/ext_common.h
@@ -35,6 +35,16 @@ struct cmd_tbl;
#define EXT2_PATH_MAX 4096
/* Maximum nesting of symlinks, used to prevent a loop. */
#define EXT2_MAX_SYMLINKCNT 8
+/* Maximum file name length */
+#define EXT2_NAME_LEN 255
+
+/*
+ * Revision levels
+ */
+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
+#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
+
+#define EXT2_GOOD_OLD_INODE_SIZE 128
/* Filetype used in directory entry. */
#define FILETYPE_UNKNOWN 0
@@ -48,6 +58,10 @@ struct cmd_tbl;
#define FILETYPE_INO_DIRECTORY 0040000
#define FILETYPE_INO_SYMLINK 0120000
#define EXT2_ROOT_INO 2 /* Root inode */
+#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */
+
+/* First non-reserved inode for old ext2 filesystems */
+#define EXT2_GOOD_OLD_FIRST_INO 11
/* The size of an ext2 block in bytes. */
#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
diff --git a/arch/arm/include/asm/mach-imx/image.h b/include/imx_container.h
index ee67ca96f4c..54cd684e35d 100644
--- a/arch/arm/include/asm/mach-imx/image.h
+++ b/include/imx_container.h
@@ -18,6 +18,9 @@
#define CONTAINER_HDR_QSPI_OFFSET SZ_4K
#define CONTAINER_HDR_NAND_OFFSET SZ_128M
+#define CONTAINER_HDR_TAG 0x87
+#define CONTAINER_HDR_VERSION 0
+
struct container_hdr {
u8 version;
u8 length_lsb;
@@ -66,4 +69,10 @@ struct generate_key_blob_hdr {
} __packed;
int get_container_size(ulong addr, u16 *header_length);
+
+static inline bool valid_container_hdr(struct container_hdr *container)
+{
+ return container->tag == CONTAINER_HDR_TAG &&
+ container->version == CONTAINER_HDR_VERSION;
+}
#endif
diff --git a/include/init.h b/include/init.h
index 4e7fe26c200..d57a24fd00d 100644
--- a/include/init.h
+++ b/include/init.h
@@ -271,6 +271,20 @@ void board_init_r(struct global_data *id, ulong dest_addr)
int cpu_init_r(void);
int mac_read_from_eeprom(void);
+
+/**
+ * serial_read_from_eeprom - read the serial number from EEPROM
+ *
+ * This function reads the serial number from the EEPROM and sets the
+ * appropriate environment variable.
+ *
+ * The environment variable is only set if it has not been set
+ * already. This ensures that any user-saved variables are never
+ * overwritten.
+ *
+ * This function must be called after relocation.
+ */
+int serial_read_from_eeprom(int devnum);
int set_cpu_clk_info(void);
int update_flash_size(int flash_size);
int arch_early_init_r(void);
diff --git a/include/sata.h b/include/sata.h
index d89f7a8a298..6111cf65d9d 100644
--- a/include/sata.h
+++ b/include/sata.h
@@ -21,4 +21,10 @@ extern struct blk_desc sata_dev_desc[];
int sata_probe(int devnum);
int sata_remove(int devnum);
+/*
+ * Remove existing AHCI SATA device uclass and all of its children,
+ * if any, and probe it again.
+ */
+int sata_rescan(bool verbose);
+
#endif
diff --git a/include/spl.h b/include/spl.h
index 1241f091237..8ff20adc28e 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -416,6 +416,16 @@ int spl_load_imx_container(struct spl_image_info *spl_image,
void preloader_console_init(void);
u32 spl_boot_device(void);
+struct spi_flash;
+
+/**
+ * spl_spi_get_uboot_offs() - Lookup function for the SPI boot offset
+ * @flash: The spi flash to boot from
+ *
+ * Return: The offset of U-Boot within the SPI flash
+ */
+unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash);
+
/**
* spl_spi_boot_bus() - Lookup function for the SPI boot bus source.
*
@@ -699,7 +709,23 @@ static inline const char *spl_loader_name(const struct spl_image_loader *loader)
}
#endif
+#define SPL_LOAD_IMAGE_GET(_priority, _boot_device, _method) \
+ ll_entry_get(struct spl_image_loader, \
+ _boot_device ## _priority ## _method, spl_image_loader)
+
/* SPL FAT image functions */
+
+/**
+ * spl_fat_force_reregister() - Force reregistration of FAT block devices
+ *
+ * To avoid repeatedly looking up block devices, spl_load_image_fat keeps track
+ * of whether it has already registered a block device. This is fine for most
+ * cases, but when running unit tests all devices are removed and recreated
+ * in-between tests. This function will force re-registration of any block
+ * devices, ensuring that we don't try to use an invalid block device.
+ */
+void spl_fat_force_reregister(void);
+
int spl_load_image_fat(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev,
struct blk_desc *block_dev, int partition,
@@ -779,6 +805,16 @@ bool spl_was_boot_source(void);
*/
int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr);
+/**
+ * spl_mmc_clear_cache() - Clear cached MMC devices
+ *
+ * To avoid reinitializing MMCs, spl_mmc_load caches the most-recently-used MMC
+ * device. This is fine for most cases, but when running unit tests all devices
+ * are removed and recreated in-between tests. This function will clear any
+ * cached state, ensuring that we don't try to use an invalid MMC.
+ */
+void spl_mmc_clear_cache(void);
+
int spl_mmc_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev);
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/include/sunxi_gpio.h
index 6eaeece4e24..db3742c0397 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/include/sunxi_gpio.h
@@ -3,13 +3,29 @@
* (C) Copyright 2007-2012
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Definitions that are shared between the Allwinner pinctrl and GPIO drivers,
+ * also used by some non-DM SPL code directly.
*/
#ifndef _SUNXI_GPIO_H
#define _SUNXI_GPIO_H
#include <linux/types.h>
-#include <asm/arch/cpu.h>
+
+#if defined(CONFIG_MACH_SUN9I)
+#define SUNXI_PIO_BASE 0x06000800
+#define SUNXI_R_PIO_BASE 0x08002c00
+#elif defined(CONFIG_SUN50I_GEN_H6)
+#define SUNXI_PIO_BASE 0x0300b000
+#define SUNXI_R_PIO_BASE 0x07022000
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#define SUNXI_PIO_BASE 0x02000000
+#define SUNXI_R_PIO_BASE 0x07022000
+#else
+#define SUNXI_PIO_BASE 0x01c20800
+#define SUNXI_R_PIO_BASE 0x01f02c00
+#endif
/*
* sunxi has 9 banks of gpio, they are:
@@ -29,13 +45,6 @@
#define SUNXI_GPIO_I 8
/*
- * This defines the number of GPIO banks for the _main_ GPIO controller.
- * You should fix up the padding in struct sunxi_gpio_reg below if you
- * change this.
- */
-#define SUNXI_GPIO_BANKS 9
-
-/*
* sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
* at a different register offset.
*
@@ -52,47 +61,9 @@
#define SUNXI_GPIO_M 12
#define SUNXI_GPIO_N 13
-struct sunxi_gpio {
- u32 cfg[4];
- u32 dat;
- u32 drv[2];
- u32 pull[2];
-};
-
-/* gpio interrupt control */
-struct sunxi_gpio_int {
- u32 cfg[3];
- u32 ctl;
- u32 sta;
- u32 deb; /* interrupt debounce */
-};
-
-struct sunxi_gpio_reg {
- struct sunxi_gpio gpio_bank[SUNXI_GPIO_BANKS];
- u8 res[0xbc];
- struct sunxi_gpio_int gpio_int;
-};
-
#define SUN50I_H6_GPIO_POW_MOD_SEL 0x340
#define SUN50I_H6_GPIO_POW_MOD_VAL 0x348
-#define BANK_TO_GPIO(bank) (((bank) < SUNXI_GPIO_L) ? \
- &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
- &((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
-
-#define GPIO_BANK(pin) ((pin) >> 5)
-#define GPIO_NUM(pin) ((pin) & 0x1f)
-
-#define GPIO_CFG_INDEX(pin) (((pin) & 0x1f) >> 3)
-#define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1f) & 0x7) << 2)
-
-#define GPIO_DRV_INDEX(pin) (((pin) & 0x1f) >> 4)
-#define GPIO_DRV_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-
-#define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
-#define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-
-/* GPIO bank sizes */
#define SUNXI_GPIOS_PER_BANK 32
#define SUNXI_GPIO_NEXT(__gpio) \
@@ -133,7 +104,6 @@ enum sunxi_gpio_number {
/* GPIO pin function config */
#define SUNXI_GPIO_INPUT 0
#define SUNXI_GPIO_OUTPUT 1
-#define SUNXI_GPIO_DISABLE 7
#define SUN8I_H3_GPA_UART0 2
#define SUN8I_H3_GPA_UART2 2
@@ -202,6 +172,14 @@ enum sunxi_gpio_number {
#define SUN9I_GPN_R_RSB 3
+#ifdef CONFIG_SUNXI_NEW_PINCTRL
+ #define SUNXI_PINCTRL_BANK_SIZE 0x30
+ #define SUNXI_GPIO_DISABLE 0xf
+#else
+ #define SUNXI_PINCTRL_BANK_SIZE 0x24
+ #define SUNXI_GPIO_DISABLE 0x7
+#endif
+
/* GPIO pin pull-up/down config */
#define SUNXI_GPIO_PULL_DISABLE 0
#define SUNXI_GPIO_PULL_UP 1
@@ -213,18 +191,19 @@ enum sunxi_gpio_number {
#define SUNXI_GPIO_AXP0_GPIO_COUNT 6
struct sunxi_gpio_plat {
- struct sunxi_gpio *regs;
+ void *regs;
char bank_name[3];
};
-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
+/* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */
+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
int sunxi_gpio_get_cfgpin(u32 pin);
void sunxi_gpio_set_drv(u32 pin, u32 val);
-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
void sunxi_gpio_set_pull(u32 pin, u32 val);
-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val);
+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val);
int sunxi_name_to_gpio(const char *name);
#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
diff --git a/include/test/spl.h b/include/test/spl.h
new file mode 100644
index 00000000000..c1f64658502
--- /dev/null
+++ b/include/test/spl.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#ifndef TEST_SPL_H
+#define TEST_SPL_H
+
+struct unit_test_state;
+struct spl_image_info;
+
+/* Declare a new SPL test */
+#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test)
+
+/**
+ * generate_data() - Generate some test payload data
+ * @data: The location to fill
+ * @size: The size of @data
+ * @test_name: The seed for the data
+ *
+ * Fill @data with data. The upper nibbles will be an incrementing counter
+ * (0x00, 0x10, 0x20...) to make the data identifiable in a hex dump. The lower
+ * nibbles are random bits seeded with @test_name.
+ */
+void generate_data(char *data, size_t size, const char *test_name);
+
+/**
+ * enum spl_test_image - Image types for testing
+ * @LEGACY: "Legacy" uImages
+ * @LEGACY_LZMA: "Legacy" uImages, LZMA compressed
+ * @IMX8: i.MX8 Container images
+ * @FIT_INTERNAL: FITs with internal data
+ * @FIT_EXTERNAL: FITs with external data
+ */
+enum spl_test_image {
+ LEGACY,
+ LEGACY_LZMA,
+ IMX8,
+ FIT_INTERNAL,
+ FIT_EXTERNAL,
+};
+
+/**
+ * create_image() - Create an image for testing
+ * @dst: The location to create the image at
+ * @type: The type of image to create
+ * @info: Image parameters
+ * @data_offset: Offset of payload data within the image
+ *
+ * Create a new image at @dst. @dst must be initialized to all zeros. @info
+ * should already have name and size filled in. All other parameters will be
+ * filled in by this function. @info can later be passed to check_image_info().
+ *
+ * If @dst is %NULL, then no data is written. Otherwise, @dst must be
+ * initialized to zeros, except payload data which must already be present at
+ * @data_offset. @data_offset may be %NULL if unnecessary.
+ *
+ * Typically, this function will be called as follows:
+ *
+ * size = create_image(NULL, type, &info, &off);
+ * img = calloc(size, 1);
+ * generate_data(img + off, ...);
+ * create_image(img, type, &info, NULL);
+ *
+ * Return: The size of the image, or 0 on error
+ */
+size_t create_image(void *dst, enum spl_test_image type,
+ struct spl_image_info *info, size_t *data_offset);
+
+/**
+ * check_image_info() - Check image info after loading
+ * @uts: Current unit test state
+ * @info1: The base, known good info
+ * @info2: The info to check
+ *
+ * Check @info2 against @info1. This function is typically called after calling
+ * a function to load/parse an image. Image data is not checked.
+ *
+ * Return: 0 on success, or 1 on failure
+ */
+int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1,
+ struct spl_image_info *info2);
+
+/**
+ * typedef write_image_t - Callback for writing an image
+ * @uts: Current unit test state
+ * @img: Image to write
+ * @size: Size of @img
+ *
+ * Write @img to a location which will be read by a &struct spl_image_loader.
+ *
+ * Return: 0 on success or 1 on failure
+ */
+typedef int write_image_t(struct unit_test_state *its, void *img, size_t size);
+
+/**
+ * do_spl_test_load() - Test loading with an SPL image loader
+ * @uts: Current unit test state
+ * @test_name: Name of the current test
+ * @type: Type of image to try loading
+ * @loader: The loader to test
+ * @write_image: Callback to write the image to the backing storage
+ *
+ * Test @loader, performing the common tasks of setting up the image and
+ * checking it was loaded correctly. The caller must supply a @write_image
+ * callback to write the image to a location which will be read by @loader.
+ *
+ * Return: 0 on success or 1 on failure
+ */
+int do_spl_test_load(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type, struct spl_image_loader *loader,
+ write_image_t write_image);
+
+/**
+ * image_supported() - Determine whether an image type is supported
+ * @type: The image type to check
+ *
+ * Return: %true if supported and %false otherwise
+ */
+static inline bool image_supported(enum spl_test_image type)
+{
+ switch (type) {
+ case LEGACY_LZMA:
+ if (!IS_ENABLED(CONFIG_SPL_LZMA))
+ return false;
+ case LEGACY:
+ return IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT);
+ case IMX8:
+ return IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER);
+ case FIT_INTERNAL:
+ case FIT_EXTERNAL:
+ return IS_ENABLED(CONFIG_SPL_LOAD_FIT) ||
+ IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL);
+ }
+
+ return false;
+}
+
+/* Declare an image test (skipped if the image type is unsupported) */
+#define SPL_IMG_TEST(func, type, flags) \
+static int func##_##type(struct unit_test_state *uts) \
+{ \
+ if (!image_supported(type)) \
+ return -EAGAIN; \
+ return func(uts, __func__, type); \
+} \
+SPL_TEST(func##_##type, flags)
+
+/* More than a couple blocks, and will not be aligned to anything */
+#define SPL_TEST_DATA_SIZE 4099
+
+/* Flags necessary for accessing DM devices */
+#define DM_FLAGS (UT_TESTF_DM | UT_TESTF_SCAN_FDT)
+
+#endif /* TEST_SPL_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 79cf9ef0fa3..f6ca559897e 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -687,6 +687,12 @@ config SPL_CRC8
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_CRC16
+ bool "Support CRC16 in SPL"
+ depends on SPL
+ help
+ Enables CRC16 support in SPL. This is not normally required.
+
config CRC32
def_bool y
help
diff --git a/lib/Makefile b/lib/Makefile
index 1c31ad9531e..2a76acf100d 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_TPM_V2) += tpm-v2.o
endif
obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o
+obj-$(CONFIG_$(SPL_TPL_)CRC16) += crc16.o
obj-y += crypto/
diff --git a/net/Makefile b/net/Makefile
index 3e2d061338d..64ab7ec740a 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -27,8 +27,8 @@ obj-$(CONFIG_CMD_PCAP) += pcap.o
obj-$(CONFIG_CMD_RARP) += rarp.o
obj-$(CONFIG_CMD_SNTP) += sntp.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
-obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot_udp.o
-obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o
+obj-$(CONFIG_$(SPL_TPL_)UDP_FUNCTION_FASTBOOT) += fastboot_udp.o
+obj-$(CONFIG_$(SPL_TPL_)TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o
obj-$(CONFIG_CMD_WOL) += wol.o
obj-$(CONFIG_PROT_UDP) += udp.o
obj-$(CONFIG_PROT_TCP) += tcp.o
diff --git a/net/bootp.c b/net/bootp.c
index 8b1a4ae2ef8..7b0f45e18a9 100644
--- a/net/bootp.c
+++ b/net/bootp.c
@@ -41,9 +41,6 @@
*/
#define TIMEOUT_MS ((3 + (CONFIG_NET_RETRY_COUNT * 5)) * 1000)
-#define PORT_BOOTPS 67 /* BOOTP server UDP port */
-#define PORT_BOOTPC 68 /* BOOTP client UDP port */
-
#ifndef CFG_DHCP_MIN_EXT_LEN /* minimal length of extension list */
#define CFG_DHCP_MIN_EXT_LEN 64
#endif
@@ -1076,6 +1073,11 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
CONFIG_SYS_BOOTFILE_PREFIX,
strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) {
#endif /* CONFIG_SYS_BOOTFILE_PREFIX */
+ if (CONFIG_IS_ENABLED(UNIT_TEST) &&
+ dhcp_message_type((u8 *)bp->bp_vend) == -1) {
+ debug("got BOOTP response; transitioning to BOUND\n");
+ goto dhcp_got_bootp;
+ }
dhcp_packet_process_options(bp);
if (CONFIG_IS_ENABLED(EFI_LOADER) &&
IS_ENABLED(CONFIG_NETDEVICES))
@@ -1102,6 +1104,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip,
debug("DHCP State: REQUESTING\n");
if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) {
+dhcp_got_bootp:
dhcp_packet_process_options(bp);
/* Store net params from reply */
store_net_params(bp);
diff --git a/net/bootp.h b/net/bootp.h
index 567340ec5d4..4e32b19d424 100644
--- a/net/bootp.h
+++ b/net/bootp.h
@@ -15,6 +15,9 @@
/**********************************************************************/
+#define PORT_BOOTPS 67 /* BOOTP server UDP port */
+#define PORT_BOOTPC 68 /* BOOTP client UDP port */
+
/*
* BOOTP header.
*/
diff --git a/net/net.c b/net/net.c
index e6f61f0f8f6..8357f084101 100644
--- a/net/net.c
+++ b/net/net.c
@@ -511,12 +511,12 @@ restart:
tftp_start_server();
break;
#endif
-#if defined(CONFIG_UDP_FUNCTION_FASTBOOT)
+#if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)
case FASTBOOT_UDP:
fastboot_udp_start_server();
break;
#endif
-#if defined(CONFIG_TCP_FUNCTION_FASTBOOT)
+#if CONFIG_IS_ENABLED(TCP_FUNCTION_FASTBOOT)
case FASTBOOT_TCP:
fastboot_tcp_start_server();
break;
diff --git a/test/Kconfig b/test/Kconfig
index 830245b6f9a..ca648d23376 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -101,6 +101,7 @@ config UT_UNICODE
source "test/dm/Kconfig"
source "test/env/Kconfig"
+source "test/image/Kconfig"
source "test/lib/Kconfig"
source "test/optee/Kconfig"
source "test/overlay/Kconfig"
diff --git a/test/Makefile b/test/Makefile
index 178773647a8..8e1fed2c28b 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -3,9 +3,6 @@
# (C) Copyright 2012 The Chromium Authors
obj-y += test-main.o
-ifdef CONFIG_SPL_LOAD_FIT
-obj-$(CONFIG_SANDBOX) += image/
-endif
ifneq ($(CONFIG_$(SPL_)BLOBLIST),)
obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o
@@ -30,4 +27,6 @@ obj-$(CONFIG_UNIT_TEST) += boot/
obj-$(CONFIG_UNIT_TEST) += common/
obj-y += log/
obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o
+else
+obj-$(CONFIG_SPL_UT_LOAD) += image/
endif
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index c5f14a7a132..0702fccdae6 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -190,12 +190,21 @@ static int bootdev_test_any(struct unit_test_state *uts)
BOOTSTD_TEST(bootdev_test_any, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
UT_TESTF_ETH_BOOTDEV);
-/* Check bootdev ordering with the bootdev-order property */
+/*
+ * Check bootdev ordering with the bootdev-order property and boot_targets
+ * environment variable
+ */
static int bootdev_test_order(struct unit_test_state *uts)
{
struct bootflow_iter iter;
struct bootflow bflow;
+ test_set_skip_delays(true);
+
+ /* Start up USB which gives us three additional bootdevs */
+ usb_started = false;
+ ut_assertok(run_command("usb start", 0));
+
/*
* First try the order set by the bootdev-order property
* Like all sandbox unit tests this relies on the devicetree setting up
@@ -213,17 +222,22 @@ static int bootdev_test_order(struct unit_test_state *uts)
bootflow_iter_uninit(&iter);
/* Use the environment variable to override it */
- ut_assertok(env_set("boot_targets", "mmc1 mmc2"));
+ ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb"));
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(5, iter.num_devs);
ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
+ ut_asserteq_str("usb_mass_storage.lun0.bootdev",
+ iter.dev_used[2]->name);
bootflow_iter_uninit(&iter);
- /* Make sure it scans a bootdevs in each target */
- ut_assertok(env_set("boot_targets", "mmc spi"));
- ut_asserteq(0, bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ /* Try a single uclass */
+ ut_assertok(env_set("boot_targets", NULL));
+ ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+
+ /* Now scan past mmc1 and make sure that only mmc0 shows up */
ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(3, iter.num_devs);
ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
@@ -231,6 +245,34 @@ static int bootdev_test_order(struct unit_test_state *uts)
ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
bootflow_iter_uninit(&iter);
+ /* Try a single uclass with boot_targets */
+ ut_assertok(env_set("boot_targets", "mmc"));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+
+ /* Now scan past mmc1 and make sure that only mmc0 shows up */
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(3, iter.num_devs);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
+ ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
+ bootflow_iter_uninit(&iter);
+
+ /* Try a single uclass with boot_targets */
+ ut_assertok(env_set("boot_targets", "mmc usb"));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+
+ /* Now scan past mmc1 and make sure that the 3 USB devices show up */
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(6, iter.num_devs);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
+ ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
+ ut_asserteq_str("usb_mass_storage.lun0.bootdev",
+ iter.dev_used[3]->name);
+ bootflow_iter_uninit(&iter);
+
return 0;
}
BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
index 653d7b1c8b3..2bbebcdbf28 100644
--- a/test/dm/wdt.c
+++ b/test/dm/wdt.c
@@ -54,7 +54,7 @@ static int dm_test_wdt_gpio_toggle(struct unit_test_state *uts)
*/
struct udevice *wdt, *gpio;
const u64 timeout = 42;
- const int offset = 7;
+ const int offset = 8;
int val;
ut_assertok(uclass_get_device_by_name(UCLASS_WDT,
@@ -115,7 +115,7 @@ static int dm_test_wdt_watchdog_reset(struct unit_test_state *uts)
struct udevice *gpio_wdt, *sandbox_wdt;
struct udevice *gpio;
const u64 timeout = 42;
- const int offset = 7;
+ const int offset = 8;
uint reset_count;
int val;
diff --git a/test/image/Kconfig b/test/image/Kconfig
new file mode 100644
index 00000000000..8f9e6ae036b
--- /dev/null
+++ b/test/image/Kconfig
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+
+config SPL_UT_LOAD
+ bool "Unit tests for SPL load methods"
+ depends on SPL_UNIT_TEST
+ default y if SANDBOX
+ help
+ Test various SPL load methods.
+
+if SPL_UT_LOAD
+
+config SPL_UT_LOAD_FS
+ bool "Unit tests for filesystems"
+ depends on SANDBOX && SPL_OF_REAL
+ depends on FS_LOADER
+ depends on SPL_BLK_FS
+ depends on SPL_FS_FAT
+ depends on SPL_FS_EXT4
+ depends on SPL_MMC_WRITE
+ depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+ default y
+ help
+ Test filesystems and the various load methods which use them.
+
+config SPL_UT_LOAD_NET
+ bool "Test loading over TFTP"
+ depends on SANDBOX && SPL_OF_REAL
+ depends on SPL_ETH
+ depends on USE_BOOTFILE
+ default y
+ help
+ Test loading images over TFTP using the NET image load method.
+
+config SPL_UT_LOAD_SPI
+ bool "Test loading from SPI Flash"
+ depends on SANDBOX && SPL_OF_REAL
+ depends on SPL_SPI_LOAD
+ default y
+ help
+ Test the SPI flash image load metod.
+
+config SPL_UT_LOAD_OS
+ bool "Test loading from the host OS"
+ depends on SANDBOX && SPL_LOAD_FIT
+ default y
+ help
+ Smoke test to ensure that loading U-boot works in sandbox.
+
+endif
diff --git a/test/image/Makefile b/test/image/Makefile
index c4039df707f..b30210106a4 100644
--- a/test/image/Makefile
+++ b/test/image/Makefile
@@ -2,4 +2,9 @@
#
# Copyright 2021 Google LLC
-obj-$(CONFIG_SPL_BUILD) += spl_load.o
+obj-y += spl_load.o
+obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o
+obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o
+obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o
+obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o
+obj-$(CONFIG_SPL_UT_LOAD_SPI) += spl_load_spi.o
diff --git a/test/image/spl_load.c b/test/image/spl_load.c
index 4e27ff460ab..ab4c14d6491 100644
--- a/test/image/spl_load.c
+++ b/test/image/spl_load.c
@@ -1,91 +1,661 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright 2021 Google LLC
- * Written by Simon Glass <sjg@chromium.org>
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
*/
#include <common.h>
#include <image.h>
+#include <imx_container.h>
#include <mapmem.h>
-#include <os.h>
+#include <memalign.h>
+#include <rand.h>
+#include <spi_flash.h>
#include <spl.h>
+#include <test/spl.h>
#include <test/ut.h>
+#include <u-boot/crc.h>
-/* Declare a new SPL test */
-#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test)
+int board_fit_config_name_match(const char *name)
+{
+ return 0;
+}
-/* Context used for this test */
-struct text_ctx {
- int fd;
-};
+struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+ return map_sysmem(0x100000, 0);
+}
+
+/* Try to reuse the load buffer to conserve memory */
+void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
+{
+ static void *buf;
+ static size_t size;
+
+ if (size < sectors * bl_len) {
+ free(buf);
+ size = sectors * bl_len;
+ buf = malloc_cache_aligned(size);
+ }
+ return buf;
+}
+
+/* Local flags for spl_image; start from the "top" to avoid conflicts */
+#define SPL_IMX_CONTAINER 0x80000000
+#define SPL_COMP_LZMA 0x40000000
-static ulong read_fit_image(struct spl_load_info *load, ulong sector,
- ulong count, void *buf)
+void generate_data(char *data, size_t size, const char *test_name)
{
- struct text_ctx *text_ctx = load->priv;
- off_t offset, ret;
- ssize_t res;
+ int i;
+ unsigned int seed = 1;
+
+ while (*test_name) {
+ seed += *test_name++;
+ rand_r(&seed);
+ }
+
+ for (i = 0; i < size; i++)
+ data[i] = (i & 0xf) << 4 | (rand_r(&seed) & 0xf);
+}
+
+static size_t create_legacy(void *dst, struct spl_image_info *spl_image,
+ size_t *data_offset)
+{
+ struct legacy_img_hdr *hdr = dst;
+ void *data = dst + sizeof(*hdr);
+
+ if (data_offset)
+ *data_offset = data - dst;
+
+ if (!dst)
+ goto out;
+
+ image_set_magic(hdr, IH_MAGIC);
+ image_set_time(hdr, 0);
+ image_set_size(hdr, spl_image->size);
+ image_set_load(hdr, spl_image->load_addr);
+ image_set_ep(hdr, spl_image->entry_point);
+ image_set_dcrc(hdr, crc32(0, data, spl_image->size));
+ image_set_os(hdr, spl_image->os);
+ image_set_arch(hdr, IH_ARCH_DEFAULT);
+ image_set_type(hdr, IH_TYPE_FIRMWARE);
+ image_set_comp(hdr, spl_image->flags & SPL_COMP_LZMA ? IH_COMP_LZMA :
+ IH_COMP_NONE);
+ image_set_name(hdr, spl_image->name);
+ image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr)));
+
+out:
+ return sizeof(*hdr) + spl_image->size;
+}
+
+static size_t create_imx8(void *dst, struct spl_image_info *spl_image,
+ size_t *data_offset)
+{
+ struct container_hdr *hdr = dst;
+ struct boot_img_t *img = dst + sizeof(*hdr);
+ size_t length = sizeof(*hdr) + sizeof(*img);
+ /* Align to MMC block size for now */
+ void *data = dst + 512;
+
+ if (data_offset)
+ *data_offset = data - dst;
- offset = sector * load->bl_len;
- ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET);
- if (ret != offset) {
- printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset,
- ret, errno);
+ if (!dst)
+ goto out;
+
+ hdr->version = CONTAINER_HDR_VERSION;
+ hdr->length_lsb = length & 0xff;
+ hdr->length_msb = length >> 8;
+ hdr->tag = CONTAINER_HDR_TAG;
+ hdr->num_images = 1;
+
+ /* spl_load_imx_container doesn't handle endianness; whoops! */
+ img->offset = data - dst;
+ img->size = spl_image->size;
+ img->dst = spl_image->load_addr;
+ img->entry = spl_image->entry_point;
+
+out:
+ return data - dst + spl_image->size;
+}
+
+#define ADDRESS_CELLS (sizeof(uintptr_t) / sizeof(u32))
+
+static inline int fdt_property_addr(void *fdt, const char *name, uintptr_t val)
+{
+ if (sizeof(uintptr_t) == sizeof(u32))
+ return fdt_property_u32(fdt, name, val);
+ return fdt_property_u64(fdt, name, val);
+}
+
+static size_t start_fit(void *dst, size_t fit_size, size_t data_size,
+ bool external)
+{
+ void *data;
+
+ if (fdt_create(dst, fit_size))
+ return 0;
+ if (fdt_finish_reservemap(dst))
+ return 0;
+ if (fdt_begin_node(dst, ""))
+ return 0;
+ if (fdt_property_u32(dst, FIT_TIMESTAMP_PROP, 0))
return 0;
+ if (fdt_property_u32(dst, "#address-cells", ADDRESS_CELLS))
+ return 0;
+ if (fdt_property_string(dst, FIT_DESC_PROP, ""))
+ return 0;
+
+ if (fdt_begin_node(dst, "images"))
+ return 0;
+ if (fdt_begin_node(dst, "u-boot"))
+ return 0;
+
+ if (external) {
+ if (fdt_property_u32(dst, FIT_DATA_OFFSET_PROP, 0))
+ return 0;
+ return fit_size;
}
- res = os_read(text_ctx->fd, buf, count * load->bl_len);
- if (res == -1) {
- printf("Failed to read %lx bytes, got %ld (errno=%d)\n",
- count * load->bl_len, res, errno);
+ if (fdt_property_placeholder(dst, FIT_DATA_PROP, data_size, &data))
return 0;
+ return data - dst;
+}
+
+static size_t create_fit(void *dst, struct spl_image_info *spl_image,
+ size_t *data_offset, bool external)
+{
+ size_t prop_size = 596, total_size = prop_size + spl_image->size;
+ size_t off, size;
+
+ if (external) {
+ size = prop_size;
+ off = size;
+ } else {
+ char tmp[256];
+
+ size = total_size;
+ off = start_fit(tmp, sizeof(tmp), 0, false);
+ if (!off)
+ return 0;
}
- return count;
+ if (data_offset)
+ *data_offset = off;
+
+ if (!dst)
+ goto out;
+
+ if (start_fit(dst, size, spl_image->size, external) != off)
+ return 0;
+
+ if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name))
+ return 0;
+ if (fdt_property_string(dst, FIT_TYPE_PROP, "firmware"))
+ return 0;
+ if (fdt_property_string(dst, FIT_COMP_PROP, "none"))
+ return 0;
+ if (fdt_property_u32(dst, FIT_DATA_SIZE_PROP, spl_image->size))
+ return 0;
+ if (fdt_property_string(dst, FIT_OS_PROP,
+ genimg_get_os_short_name(spl_image->os)))
+ return 0;
+ if (fdt_property_string(dst, FIT_ARCH_PROP,
+ genimg_get_arch_short_name(IH_ARCH_DEFAULT)))
+ return 0;
+ if (fdt_property_addr(dst, FIT_ENTRY_PROP, spl_image->entry_point))
+ return 0;
+ if (fdt_property_addr(dst, FIT_LOAD_PROP, spl_image->load_addr))
+ return 0;
+ if (fdt_end_node(dst)) /* u-boot */
+ return 0;
+ if (fdt_end_node(dst)) /* images */
+ return 0;
+
+ if (fdt_begin_node(dst, "configurations"))
+ return 0;
+ if (fdt_property_string(dst, FIT_DEFAULT_PROP, "config-1"))
+ return 0;
+ if (fdt_begin_node(dst, "config-1"))
+ return 0;
+ if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name))
+ return 0;
+ if (fdt_property_string(dst, FIT_FIRMWARE_PROP, "u-boot"))
+ return 0;
+ if (fdt_end_node(dst)) /* configurations */
+ return 0;
+ if (fdt_end_node(dst)) /* config-1 */
+ return 0;
+
+ if (fdt_end_node(dst)) /* root */
+ return 0;
+ if (fdt_finish(dst))
+ return 0;
+
+ if (external) {
+ if (fdt_totalsize(dst) > size)
+ return 0;
+ fdt_set_totalsize(dst, size);
+ }
+
+out:
+ return total_size;
}
-int board_fit_config_name_match(const char *name)
+size_t create_image(void *dst, enum spl_test_image type,
+ struct spl_image_info *info, size_t *data_offset)
{
+ bool external = false;
+
+ info->os = IH_OS_U_BOOT;
+ info->load_addr = CONFIG_TEXT_BASE;
+ info->entry_point = CONFIG_TEXT_BASE + 0x100;
+ info->flags = 0;
+
+ switch (type) {
+ case LEGACY_LZMA:
+ info->flags = SPL_COMP_LZMA;
+ case LEGACY:
+ return create_legacy(dst, info, data_offset);
+ case IMX8:
+ info->flags = SPL_IMX_CONTAINER;
+ return create_imx8(dst, info, data_offset);
+ case FIT_EXTERNAL:
+ /*
+ * spl_fit_append_fdt will clobber external images with U-Boot's
+ * FDT if the image doesn't have one. Just set the OS to
+ * something which doesn't take a devicetree.
+ */
+ if (!IS_ENABLED(CONFIG_LOAD_FIT_FULL))
+ info->os = IH_OS_TEE;
+ external = true;
+ case FIT_INTERNAL:
+ info->flags = SPL_FIT_FOUND;
+ return create_fit(dst, info, data_offset, external);
+ }
+
return 0;
}
-struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
+int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1,
+ struct spl_image_info *info2)
{
- return map_sysmem(0x100000, 0);
+ if (info2->name) {
+ if (info1->flags & SPL_FIT_FOUND)
+ ut_asserteq_str(genimg_get_os_name(info1->os),
+ info2->name);
+ else
+ ut_asserteq_str(info1->name, info2->name);
+ }
+
+ if (info1->flags & SPL_IMX_CONTAINER)
+ ut_asserteq(IH_OS_INVALID, info2->os);
+ else
+ ut_asserteq(info1->os, info2->os);
+
+ ut_asserteq(info1->entry_point, info2->entry_point);
+ if (info1->flags & (SPL_FIT_FOUND | SPL_IMX_CONTAINER) ||
+ info2->flags & SPL_COPY_PAYLOAD_ONLY) {
+ ut_asserteq(info1->load_addr, info2->load_addr);
+ if (info1->flags & SPL_IMX_CONTAINER)
+ ut_asserteq(0, info2->size);
+ else if (!(info1->flags & SPL_COMP_LZMA))
+ ut_asserteq(info1->size, info2->size);
+ } else {
+ ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr),
+ info2->load_addr);
+ ut_asserteq(info1->size + sizeof(struct legacy_img_hdr),
+ info2->size);
+ }
+
+ return 0;
+}
+
+static ulong spl_test_read(struct spl_load_info *load, ulong sector,
+ ulong count, void *buf)
+{
+ memcpy(buf, load->priv + sector, count);
+ return count;
}
-static int spl_test_load(struct unit_test_state *uts)
+static int spl_test_image(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
{
- struct spl_image_info image;
- struct legacy_img_hdr *header;
- struct text_ctx text_ctx;
- struct spl_load_info load;
- char fname[256];
- int ret;
- int fd;
-
- memset(&load, '\0', sizeof(load));
- load.bl_len = 512;
- load.read = read_fit_image;
-
- ret = sandbox_find_next_phase(fname, sizeof(fname), true);
- if (ret) {
- printf("(%s not found, error %d)\n", fname, ret);
- return ret;
+ size_t img_size, img_data, data_size = SPL_TEST_DATA_SIZE;
+ struct spl_image_info info_write = {
+ .name = test_name,
+ .size = data_size,
+ }, info_read = { };
+ char *data;
+ void *img;
+
+ img_size = create_image(NULL, type, &info_write, &img_data);
+ ut_assert(img_size);
+ img = calloc(img_size, 1);
+ ut_assertnonnull(img);
+
+ data = img + img_data;
+ generate_data(data, data_size, test_name);
+ ut_asserteq(img_size, create_image(img, type, &info_write, NULL));
+
+ if (type == LEGACY) {
+ ut_assertok(spl_parse_image_header(&info_read, NULL, img));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ } else {
+ struct spl_load_info load = {
+ .bl_len = 1,
+ .priv = img,
+ .read = spl_test_read,
+ };
+
+ if (type == IMX8)
+ ut_assertok(spl_load_imx_container(&info_read, &load,
+ 0));
+ else if (IS_ENABLED(CONFIG_SPL_FIT_FULL))
+ ut_assertok(spl_parse_image_header(&info_read, NULL,
+ img));
+ else
+ ut_assertok(spl_load_simple_fit(&info_read, &load, 0,
+ img));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ ut_asserteq_mem(data, phys_to_virt(info_write.load_addr),
+ data_size);
}
- load.filename = fname;
- header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));
+ free(img);
+ return 0;
+}
+SPL_IMG_TEST(spl_test_image, LEGACY, 0);
+SPL_IMG_TEST(spl_test_image, IMX8, 0);
+SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0);
+SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0);
+
+/*
+ * LZMA is too complex to generate on the fly, so let's use some data I put in
+ * the oven^H^H^H^H compressed earlier
+ */
+static const char lzma_compressed[] = {
+ 0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88,
+ 0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9,
+ 0x41, 0x79, 0xfe, 0x90, 0x0b, 0x31, 0x7b, 0x79, 0x91, 0xb8, 0x5f, 0x33,
+ 0x11, 0x04, 0xc3, 0x4f, 0xf5, 0x71, 0xd1, 0xfb, 0x94, 0x6b, 0x5f, 0x78,
+ 0xe2, 0xfa, 0x6a, 0x21, 0xb6, 0x1d, 0x11, 0x0e, 0x5b, 0x56, 0x6a, 0x5b,
+ 0xe9, 0x56, 0x5f, 0x8b, 0x87, 0x61, 0x96, 0x6d, 0xce, 0x66, 0xbb, 0xb6,
+ 0xe7, 0x13, 0x5a, 0xd8, 0x84, 0x29, 0x60, 0xa0, 0x80, 0x43, 0xdd, 0x0f,
+ 0x4b, 0x85, 0xb0, 0x04, 0x9d, 0x9f, 0x28, 0x97, 0x0a, 0x1e, 0x16, 0xb0,
+ 0x45, 0x33, 0x5e, 0x79, 0x4f, 0xaa, 0xee, 0x79, 0x6e, 0xc3, 0x4e, 0x3d,
+ 0xe8, 0x67, 0x7c, 0xe0, 0xd0, 0xcc, 0x05, 0x40, 0xae, 0x6b, 0x97, 0x82,
+ 0x97, 0x02, 0x01, 0xe2, 0xe3, 0xbc, 0xe4, 0x9b, 0xb3, 0x28, 0xed, 0x5e,
+ 0x0d, 0x68, 0x6e, 0xe5, 0x17, 0x0a, 0x86, 0x5a, 0xcd, 0x8d, 0x46, 0x2d,
+ 0x06, 0x10, 0xa6, 0x90, 0x44, 0xa1, 0xfc, 0x66, 0x6d, 0x7c, 0x57, 0x57,
+ 0x07, 0xbc, 0x95, 0xb2, 0x8d, 0xf0, 0x9f, 0x4d, 0x90, 0x04, 0xaf, 0x0c,
+ 0x23, 0x51, 0x1b, 0x34, 0xd5, 0x5c, 0x5d, 0x87, 0x5e, 0x10, 0x2b, 0x71,
+ 0xc2, 0xcf, 0xc5, 0x9d, 0x4b, 0x89, 0x01, 0xc4, 0x97, 0xf2, 0xea, 0x83,
+ 0x97, 0xfa, 0xe0, 0x51, 0x96, 0x78, 0x4f, 0x44, 0xb8, 0xa8, 0x9d, 0x03,
+ 0x1c, 0x6e, 0xb7, 0xc6, 0xd7, 0xc5, 0x3e, 0x32, 0x65, 0xa7, 0x06, 0xab,
+ 0x86, 0xfb, 0xd2, 0x9b, 0xd7, 0x86, 0xa8, 0xfe, 0x46, 0x41, 0x2e, 0xc2,
+ 0x4e, 0xed, 0xa2, 0x9b, 0x79, 0x36, 0x37, 0x49, 0x90, 0xfc, 0xa6, 0x14,
+ 0x93, 0x17, 0x82, 0x62, 0x3f, 0x79, 0x6b, 0x86, 0xc2, 0xeb, 0x82, 0xfe,
+ 0x87, 0x49, 0xa5, 0x7e, 0x41, 0xe3, 0x59, 0x60, 0x15, 0x61, 0x4e, 0x3b,
+ 0x16, 0xcf, 0xdb, 0x49, 0x2c, 0x84, 0x92, 0x26, 0x40, 0x04, 0x78, 0xd3,
+ 0xd6, 0xa6, 0xed, 0x6e, 0x63, 0x49, 0xcb, 0xea, 0xfe, 0x43, 0x85, 0x21,
+ 0x1a, 0x28, 0x36, 0x0a, 0x3e, 0x2a, 0xad, 0xba, 0xfc, 0x8a, 0x37, 0x18,
+ 0xb4, 0x80, 0xbe, 0x6a, 0x36, 0x14, 0x03, 0xdd, 0xa3, 0x37, 0xbd, 0xc1,
+ 0x8a, 0xbb, 0x2d, 0xd4, 0x08, 0xd7, 0x4b, 0xc4, 0xe9, 0xb8, 0xb4, 0x65,
+ 0xdd, 0xf6, 0xe8, 0x17, 0x2c, 0x2c, 0x9b, 0x1e, 0x92, 0x0b, 0xcb, 0x22,
+ 0x7c, 0x1b, 0x74, 0x8d, 0x65, 0x11, 0x5f, 0xfe, 0xf5, 0x2a, 0xc2, 0xbe,
+ 0xea, 0xa2, 0xf1, 0x7b, 0xe8, 0xaf, 0x32, 0x5a, 0x0a, 0x5b, 0xd2, 0x5a,
+ 0x11, 0x22, 0x79, 0xfa, 0xae, 0x2d, 0xe8, 0xc6, 0x17, 0xba, 0x17, 0x81,
+ 0x6a, 0x63, 0xb5, 0x26, 0xd7, 0x8d, 0xd0, 0x66, 0x0c, 0x4a, 0x0c, 0x22,
+ 0x1b, 0x20, 0x9f, 0x3d, 0x0b, 0x1b, 0x59, 0x53, 0x89, 0x9b, 0x5e, 0xbd,
+ 0x3d, 0xd1, 0xdd, 0xff, 0xca, 0xb2, 0xb7, 0x12, 0x8d, 0x03, 0xaa, 0xc3,
+ 0x1d, 0x56, 0x76, 0x14, 0xf8, 0xee, 0xb3, 0xeb, 0x80, 0x38, 0xc1, 0xc1,
+ 0x1a, 0xef, 0x4a, 0xd5, 0x16, 0x1f, 0x5e, 0x21, 0x5d, 0x46, 0x01, 0xb3,
+ 0xa4, 0xf7, 0x99, 0x94, 0x05, 0xc6, 0xc8, 0x06, 0xd8, 0x1c, 0xac, 0x47,
+ 0x13, 0x54, 0x13, 0x1b, 0x1f, 0xb6, 0x23, 0x9c, 0x73, 0x2b, 0x57, 0x32,
+ 0x94, 0x92, 0xf1, 0x71, 0x44, 0x40, 0x02, 0xc3, 0x21, 0x4a, 0x2f, 0x36,
+ 0x5e, 0x8a, 0xd0, 0x4b, 0x02, 0xc7, 0x6e, 0xcf, 0xed, 0xa2, 0xdb, 0xce,
+ 0x0a, 0x0f, 0x66, 0x4f, 0xb2, 0x3d, 0xb6, 0xcc, 0x75, 0x45, 0x80, 0x0a,
+ 0x49, 0x4a, 0xe7, 0xe7, 0x24, 0x62, 0x65, 0xc7, 0x02, 0x22, 0x13, 0xbe,
+ 0x6c, 0xa9, 0x9a, 0x8b, 0xa9, 0x1b, 0x2b, 0x3a, 0xde, 0x5e, 0x37, 0xbd,
+ 0x7f, 0x85, 0xd1, 0x32, 0x1d, 0xbf, 0x03, 0x8a, 0x3b, 0xe5, 0xb3, 0xfd,
+ 0x01, 0xca, 0xde, 0x0d, 0x7a, 0x5b, 0x01, 0x05, 0x1d, 0x3c, 0x23, 0x00,
+ 0x60, 0xb7, 0x50, 0xfd, 0x0d, 0xd7, 0x63, 0x92, 0xd6, 0xb0, 0x48, 0x3a,
+ 0x2d, 0xa3, 0xf8, 0xf6, 0x44, 0xe1, 0xda, 0x3b, 0xf4, 0x39, 0x47, 0xc4,
+ 0x4d, 0x8f, 0x54, 0x78, 0xec, 0x27, 0x7b, 0xc6, 0xe4, 0x81, 0x3a, 0x3f,
+ 0xa5, 0x61, 0x9d, 0xcb, 0x71, 0x0b, 0x0d, 0x55, 0xea, 0x5b, 0xeb, 0x58,
+ 0xa5, 0x49, 0xb5, 0x44, 0x1b, 0xb0, 0x0d, 0x1f, 0x58, 0xfb, 0x7a, 0xd4,
+ 0x09, 0x1e, 0x9a, 0x7e, 0x21, 0xba, 0xb3, 0x36, 0xa6, 0x04, 0x74, 0xe1,
+ 0xd0, 0xca, 0x02, 0x11, 0x84, 0x93, 0x8f, 0x86, 0x3d, 0x79, 0xbf, 0xa8,
+ 0xec, 0x0a, 0x23, 0x5e, 0xde, 0xc4, 0xc6, 0xda, 0x45, 0xbd, 0x95, 0x74,
+ 0x7b, 0xbf, 0xc1, 0x80, 0x48, 0x3f, 0x10, 0xb6, 0xb9, 0x5c, 0x31, 0x52,
+ 0x06, 0x5a, 0xac, 0xec, 0x94, 0x21, 0x80, 0x51, 0xba, 0x64, 0xed, 0x9d,
+ 0x27, 0x72, 0x8d, 0x17, 0x43, 0x5f, 0xf1, 0x60, 0xfa, 0xb5, 0x65, 0xd4,
+ 0xb9, 0xf8, 0xfc, 0x48, 0x7b, 0xe3, 0xfe, 0xae, 0xe4, 0x71, 0x4a, 0x3d,
+ 0x8c, 0xf5, 0x72, 0x8b, 0xbf, 0x60, 0xd8, 0x6a, 0x8f, 0x51, 0x82, 0xae,
+ 0x98, 0xd0, 0x56, 0xf9, 0xa8, 0x3a, 0xad, 0x86, 0x26, 0xa8, 0x5a, 0xf8,
+ 0x63, 0x87, 0x2c, 0x74, 0xbf, 0xf9, 0x7d, 0x00, 0xa0, 0x2f, 0x17, 0x23,
+ 0xb7, 0x62, 0x94, 0x19, 0x47, 0x57, 0xf9, 0xa8, 0xe7, 0x4b, 0xe9, 0x2b,
+ 0xe8, 0xb4, 0x03, 0xbf, 0x23, 0x75, 0xfe, 0xc3, 0x94, 0xc0, 0xa9, 0x5b,
+ 0x07, 0xb5, 0x75, 0x87, 0xcc, 0xa5, 0xb5, 0x9b, 0x35, 0x29, 0xe4, 0xb1,
+ 0xaa, 0x04, 0x57, 0xe9, 0xa3, 0xd0, 0xa3, 0xe4, 0x11, 0xe1, 0xaa, 0x3b,
+ 0x67, 0x09, 0x60, 0x83, 0x23, 0x72, 0xa6, 0x7b, 0x73, 0x22, 0x5b, 0x4a,
+ 0xe0, 0xf0, 0xa3, 0xeb, 0x9c, 0x91, 0xda, 0xba, 0x8b, 0xc1, 0x32, 0xa9,
+ 0x24, 0x13, 0x51, 0xe4, 0x67, 0x49, 0x4a, 0xd9, 0x3d, 0xae, 0x80, 0xfd,
+ 0x0a, 0x0d, 0x56, 0x98, 0x66, 0xa2, 0x6d, 0x92, 0x54, 0x7f, 0x82, 0xe5,
+ 0x17, 0x39, 0xd3, 0xaa, 0xc4, 0x4e, 0x6f, 0xe1, 0x2e, 0xfe, 0x03, 0x44,
+ 0x8a, 0xdd, 0xeb, 0xc0, 0x74, 0x79, 0x63, 0x33, 0x2b, 0x4b, 0xb5, 0x62,
+ 0xdd, 0x47, 0xba, 0x6e, 0xfc, 0x91, 0x08, 0xa9, 0x17, 0x8c, 0x47, 0x61,
+ 0xd9, 0x32, 0xe9, 0xa0, 0xb3, 0xa2, 0x82, 0xc9, 0xa6, 0x32, 0xa1, 0xca,
+ 0x7c, 0x41, 0xa6, 0x5a, 0xe2, 0x46, 0xb6, 0x45, 0x53, 0x72, 0x55, 0x9e,
+ 0xdf, 0xac, 0x96, 0x68, 0xe5, 0xdc, 0x4e, 0x2d, 0xa8, 0x1e, 0x7a, 0x8e,
+ 0xff, 0x54, 0xe4, 0x0a, 0x33, 0x5d, 0x97, 0xdf, 0x4e, 0x36, 0x96, 0xba,
+ 0x52, 0xd9, 0xa9, 0xec, 0x52, 0xe5, 0x1d, 0x94, 0xfe, 0x1c, 0x46, 0x54,
+ 0xa6, 0x8e, 0x85, 0x47, 0xba, 0xeb, 0x4b, 0x8d, 0x57, 0xe4, 0x34, 0x24,
+ 0x9e, 0x80, 0xb5, 0xc9, 0xa9, 0x94, 0x1d, 0xe4, 0x18, 0xb6, 0x07, 0x1e,
+ 0xfa, 0xe0, 0x1c, 0x88, 0x06, 0x84, 0xaa, 0xcb, 0x5e, 0xfa, 0x15, 0x5a,
+ 0xdd, 0x10, 0x43, 0x81, 0xf2, 0x50, 0x3e, 0x93, 0x26, 0x77, 0x1c, 0x77,
+ 0xe9, 0x0c, 0xfc, 0x5f, 0xdd, 0x67, 0x31, 0x02, 0xc6, 0xdd, 0xf4, 0x30,
+ 0x76, 0x51, 0xce, 0x56, 0xba, 0x7f, 0x44, 0xbd, 0x42, 0x9f, 0x10, 0x8c,
+ 0x56, 0x49, 0x48, 0xa2, 0xcb, 0xc4, 0xdd, 0x29, 0xae, 0xf0, 0x33, 0x35,
+ 0x46, 0x69, 0x1d, 0xae, 0xde, 0xde, 0x98, 0x82, 0x79, 0xa6, 0x50, 0x28,
+ 0xb3, 0x5f, 0x10, 0x24, 0x63, 0xee, 0x9a, 0x22, 0xbe, 0xf8, 0x3a, 0xf4,
+ 0xab, 0x98, 0xfe, 0xdf, 0x30, 0x03, 0xe8, 0x45, 0x8c, 0xf4, 0x85, 0xc6,
+ 0x98, 0x7b, 0x35, 0xb8, 0x30, 0x9c, 0x15, 0xa6, 0x45, 0xbd, 0x39, 0x84,
+ 0xe7, 0x43, 0x4b, 0x05, 0xa4, 0x8f, 0x52, 0x8e, 0x4a, 0xe4, 0x87, 0xc1,
+ 0xdc, 0xdf, 0x25, 0x9c, 0x5c, 0x37, 0xd0, 0x66, 0x12, 0x41, 0x66, 0x8c,
+ 0x28, 0xd0, 0x3f, 0x5c, 0x7f, 0x15, 0x9b, 0xcf, 0xa0, 0xae, 0x29, 0x33,
+ 0xb0, 0xe4, 0xb7, 0x36, 0x2a, 0x45, 0x83, 0xff, 0x86, 0x75, 0xcf, 0xa7,
+ 0x4d, 0x5c, 0xa8, 0xcf, 0x3f, 0xf2, 0xc8, 0xde, 0xdd, 0xad, 0x42, 0x8f,
+ 0x0e, 0xd0, 0x11, 0x24, 0x42, 0x86, 0x51, 0x52, 0x76, 0x21, 0x68, 0xf1,
+ 0xa7, 0x8f, 0xdb, 0x5b, 0x78, 0xfa, 0x44, 0x5f, 0xee, 0x31, 0xda, 0x62,
+ 0x5f, 0xfe, 0x69, 0xae, 0x97, 0xc9, 0xb5, 0x04, 0x76, 0x79, 0x2e, 0xb9,
+ 0xd9, 0x1b, 0xdd, 0xb7, 0xc4, 0x12, 0x78, 0xb2, 0x4d, 0xab, 0xd2, 0x29,
+ 0x25, 0x8c, 0xd5, 0x52, 0x4a, 0xd7, 0x2e, 0x18, 0x9d, 0xa2, 0xee, 0x7b,
+ 0xa5, 0xe5, 0x35, 0x3c, 0xb5, 0x54, 0x1c, 0x7f, 0x87, 0x4b, 0xc0, 0xbb,
+ 0x1a, 0x85, 0x19, 0xc0, 0xa9, 0x2b, 0x4d, 0xed, 0x71, 0xc0, 0x15, 0xb3,
+ 0x49, 0x2c, 0x46, 0xfc, 0x37, 0x40, 0xc0, 0x60, 0xd0, 0x00, 0x96, 0xfa,
+ 0x7f, 0xbb, 0x30, 0x94, 0x6b, 0x81, 0x61, 0xc5, 0x13, 0x93, 0x95, 0xaa,
+ 0xf3, 0x8d, 0x1d, 0xac, 0xdb, 0xbd, 0xc3, 0x90, 0xf3, 0xd2, 0x5f, 0x3a,
+ 0x08, 0xb1, 0xc9, 0x3a, 0xe8, 0x25, 0x4d, 0x20, 0x2a, 0xe9, 0x4c, 0xaf,
+ 0x9b, 0x54, 0x7b, 0xaf, 0x89, 0x44, 0x3a, 0x60, 0x23, 0xd3, 0x02, 0xb1,
+ 0xb3, 0x9a, 0x3a, 0xb0, 0xa0, 0xdb, 0x61, 0x0b, 0xac, 0x55, 0xa1, 0x36,
+ 0x55, 0x5b, 0xc4, 0xc5, 0xbd, 0x2a, 0x16, 0xe9, 0xe7, 0x86, 0x7f, 0xdb,
+ 0xee, 0x90, 0xfa, 0xfd, 0x08, 0x7f, 0x1a, 0x43, 0xe0, 0xb8, 0x21, 0xb3,
+ 0xe3, 0xdf, 0x27, 0x56, 0x61, 0xc4, 0xe8, 0xd5, 0x60, 0xe9, 0x6d, 0x49,
+ 0xd9, 0xa8, 0xf5, 0xd9, 0xfc, 0x66, 0x82, 0xe9, 0x80, 0x5b, 0x85, 0x16,
+ 0x55, 0x2b, 0xef, 0x50, 0x90, 0x6c, 0x5d, 0x81, 0x00, 0x00, 0x88, 0x9b,
+ 0xb4, 0x62, 0x49, 0x46, 0x2e, 0x5d, 0x71, 0x95, 0xff, 0x63, 0xfb, 0x93,
+ 0x23, 0xf8, 0x9f, 0xa2, 0x55, 0x56, 0xd4, 0xd5, 0xf7, 0xae, 0xaf, 0xd3,
+ 0xf6, 0x82, 0xc8, 0xdd, 0x89, 0x0f, 0x7e, 0x89, 0x0d, 0x0d, 0x7f, 0x4f,
+ 0x84, 0xa7, 0x16, 0xe8, 0xaf, 0xf2, 0x95, 0xd7, 0xc3, 0x66, 0xd6, 0x85,
+ 0x5b, 0xa1, 0xbb, 0xea, 0x31, 0x02, 0xac, 0xa2, 0x7b, 0x50, 0xf4, 0x78,
+ 0x29, 0x49, 0x59, 0xf6, 0x41, 0x42, 0x52, 0xa8, 0x19, 0xfb, 0x3d, 0xda,
+ 0xa9, 0x8d, 0xac, 0xe1, 0x25, 0xd4, 0x12, 0x1e, 0x2b, 0x48, 0x44, 0xb0,
+ 0xf6, 0x29, 0xd0, 0x55, 0x22, 0xb4, 0xe7, 0xbc, 0x22, 0x97, 0x1f, 0xe2,
+ 0xe1, 0x73, 0x16, 0x13, 0x7a, 0x00, 0x62, 0x14, 0xcb, 0x25, 0x9b, 0x21,
+ 0x98, 0x9d, 0xb8, 0xd8, 0xf4, 0x65, 0xf6, 0x8f, 0x39, 0xe4, 0x76, 0xf7,
+ 0x30, 0xaf, 0xbc, 0x3a, 0xfe, 0x0e, 0xf1, 0x81, 0xa7, 0xff, 0x4d, 0xa7,
+ 0xff, 0xbf, 0x15, 0x60, 0x0b, 0xcd, 0x69, 0xd5, 0x77, 0xba, 0xcb, 0x7b,
+ 0x5a, 0xfb, 0x34, 0xc7, 0x5d, 0x13, 0x33, 0xd7, 0x86, 0x02, 0x43, 0x57,
+ 0x52, 0x2c, 0x74, 0x61, 0x21, 0xa3, 0x34, 0xf5, 0x89, 0x51, 0x44, 0x89,
+ 0xfc, 0xbb, 0x57, 0x5c, 0x6d, 0xb0, 0x2e, 0x8c, 0xff, 0x73, 0xe5, 0x09,
+ 0x13, 0x3b, 0x45, 0x5b, 0x27, 0x88, 0xee, 0x9b, 0xab, 0x57, 0x7c, 0x9b,
+ 0xb9, 0x78, 0x73, 0xd2, 0x2d, 0x98, 0x6f, 0xd2, 0x78, 0xb3, 0xeb, 0xaa,
+ 0x18, 0x44, 0x87, 0x6d, 0x51, 0x1e, 0x9b, 0x73, 0xaa, 0x91, 0x1a, 0x4f,
+ 0x69, 0x78, 0xef, 0x3f, 0xb1, 0x2d, 0x39, 0x3e, 0xda, 0x31, 0xfc, 0x99,
+ 0xf6, 0xa2, 0x8c, 0xe5, 0xfd, 0x97, 0x95, 0x77, 0x37, 0xef, 0xf5, 0xd1,
+ 0xc8, 0x74, 0x2c, 0x9a, 0x1f, 0x23, 0x8f, 0x72, 0x96, 0x3d, 0xb5, 0xad,
+ 0x28, 0xa0, 0x6c, 0x66, 0xe8, 0xee, 0xaa, 0x9d, 0xc2, 0x8a, 0x56, 0x54,
+ 0x89, 0x74, 0x56, 0xdc, 0x57, 0x49, 0xc3, 0x8e, 0xb9, 0x3a, 0x91, 0x34,
+ 0xc4, 0x5e, 0x0b, 0x13, 0x63, 0x5e, 0xeb, 0xc5, 0xef, 0xc7, 0xe9, 0x7f,
+ 0x27, 0xe8, 0xe7, 0xe5, 0x0d, 0x83, 0x95, 0x5f, 0x8a, 0xf2, 0xb2, 0x22,
+ 0x03, 0x8d, 0x71, 0x4f, 0x62, 0xb7, 0xf1, 0x87, 0xf5, 0x3f, 0xc4, 0x23,
+ 0x21, 0x40, 0x35, 0xcf, 0x79, 0x7a, 0x5b, 0x9d, 0x76, 0xb2, 0xdc, 0x6a,
+ 0xb5, 0x1d, 0x8b, 0xb6, 0x9a, 0x19, 0xe4, 0x87, 0xf5, 0xce, 0x38, 0xf3,
+ 0x70, 0xbf, 0x9e, 0x86, 0xa6, 0x07, 0x53, 0xdd, 0x5d, 0xc7, 0x72, 0x84,
+ 0x47, 0x38, 0xd0, 0xe2, 0xeb, 0x64, 0x4c, 0x3a, 0x1e, 0xf6, 0x56, 0x79,
+ 0x75, 0x75, 0x14, 0x5d, 0xe4, 0x1d, 0x9d, 0xbb, 0xe1, 0x35, 0x03, 0x5e,
+ 0x4f, 0x8f, 0xea, 0x95, 0xde, 0x19, 0x57, 0x98, 0xe9, 0x2c, 0x42, 0x22,
+ 0xcb, 0x0f, 0x15, 0x7a, 0x6b, 0x53, 0xc3, 0xec, 0xdc, 0xa0, 0x66, 0x26,
+ 0x91, 0x04, 0x83, 0x75, 0x09, 0x0c, 0x22, 0x05, 0xec, 0x3a, 0x2d, 0x39,
+ 0xea, 0x19, 0xf2, 0x1d, 0xdb, 0xba, 0x5c, 0x46, 0x47, 0xd4, 0x94, 0x6d,
+ 0x51, 0xdb, 0x68, 0xde, 0x0c, 0xa0, 0x36, 0x8f, 0xbc, 0xfd, 0x9b, 0x8f,
+ 0xfe, 0x04, 0x1f, 0xde, 0x1e, 0x77, 0xb5, 0x80, 0xb9, 0x9c, 0x1b, 0x24,
+ 0x61, 0xfc, 0x2b, 0xc0, 0x42, 0x2b, 0xc5, 0x90, 0x58, 0xa2, 0xb1, 0x38,
+ 0x58, 0xf2, 0x8b, 0x65, 0xbf, 0xe8, 0xe6, 0x79, 0xcf, 0x65, 0x35, 0xa5,
+ 0xe1, 0xb7, 0x8b, 0x95, 0x54, 0xd7, 0x1d, 0xf0, 0x91, 0x18, 0xc0, 0x5d,
+ 0x2c, 0xb5, 0xca, 0x1a, 0x7f, 0x8d, 0xfb, 0x9e, 0x57, 0x1c, 0x5c, 0xf0,
+ 0x94, 0x36, 0x51, 0x95, 0x27, 0x62, 0xca, 0x92, 0x96, 0xe5, 0x00, 0x2e,
+ 0xa4, 0x41, 0x97, 0xbf, 0x28, 0x3c, 0x6d, 0xc1, 0xb7, 0xe9, 0x1c, 0x2e,
+ 0x3e, 0xe0, 0x5e, 0x89, 0x0c, 0x78, 0x88, 0x80, 0xb8, 0x30, 0xd2, 0x22,
+ 0xf9, 0x71, 0xb4, 0xc8, 0xee, 0xe6, 0x80, 0x04, 0x04, 0x9a, 0xfb, 0x0c,
+ 0x36, 0xcb, 0xea, 0x66, 0xf9, 0x52, 0x8c, 0x66, 0xbf, 0x4c, 0x0f, 0xf4,
+ 0xf8, 0x1e, 0x7e, 0x39, 0x80, 0xe8, 0x82, 0x4b, 0x0e, 0x66, 0x1d, 0x51,
+ 0x16, 0xa9, 0x8d, 0xd6, 0xea, 0x33, 0xb0, 0x2c, 0x36, 0x25, 0xf5, 0x01,
+ 0x30, 0x7e, 0x03, 0x7f, 0xae, 0x8e, 0xd6, 0x25, 0x62, 0x6d, 0x99, 0x8c,
+ 0x1f, 0xc1, 0x22, 0xf0, 0x94, 0x80, 0xbf, 0x82, 0x51, 0xea, 0xc2, 0x5a,
+ 0x3c, 0x85, 0x2a, 0x5d, 0xbe, 0xae, 0xe1, 0xe3, 0x07, 0x92, 0xd2, 0x40,
+ 0x47, 0xe8, 0x0f, 0x1a, 0xa5, 0x73, 0x64, 0x26, 0xc4, 0xac, 0xca, 0xc2,
+ 0x83, 0x5a, 0x56, 0xbc, 0x81, 0x21, 0xcb, 0x72, 0xf3, 0xe7, 0x82, 0x1e,
+ 0xc8, 0x54, 0x18, 0x42, 0xfe, 0xd6, 0xfc, 0x96, 0x0e, 0x03, 0x29, 0x98,
+ 0x4f, 0xd1, 0xd2, 0x98, 0x7c, 0x9e, 0x4e, 0x1a, 0x0f, 0xd6, 0x4e, 0xa4,
+ 0x52, 0x1b, 0xd1, 0xd8, 0x36, 0xf7, 0x47, 0x5f, 0xce, 0xcb, 0x87, 0x36,
+ 0xc8, 0x9b, 0x44, 0xc6, 0x7a, 0xf3, 0x45, 0x28, 0xae, 0x96, 0x5a, 0x85,
+ 0x62, 0x8b, 0x10, 0xc2, 0x7b, 0x39, 0x51, 0xdf, 0xf4, 0x21, 0xc2, 0x6b,
+ 0x6f, 0x93, 0x27, 0xed, 0xf6, 0xea, 0xff, 0x2a, 0x21, 0x70, 0x84, 0x4e,
+ 0x21, 0xac, 0xbc, 0x06, 0x41, 0xd3, 0x59, 0xa0, 0xa1, 0x50, 0xa6, 0x87,
+ 0xa2, 0x48, 0xad, 0x94, 0x44, 0x8d, 0x2f, 0xa8, 0xc6, 0x10, 0xb5, 0xeb,
+ 0x66, 0x82, 0x94, 0x5f, 0xae, 0x6a, 0x56, 0xb4, 0x8d, 0xf4, 0x62, 0x80,
+ 0xe4, 0x42, 0xc4, 0xbc, 0xe7, 0xee, 0xa6, 0x96, 0x3b, 0xfd, 0xc0, 0x92,
+ 0x7d, 0xcd, 0xe7, 0x0c, 0x99, 0x9a, 0xb6, 0x83, 0xcf, 0x45, 0xe5, 0x74,
+ 0xb3, 0xbc, 0xc0, 0x40, 0xad, 0x4d, 0xfc, 0xa7, 0x92, 0x35, 0x13, 0x81,
+ 0x5c, 0x9c, 0x21, 0x00, 0xa4, 0x37, 0x07, 0x1d, 0x19, 0xfc, 0x88, 0x4d,
+ 0x71, 0x43, 0x7d, 0x94, 0xf7, 0x32, 0xb8, 0x4b, 0x8a, 0x54, 0xd6, 0xe4,
+ 0x37, 0x4f, 0x27, 0x1f, 0xfd, 0x45, 0x83, 0xb9, 0x14, 0x5a, 0xf7, 0x36,
+ 0xdc, 0x98, 0xad, 0x99, 0xb9, 0x38, 0x69, 0xac, 0x18, 0x7e, 0x47, 0xd0,
+ 0x63, 0x27, 0xba, 0xe7, 0xd5, 0x1d, 0x7b, 0x6e, 0xde, 0x28, 0x7b, 0xf1,
+ 0x84, 0x4d, 0x2d, 0x7c, 0x16, 0x38, 0x4b, 0x16, 0xa9, 0x10, 0x83, 0xfb,
+ 0xe0, 0xe0, 0x6f, 0xdd, 0x03, 0x0a, 0xb8, 0x81, 0xf5, 0x8c, 0x98, 0xc3,
+ 0xf4, 0xc8, 0x31, 0x3a, 0xed, 0x14, 0x83, 0x89, 0xc3, 0x0e, 0xf7, 0xba,
+ 0x84, 0xb0, 0x49, 0xdf, 0xc6, 0x6b, 0xed, 0xbe, 0xd4, 0xa3, 0x83, 0x3a,
+ 0xe6, 0x6d, 0xa3, 0x83, 0x17, 0x43, 0x5e, 0x3a, 0x83, 0xda, 0x81, 0xe3,
+ 0x26, 0x95, 0x6b, 0xe5, 0x30, 0x28, 0x6d, 0xec, 0xd7, 0xd7, 0x35, 0xfa,
+ 0x1a, 0xad, 0x86, 0x04, 0x05, 0x2c, 0x76, 0x3f, 0xb2, 0x83, 0x92, 0x4e,
+ 0xef, 0x05, 0xde, 0x13, 0x26, 0x68, 0x80, 0x57, 0xee, 0x92, 0x80, 0xa3,
+ 0x99, 0xb4, 0xac, 0x98, 0x31, 0xd4, 0xf3, 0xe2, 0x60, 0xd9, 0xb9, 0x8d,
+ 0x20, 0xf7, 0x97, 0x70, 0x10, 0xd6, 0xba, 0x86, 0xb8, 0x9c, 0xb8, 0xf8,
+ 0x49, 0x71, 0x28, 0x9d, 0x05, 0x38, 0x1f, 0x63, 0xba, 0xf7, 0x15, 0x60,
+ 0x96, 0x61, 0x84, 0x68, 0xeb, 0x5d, 0x28, 0x51, 0xe3, 0x51, 0xdd, 0x69,
+ 0x8a, 0xdd, 0xba, 0xec, 0xbd, 0xd3, 0xa1, 0x42, 0x83, 0x59, 0x77, 0x11,
+ 0x12, 0x86, 0x5b, 0x8d, 0x30, 0xcf, 0xdf, 0x6f, 0xea, 0x9d, 0x31, 0xa2,
+ 0x65, 0xa5, 0x61, 0xc0, 0xde, 0x52, 0x6c, 0x72, 0x71, 0x0b, 0x4c, 0x7a,
+ 0x4c, 0x9f, 0x75, 0x74, 0x38, 0xc8, 0xdd, 0x12, 0xba, 0x21, 0x57, 0x1b,
+ 0x45, 0xb3, 0x02, 0x1d, 0x67, 0x22, 0x66, 0x53, 0x18, 0x48, 0xed, 0x60,
+ 0x40, 0x55, 0xd1, 0x25, 0x3b, 0xbc, 0x08, 0x7b, 0x19, 0x8a, 0x30, 0x5b,
+ 0x02, 0x4f, 0x65, 0x42, 0xff, 0xce, 0x87, 0xe8, 0x97, 0x2b, 0xbb, 0xfe,
+ 0x52, 0x52, 0x72, 0xe8, 0xb5, 0x77, 0xb7, 0x8e, 0x94, 0x34, 0xbc, 0x46,
+ 0xf1, 0xe1, 0x94, 0x98, 0x19, 0xbe, 0x7c, 0x3f, 0xf6, 0x0e, 0xe4, 0xbb,
+ 0x88, 0x32, 0x07, 0x83, 0x64, 0xad, 0xd7, 0xd1, 0xe8, 0x35, 0x8d, 0x5d,
+ 0x70, 0x16, 0xc8, 0x11, 0x94, 0x39, 0xc9, 0xac, 0xd6, 0xed, 0x6b, 0xdf,
+ 0xc8, 0xf3, 0x1d, 0x5e, 0x37, 0xd8, 0xb5, 0x86, 0x9b, 0xc2, 0xdc, 0x3c,
+ 0x5c, 0x04, 0x52, 0x5c, 0x11, 0x88, 0x0a, 0x2b, 0x78, 0x48, 0x9e, 0x5e,
+ 0x98, 0x57, 0x5a, 0xd1, 0x77, 0x1c, 0x7d, 0x5f, 0x60, 0xbb, 0x61, 0x7e,
+ 0x7e, 0x2a, 0xaf, 0x44, 0x14, 0x88, 0xfc, 0xa5, 0x31, 0xb7, 0xd4, 0x44,
+ 0x48, 0xda, 0xb5, 0x71, 0xa8, 0xd8, 0x4f, 0x79, 0xcd, 0xe4, 0xbe, 0xb6,
+ 0x1a, 0x61, 0x74, 0x4b, 0xd8, 0xec, 0xd7, 0xbf, 0xad, 0x57, 0x00, 0x42,
+ 0x04, 0xe8, 0xb3, 0xec, 0x47, 0x1d, 0x2a, 0x0a, 0xde, 0x7c, 0x6e, 0x5e,
+ 0xf8, 0xaa, 0x44, 0x05, 0x10, 0xab, 0xe9, 0x4e, 0xd7, 0x44, 0x0b, 0x97,
+ 0x6f, 0x1a, 0xc1, 0x59, 0x2b, 0xe4, 0xe1, 0x8a, 0x13, 0x82, 0x65, 0xd8,
+ 0xae, 0x5f, 0x2b, 0xbc, 0xa6, 0x14, 0x39, 0xaf, 0x38, 0x41, 0x26, 0x74,
+ 0xdb, 0x55, 0x6b, 0xe2, 0x21, 0x80, 0x5d, 0x20, 0xc3, 0xf5, 0x82, 0xee,
+ 0xcc, 0x3c, 0xc9, 0xb4, 0xeb, 0x52, 0xe9, 0x13, 0x8a, 0xea, 0xc6, 0x19,
+ 0x70, 0x37, 0x1b, 0xb8, 0x2e, 0x86, 0xa2, 0xe9, 0x9d, 0xb6, 0xd5, 0xd6,
+ 0xf3, 0xa8, 0x31, 0xf3, 0x02, 0xaa, 0x10, 0x33, 0x3f, 0xba, 0xf8, 0xf9,
+ 0x46, 0x5b, 0xe1, 0xd7, 0x34, 0x9f, 0x94, 0xcb, 0xfb, 0xb1, 0x3d, 0x60,
+ 0x77, 0x85, 0x14, 0xd4, 0xcf, 0x55, 0x60, 0x5d, 0x47, 0x6c, 0x07, 0xb4,
+ 0xc7, 0x73, 0xbd, 0x49, 0xbd, 0xa5, 0x31, 0xa1, 0xfa, 0x34, 0x3a, 0x8b,
+ 0x77, 0x1b, 0xaa, 0xaf, 0xa5, 0x87, 0x12, 0x4e, 0x36, 0x06, 0x14, 0xe7,
+ 0xb3, 0xb8, 0x87, 0x6c, 0x4b, 0x50, 0xc9, 0x52, 0x1b, 0x19, 0x48, 0x69,
+ 0x5b, 0x7f, 0xd8, 0xc9, 0x14, 0xb8, 0x11, 0xa0, 0x51, 0x09, 0xbd, 0x42,
+ 0x5a, 0x50, 0x32, 0x57, 0x69, 0x39, 0x30, 0xdb, 0xbf, 0x8b, 0x93, 0x54,
+ 0x43, 0x80, 0x4e, 0xd0, 0xc6, 0xf2, 0x81, 0x15, 0x6d, 0xef, 0x5a, 0xb6,
+ 0x4d, 0x70, 0x93, 0x88, 0x8d, 0xce, 0x0d, 0xb8, 0xe9, 0xac, 0xa2, 0xcd,
+ 0xc7, 0x18, 0xa5, 0x95, 0xb7, 0xf6, 0x0c, 0x6f, 0xe1, 0x10, 0x7b, 0x22,
+ 0xf8, 0x81, 0x18, 0x42, 0x6a, 0x09, 0x75, 0x20, 0xb4, 0x2f, 0x67, 0x7a,
+ 0xda, 0x55, 0x28, 0xc3, 0x81, 0xf7, 0xc1, 0xf0, 0xe6, 0x1b, 0x29, 0x9c,
+ 0x72, 0x87, 0xe5, 0x4c, 0xa9, 0x5b, 0x5b, 0x62, 0xb5, 0xb7, 0x1e, 0x82,
+ 0xc3, 0x7b, 0xaf, 0xe9, 0x6f, 0x37, 0x31, 0x9f, 0x79, 0xe7, 0x4f, 0x06,
+ 0x1e, 0xff, 0xff, 0x80, 0x8e, 0x00, 0x00
+};
- fd = os_open(fname, OS_O_RDONLY);
- ut_assert(fd >= 0);
- ut_asserteq(512, os_read(fd, header, 512));
- text_ctx.fd = fd;
+int do_spl_test_load(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type, struct spl_image_loader *loader,
+ int (*write_image)(struct unit_test_state *, void *, size_t))
+{
+ size_t img_size, img_data, plain_size = SPL_TEST_DATA_SIZE;
+ struct spl_image_info info_write = {
+ .name = test_name,
+ .size = type == LEGACY_LZMA ? sizeof(lzma_compressed) :
+ plain_size,
+ }, info_read = { };
+ struct spl_boot_device bootdev = {
+ .boot_device = loader->boot_device,
+ };
+ char *data, *plain;
+ void *img;
+
+ img_size = create_image(NULL, type, &info_write, &img_data);
+ ut_assert(img_size);
+ img = calloc(img_size, 1);
+ ut_assertnonnull(img);
+
+ data = img + img_data;
+ if (type == LEGACY_LZMA) {
+ plain = malloc(plain_size);
+ ut_assertnonnull(plain);
+ generate_data(plain, plain_size, "lzma");
+ memcpy(data, lzma_compressed, sizeof(lzma_compressed));
+ } else {
+ plain = data;
+ generate_data(plain, plain_size, test_name);
+ }
+ ut_asserteq(img_size, create_image(img, type, &info_write, NULL));
- load.priv = &text_ctx;
+ if (write_image(uts, img, img_size))
+ return CMD_RET_FAILURE;
- ut_assertok(spl_load_simple_fit(&image, &load, 0, header));
+ ut_assertok(loader->load_image(&info_read, &bootdev));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ if (type == LEGACY_LZMA)
+ ut_asserteq(plain_size, info_read.size);
+ ut_asserteq_mem(plain, phys_to_virt(info_write.load_addr), plain_size);
+ if (type == LEGACY_LZMA)
+ free(plain);
+ free(img);
return 0;
}
-SPL_TEST(spl_test_load, 0);
diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c
new file mode 100644
index 00000000000..297ab08a820
--- /dev/null
+++ b/test/image/spl_load_fs.c
@@ -0,0 +1,428 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <ext_common.h>
+#include <ext4fs.h>
+#include <fat.h>
+#include <fs.h>
+#include <memalign.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <linux/stat.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+/**
+ * create_ext2() - Create an "ext2" filesystem with a single file
+ * @dst: The location of the new filesystem; MUST be zeroed
+ * @size: The size of the file
+ * @filename: The name of the file
+ * @data_offset: Filled with the offset of the file data from @dst
+ *
+ * Budget mke2fs. We use 1k blocks (to reduce overhead) with a single block
+ * group, which limits us to 8M of data. Almost every feature which increases
+ * complexity (checksums, hash tree directories, etc.) is disabled. We do cheat
+ * a little and use extents from ext4 to save having to deal with indirects, but
+ * U-Boot doesn't care.
+ *
+ * If @dst is %NULL, nothing is copied.
+ *
+ * Return: The size of the filesystem in bytes
+ */
+static size_t create_ext2(void *dst, size_t size, const char *filename,
+ size_t *data_offset)
+{
+ u32 super_block = 1;
+ u32 group_block = 2;
+ u32 block_bitmap_block = 3;
+ u32 inode_bitmap_block = 4;
+ u32 inode_table_block = 5;
+ u32 root_block = 6;
+ u32 file_block = 7;
+
+ u32 root_ino = EXT2_ROOT_INO;
+ u32 file_ino = EXT2_BOOT_LOADER_INO;
+
+ u32 block_size = EXT2_MIN_BLOCK_SIZE;
+ u32 inode_size = sizeof(struct ext2_inode);
+
+ u32 file_blocks = (size + block_size - 1) / block_size;
+ u32 blocks = file_block + file_blocks;
+ u32 inodes = block_size / inode_size;
+ u32 filename_len = strlen(filename);
+ u32 dirent_len = ALIGN(filename_len, sizeof(struct ext2_dirent)) +
+ sizeof(struct ext2_dirent);
+
+ struct ext2_sblock *sblock = dst + super_block * block_size;
+ struct ext2_block_group *bg = dst + group_block * block_size;
+ struct ext2_inode *inode_table = dst + inode_table_block * block_size;
+ struct ext2_inode *root_inode = &inode_table[root_ino - 1];
+ struct ext2_inode *file_inode = &inode_table[file_ino - 1];
+ struct ext4_extent_header *ext_block = (void *)&file_inode->b;
+ struct ext4_extent *extent = (void *)(ext_block + 1);
+ struct ext2_dirent *dot = dst + root_block * block_size;
+ struct ext2_dirent *dotdot = dot + 2;
+ struct ext2_dirent *dirent = dotdot + 2;
+ struct ext2_dirent *last = ((void *)dirent) + dirent_len;
+
+ /* Make sure we fit in one block group */
+ if (blocks > block_size * 8)
+ return 0;
+
+ if (filename_len > EXT2_NAME_LEN)
+ return 0;
+
+ if (data_offset)
+ *data_offset = file_block * block_size;
+
+ if (!dst)
+ goto out;
+
+ sblock->total_inodes = cpu_to_le32(inodes);
+ sblock->total_blocks = cpu_to_le32(blocks);
+ sblock->first_data_block = cpu_to_le32(super_block);
+ sblock->blocks_per_group = cpu_to_le32(blocks);
+ sblock->fragments_per_group = cpu_to_le32(blocks);
+ sblock->inodes_per_group = cpu_to_le32(inodes);
+ sblock->magic = cpu_to_le16(EXT2_MAGIC);
+ /* Done mostly so we can pretend to be (in)compatible */
+ sblock->revision_level = cpu_to_le32(EXT2_DYNAMIC_REV);
+ /* Not really accurate but it doesn't matter */
+ sblock->first_inode = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
+ sblock->inode_size = cpu_to_le32(inode_size);
+ sblock->feature_incompat = cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS);
+
+ bg->block_id = cpu_to_le32(block_bitmap_block);
+ bg->inode_id = cpu_to_le32(inode_bitmap_block);
+ bg->inode_table_id = cpu_to_le32(inode_table_block);
+
+ /*
+ * All blocks/inodes are in-use. I don't want to have to deal with
+ * endianness, so just fill everything in.
+ */
+ memset(dst + block_bitmap_block * block_size, 0xff, block_size * 2);
+
+ root_inode->mode = cpu_to_le16(S_IFDIR | 0755);
+ root_inode->size = cpu_to_le32(block_size);
+ root_inode->nlinks = cpu_to_le16(3);
+ root_inode->blockcnt = cpu_to_le32(1);
+ root_inode->flags = cpu_to_le32(EXT4_TOPDIR_FL);
+ root_inode->b.blocks.dir_blocks[0] = root_block;
+
+ file_inode->mode = cpu_to_le16(S_IFREG | 0644);
+ file_inode->size = cpu_to_le32(size);
+ file_inode->nlinks = cpu_to_le16(1);
+ file_inode->blockcnt = cpu_to_le32(file_blocks);
+ file_inode->flags = cpu_to_le32(EXT4_EXTENTS_FL);
+ ext_block->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC);
+ ext_block->eh_entries = cpu_to_le16(1);
+ ext_block->eh_max = cpu_to_le16(sizeof(file_inode->b) /
+ sizeof(*ext_block) - 1);
+ extent->ee_len = cpu_to_le16(file_blocks);
+ extent->ee_start_lo = cpu_to_le16(file_block);
+
+ /* I'm not sure we need these, but it can't hurt */
+ dot->inode = cpu_to_le32(root_ino);
+ dot->direntlen = cpu_to_le16(2 * sizeof(*dot));
+ dot->namelen = 1;
+ dot->filetype = FILETYPE_DIRECTORY;
+ memcpy(dot + 1, ".", dot->namelen);
+
+ dotdot->inode = cpu_to_le32(root_ino);
+ dotdot->direntlen = cpu_to_le16(2 * sizeof(*dotdot));
+ dotdot->namelen = 2;
+ dotdot->filetype = FILETYPE_DIRECTORY;
+ memcpy(dotdot + 1, "..", dotdot->namelen);
+
+ dirent->inode = cpu_to_le32(file_ino);
+ dirent->direntlen = cpu_to_le16(dirent_len);
+ dirent->namelen = filename_len;
+ dirent->filetype = FILETYPE_REG;
+ memcpy(dirent + 1, filename, filename_len);
+
+ last->direntlen = block_size - dirent_len;
+
+out:
+ return (size_t)blocks * block_size;
+}
+
+/**
+ * create_fat() - Create a FAT32 filesystem with a single file
+ * @dst: The location of the new filesystem; MUST be zeroed
+ * @size: The size of the file
+ * @filename: The name of the file
+ * @data_offset: Filled with the offset of the file data from @dst
+ *
+ * Budget mkfs.fat. We use FAT32 (so I don't have to deal with FAT12) with no
+ * info sector, and a single one-sector FAT. This limits us to 64k of data
+ * (enough for anyone). The filename must fit in 8.3.
+ *
+ * If @dst is %NULL, nothing is copied.
+ *
+ * Return: The size of the filesystem in bytes
+ */
+static size_t create_fat(void *dst, size_t size, const char *filename,
+ size_t *data_offset)
+{
+ u16 boot_sector = 0;
+ u16 fat_sector = 1;
+ u32 root_sector = 2;
+ u32 file_sector = 3;
+
+ u16 sector_size = 512;
+ u32 file_sectors = (size + sector_size - 1) / sector_size;
+ u32 sectors = file_sector + file_sectors;
+
+ char *ext;
+ size_t filename_len, ext_len;
+ int i;
+
+ struct boot_sector *bs = dst + boot_sector * sector_size;
+ struct volume_info *vi = (void *)(bs + 1);
+ __le32 *fat = dst + fat_sector * sector_size;
+ struct dir_entry *dirent = dst + root_sector * sector_size;
+
+ /* Make sure we fit in the FAT */
+ if (sectors > sector_size / sizeof(u32))
+ return 0;
+
+ ext = strchr(filename, '.');
+ if (ext) {
+ filename_len = ext - filename;
+ ext++;
+ ext_len = strlen(ext);
+ } else {
+ filename_len = strlen(filename);
+ ext_len = 0;
+ }
+
+ if (filename_len > 8 || ext_len > 3)
+ return 0;
+
+ if (data_offset)
+ *data_offset = file_sector * sector_size;
+
+ if (!dst)
+ goto out;
+
+ bs->sector_size[0] = sector_size & 0xff;
+ bs->sector_size[1] = sector_size >> 8;
+ bs->cluster_size = 1;
+ bs->reserved = cpu_to_le16(fat_sector);
+ bs->fats = 1;
+ bs->media = 0xf8;
+ bs->total_sect = cpu_to_le32(sectors);
+ bs->fat32_length = cpu_to_le32(1);
+ bs->root_cluster = cpu_to_le32(root_sector);
+
+ vi->ext_boot_sign = 0x29;
+ memcpy(vi->fs_type, FAT32_SIGN, sizeof(vi->fs_type));
+
+ memcpy(dst + 0x1fe, "\x55\xAA", 2);
+
+ fat[0] = cpu_to_le32(0x0ffffff8);
+ fat[1] = cpu_to_le32(0x0fffffff);
+ fat[2] = cpu_to_le32(0x0ffffff8);
+ for (i = file_sector; file_sectors > 1; file_sectors--, i++)
+ fat[i] = cpu_to_le32(i + 1);
+ fat[i] = cpu_to_le32(0x0ffffff8);
+
+ for (i = 0; i < sizeof(dirent->nameext.name); i++) {
+ if (i < filename_len)
+ dirent->nameext.name[i] = toupper(filename[i]);
+ else
+ dirent->nameext.name[i] = ' ';
+ }
+
+ for (i = 0; i < sizeof(dirent->nameext.ext); i++) {
+ if (i < ext_len)
+ dirent->nameext.ext[i] = toupper(ext[i]);
+ else
+ dirent->nameext.ext[i] = ' ';
+ }
+
+ dirent->start = cpu_to_le16(file_sector);
+ dirent->size = cpu_to_le32(size);
+
+out:
+ return sectors * sector_size;
+}
+
+typedef size_t (*create_fs_t)(void *, size_t, const char *, size_t *);
+
+static int spl_test_fs(struct unit_test_state *uts, const char *test_name,
+ create_fs_t create)
+{
+ const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
+ struct blk_desc *dev_desc;
+ char *data_write, *data_read;
+ void *fs;
+ size_t fs_size, fs_data, fs_blocks, data_size = SPL_TEST_DATA_SIZE;
+ loff_t actread;
+
+ fs_size = create(NULL, data_size, filename, &fs_data);
+ ut_assert(fs_size);
+ fs = calloc(fs_size, 1);
+ ut_assertnonnull(fs);
+
+ data_write = fs + fs_data;
+ generate_data(data_write, data_size, test_name);
+ ut_asserteq(fs_size, create(fs, data_size, filename, NULL));
+
+ dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
+ ut_assertnonnull(dev_desc);
+ ut_asserteq(512, dev_desc->blksz);
+ fs_blocks = fs_size / dev_desc->blksz;
+ ut_asserteq(fs_blocks, blk_dwrite(dev_desc, 0, fs_blocks, fs));
+
+ /* We have to use malloc so we can call virt_to_phys */
+ data_read = malloc_cache_aligned(data_size);
+ ut_assertnonnull(data_read);
+ ut_assertok(fs_set_blk_dev_with_part(dev_desc, 0));
+ ut_assertok(fs_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
+ virt_to_phys(data_read), 0, data_size, &actread));
+ ut_asserteq(data_size, actread);
+ ut_asserteq_mem(data_write, data_read, data_size);
+
+ free(data_read);
+ free(fs);
+ return 0;
+}
+
+static int spl_test_ext(struct unit_test_state *uts)
+{
+ return spl_test_fs(uts, __func__, create_ext2);
+}
+SPL_TEST(spl_test_ext, DM_FLAGS);
+
+static int spl_test_fat(struct unit_test_state *uts)
+{
+ spl_fat_force_reregister();
+ return spl_test_fs(uts, __func__, create_fat);
+}
+SPL_TEST(spl_test_fat, DM_FLAGS);
+
+static bool spl_mmc_raw;
+
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
+{
+ return spl_mmc_raw ? MMCSD_MODE_RAW : MMCSD_MODE_FS;
+}
+
+static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type, create_fs_t create_fs,
+ bool blk_mode)
+{
+ const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
+ struct blk_desc *dev_desc;
+ size_t fs_size, fs_data, img_size, img_data,
+ data_size = SPL_TEST_DATA_SIZE;
+ struct spl_image_info info_write = {
+ .name = test_name,
+ .size = data_size,
+ }, info_read = { };
+ struct disk_partition part = {
+ .start = 1,
+ .sys_ind = 0x83,
+ };
+ struct spl_image_loader *loader =
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
+ struct spl_boot_device bootdev = {
+ .boot_device = loader->boot_device,
+ };
+ void *fs;
+ char *data;
+
+ img_size = create_image(NULL, type, &info_write, &img_data);
+ ut_assert(img_size);
+ fs_size = create_fs(NULL, img_size, filename, &fs_data);
+ ut_assert(fs_size);
+ fs = calloc(fs_size, 1);
+ ut_assertnonnull(fs);
+
+ data = fs + fs_data + img_data;
+ generate_data(data, data_size, test_name);
+ ut_asserteq(img_size, create_image(fs + fs_data, type, &info_write,
+ NULL));
+ ut_asserteq(fs_size, create_fs(fs, img_size, filename, NULL));
+
+ dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
+ ut_assertnonnull(dev_desc);
+
+ ut_asserteq(512, dev_desc->blksz);
+ part.size = fs_size / dev_desc->blksz;
+ ut_assertok(write_mbr_partitions(dev_desc, &part, 1, 0));
+ ut_asserteq(part.size, blk_dwrite(dev_desc, part.start, part.size, fs));
+
+ spl_mmc_raw = false;
+ if (blk_mode)
+ ut_assertok(spl_blk_load_image(&info_read, &bootdev, UCLASS_MMC,
+ 0, 1));
+ else
+ ut_assertok(loader->load_image(&info_read, &bootdev));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ ut_asserteq_mem(data, phys_to_virt(info_write.load_addr), data_size);
+
+ free(fs);
+ return 0;
+}
+
+static int spl_test_blk(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ spl_fat_force_reregister();
+ if (spl_test_mmc_fs(uts, test_name, type, create_fat, true))
+ return CMD_RET_FAILURE;
+
+ return spl_test_mmc_fs(uts, test_name, type, create_ext2, true);
+}
+SPL_IMG_TEST(spl_test_blk, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_blk, FIT_EXTERNAL, DM_FLAGS);
+SPL_IMG_TEST(spl_test_blk, FIT_INTERNAL, DM_FLAGS);
+
+static int spl_test_mmc_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ struct blk_desc *dev_desc;
+ size_t img_blocks;
+
+ dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
+ ut_assertnonnull(dev_desc);
+
+ img_blocks = DIV_ROUND_UP(img_size, dev_desc->blksz);
+ ut_asserteq(img_blocks, blk_dwrite(dev_desc,
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
+ img_blocks, img));
+
+ spl_mmc_raw = true;
+ return 0;
+}
+
+static int spl_test_mmc(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ spl_mmc_clear_cache();
+ spl_fat_force_reregister();
+
+ if (type == LEGACY &&
+ spl_test_mmc_fs(uts, test_name, type, create_ext2, false))
+ return CMD_RET_FAILURE;
+
+ if (type != IMX8 &&
+ spl_test_mmc_fs(uts, test_name, type, create_fat, false))
+ return CMD_RET_FAILURE;
+
+ return do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1,
+ spl_mmc_load_image),
+ spl_test_mmc_write_image);
+}
+SPL_IMG_TEST(spl_test_mmc, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_mmc, IMX8, DM_FLAGS);
+SPL_IMG_TEST(spl_test_mmc, FIT_EXTERNAL, DM_FLAGS);
+SPL_IMG_TEST(spl_test_mmc, FIT_INTERNAL, DM_FLAGS);
diff --git a/test/image/spl_load_net.c b/test/image/spl_load_net.c
new file mode 100644
index 00000000000..f570cef163f
--- /dev/null
+++ b/test/image/spl_load_net.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <test/spl.h>
+#include <asm/eth.h>
+#include <test/ut.h>
+#include "../../net/bootp.h"
+
+/*
+ * sandbox_eth_bootp_req_to_reply()
+ *
+ * Check if a BOOTP request was sent. If so, inject a reply
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+static int sandbox_eth_bootp_req_to_reply(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct ethernet_hdr *eth = packet;
+ struct ip_udp_hdr *ip;
+ struct bootp_hdr *bp;
+ struct ethernet_hdr *eth_recv;
+ struct ip_udp_hdr *ipr;
+ struct bootp_hdr *bpr;
+
+ if (ntohs(eth->et_protlen) != PROT_IP)
+ return -EAGAIN;
+
+ ip = packet + ETHER_HDR_SIZE;
+ if (ip->ip_p != IPPROTO_UDP)
+ return -EAGAIN;
+
+ if (ntohs(ip->udp_dst) != PORT_BOOTPS)
+ return -EAGAIN;
+
+ bp = (void *)ip + IP_UDP_HDR_SIZE;
+ if (bp->bp_op != OP_BOOTREQUEST)
+ return -EAGAIN;
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return 0;
+
+ /* reply to the request */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+ memcpy(eth_recv, packet, len);
+ ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+ bpr = (void *)ipr + IP_UDP_HDR_SIZE;
+ memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ ipr->ip_sum = 0;
+ ipr->ip_off = 0;
+ net_write_ip(&ipr->ip_dst, net_ip);
+ net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr);
+ ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+ ipr->udp_src = ip->udp_dst;
+ ipr->udp_dst = ip->udp_src;
+
+ bpr->bp_op = OP_BOOTREPLY;
+ net_write_ip(&bpr->bp_yiaddr, net_ip);
+ net_write_ip(&bpr->bp_siaddr, priv->fake_host_ipaddr);
+ copy_filename(bpr->bp_file, CONFIG_BOOTFILE, sizeof(CONFIG_BOOTFILE));
+ memset(&bpr->bp_vend, 0, sizeof(bpr->bp_vend));
+
+ priv->recv_packet_length[priv->recv_packets] = len;
+ ++priv->recv_packets;
+
+ return 0;
+}
+
+struct spl_test_net_priv {
+ struct unit_test_state *uts;
+ void *img;
+ size_t img_size;
+ u16 port;
+};
+
+/* Well known TFTP port # */
+#define TFTP_PORT 69
+/* Transaction ID, chosen at random */
+#define TFTP_TID 21313
+
+/*
+ * TFTP operations.
+ */
+#define TFTP_RRQ 1
+#define TFTP_DATA 3
+#define TFTP_ACK 4
+
+/* default TFTP block size */
+#define TFTP_BLOCK_SIZE 512
+
+struct tftp_hdr {
+ u16 opcode;
+ u16 block;
+};
+
+#define TFTP_HDR_SIZE sizeof(struct tftp_hdr)
+
+/*
+ * sandbox_eth_tftp_req_to_reply()
+ *
+ * Check if a TFTP request was sent. If so, inject a reply. We don't support
+ * options, and we don't check for rollover, so we are limited files of less
+ * than 32M.
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+static int sandbox_eth_tftp_req_to_reply(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct spl_test_net_priv *test_priv = priv->priv;
+ struct ethernet_hdr *eth = packet;
+ struct ip_udp_hdr *ip;
+ struct tftp_hdr *tftp;
+ struct ethernet_hdr *eth_recv;
+ struct ip_udp_hdr *ipr;
+ struct tftp_hdr *tftpr;
+ size_t size;
+ u16 block;
+
+ if (ntohs(eth->et_protlen) != PROT_IP)
+ return -EAGAIN;
+
+ ip = packet + ETHER_HDR_SIZE;
+ if (ip->ip_p != IPPROTO_UDP)
+ return -EAGAIN;
+
+ if (ntohs(ip->udp_dst) == TFTP_PORT) {
+ tftp = (void *)ip + IP_UDP_HDR_SIZE;
+ if (htons(tftp->opcode) != TFTP_RRQ)
+ return -EAGAIN;
+
+ block = 0;
+ } else if (ntohs(ip->udp_dst) == TFTP_TID) {
+ tftp = (void *)ip + IP_UDP_HDR_SIZE;
+ if (htons(tftp->opcode) != TFTP_ACK)
+ return -EAGAIN;
+
+ block = htons(tftp->block);
+ } else {
+ return -EAGAIN;
+ }
+
+ if (block * TFTP_BLOCK_SIZE > test_priv->img_size)
+ return 0;
+
+ size = min(test_priv->img_size - block * TFTP_BLOCK_SIZE,
+ (size_t)TFTP_BLOCK_SIZE);
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return 0;
+
+ /* reply to the request */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+ memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ eth_recv->et_protlen = htons(PROT_IP);
+
+ ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+ ipr->ip_hl_v = 0x45;
+ ipr->ip_len = htons(IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size);
+ ipr->ip_off = htons(IP_FLAGS_DFRAG);
+ ipr->ip_ttl = 255;
+ ipr->ip_p = IPPROTO_UDP;
+ ipr->ip_sum = 0;
+ net_copy_ip(&ipr->ip_dst, &ip->ip_src);
+ net_copy_ip(&ipr->ip_src, &ip->ip_dst);
+ ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+
+ ipr->udp_src = htons(TFTP_TID);
+ ipr->udp_dst = ip->udp_src;
+ ipr->udp_len = htons(UDP_HDR_SIZE + TFTP_HDR_SIZE + size);
+ ipr->udp_xsum = 0;
+
+ tftpr = (void *)ipr + IP_UDP_HDR_SIZE;
+ tftpr->opcode = htons(TFTP_DATA);
+ tftpr->block = htons(block + 1);
+ memcpy((void *)tftpr + TFTP_HDR_SIZE,
+ test_priv->img + block * TFTP_BLOCK_SIZE, size);
+
+ priv->recv_packet_length[priv->recv_packets] =
+ ETHER_HDR_SIZE + IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size;
+ ++priv->recv_packets;
+
+ return 0;
+}
+
+static int spl_net_handler(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ int old_packets = priv->recv_packets;
+
+ priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
+ net_ip = string_to_ip("1.1.2.2");
+
+ sandbox_eth_arp_req_to_reply(dev, packet, len);
+ sandbox_eth_bootp_req_to_reply(dev, packet, len);
+ sandbox_eth_tftp_req_to_reply(dev, packet, len);
+
+ if (old_packets == priv->recv_packets)
+ return 0;
+
+ return 0;
+}
+
+static int spl_test_net_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ struct spl_test_net_priv *test_priv = malloc(sizeof(*test_priv));
+
+ ut_assertnonnull(test_priv);
+ test_priv->uts = uts;
+ test_priv->img = img;
+ test_priv->img_size = img_size;
+
+ sandbox_eth_set_tx_handler(0, spl_net_handler);
+ sandbox_eth_set_priv(0, test_priv);
+ return 0;
+}
+
+static int spl_test_net(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ struct eth_sandbox_priv *priv;
+ struct udevice *dev;
+ int ret;
+
+ net_server_ip = string_to_ip("1.1.2.4");
+ ret = do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_CPGMAC,
+ spl_net_load_image_cpgmac),
+ spl_test_net_write_image);
+
+ sandbox_eth_set_tx_handler(0, NULL);
+ ut_assertok(uclass_get_device(UCLASS_ETH, 0, &dev));
+ priv = dev_get_priv(dev);
+ free(priv->priv);
+ return ret;
+}
+SPL_IMG_TEST(spl_test_net, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_net, FIT_INTERNAL, DM_FLAGS);
+SPL_IMG_TEST(spl_test_net, FIT_EXTERNAL, DM_FLAGS);
diff --git a/test/image/spl_load_nor.c b/test/image/spl_load_nor.c
new file mode 100644
index 00000000000..a62bb60d253
--- /dev/null
+++ b/test/image/spl_load_nor.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+static void *spl_test_nor_base;
+
+unsigned long spl_nor_get_uboot_base(void)
+{
+ return virt_to_phys(spl_test_nor_base);
+}
+
+static int spl_test_nor_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ spl_test_nor_base = img;
+ return 0;
+}
+
+static int spl_test_nor(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ return do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_NOR,
+ spl_nor_load_image),
+ spl_test_nor_write_image);
+}
+SPL_IMG_TEST(spl_test_nor, LEGACY, 0);
+SPL_IMG_TEST(spl_test_nor, LEGACY_LZMA, 0);
+SPL_IMG_TEST(spl_test_nor, IMX8, 0);
+SPL_IMG_TEST(spl_test_nor, FIT_INTERNAL, 0);
+SPL_IMG_TEST(spl_test_nor, FIT_EXTERNAL, 0);
diff --git a/test/image/spl_load_os.c b/test/image/spl_load_os.c
new file mode 100644
index 00000000000..49edf152d78
--- /dev/null
+++ b/test/image/spl_load_os.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <image.h>
+#include <os.h>
+#include <spl.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+/* Context used for this test */
+struct text_ctx {
+ int fd;
+};
+
+static ulong read_fit_image(struct spl_load_info *load, ulong sector,
+ ulong count, void *buf)
+{
+ struct text_ctx *text_ctx = load->priv;
+ off_t offset, ret;
+ ssize_t res;
+
+ offset = sector * load->bl_len;
+ ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET);
+ if (ret != offset) {
+ printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset,
+ ret, errno);
+ return 0;
+ }
+
+ res = os_read(text_ctx->fd, buf, count * load->bl_len);
+ if (res == -1) {
+ printf("Failed to read %lx bytes, got %ld (errno=%d)\n",
+ count * load->bl_len, res, errno);
+ return 0;
+ }
+
+ return count;
+}
+
+static int spl_test_load(struct unit_test_state *uts)
+{
+ struct spl_image_info image;
+ struct legacy_img_hdr *header;
+ struct text_ctx text_ctx;
+ struct spl_load_info load;
+ char fname[256];
+ int ret;
+ int fd;
+
+ memset(&load, '\0', sizeof(load));
+ load.bl_len = 512;
+ load.read = read_fit_image;
+
+ ret = sandbox_find_next_phase(fname, sizeof(fname), true);
+ if (ret)
+ ut_assertf(0, "%s not found, error %d\n", fname, ret);
+ load.filename = fname;
+
+ header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));
+
+ fd = os_open(fname, OS_O_RDONLY);
+ ut_assert(fd >= 0);
+ ut_asserteq(512, os_read(fd, header, 512));
+ text_ctx.fd = fd;
+
+ load.priv = &text_ctx;
+
+ ut_assertok(spl_load_simple_fit(&image, &load, 0, header));
+
+ return 0;
+}
+SPL_TEST(spl_test_load, 0);
diff --git a/test/image/spl_load_spi.c b/test/image/spl_load_spi.c
new file mode 100644
index 00000000000..8f9b6e0139b
--- /dev/null
+++ b/test/image/spl_load_spi.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi_flash.h>
+#include <spl.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+static int spl_test_spi_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ struct spi_flash *flash;
+
+ flash = spi_flash_probe(spl_spi_boot_bus(), spl_spi_boot_cs(),
+ CONFIG_SF_DEFAULT_SPEED,
+ CONFIG_SF_DEFAULT_MODE);
+ ut_assertnonnull(flash);
+ ut_assertok(spi_flash_write(flash, spl_spi_get_uboot_offs(flash),
+ img_size, img));
+
+ return 0;
+}
+
+static int spl_test_spi(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ return do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(1, BOOT_DEVICE_SPI,
+ spl_spi_load_image),
+ spl_test_spi_write_image);
+}
+SPL_IMG_TEST(spl_test_spi, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_spi, IMX8, DM_FLAGS);
+SPL_IMG_TEST(spl_test_spi, FIT_INTERNAL, DM_FLAGS);
+#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)
+SPL_IMG_TEST(spl_test_spi, FIT_EXTERNAL, DM_FLAGS);
+#endif
diff --git a/test/py/tests/test_spl.py b/test/py/tests/test_spl.py
index bd273dad893..42e4c4342b2 100644
--- a/test/py/tests/test_spl.py
+++ b/test/py/tests/test_spl.py
@@ -5,6 +5,16 @@
import os.path
import pytest
+@pytest.mark.buildconfigspec('spl_unit_test')
+def test_ut_spl_init(u_boot_console):
+ """Initialize data for ut spl tests."""
+
+ fn = u_boot_console.config.source_dir + '/spi.bin'
+ if not os.path.exists(fn):
+ data = b'\x00' * (2 * 1024 * 1024)
+ with open(fn, 'wb') as fh:
+ fh.write(data)
+
def test_spl(u_boot_console, ut_spl_subtest):
"""Execute a "ut" subtest.
diff --git a/test/test-main.c b/test/test-main.c
index edb20bc4b9c..b7015d9f38d 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -303,7 +303,7 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
if (test->flags & UT_TESTF_PROBE_TEST)
ut_assertok(do_autoprobe(uts));
- if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
+ if (CONFIG_IS_ENABLED(OF_REAL) &&
(test->flags & UT_TESTF_SCAN_FDT)) {
/*
* only set this if we know the ethernet uclass will be created