summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/Kconfig8
-rw-r--r--arch/arc/dts/Makefile2
-rw-r--r--arch/arm/Kconfig6
-rw-r--r--arch/arm/cpu/armv8/fel_utils.S2
-rw-r--r--arch/arm/cpu/armv8/fsl-layerscape/cpu.c2
-rw-r--r--arch/arm/dts/at91-sam9x60_curiosity-u-boot.dtsi4
-rw-r--r--arch/arm/dts/at91-sam9x60_curiosity.dts4
-rw-r--r--arch/arm/dts/at91-sam9x75_curiosity-u-boot.dtsi95
-rw-r--r--arch/arm/dts/ipq5424-rdp466-u-boot.dtsi37
-rw-r--r--arch/arm/dts/k3-am625-phycore-som-binman.dtsi94
-rw-r--r--arch/arm/dts/qcs615-ride-u-boot.dtsi14
-rw-r--r--arch/arm/dts/qcs8300-ride-u-boot.dtsi19
-rw-r--r--arch/arm/dts/sam9x60.dtsi8
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h7
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h4
-rw-r--r--arch/arm/include/asm/arch-sunxi/dram.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/dram_sun50i_a133.h230
-rw-r--r--arch/arm/lib/crt0.S2
-rw-r--r--arch/arm/lib/crt0_64.S2
-rw-r--r--arch/arm/mach-airoha/an7581/init.c3
-rw-r--r--arch/arm/mach-apple/board.c27
-rw-r--r--arch/arm/mach-at91/Kconfig12
-rw-r--r--arch/arm/mach-at91/arm926ejs/Makefile1
-rw-r--r--arch/arm/mach-at91/arm926ejs/sam9x7_devices.c49
-rw-r--r--arch/arm/mach-at91/include/mach/at91_wdt.h25
-rw-r--r--arch/arm/mach-at91/include/mach/hardware.h2
-rw-r--r--arch/arm/mach-at91/include/mach/sam9x7.h172
-rw-r--r--arch/arm/mach-at91/spl.c4
-rw-r--r--arch/arm/mach-imx/imx8/cpu.c4
-rw-r--r--arch/arm/mach-imx/imx8ulp/soc.c4
-rw-r--r--arch/arm/mach-imx/imx9/scmi/soc.c4
-rw-r--r--arch/arm/mach-imx/imx9/soc.c4
-rw-r--r--arch/arm/mach-imx/mmc_env.c4
-rw-r--r--arch/arm/mach-imx/mx6/soc.c10
-rw-r--r--arch/arm/mach-imx/mx7ulp/soc.c4
-rw-r--r--arch/arm/mach-k3/am62ax/am62a7_init.c5
-rw-r--r--arch/arm/mach-k3/am62px/am62p5_init.c4
-rw-r--r--arch/arm/mach-k3/arm64/arm64-mmu.c257
-rw-r--r--arch/arm/mach-k3/common.c111
-rw-r--r--arch/arm/mach-k3/common.h2
-rw-r--r--arch/arm/mach-k3/include/mach/am62_hardware.h4
-rw-r--r--arch/arm/mach-k3/include/mach/am62a_hardware.h4
-rw-r--r--arch/arm/mach-k3/include/mach/am62p_hardware.h4
-rw-r--r--arch/arm/mach-k3/include/mach/am64_hardware.h9
-rw-r--r--arch/arm/mach-k3/include/mach/am6_hardware.h9
-rw-r--r--arch/arm/mach-k3/include/mach/j721e_hardware.h9
-rw-r--r--arch/arm/mach-k3/include/mach/j721s2_hardware.h9
-rw-r--r--arch/arm/mach-k3/include/mach/j722s_hardware.h4
-rw-r--r--arch/arm/mach-k3/include/mach/j784s4_hardware.h9
-rw-r--r--arch/arm/mach-k3/include/mach/k3-ddr.h12
-rw-r--r--arch/arm/mach-k3/j721e/j721e_init.c13
-rw-r--r--arch/arm/mach-k3/j721s2/j721s2_init.c11
-rw-r--r--arch/arm/mach-k3/j722s/j722s_init.c6
-rw-r--r--arch/arm/mach-k3/j784s4/j784s4_init.c11
-rw-r--r--arch/arm/mach-mediatek/tzcfg.c8
-rw-r--r--arch/arm/mach-mvebu/armada8k/cpu.c2
-rw-r--r--arch/arm/mach-rockchip/Kconfig4
-rw-r--r--arch/arm/mach-rockchip/board.c4
-rw-r--r--arch/arm/mach-snapdragon/board.c75
-rw-r--r--arch/arm/mach-snapdragon/capsule_update.c274
-rw-r--r--arch/arm/mach-snapdragon/of_fixup.c13
-rw-r--r--arch/arm/mach-snapdragon/qcom-priv.h14
-rw-r--r--arch/arm/mach-sunxi/Kconfig114
-rw-r--r--arch/arm/mach-sunxi/Makefile2
-rw-r--r--arch/arm/mach-sunxi/board.c4
-rw-r--r--arch/arm/mach-sunxi/clock_sun50i_h6.c3
-rw-r--r--arch/arm/mach-sunxi/cpu_info.c2
-rw-r--r--arch/arm/mach-sunxi/dram_sun50i_a133.c1204
-rw-r--r--arch/arm/mach-sunxi/dram_timings/Makefile2
-rw-r--r--arch/arm/mach-sunxi/dram_timings/a133_ddr4.c80
-rw-r--r--arch/arm/mach-sunxi/dram_timings/a133_lpddr4.c102
-rw-r--r--arch/m68k/Kconfig5
-rw-r--r--arch/m68k/dts/Makefile3
-rw-r--r--arch/m68k/dts/astro_mcf5373l.dts27
-rw-r--r--arch/microblaze/dts/Makefile2
-rw-r--r--arch/mips/include/asm/processor.h16
-rw-r--r--arch/nios2/dts/Makefile2
-rw-r--r--arch/powerpc/cpu/mpc85xx/mp.c4
-rw-r--r--arch/powerpc/lib/misc.c5
-rw-r--r--arch/riscv/dts/Makefile2
-rw-r--r--arch/sandbox/cpu/state.c6
-rw-r--r--arch/sandbox/dts/Makefile2
-rw-r--r--arch/sandbox/include/asm/state.h1
-rw-r--r--arch/x86/dts/Makefile2
84 files changed, 3098 insertions, 250 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index ea33d07c086..7e05e0c2263 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -63,6 +63,13 @@ config SYS_CACHELINE_SIZE
default 64 if RISCV
default 32 if MIPS
+config SYS_DTC_PAD_BYTES
+ int "Size in bytes to pad device tree blob"
+ default 32768 if X86 && EFI_APP
+ default 4096 if ARC || ARM64 || M68K || MICROBLAZE || NIOS2 \
+ || RISCV || SANDBOX || X86
+ default 0
+
config LINKER_LIST_ALIGN
int
default 32 if SANDBOX
@@ -213,6 +220,7 @@ config SANDBOX
imply BITREVERSE
select BLOBLIST
imply LTO
+ imply CMD_BOOTEFI_SELFTEST
imply CMD_DM
imply CMD_EXCEPTION
imply CMD_GETTIME
diff --git a/arch/arc/dts/Makefile b/arch/arc/dts/Makefile
index fe6ad7b849a..87c627c01c8 100644
--- a/arch/arc/dts/Makefile
+++ b/arch/arc/dts/Makefile
@@ -11,4 +11,4 @@ dtb-$(CONFIG_TARGET_IOT_DEVKIT) += iot_devkit.dtb
include $(srctree)/scripts/Makefile.dts
# Add any required device tree compiler flags here
-DTC_FLAGS += -R 4 -p 0x1000
+DTC_FLAGS += -R 4
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index f6430a5aaf0..1d096ad6554 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -832,6 +832,7 @@ config ARCH_K3
select FIT
select REGEX
select FIT_SIGNATURE if ARM64
+ select LTO
imply TI_SECURE_DEVICE
config ARCH_OMAP2PLUS
@@ -1079,7 +1080,7 @@ config ARCH_OWL
select CLK
select CLK_OWL
select OF_CONTROL
- select SYS_RELOC_GD_ENV_ADDR
+ select ENV_RELOC_GD_ENV_ADDR
imply CMD_DM
config ARCH_QEMU
@@ -1137,6 +1138,7 @@ config ARCH_SNAPDRAGON
select LINUX_KERNEL_IMAGE_HEADER if !ENABLE_ARM_SOC_BOOT0_HOOK
select SYSRESET
select SYSRESET_PSCI
+ select ANDROID_BOOT_IMAGE_IGNORE_BLOB_ADDR
imply OF_UPSTREAM
imply CMD_DM
imply DM_USB_GADGET
@@ -1219,7 +1221,7 @@ config ARCH_SUNXI
select USB_STORAGE if DISTRO_DEFAULTS && USB_HOST
select SPL_USE_TINY_PRINTF if SPL
select USE_PREBOOT
- select SYS_RELOC_GD_ENV_ADDR
+ select ENV_RELOC_GD_ENV_ADDR
imply BOARD_LATE_INIT
imply CMD_DM
imply CMD_GPT
diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 044a7c16cc5..6a7ec9a7ec1 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -41,7 +41,7 @@ ENTRY(return_to_fel)
str w2, [x1]
ldr w0, =0xfa50392f // CPU hotplug magic
-#ifdef CONFIG_MACH_SUN50I_H616
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_A133)
ldr w2, =(SUNXI_R_CPUCFG_BASE + 0x1c0)
str w0, [x2], #0x4
#elif CONFIG_MACH_SUN50I_H6
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index d2d3e346a36..cfbaa475701 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -802,7 +802,7 @@ enum boot_src get_boot_src(void)
int mmc_get_env_dev(void)
{
enum boot_src src = get_boot_src();
- int dev = CONFIG_SYS_MMC_ENV_DEV;
+ int dev = CONFIG_ENV_MMC_DEVICE_INDEX;
switch (src) {
case BOOT_SOURCE_SD_MMC:
diff --git a/arch/arm/dts/at91-sam9x60_curiosity-u-boot.dtsi b/arch/arm/dts/at91-sam9x60_curiosity-u-boot.dtsi
index dd4623311c9..9144387861e 100644
--- a/arch/arm/dts/at91-sam9x60_curiosity-u-boot.dtsi
+++ b/arch/arm/dts/at91-sam9x60_curiosity-u-boot.dtsi
@@ -95,3 +95,7 @@
&slow_xtal {
bootph-all;
};
+
+&watchdog {
+ timeout-sec = <16>;
+};
diff --git a/arch/arm/dts/at91-sam9x60_curiosity.dts b/arch/arm/dts/at91-sam9x60_curiosity.dts
index 1c7f0fa6a49..f165fdadb9e 100644
--- a/arch/arm/dts/at91-sam9x60_curiosity.dts
+++ b/arch/arm/dts/at91-sam9x60_curiosity.dts
@@ -336,3 +336,7 @@
&usb2 {
status = "okay";
};
+
+&watchdog {
+ status = "okay";
+};
diff --git a/arch/arm/dts/at91-sam9x75_curiosity-u-boot.dtsi b/arch/arm/dts/at91-sam9x75_curiosity-u-boot.dtsi
new file mode 100644
index 00000000000..94585ee0232
--- /dev/null
+++ b/arch/arm/dts/at91-sam9x75_curiosity-u-boot.dtsi
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * at91-sam9x75_curiosity-u-boot.dtsi - Device Tree file for SAM9X75
+ * CURIOSITY board.
+ *
+ * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Manikandan Muralidharan <manikandan.m@microchip.com>
+ */
+
+/ {
+ cpus {
+ cpu@0 {
+ clocks = <&pmc PMC_TYPE_CORE 25>, <&pmc PMC_TYPE_CORE 17>, <&main_xtal>;
+ clock-names = "cpu", "master", "xtal";
+ };
+ };
+
+ clocks {
+ slow_rc_osc: slow_rc_osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <18500>;
+ };
+ };
+
+ ahb {
+ bootph-all;
+
+ apb {
+ bootph-all;
+
+ pinctrl {
+ bootph-all;
+ };
+ };
+ };
+
+ chosen {
+ bootph-all;
+ };
+};
+
+&clk32k {
+ bootph-all;
+ clocks = <&slow_rc_osc>, <&slow_xtal>;
+};
+
+&dbgu {
+ bootph-all;
+};
+
+&gmac {
+ compatible = "microchip,sam9x7-gem", "cdns,sama7g5-gem";
+};
+
+&main_xtal {
+ bootph-all;
+};
+
+&pinctrl_dbgu_default {
+ bootph-all;
+};
+
+&pinctrl_sdmmc0_default {
+ bootph-all;
+};
+
+&pioA {
+ bootph-all;
+};
+
+&pioB {
+ bootph-all;
+};
+
+&pit64b0 {
+ bootph-all;
+};
+
+&pmc {
+ bootph-all;
+};
+
+&sdmmc0 {
+ bootph-all;
+};
+
+&slow_xtal {
+ bootph-all;
+};
+
+&slow_rc_osc {
+ bootph-all;
+};
diff --git a/arch/arm/dts/ipq5424-rdp466-u-boot.dtsi b/arch/arm/dts/ipq5424-rdp466-u-boot.dtsi
new file mode 100644
index 00000000000..9e4af4d9f72
--- /dev/null
+++ b/arch/arm/dts/ipq5424-rdp466-u-boot.dtsi
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IPQ5424 RDP466 board device tree source
+ *
+ * Copyright (c) 2025 The Linux Foundation. All rights reserved.
+ */
+
+/ {
+ /* Will be removed when SMEM parsing is updated */
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x20000000>;
+ };
+
+};
+
+ &sdhc {
+ sdhci-caps-mask = <0x0 0x04000000>;
+ sdhci-caps = <0x0 0x04000000>; /* SDHCI_CAN_VDD_180 */
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ max-frequency = <192000000>;
+ bus-width = <4>;
+ pinctrl-0 = <&sdc_default_state>;
+ pinctrl-names = "default";
+ non-removable;
+
+ /*
+ * This reset is needed to clear out the settings done by
+ * previous boot loader. Without this the SDHCI_RESET_ALL
+ * reset done sdhci_init() times out.
+ */
+ resets = <&gcc GCC_SDCC_BCR>;
+
+ status = "okay";
+ };
+
diff --git a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi
index 32d8804a395..6deebdadf09 100644
--- a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi
+++ b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi
@@ -400,11 +400,105 @@
};
&binman {
+ tifsstub-hs {
+ filename = "tifsstub.bin_hs";
+ ti-secure-rom {
+ content = <&tifsstub_hs_cert>;
+ core = "secure";
+ load = <0x40000>;
+ sw-rev = <CONFIG_K3_X509_SWRV>;
+ keyfile = "custMpk.pem";
+ countersign;
+ tifsstub;
+ };
+ tifsstub_hs_cert: tifsstub-hs-cert.bin {
+ filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-cert.bin";
+ type = "blob-ext";
+ optional;
+ };
+ tifsstub_hs_enc: tifsstub-hs-enc.bin {
+ filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-enc.bin";
+ type = "blob-ext";
+ optional;
+ };
+ };
+
+ tifsstub-fs {
+ filename = "tifsstub.bin_fs";
+ tifsstub_fs_cert: tifsstub-fs-cert.bin {
+ filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-cert.bin";
+ type = "blob-ext";
+ optional;
+ };
+ tifsstub_fs_enc: tifsstub-fs-enc.bin {
+ filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-enc.bin";
+ type = "blob-ext";
+ optional;
+ };
+
+ };
+
+ tifsstub-gp {
+ filename = "tifsstub.bin_gp";
+ ti-secure-rom {
+ content = <&tifsstub_gp>;
+ core = "secure";
+ load = <0x60000>;
+ sw-rev = <CONFIG_K3_X509_SWRV>;
+ keyfile = "ti-degenerate-key.pem";
+ tifsstub;
+ };
+ tifsstub_gp: tifsstub-gp.bin {
+ filename = "ti-sysfw/ti-fs-stub-firmware-am62x-gp.bin";
+ type = "blob-ext";
+ optional;
+ };
+ };
+
ti-spl_unsigned {
insert-template = <&ti_spl_unsigned_template>;
fit {
images {
+ tifsstub-hs {
+ description = "TIFSSTUB";
+ type = "firmware";
+ arch = "arm32";
+ compression = "none";
+ os = "tifsstub-hs";
+ load = <0x9dc00000>;
+ entry = <0x9dc00000>;
+ blob-ext {
+ filename = "tifsstub.bin_hs";
+ };
+ };
+
+ tifsstub-fs {
+ description = "TIFSSTUB";
+ type = "firmware";
+ arch = "arm32";
+ compression = "none";
+ os = "tifsstub-fs";
+ load = <0x9dc00000>;
+ entry = <0x9dc00000>;
+ blob-ext {
+ filename = "tifsstub.bin_fs";
+ };
+ };
+
+ tifsstub-gp {
+ description = "TIFSSTUB";
+ type = "firmware";
+ arch = "arm32";
+ compression = "none";
+ os = "tifsstub-gp";
+ load = <0x9dc00000>;
+ entry = <0x9dc00000>;
+ blob-ext {
+ filename = "tifsstub.bin_gp";
+ };
+ };
+
dm {
ti-dm {
filename = "ti-dm/am62xx/ipc_echo_testb_mcu1_0_release_strip.xer5f";
diff --git a/arch/arm/dts/qcs615-ride-u-boot.dtsi b/arch/arm/dts/qcs615-ride-u-boot.dtsi
new file mode 100644
index 00000000000..68fffc70fcb
--- /dev/null
+++ b/arch/arm/dts/qcs615-ride-u-boot.dtsi
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/ {
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x7a00000>,
+ <0x0 0x89600000 0x0 0x30100000>,
+ <0x0 0xc0000000 0x0 0xc0000000>,
+ <0x1 0x80000000 0x1 0x00000000>;
+ };
+};
diff --git a/arch/arm/dts/qcs8300-ride-u-boot.dtsi b/arch/arm/dts/qcs8300-ride-u-boot.dtsi
new file mode 100644
index 00000000000..8c353ace71e
--- /dev/null
+++ b/arch/arm/dts/qcs8300-ride-u-boot.dtsi
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/ {
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x0 0x11a80000>,
+ <0x0 0xc0000000 0x0 0x10000000>,
+ <0x0 0xd3100000 0x0 0x26b00000>,
+ <0xe 0x80000000 0x1 0x00000000>,
+ <0xa 0x80000000 0x1 0x80000000>,
+ <0x0 0xb0800000 0x0 0x0f200000>,
+ <0x0 0xd0100000 0x0 0x01800000>,
+ <0x0 0x91b00000 0x0 0x1e500000>;
+ };
+};
+
diff --git a/arch/arm/dts/sam9x60.dtsi b/arch/arm/dts/sam9x60.dtsi
index 7631dfaa07f..79449042c24 100644
--- a/arch/arm/dts/sam9x60.dtsi
+++ b/arch/arm/dts/sam9x60.dtsi
@@ -311,6 +311,14 @@
clocks = <&slow_rc_osc>, <&slow_xtal>;
#clock-cells = <1>;
};
+
+ watchdog: watchdog@ffffff80 {
+ compatible = "microchip,sam9x60-wdt";
+ reg = <0xffffff80 0x24>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
+ clocks = <&clk32 0>;
+ status = "disabled";
+ };
};
};
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 ccacc99d018..575dff68804 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -90,6 +90,13 @@
#define CCM_PLL6_DEFAULT 0xe8216300
#define CCM_PSI_AHB1_AHB2_DEFAULT 0x03000002
#define CCM_APB1_DEFAULT 0x03000102
+
+#elif CONFIG_MACH_SUN50I_A133 /* A133 */
+
+#define CCM_PLL6_DEFAULT 0xb8003100
+#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_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index 8a3f465545a..2a9b086991c 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -29,6 +29,10 @@
#define SUNXI_DRAM_COM_BASE 0x047FA000
#define SUNXI_DRAM_CTL0_BASE 0x047FB000
#define SUNXI_DRAM_PHY0_BASE 0x04800000
+#elif CONFIG_MACH_SUN50I_A133
+#define SUNXI_DRAM_COM_BASE 0x04810000
+#define SUNXI_DRAM_CTL0_BASE 0x04820000
+#define SUNXI_DRAM_PHY0_BASE 0x04830000
#endif
#define SUNXI_TWI0_BASE 0x05002000
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 9d21b492418..0708ae3ee3b 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -31,6 +31,8 @@
#include <asm/arch/dram_sun50i_h6.h>
#elif defined(CONFIG_MACH_SUN50I_H616)
#include <asm/arch/dram_sun50i_h616.h>
+#elif defined(CONFIG_DRAM_SUN50I_A133)
+#include <asm/arch/dram_sun50i_a133.h>
#elif defined(CONFIG_MACH_SUNIV)
#include <asm/arch/dram_suniv.h>
#else
diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_a133.h b/arch/arm/include/asm/arch-sunxi/dram_sun50i_a133.h
new file mode 100644
index 00000000000..a5fc6ad3656
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_a133.h
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * A133 dram controller register and constant defines
+ *
+ * (C) Copyright 2024 MasterR3C0RD <masterr3c0rd@epochal.quest>
+ */
+
+#ifndef _SUNXI_DRAM_SUN50I_A133_H
+#define _SUNXI_DRAM_SUN50I_A133_H
+
+#include <linux/bitops.h>
+
+enum sunxi_dram_type {
+ SUNXI_DRAM_TYPE_DDR3 = 3,
+ SUNXI_DRAM_TYPE_DDR4,
+ SUNXI_DRAM_TYPE_LPDDR3 = 7,
+ SUNXI_DRAM_TYPE_LPDDR4
+};
+
+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);
+}
+
+/* MBUS part is largely the same as in H6, except for one special register */
+#define MCTL_COM_UNK_008 0x008
+/* NOTE: This register has the same importance as mctl_ctl->clken in H616 */
+#define MCTL_COM_MAER0 0x020
+
+/*
+ * Controller registers seems to be the same or at least very similar
+ * to those in H6.
+ */
+struct sunxi_mctl_ctl_reg {
+ u32 mstr; /* 0x000 */
+ u32 statr; /* 0x004 unused */
+ u32 mstr1; /* 0x008 unused */
+ u32 clken; /* 0x00c */
+ u32 mrctrl0; /* 0x010 unused */
+ u32 mrctrl1; /* 0x014 unused */
+ u32 mrstatr; /* 0x018 unused */
+ u32 mrctrl2; /* 0x01c unused */
+ u32 derateen; /* 0x020 unused */
+ u32 derateint; /* 0x024 unused */
+ u8 reserved_0x028[8]; /* 0x028 */
+ u32 pwrctl; /* 0x030 unused */
+ u32 pwrtmg; /* 0x034 unused */
+ u32 hwlpctl; /* 0x038 unused */
+ u8 reserved_0x03c[20]; /* 0x03c */
+ u32 rfshctl0; /* 0x050 unused */
+ u32 rfshctl1; /* 0x054 unused */
+ u8 reserved_0x058[8]; /* 0x05c */
+ u32 rfshctl3; /* 0x060 */
+ u32 rfshtmg; /* 0x064 */
+ u8 reserved_0x068[104]; /* 0x068 */
+ u32 init[8]; /* 0x0d0 */
+ u32 dimmctl; /* 0x0f0 unused */
+ u32 rankctl; /* 0x0f4 */
+ u8 reserved_0x0f8[8]; /* 0x0f8 */
+ u32 dramtmg[17]; /* 0x100 */
+ u8 reserved_0x144[60]; /* 0x144 */
+ u32 zqctl[3]; /* 0x180 */
+ u32 zqstat; /* 0x18c unused */
+ u32 dfitmg0; /* 0x190 */
+ u32 dfitmg1; /* 0x194 */
+ u32 dfilpcfg[2]; /* 0x198 unused */
+ u32 dfiupd[3]; /* 0x1a0 */
+ u32 reserved_0x1ac; /* 0x1ac */
+ u32 dfimisc; /* 0x1b0 */
+ u32 dfitmg2; /* 0x1b4 unused */
+ u32 dfitmg3; /* 0x1b8 unused */
+ u32 dfistat; /* 0x1bc */
+ u32 dbictl; /* 0x1c0 */
+ u8 reserved_0x1c4[60]; /* 0x1c4 */
+ u32 addrmap[12]; /* 0x200 */
+ u8 reserved_0x230[16]; /* 0x230 */
+ u32 odtcfg; /* 0x240 */
+ u32 odtmap; /* 0x244 */
+ u8 reserved_0x248[8]; /* 0x248 */
+ u32 sched[2]; /* 0x250 */
+ u8 reserved_0x258[180]; /* 0x258 */
+ u32 dbgcmd; /* 0x30c unused */
+ u32 dbgstat; /* 0x310 unused */
+ u8 reserved_0x314[12]; /* 0x314 */
+ u32 swctl; /* 0x320 */
+ u32 swstat; /* 0x324 */
+ u8 reserved_0x328[7768]; /* 0x328 */
+ u32 unk_0x2180; /* 0x2180 */
+ u8 reserved_0x2184[188]; /* 0x2184 */
+ u32 unk_0x2240; /* 0x2240 */
+ u8 reserved_0x2244[3900]; /* 0x2244 */
+ u32 unk_0x3180; /* 0x3180 */
+ u8 reserved_0x3184[188]; /* 0x3184 */
+ u32 unk_0x3240; /* 0x3240 */
+ u8 reserved_0x3244[3900]; /* 0x3244 */
+ u32 unk_0x4180; /* 0x4180 */
+ u8 reserved_0x4184[188]; /* 0x4184 */
+ u32 unk_0x4240; /* 0x4240 */
+};
+
+check_member(sunxi_mctl_ctl_reg, swstat, 0x324);
+check_member(sunxi_mctl_ctl_reg, unk_0x4240, 0x4240);
+
+#define MSTR_DEVICETYPE_DDR3 BIT(0)
+#define MSTR_DEVICETYPE_LPDDR2 BIT(2)
+#define MSTR_DEVICETYPE_LPDDR3 BIT(3)
+#define MSTR_DEVICETYPE_DDR4 BIT(4)
+#define MSTR_DEVICETYPE_LPDDR4 BIT(5)
+#define MSTR_DEVICETYPE_MASK GENMASK(5, 0)
+#define MSTR_GEARDOWNMODE BIT(0) /* Same as MSTR_DEVICETYPE_DDR3, only used for DDR4 */
+#define MSTR_2TMODE BIT(10)
+#define MSTR_BUSWIDTH_FULL (0 << 12)
+#define MSTR_BUSWIDTH_HALF (1 << 12)
+#define MSTR_ACTIVE_RANKS(x) (((x == 1) ? 3 : 1) << 24)
+#define MSTR_BURST_LENGTH(x) (((x) >> 1) << 16)
+#define MSTR_DEVICECONFIG_X32 (3 << 30)
+
+#define TPR10_CA_BIT_DELAY BIT(16)
+#define TPR10_DX_BIT_DELAY0 BIT(17)
+#define TPR10_DX_BIT_DELAY1 BIT(18)
+#define TPR10_WRITE_LEVELING BIT(20)
+#define TPR10_READ_CALIBRATION BIT(21)
+#define TPR10_READ_TRAINING BIT(22)
+#define TPR10_WRITE_TRAINING BIT(23)
+
+/* MRCTRL constants */
+#define MRCTRL0_MR_RANKS_ALL (3 << 4)
+#define MRCTRL0_MR_ADDR(x) (x << 12)
+#define MRCTRL0_MR_WR BIT(31)
+
+#define MRCTRL1_MR_ADDR(x) (x << 8)
+#define MRCTRL1_MR_DATA(x) (x)
+
+/* ADDRMAP constants */
+#define ADDRMAP_DISABLED_3F_B(b) (0x3f + b)
+#define ADDRMAP_DISABLED_1F_B(b) (0x1f + b)
+#define ADDRMAP_DISABLED_0F_B(b) (0x0f + b)
+
+#define _ADDRMAP_VALUE(a,x,b) (((a) - b) << (x * 8))
+
+/*
+ * Bx = internal base
+ * The selected HIF address bit for each address bit is determined
+ * by adding the internal base to the value of each field
+ * */
+
+#define ADDRMAP0_CS0_B6(v) _ADDRMAP_VALUE(v, 0, 6)
+
+#define ADDRMAP1_BANK0_B2(v) _ADDRMAP_VALUE(v, 0, 2)
+#define ADDRMAP1_BANK1_B3(v) _ADDRMAP_VALUE(v, 1, 3)
+#define ADDRMAP1_BANK2_B4(v) _ADDRMAP_VALUE(v, 2, 4)
+
+#define ADDRMAP2_COL2_B2(v) _ADDRMAP_VALUE(v, 0, 2)
+#define ADDRMAP2_COL3_B3(v) _ADDRMAP_VALUE(v, 1, 3)
+#define ADDRMAP2_COL4_B4(v) _ADDRMAP_VALUE(v, 2, 4)
+#define ADDRMAP2_COL5_B5(v) _ADDRMAP_VALUE(v, 3, 5)
+
+#define ADDRMAP3_COL6_B6(v) _ADDRMAP_VALUE(v, 0, 6)
+#define ADDRMAP3_COL7_B7(v) _ADDRMAP_VALUE(v, 1, 7)
+#define ADDRMAP3_COL8_B8(v) _ADDRMAP_VALUE(v, 2, 8)
+#define ADDRMAP3_COL9_B9(v) _ADDRMAP_VALUE(v, 3, 9)
+
+#define ADDRMAP4_COL10_B10(v) _ADDRMAP_VALUE(v, 0, 10)
+#define ADDRMAP4_COL11_B11(v) _ADDRMAP_VALUE(v, 1, 11)
+
+#define ADDRMAP5_ROW0_B6(v) _ADDRMAP_VALUE(v, 0, 6)
+#define ADDRMAP5_ROW1_B7(v) _ADDRMAP_VALUE(v, 1, 7)
+#define ADDRMAP5_ROW2_10_B8(v) _ADDRMAP_VALUE(v, 2, 8)
+#define ADDRMAP5_ROW11_B17(v) _ADDRMAP_VALUE(v, 3, 17)
+
+#define ADDRMAP6_ROW12_B18(v) _ADDRMAP_VALUE(v, 0, 18)
+#define ADDRMAP6_ROW13_B19(v) _ADDRMAP_VALUE(v, 1, 19)
+#define ADDRMAP6_ROW14_B20(v) _ADDRMAP_VALUE(v, 2, 20)
+#define ADDRMAP6_ROW15_B21(v) _ADDRMAP_VALUE(v, 3, 21)
+
+#define ADDRMAP7_ROW16_B22(v) _ADDRMAP_VALUE(v, 0, 22)
+#define ADDRMAP7_ROW17_B23(v) _ADDRMAP_VALUE(v, 1, 23)
+
+#define ADDRMAP8_BG0_B2(v) _ADDRMAP_VALUE(v, 0, 2)
+#define ADDRMAP8_BG1_B3(v) _ADDRMAP_VALUE(v, 1, 3)
+
+/* These are only used if ADDRMAP5_ROW_BITS_2_10 = ADDRMAP_DISABLED_0F */
+#define ADDRMAP9_ROW2_B8(v) _ADDRMAP_VALUE(v, 0, 8)
+#define ADDRMAP9_ROW3_B9(v) _ADDRMAP_VALUE(v, 1, 9)
+#define ADDRMAP9_ROW4_B10(v) _ADDRMAP_VALUE(v, 2, 10)
+#define ADDRMAP9_ROW5_B11(v) _ADDRMAP_VALUE(v, 3, 11)
+
+#define ADDRMAP10_ROW6_B12(v) _ADDRMAP_VALUE(v, 0, 12)
+#define ADDRMAP10_ROW7_B13(v) _ADDRMAP_VALUE(v, 1, 13)
+#define ADDRMAP10_ROW8_B14(v) _ADDRMAP_VALUE(v, 2, 14)
+#define ADDRMAP10_ROW9_B15(v) _ADDRMAP_VALUE(v, 3, 15)
+
+#define ADDRMAP11_ROW10_B16(v) _ADDRMAP_VALUE(v, 0, 16)
+
+struct dram_para {
+ uint32_t clk;
+ enum sunxi_dram_type type;
+ uint32_t dx_odt;
+ uint32_t dx_dri;
+ uint32_t ca_dri;
+ uint32_t para0;
+ uint32_t mr11;
+ uint32_t mr12;
+ uint32_t mr13;
+ uint32_t mr14;
+ uint32_t tpr1;
+ uint32_t tpr2;
+ uint32_t tpr3;
+ uint32_t tpr6;
+ uint32_t tpr10;
+ uint32_t tpr11;
+ uint32_t tpr12;
+ uint32_t tpr13;
+ uint32_t tpr14;
+};
+
+void mctl_set_timing_params(const struct dram_para *para);
+
+struct dram_config {
+ u8 cols; /* Column bits */
+ u8 rows; /* Row bits */
+ u8 ranks; /* Rank bits (different from H616!) */
+ u8 banks; /* Bank bits */
+ u8 bankgrps; /* Bank group bits */
+ u8 bus_full_width; /* 1 = x32, 0 = x16 */
+};
+
+#endif /* _SUNXI_DRAM_SUN50I_A133_H */
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index a50dde60e8b..3e11fadafc6 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -145,7 +145,7 @@ ENTRY(_main)
ldr r1, =CONFIG_TEXT_BASE
sub r1, r0
add lr, r1
-#if defined(CONFIG_SYS_RELOC_GD_ENV_ADDR)
+#if defined(CONFIG_ENV_RELOC_GD_ENV_ADDR)
ldr r0, [r9, #GD_ENV_ADDR] /* r0 = gd->env_addr */
add r0, r0, r1
str r0, [r9, #GD_ENV_ADDR]
diff --git a/arch/arm/lib/crt0_64.S b/arch/arm/lib/crt0_64.S
index 30950ddaf9b..f3f279f2c39 100644
--- a/arch/arm/lib/crt0_64.S
+++ b/arch/arm/lib/crt0_64.S
@@ -119,7 +119,7 @@ ENTRY(_main)
ldr x9, _TEXT_BASE /* x9 <- Linked value of _start */
sub x9, x9, x0 /* x9 <- Run-vs-link offset */
add lr, lr, x9
-#if defined(CONFIG_SYS_RELOC_GD_ENV_ADDR)
+#if defined(CONFIG_ENV_RELOC_GD_ENV_ADDR)
ldr x0, [x18, #GD_ENV_ADDR] /* x0 <- gd->env_addr */
add x0, x0, x9
str x0, [x18, #GD_ENV_ADDR]
diff --git a/arch/arm/mach-airoha/an7581/init.c b/arch/arm/mach-airoha/an7581/init.c
index cefe9c6db9e..d149e0ee3c8 100644
--- a/arch/arm/mach-airoha/an7581/init.c
+++ b/arch/arm/mach-airoha/an7581/init.c
@@ -2,6 +2,7 @@
#include <fdtdec.h>
#include <init.h>
+#include <sysreset.h>
#include <asm/armv8/mmu.h>
#include <asm/system.h>
@@ -21,7 +22,7 @@ int dram_init_banksize(void)
return fdtdec_setup_memory_banksize();
}
-void reset_cpu(ulong addr)
+void reset_cpu(void)
{
psci_system_reset();
}
diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
index 2604c5a710e..4cd8979bdc2 100644
--- a/arch/arm/mach-apple/board.c
+++ b/arch/arm/mach-apple/board.c
@@ -773,22 +773,31 @@ u64 get_page_table_size(void)
#define KERNEL_COMP_SIZE SZ_128M
+#define lmb_alloc(size, addr) lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
+
int board_late_init(void)
{
u32 status = 0;
+ phys_addr_t addr;
/* somewhat based on the Linux Kernel boot requirements:
* align by 2M and maximal FDT size 2M
*/
- status |= env_set_hex("loadaddr", lmb_alloc(SZ_1G, SZ_2M));
- status |= env_set_hex("fdt_addr_r", lmb_alloc(SZ_2M, SZ_2M));
- status |= env_set_hex("kernel_addr_r", lmb_alloc(SZ_128M, SZ_2M));
- status |= env_set_hex("ramdisk_addr_r", lmb_alloc(SZ_1G, SZ_2M));
- status |= env_set_hex("kernel_comp_addr_r",
- lmb_alloc(KERNEL_COMP_SIZE, SZ_2M));
- status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
- status |= env_set_hex("scriptaddr", lmb_alloc(SZ_4M, SZ_2M));
- status |= env_set_hex("pxefile_addr_r", lmb_alloc(SZ_4M, SZ_2M));
+ status |= !lmb_alloc(SZ_1G, &addr) ? env_set_hex("loadaddr", addr) : 1;
+ status |= !lmb_alloc(SZ_2M, &addr) ?
+ env_set_hex("fdt_addr_r", addr) : 1;
+ status |= !lmb_alloc(SZ_128M, &addr) ?
+ env_set_hex("kernel_addr_r", addr) : 1;
+ status |= !lmb_alloc(SZ_1G, &addr) ?
+ env_set_hex("ramdisk_addr_r", addr) : 1;
+ status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+ env_set_hex("kernel_comp_addr_r", addr) : 1;
+ status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+ env_set_hex("kernel_comp_size", addr) : 1;
+ status |= !lmb_alloc(SZ_4M, &addr) ?
+ env_set_hex("scriptaddr", addr) : 1;
+ status |= !lmb_alloc(SZ_4M, &addr) ?
+ env_set_hex("pxefile_addr_r", addr) : 1;
if (status)
log_warning("late_init: Failed to set run time variables\n");
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 7c4ccc427c8..d21534ce883 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -43,6 +43,10 @@ config SAM9X60
bool
select CPU_ARM926EJS
+config SAM9X7
+ bool
+ select CPU_ARM926EJS
+
config SAMA7G5
bool
select CPU_V7A
@@ -154,6 +158,13 @@ config TARGET_SAM9X60_CURIOSITY
select BOARD_EARLY_INIT_F
select BOARD_LATE_INIT
+config TARGET_SAM9X75_CURIOSITY
+ bool "SAM9X75 CURIOSITY board"
+ select SAM9X7
+ select BOARD_EARLY_INIT_F
+ select BOARD_LATE_INIT
+ imply OF_UPSTREAM
+
config TARGET_SAMA5D2_PTC_EK
bool "SAMA5D2 PTC EK board"
select BOARD_EARLY_INIT_F
@@ -351,6 +362,7 @@ source "board/atmel/at91sam9rlek/Kconfig"
source "board/atmel/at91sam9x5ek/Kconfig"
source "board/atmel/sam9x60ek/Kconfig"
source "board/atmel/sam9x60_curiosity/Kconfig"
+source "board/atmel/sam9x75_curiosity/Kconfig"
source "board/atmel/sama7g5ek/Kconfig"
source "board/atmel/sama7g54_curiosity/Kconfig"
source "board/atmel/sama5d2_ptc_ek/Kconfig"
diff --git a/arch/arm/mach-at91/arm926ejs/Makefile b/arch/arm/mach-at91/arm926ejs/Makefile
index 62c44b997e4..8a9464cdfba 100644
--- a/arch/arm/mach-at91/arm926ejs/Makefile
+++ b/arch/arm/mach-at91/arm926ejs/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_AT91SAM9G45) += at91sam9m10g45_devices.o
obj-$(CONFIG_AT91SAM9N12) += at91sam9n12_devices.o
obj-$(CONFIG_AT91SAM9X5) += at91sam9x5_devices.o
obj-$(CONFIG_SAM9X60) += sam9x60_devices.o
+obj-$(CONFIG_SAM9X7) += sam9x7_devices.o
obj-y += clock.o
obj-y += cpu.o
ifndef CONFIG_$(PHASE_)SYSRESET
diff --git a/arch/arm/mach-at91/arm926ejs/sam9x7_devices.c b/arch/arm/mach-at91/arm926ejs/sam9x7_devices.c
new file mode 100644
index 00000000000..c65764a3de4
--- /dev/null
+++ b/arch/arm/mach-at91/arm926ejs/sam9x7_devices.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries
+ */
+
+#include <asm/arch/at91_common.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/gpio.h>
+#include <asm/io.h>
+
+unsigned int get_chip_id(void)
+{
+ /* The 0x40 is the offset of cidr in DBGU */
+ return readl(ATMEL_BASE_DBGU + 0x40);
+}
+
+unsigned int get_extension_chip_id(void)
+{
+ /* The 0x44 is the offset of exid in DBGU */
+ return readl(ATMEL_BASE_DBGU + 0x44);
+}
+
+char *get_cpu_name(void)
+{
+ unsigned int extension_id = get_extension_chip_id();
+
+ if (cpu_is_sam9x7()) {
+ switch (extension_id) {
+ case ARCH_EXID_SAM9X70:
+ return "SAM9X70";
+ case ARCH_EXID_SAM9X72:
+ return "SAM9X72";
+ case ARCH_EXID_SAM9X75:
+ return "SAM9X75";
+ case ARCH_EXID_SAM9X75_D1M:
+ return "SAM9X75 16MB DDR2 SiP";
+ case ARCH_EXID_SAM9X75_D5M:
+ return "SAM9X75 64MB DDR2 SiP";
+ case ARCH_EXID_SAM9X75_D1G:
+ return "SAM9X75 125MB DDR3L SiP";
+ case ARCH_EXID_SAM9X75_D2G:
+ return "SAM9X75 250MB DDR3L SiP";
+ default:
+ return "Unknown CPU type";
+ }
+ } else {
+ return "Unknown CPU type";
+ }
+}
diff --git a/arch/arm/mach-at91/include/mach/at91_wdt.h b/arch/arm/mach-at91/include/mach/at91_wdt.h
index 25d95fab1f8..3780f0bfe40 100644
--- a/arch/arm/mach-at91/include/mach/at91_wdt.h
+++ b/arch/arm/mach-at91/include/mach/at91_wdt.h
@@ -19,15 +19,16 @@
#else
-typedef struct at91_wdt {
- u32 cr;
- u32 mr;
- u32 sr;
-} at91_wdt_t;
+enum {
+ AT91_WDT_MODE_SAM9260 = 0,
+ AT91_WDT_MODE_SAM9X60 = 1
+};
struct at91_wdt_priv {
void __iomem *regs;
- u32 regval;
+ u32 mr;
+ u32 wddis;
+ u8 mode;
};
#endif
@@ -39,14 +40,22 @@ struct at91_wdt_priv {
/* Watchdog Mode Register*/
#define AT91_WDT_MR 0x04
-#define AT91_WDT_MR_WDV(x) (x & 0xfff)
+#define AT91_WDT_MR_WDV(x) ((x) & 0xfff)
+#define AT91_SAM9X60_MR_PERIODRST 0x00000010
#define AT91_WDT_MR_WDFIEN 0x00001000
+#define AT91_SAM9X60_MR_WDDIS 0x00001000
#define AT91_WDT_MR_WDRSTEN 0x00002000
#define AT91_WDT_MR_WDRPROC 0x00004000
#define AT91_WDT_MR_WDDIS 0x00008000
-#define AT91_WDT_MR_WDD(x) ((x & 0xfff) << 16)
+#define AT91_WDT_MR_WDD(x) (((x) & 0xfff) << 16)
#define AT91_WDT_MR_WDDBGHLT 0x10000000
+#define AT91_SAM9X60_MR_WDIDLEHLT 0x10000000
#define AT91_WDT_MR_WDIDLEHLT 0x20000000
+#define AT91_SAM9X60_MR_WDDBGHLT 0x20000000
+
+/* Watchdog Window Level Register */
+#define AT91_SAM9X60_WLR 0x0c
+#define AT91_SAM9X60_WLR_COUNTER(x) ((x) & 0xfff)
/* Hardware timeout in seconds */
#define WDT_MAX_TIMEOUT 16
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
index 988ef492b62..de89714b097 100644
--- a/arch/arm/mach-at91/include/mach/hardware.h
+++ b/arch/arm/mach-at91/include/mach/hardware.h
@@ -23,6 +23,8 @@
# include <asm/arch/at91sam9x5.h>
#elif defined(CONFIG_SAM9X60)
# include <asm/arch/sam9x60.h>
+#elif defined(CONFIG_SAM9X7)
+# include <asm/arch/sam9x7.h>
#elif defined(CONFIG_SAMA7G5)
# include <asm/arch/sama7g5.h>
#elif defined(CONFIG_SAMA5D2)
diff --git a/arch/arm/mach-at91/include/mach/sam9x7.h b/arch/arm/mach-at91/include/mach/sam9x7.h
new file mode 100644
index 00000000000..998fa786f90
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/sam9x7.h
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Chip-specific header file for the SAM9X7 SoC.
+ *
+ * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries
+ */
+
+#ifndef __SAM9X7_H__
+#define __SAM9X7_H__
+
+/*
+ * Peripheral identifiers/interrupts.
+ */
+#define ATMEL_ID_FIQ 0 /* Advanced Interrupt Controller - FIQ */
+#define ATMEL_ID_SYS 1 /* System Controller Interrupt */
+#define ATMEL_ID_PIOA 2 /* Parallel I/O Controller A */
+#define ATMEL_ID_PIOB 3 /* Parallel I/O Controller B */
+#define ATMEL_ID_PIOC 4 /* Parallel I/O Controller C */
+#define ATMEL_ID_FLEXCOM0 5 /* FLEXCOM 0 */
+#define ATMEL_ID_FLEXCOM1 6 /* FLEXCOM 1 */
+#define ATMEL_ID_FLEXCOM2 7 /* FLEXCOM 2 */
+#define ATMEL_ID_FLEXCOM3 8 /* FLEXCOM 3 */
+#define ATMEL_ID_FLEXCOM6 9 /* FLEXCOM 6 */
+#define ATMEL_ID_FLEXCOM7 10 /* FLEXCOM 7 */
+#define ATMEL_ID_FLEXCOM8 11 /* FLEXCOM 8 */
+#define ATMEL_ID_SDMMC0 12 /* SDMMC 0 */
+#define ATMEL_ID_FLEXCOM4 13 /* FLEXCOM 4 */
+#define ATMEL_ID_FLEXCOM5 14 /* FLEXCOM 5 */
+#define ATMEL_ID_FLEXCOM9 15 /* FLEXCOM 9 */
+#define ATMEL_ID_FLEXCOM10 16 /* FLEXCOM 10 */
+#define ATMEL_ID_TC01 17 /* Timer Counter 0, 1, 2, 3, 4 and 5 */
+#define ATMEL_ID_PWM 18 /* Pulse Width Modulation Controller */
+#define ATMEL_ID_ADC 19 /* ADC Controller */
+#define ATMEL_ID_XDMAC0 20 /* XDMA Controller 0 */
+#define ATMEL_ID_MATRIX 21 /* BUS Matrix */
+#define ATMEL_ID_UHPHS 22 /* USB Host High Speed */
+#define ATMEL_ID_UDPHS 23 /* USB Device High Speed */
+#define ATMEL_ID_GMAC 24 /* GMAC */
+#define ATMEL_ID_LCDC 25 /* LCD Controller */
+#define ATMEL_ID_SDMMC1 26 /* SDMMC 1 */
+#define ATMEL_ID_SSC 28 /* Synchronous Serial Controller */
+#define ATMEL_ID_IRQ 31 /* Advanced Interrupt Controller - IRQ */
+#define ATMEL_ID_TRNG 38 /* True Random Number Generator */
+#define ATMEL_ID_PIOD 44 /* Parallel I/O Controller D */
+#define ATMEL_ID_DBGU 47 /* Debug unit */
+
+/*
+ * User Peripheral physical base addresses.
+ */
+#define ATMEL_BASE_FLEXCOM4 0xf0000000
+#define ATMEL_BASE_FLEXCOM5 0xf0004000
+#define ATMEL_BASE_XDMA0 0xf0008000
+#define ATMEL_BASE_SSC 0xf0010000
+#define ATMEL_BASE_QSPI 0xf0014000
+#define ATMEL_BASE_CAN0 0xf8000000
+#define ATMEL_BASE_CAN1 0xf8004000
+#define ATMEL_BASE_TC0 0xf8008000
+#define ATMEL_BASE_TC1 0xf800c000
+#define ATMEL_BASE_FLEXCOM6 0xf8010000
+#define ATMEL_BASE_FLEXCOM7 0xf8014000
+#define ATMEL_BASE_FLEXCOM8 0xf8018000
+#define ATMEL_BASE_FLEXCOM0 0xf801c000
+#define ATMEL_BASE_FLEXCOM1 0xf8020000
+#define ATMEL_BASE_FLEXCOM2 0xf8024000
+#define ATMEL_BASE_FLEXCOM3 0xf8028000
+#define ATMEL_BASE_GMAC 0xf802c000
+#define ATMEL_BASE_PWM 0xf8034000
+#define ATMEL_BASE_LCDC 0xf8038000
+#define ATMEL_BASE_UDPHS 0xf803c000
+#define ATMEL_BASE_FLEXCOM9 0xf8040000
+#define ATMEL_BASE_FLEXCOM10 0xf8044000
+#define ATMEL_BASE_ISC 0xf8048000
+#define ATMEL_BASE_ADC 0xf804c000
+#define ATMEL_BASE_SFR 0xf8050000
+#define ATMEL_BASE_SYS 0xffffc000
+
+/*
+ * System Peripherals
+ */
+#define ATMEL_BASE_MATRIX 0xffffde00
+#define ATMEL_BASE_PMECC 0xffffe000
+#define ATMEL_BASE_PMERRLOC 0xffffe600
+#define ATMEL_BASE_MPDDRC 0xffffe800
+#define ATMEL_BASE_SMC 0xffffea00
+#define ATMEL_BASE_SDRAMC 0xffffec00
+#define ATMEL_BASE_AIC 0xfffff100
+#define ATMEL_BASE_DBGU 0xfffff200
+#define ATMEL_BASE_PIOA 0xfffff400
+#define ATMEL_BASE_PIOB 0xfffff600
+#define ATMEL_BASE_PIOC 0xfffff800
+#define ATMEL_BASE_PIOD 0xfffffa00
+#define ATMEL_BASE_PMC 0xfffffc00
+#define ATMEL_BASE_RSTC 0xfffffe00
+#define ATMEL_BASE_SHDWC 0xfffffe10
+#define ATMEL_BASE_PIT 0xfffffe40
+#define ATMEL_BASE_GPBR 0xfffffe60
+#define ATMEL_BASE_RTC 0xfffffea8
+#define ATMEL_BASE_WDT 0xffffff80
+
+/*
+ * Internal Memory.
+ */
+#define ATMEL_BASE_ROM 0x00100000 /* Internal ROM base address */
+#define ATMEL_BASE_SRAM 0x00300000 /* Internal SRAM base address */
+#define ATMEL_BASE_UDPHS_FIFO 0x00500000 /* USB Device HS controller */
+#define ATMEL_BASE_OHCI 0x00600000 /* USB Host controller (OHCI) */
+#define ATMEL_BASE_EHCI 0x00700000 /* USB Host controller (EHCI) */
+
+/*
+ * External memory
+ */
+#define ATMEL_BASE_CS0 0x10000000
+#define ATMEL_BASE_CS1 0x20000000
+#define ATMEL_BASE_CS2 0x30000000
+#define ATMEL_BASE_CS3 0x40000000
+#define ATMEL_BASE_CS4 0x50000000
+#define ATMEL_BASE_CS5 0x60000000
+#define ATMEL_BASE_SDMMC0 0x80000000
+#define ATMEL_BASE_SDMMC1 0x90000000
+
+/*
+ * SAM9x7 series chip id definitions
+ */
+#define ARCH_ID_SAM9X7 0x89750030
+#define ARCH_EXID_SAM9X70 0x00000005
+#define ARCH_EXID_SAM9X72 0x00000004
+#define ARCH_EXID_SAM9X75 0x00000000
+#define ARCH_EXID_SAM9X75_D1G 0x00000018
+#define ARCH_EXID_SAM9X75_D2G 0x00000020
+#define ARCH_EXID_SAM9X75_D1M 0x00000003
+#define ARCH_EXID_SAM9X75_D5M 0x00000010
+
+#define cpu_is_sam9x7() (get_chip_id() == ARCH_ID_SAM9X7)
+
+/*
+ * Cpu Name
+ */
+#define ATMEL_CPU_NAME get_cpu_name()
+
+/*
+ * Timer
+ */
+#define CFG_SYS_TIMER_COUNTER 0xf0028000
+
+/*
+ * Other misc defines
+ */
+#define ATMEL_PIO_PORTS 4
+#define CPU_HAS_PCR
+#define CPU_NO_PLLB
+#define PLL_ID_PLLA 0
+#define PLL_ID_UPLL 1
+#define PLL_ID_AUDIOPLL 2
+#define PLL_ID_LVDSPLL 3
+#define PLL_ID_PLLA_DIV_2 4
+
+/*
+ * PMECC table in ROM
+ */
+#define ATMEL_PMECC_INDEX_OFFSET_512 0x0000
+#define ATMEL_PMECC_INDEX_OFFSET_1024 0x8000
+
+/*
+ * SAM9X7 specific prototypes
+ */
+#ifndef __ASSEMBLY__
+unsigned int get_chip_id(void);
+unsigned int get_extension_chip_id(void);
+char *get_cpu_name(void);
+#endif
+
+#endif
diff --git a/arch/arm/mach-at91/spl.c b/arch/arm/mach-at91/spl.c
index 5feb8f73551..a814973242a 100644
--- a/arch/arm/mach-at91/spl.c
+++ b/arch/arm/mach-at91/spl.c
@@ -14,9 +14,7 @@
#if !defined(CONFIG_WDT_AT91)
void at91_disable_wdt(void)
{
- struct at91_wdt *wdt = (struct at91_wdt *)ATMEL_BASE_WDT;
-
- writel(AT91_WDT_MR_WDDIS, &wdt->mr);
+ writel(AT91_WDT_MR_WDDIS, ATMEL_BASE_WDT + AT91_WDT_MR);
}
#endif
diff --git a/arch/arm/mach-imx/imx8/cpu.c b/arch/arm/mach-imx/imx8/cpu.c
index 37a5473ac7c..0e112af661c 100644
--- a/arch/arm/mach-imx/imx8/cpu.c
+++ b/arch/arm/mach-imx/imx8/cpu.c
@@ -451,7 +451,7 @@ void get_board_serial(struct tag_serialnr *serialnr)
#ifdef CONFIG_ENV_IS_IN_MMC
__weak int board_mmc_get_env_dev(int devno)
{
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
int mmc_get_env_dev(void)
@@ -473,7 +473,7 @@ int mmc_get_env_dev(void)
break;
default:
/* If not boot from sd/mmc, use default value */
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
return board_mmc_get_env_dev(devno);
diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c
index 2b042300103..8fe70e2424f 100644
--- a/arch/arm/mach-imx/imx8ulp/soc.c
+++ b/arch/arm/mach-imx/imx8ulp/soc.c
@@ -56,7 +56,7 @@ int mmc_get_env_dev(void)
if (ret != ROM_API_OKAY) {
puts("ROMAPI: failure at query_boot_info\n");
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
boot_type = boot >> 16;
@@ -64,7 +64,7 @@ int mmc_get_env_dev(void)
/* If not boot from sd/mmc, use default value */
if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC)
- return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV);
+ return env_get_ulong("mmcdev", 10, CONFIG_ENV_MMC_DEVICE_INDEX);
return board_mmc_get_env_dev(boot_instance);
}
diff --git a/arch/arm/mach-imx/imx9/scmi/soc.c b/arch/arm/mach-imx/imx9/scmi/soc.c
index d68a1166deb..13f13ca7d10 100644
--- a/arch/arm/mach-imx/imx9/scmi/soc.c
+++ b/arch/arm/mach-imx/imx9/scmi/soc.c
@@ -84,7 +84,7 @@ int mmc_get_env_dev(void)
ret = scmi_get_rom_data(rdata);
if (ret != 0) {
puts("SCMI: failure at rom_boot_info\n");
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
}
boot_type = rdata->boot_dev_type;
@@ -95,7 +95,7 @@ int mmc_get_env_dev(void)
/* If not boot from sd/mmc, use default value */
if (boot_type != BOOT_TYPE_SD && boot_type != BOOT_TYPE_MMC)
- return env_get_ulong("mmcdev", 10, CONFIG_SYS_MMC_ENV_DEV);
+ return env_get_ulong("mmcdev", 10, CONFIG_ENV_MMC_DEVICE_INDEX);
return board_mmc_get_env_dev(boot_instance);
}
diff --git a/arch/arm/mach-imx/imx9/soc.c b/arch/arm/mach-imx/imx9/soc.c
index bb13ca742e3..02db7cc97ba 100644
--- a/arch/arm/mach-imx/imx9/soc.c
+++ b/arch/arm/mach-imx/imx9/soc.c
@@ -48,8 +48,8 @@ __weak int board_mmc_get_env_dev(int devno)
return devno;
}
-#ifdef CONFIG_SYS_MMC_ENV_DEV
-#define IMX9_MMC_ENV_DEV CONFIG_SYS_MMC_ENV_DEV
+#ifdef CONFIG_ENV_MMC_DEVICE_INDEX
+#define IMX9_MMC_ENV_DEV CONFIG_ENV_MMC_DEVICE_INDEX
#else
#define IMX9_MMC_ENV_DEV 0
#endif
diff --git a/arch/arm/mach-imx/mmc_env.c b/arch/arm/mach-imx/mmc_env.c
index 34a7d1706f3..2ec8ddf4d59 100644
--- a/arch/arm/mach-imx/mmc_env.c
+++ b/arch/arm/mach-imx/mmc_env.c
@@ -10,7 +10,7 @@
__weak int board_mmc_get_env_dev(int devno)
{
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
int mmc_get_env_dev(void)
@@ -22,7 +22,7 @@ int mmc_get_env_dev(void)
/* If not boot from sd/mmc, use default value */
if ((boot_type != BOOT_TYPE_SD) && (boot_type != BOOT_TYPE_MMC))
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
return board_mmc_get_env_dev(devno);
}
diff --git a/arch/arm/mach-imx/mx6/soc.c b/arch/arm/mach-imx/mx6/soc.c
index d4a61731a67..50521490b35 100644
--- a/arch/arm/mach-imx/mx6/soc.c
+++ b/arch/arm/mach-imx/mx6/soc.c
@@ -502,7 +502,7 @@ int arch_cpu_init(void)
#ifdef CONFIG_ENV_IS_IN_MMC
__weak int board_mmc_get_env_dev(int devno)
{
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
static int mmc_get_boot_dev(void)
@@ -535,15 +535,15 @@ int mmc_get_env_dev(void)
/* If not boot from sd/mmc, use default value */
if (devno < 0)
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
return board_mmc_get_env_dev(devno);
}
-#ifdef CONFIG_SYS_MMC_ENV_PART
+#ifdef CONFIG_ENV_MMC_EMMC_HW_PARTITION
__weak int board_mmc_get_env_part(int devno)
{
- return CONFIG_SYS_MMC_ENV_PART;
+ return CONFIG_ENV_MMC_EMMC_HW_PARTITION;
}
uint mmc_get_env_part(struct mmc *mmc)
@@ -552,7 +552,7 @@ uint mmc_get_env_part(struct mmc *mmc)
/* If not boot from sd/mmc, use default value */
if (devno < 0)
- return CONFIG_SYS_MMC_ENV_PART;
+ return CONFIG_ENV_MMC_EMMC_HW_PARTITION;
return board_mmc_get_env_part(devno);
}
diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c
index 61d331e0181..5306e76223f 100644
--- a/arch/arm/mach-imx/mx7ulp/soc.c
+++ b/arch/arm/mach-imx/mx7ulp/soc.c
@@ -362,7 +362,7 @@ static char *get_reset_cause(char *ret)
#ifdef CONFIG_ENV_IS_IN_MMC
__weak int board_mmc_get_env_dev(int devno)
{
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
int mmc_get_env_dev(void)
@@ -372,7 +372,7 @@ int mmc_get_env_dev(void)
/* If not boot from sd/mmc, use default value */
if (get_boot_mode() == LOW_POWER_BOOT)
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
bt1_cfg = readl(CMC1_RBASE + 0x40);
devno = (bt1_cfg >> 9) & 0x7;
diff --git a/arch/arm/mach-k3/am62ax/am62a7_init.c b/arch/arm/mach-k3/am62ax/am62a7_init.c
index edd43a1d78d..00173e6836b 100644
--- a/arch/arm/mach-k3/am62ax/am62a7_init.c
+++ b/arch/arm/mach-k3/am62ax/am62a7_init.c
@@ -57,7 +57,6 @@ static void ctrl_mmr_unlock(void)
mmr_unlock(CTRL_MMR0_BASE, 1);
mmr_unlock(CTRL_MMR0_BASE, 2);
mmr_unlock(CTRL_MMR0_BASE, 4);
- mmr_unlock(CTRL_MMR0_BASE, 5);
mmr_unlock(CTRL_MMR0_BASE, 6);
/* Unlock all MCU_CTRL_MMR0 module registers */
@@ -172,6 +171,10 @@ void board_init_f(ulong dummy)
/* Output System Firmware version info */
k3_sysfw_print_ver();
+ /* Output DM Firmware version info */
+ if (IS_ENABLED(CONFIG_ARM64))
+ k3_dm_print_ver();
+
if (IS_ENABLED(CONFIG_ESM_K3)) {
/* Probe/configure ESM0 */
ret = uclass_get_device_by_name(UCLASS_MISC, "esm@420000", &dev);
diff --git a/arch/arm/mach-k3/am62px/am62p5_init.c b/arch/arm/mach-k3/am62px/am62p5_init.c
index 6e3c66e5107..44a2d445d24 100644
--- a/arch/arm/mach-k3/am62px/am62p5_init.c
+++ b/arch/arm/mach-k3/am62px/am62p5_init.c
@@ -224,6 +224,10 @@ void board_init_f(ulong dummy)
/* Output System Firmware version info */
k3_sysfw_print_ver();
+ /* Output DM Firmware version info */
+ if (IS_ENABLED(CONFIG_ARM64))
+ k3_dm_print_ver();
+
if (IS_ENABLED(CONFIG_K3_AM62A_DDRSS)) {
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret)
diff --git a/arch/arm/mach-k3/arm64/arm64-mmu.c b/arch/arm/mach-k3/arm64/arm64-mmu.c
index 0e07b1b7ce0..74c855852e9 100644
--- a/arch/arm/mach-k3/arm64/arm64-mmu.c
+++ b/arch/arm/mach-k3/arm64/arm64-mmu.c
@@ -9,11 +9,19 @@
*
*/
+#include <linux/sizes.h>
#include <asm/system.h>
#include <asm/armv8/mmu.h>
+#include <mach/k3-ddr.h>
+#include <sort.h>
-struct mm_region k3_mem_map[] = {
+#include "../common_fdt.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mm_region k3_mem_map[K3_MMU_REGIONS_COUNT] = {
{
+ /* Peripherals */
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x80000000UL,
@@ -21,24 +29,14 @@ struct mm_region k3_mem_map[] = {
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
- .virt = 0x80000000UL,
- .phys = 0x80000000UL,
- .size = 0x1e780000UL,
- .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
- PTE_BLOCK_INNER_SHARE
- }, {
- .virt = 0xa0000000UL,
- .phys = 0xa0000000UL,
- .size = 0x60000000UL,
- .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
- PTE_BLOCK_INNER_SHARE
- }, {
+ /* Higher DDR banks */
.virt = 0x880000000UL,
.phys = 0x880000000UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
+ /* Flash peripherals */
.virt = 0x500000000UL,
.phys = 0x500000000UL,
.size = 0x380000000UL,
@@ -46,9 +44,242 @@ struct mm_region k3_mem_map[] = {
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
+ /* Map SPL load region and the next 128MiB as cacheable */
+ .virt = CONFIG_SPL_TEXT_BASE,
+ .phys = CONFIG_SPL_TEXT_BASE,
+ .size = SZ_128M,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
+ /* Framebuffer reserved, size set at runtime */
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE
+ }, {
/* List terminator */
0,
}
};
struct mm_region *mem_map = k3_mem_map;
+
+int k3_spl_mem_map_init(void)
+{
+ unsigned int i;
+ int k3_map_idx = -EINVAL;
+
+ for (i = 0; i < K3_MMU_REGIONS_COUNT; i++) {
+ if (k3_mem_map[i].virt == 0 && k3_mem_map[i].phys == 0 &&
+ k3_mem_map[i].size == 0) {
+ k3_map_idx = i;
+ break;
+ }
+ }
+
+ if (k3_map_idx == -EINVAL) {
+ pr_err("%s: Failed to find fixup region in MMU memory map\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (k3_map_idx >= K3_MMU_REGIONS_COUNT - 1) {
+ pr_err("%s: Not enough space in MMU map for the added entry\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ if (CONFIG_IS_ENABLED(VIDEO)) {
+ k3_mem_map[k3_map_idx].virt = gd_video_bottom();
+ k3_mem_map[k3_map_idx].phys = gd_video_bottom();
+ k3_mem_map[k3_map_idx].size =
+ gd_video_top() - gd_video_bottom();
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+ }
+
+ k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
+
+ return 0;
+}
+
+static int dt_reserved_cmp(const void *a, const void *b)
+{
+ const struct fdt_resource *val_a = a, *val_b = b;
+
+ return (val_a->start - val_b->start);
+}
+
+int k3_mem_map_init(void)
+{
+ fdt_addr_t mem_base;
+ fdt_size_t mem_size;
+ struct fdt_resource dt_reserved[K3_MMU_REGIONS_COUNT],
+ coalesced[K3_MMU_REGIONS_COUNT];
+ int k3_map_idx = -EINVAL, ret, nodeoffset, subnode;
+ void *blob = (void *)gd->fdt_blob;
+ unsigned int carveout_len, i, j;
+
+ ret = fdt_fixup_reserved(blob, "tfa", CONFIG_K3_ATF_LOAD_ADDR, 0x80000);
+ if (ret) {
+ pr_err("%s: Failed to fixup reserved node for tfa [%d]\n",
+ __func__, ret);
+ return ret;
+ }
+
+ ret = fdt_fixup_reserved(blob, "optee", CONFIG_K3_OPTEE_LOAD_ADDR,
+ 0x1800000);
+ if (ret) {
+ pr_err("%s: Failed to fixup reserved node for optee [%d]\n",
+ __func__, ret);
+ return ret;
+ }
+
+ nodeoffset = fdt_subnode_offset(blob, 0, "memory");
+ if (nodeoffset < 0) {
+ pr_err("%s: Failed to get memory data: %s\n", __func__,
+ fdt_strerror(nodeoffset));
+ return nodeoffset;
+ }
+
+ mem_base = fdtdec_get_addr_size(blob, nodeoffset, "reg", &mem_size);
+ if (mem_base != CFG_SYS_SDRAM_BASE)
+ return -EINVAL;
+
+ for (i = 0; i < K3_MMU_REGIONS_COUNT; i++) {
+ if (k3_mem_map[i].virt == CONFIG_SPL_TEXT_BASE) {
+ k3_map_idx = i;
+ break;
+ }
+ }
+
+ if (k3_map_idx == -EINVAL) {
+ pr_err("%s: Failed to find DDR region in MMU memory map\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ i = 0;
+ nodeoffset = fdt_subnode_offset(blob, 0, "reserved-memory");
+ fdt_for_each_subnode(subnode, blob, nodeoffset) {
+ const char *name;
+ fdt_addr_t addr, end_addr;
+ fdt_size_t size;
+
+ if (i >= K3_MMU_REGIONS_COUNT) {
+ /*
+ * This is a recoverable error if the regions can be
+ * coalesced, the required logic can be implemented once
+ * requirement arises.
+ */
+ pr_err("%s: Not enough space in MMU map for carveouts\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ name = fdt_get_name(blob, subnode, NULL);
+ addr = fdtdec_get_addr_size(blob, subnode, "reg", &size);
+
+ if (addr == FDT_ADDR_T_NONE)
+ continue;
+
+ if (!fdtdec_get_bool(blob, subnode, "no-map"))
+ continue;
+
+ if (addr >= mem_base + mem_size)
+ continue;
+
+ end_addr = addr + size;
+
+ if (end_addr <= mem_base)
+ continue;
+
+ debug("Added memory carveout at 0x%llx, size: 0x%llx for '%s'\n",
+ addr, size, name);
+
+ addr = max(addr, mem_base);
+ end_addr = min(end_addr, mem_base + mem_size);
+ size = end_addr - addr;
+ dt_reserved[i].start = addr;
+ dt_reserved[i].end = end_addr;
+ i++;
+ }
+ carveout_len = i;
+
+ if (!carveout_len)
+ return 0;
+
+ /* sort carveout regions by address required for creating carveouts */
+ qsort(dt_reserved, carveout_len, sizeof(dt_reserved[0]),
+ dt_reserved_cmp);
+
+ /* coalesce regions */
+ struct fdt_resource coalescing_temp = dt_reserved[0];
+
+ j = 0;
+ for (i = 1; i < carveout_len; i++) {
+ struct fdt_resource current = dt_reserved[i];
+
+ if (coalescing_temp.end >= current.start) {
+ coalescing_temp.end = current.end;
+ continue;
+ }
+ coalesced[j] = coalescing_temp;
+ coalescing_temp = current;
+ j++;
+ }
+
+ coalesced[j] = coalescing_temp;
+ carveout_len = j + 1;
+
+ if (coalesced[0].start != mem_base) {
+ k3_mem_map[k3_map_idx].virt = mem_base;
+ k3_mem_map[k3_map_idx].phys = mem_base;
+ k3_mem_map[k3_map_idx].size = coalesced[0].start - mem_base;
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+ }
+
+ for (i = 1; i < carveout_len; i++) {
+ k3_mem_map[k3_map_idx].virt = coalesced[i - 1].end;
+ k3_mem_map[k3_map_idx].phys = coalesced[i - 1].end;
+ k3_mem_map[k3_map_idx].size =
+ coalesced[i].start - coalesced[i - 1].end;
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+ }
+
+ k3_mem_map[k3_map_idx].virt = coalesced[carveout_len - 1].end;
+ k3_mem_map[k3_map_idx].phys = coalesced[carveout_len - 1].end;
+ k3_mem_map[k3_map_idx].size =
+ mem_base + mem_size - coalesced[carveout_len - 1].end;
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+
+ /* map reserved memory as non cachable */
+ for (i = 0; i < carveout_len; i++) {
+ k3_mem_map[k3_map_idx].virt = coalesced[i].start;
+ k3_mem_map[k3_map_idx].phys = coalesced[i].start;
+ k3_mem_map[k3_map_idx].size =
+ coalesced[i].end - coalesced[i].start;
+ k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
+ PTE_BLOCK_INNER_SHARE;
+ k3_map_idx++;
+ }
+
+ debug("%s: MMU Table configured as:\n", __func__);
+ debug(" |virt start\t\t|virt end\t|phys\t\t|size\t\t|attrs:\n");
+ for (i = 0; i < k3_map_idx; i++) {
+ debug("%2d: 0x%-12llx\t0x%-12llx\t0x%-12llx\t0x%-12llx\t0x%llx\n",
+ i, k3_mem_map[i].virt,
+ k3_mem_map[i].virt + k3_mem_map[i].size,
+ k3_mem_map[i].phys, k3_mem_map[i].size,
+ k3_mem_map[i].attrs);
+ }
+
+ k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
+
+ return 0;
+}
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index 0323001d6d3..723076ee874 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -15,6 +15,7 @@
#include <asm/global_data.h>
#include <linux/printk.h>
#include "common.h"
+#include "mach/k3-ddr.h"
#include <dm.h>
#include <remoteproc.h>
#include <asm/cache.h>
@@ -31,6 +32,11 @@
#include <dm/uclass-internal.h>
#include <dm/device-internal.h>
+#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001
+#define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002
+#define PROC_ID_MCU_R5FSS0_CORE1 0x02
+#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP 0x00000100
+
#include <asm/arch/k3-qos.h>
struct ti_sci_handle *get_ti_sci_handle(void)
@@ -68,6 +74,35 @@ void k3_sysfw_print_ver(void)
ti_sci->version.firmware_revision, fw_desc);
}
+void __maybe_unused k3_dm_print_ver(void)
+{
+ struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+ struct ti_sci_firmware_ops *fw_ops = &ti_sci->ops.fw_ops;
+ struct ti_sci_dm_version_info dm_info = {0};
+ u64 fw_caps;
+ int ret;
+
+ ret = fw_ops->query_dm_cap(ti_sci, &fw_caps);
+ if (ret) {
+ printf("Failed to query DM firmware capability %d\n", ret);
+ return;
+ }
+
+ if (!(fw_caps & TI_SCI_MSG_FLAG_FW_CAP_DM))
+ return;
+
+ ret = fw_ops->get_dm_version(ti_sci, &dm_info);
+ if (ret) {
+ printf("Failed to fetch DM firmware version %d\n", ret);
+ return;
+ }
+
+ printf("DM ABI: %d.%d (firmware ver 0x%04x '%s--%s' "
+ "patch_ver: %d)\n", dm_info.abi_major, dm_info.abi_minor,
+ dm_info.dm_ver, dm_info.sci_server_version,
+ dm_info.rm_pm_hal_version, dm_info.patch_ver);
+}
+
void mmr_unlock(uintptr_t base, u32 partition)
{
/* Translate the base address */
@@ -234,9 +269,6 @@ void spl_enable_cache(void)
dram_init();
- /* reserve TLB table */
- gd->arch.tlb_size = PGTABLE_SIZE;
-
gd->ram_top += get_effective_memsize();
gd->relocaddr = gd->ram_top;
@@ -244,6 +276,15 @@ void spl_enable_cache(void)
if (ret)
panic("Failed to reserve framebuffer memory (%d)\n", ret);
+ if (IS_ENABLED(CONFIG_ARM64)) {
+ ret = k3_spl_mem_map_init();
+ if (ret)
+ panic("Failed to perform MMU fixups: %d\n", ret);
+ }
+
+ /* reserve TLB table */
+ gd->arch.tlb_size = PGTABLE_SIZE;
+
gd->arch.tlb_addr = gd->relocaddr - gd->arch.tlb_size;
gd->arch.tlb_addr &= ~(0x10000 - 1);
debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
@@ -338,3 +379,67 @@ void setup_qos(void)
writel(qos_data[i].val, (uintptr_t)qos_data[i].reg);
}
#endif
+
+int __maybe_unused shutdown_mcu_r5_core1(void)
+{
+ struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+ struct ti_sci_dev_ops *dev_ops = &ti_sci->ops.dev_ops;
+ struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops;
+ u32 dev_id_mcu_r5_core1 = put_core_ids[0];
+ u64 boot_vector;
+ u32 cfg, ctrl, sts, halted;
+ int cluster_mode_lockstep, ret;
+ bool r_state = false, c_state = false;
+
+ ret = proc_ops->proc_request(ti_sci, PROC_ID_MCU_R5FSS0_CORE1);
+ if (ret) {
+ printf("Unable to request processor control for MCU1_1 core, %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = dev_ops->is_on(ti_sci, dev_id_mcu_r5_core1, &r_state, &c_state);
+ if (ret) {
+ printf("Unable to get device status for MCU1_1 core, %d\n", ret);
+ return ret;
+ }
+
+ ret = proc_ops->get_proc_boot_status(ti_sci, PROC_ID_MCU_R5FSS0_CORE1,
+ &boot_vector, &cfg, &ctrl, &sts);
+ if (ret) {
+ printf("Unable to get Processor boot status for MCU1_1 core, %d\n",
+ ret);
+ goto release_proc_ctrl;
+ }
+
+ halted = !!(sts & PROC_BOOT_STATUS_FLAG_R5_WFI);
+ cluster_mode_lockstep = !!(cfg & PROC_BOOT_CFG_FLAG_R5_LOCKSTEP);
+
+ /*
+ * Shutdown MCU R5F Core 1 only if:
+ * - cluster is booted in SplitMode
+ * - core is powered on
+ * - core is in WFI (halted)
+ */
+ if (cluster_mode_lockstep || !c_state || !halted) {
+ ret = -EINVAL;
+ goto release_proc_ctrl;
+ }
+
+ ret = proc_ops->set_proc_boot_ctrl(ti_sci, PROC_ID_MCU_R5FSS0_CORE1,
+ PROC_BOOT_CTRL_FLAG_R5_CORE_HALT, 0);
+ if (ret) {
+ printf("Unable to Halt MCU1_1 core, %d\n", ret);
+ goto release_proc_ctrl;
+ }
+
+ ret = dev_ops->put_device(ti_sci, dev_id_mcu_r5_core1);
+ if (ret) {
+ printf("Unable to assert reset on MCU1_1 core, %d\n", ret);
+ return ret;
+ }
+
+release_proc_ctrl:
+ proc_ops->proc_release(ti_sci, PROC_ID_MCU_R5FSS0_CORE1);
+ return ret;
+}
diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h
index 02c74731fea..52d3faaab5c 100644
--- a/arch/arm/mach-k3/common.h
+++ b/arch/arm/mach-k3/common.h
@@ -42,6 +42,7 @@ int remove_fwl_region(struct fwl_data *fwl);
void remove_fwl_configs(struct fwl_data *fwl_data, size_t fwl_data_size);
int load_firmware(char *name_fw, char *name_loadaddr, u32 *loadaddr);
void k3_sysfw_print_ver(void);
+void k3_dm_print_ver(void);
void spl_enable_cache(void);
void mmr_unlock(uintptr_t base, u32 partition);
bool is_rom_loaded_sysfw(struct rom_extended_boot_data *data);
@@ -49,6 +50,7 @@ enum k3_device_type get_device_type(void);
struct ti_sci_handle *get_ti_sci_handle(void);
void do_board_detect(void);
void ti_secure_image_check_binary(void **p_image, size_t *p_size);
+int shutdown_mcu_r5_core1(void);
#if (IS_ENABLED(CONFIG_K3_QOS))
void setup_qos(void);
diff --git a/arch/arm/mach-k3/include/mach/am62_hardware.h b/arch/arm/mach-k3/include/mach/am62_hardware.h
index c33362696c4..2f5655bf24a 100644
--- a/arch/arm/mach-k3/include/mach/am62_hardware.h
+++ b/arch/arm/mach-k3/include/mach/am62_hardware.h
@@ -177,8 +177,8 @@ static inline int k3_has_gpu(void)
static const u32 put_device_ids[] = {};
-static const u32 put_core_ids[] = {};
-
#endif
+static const u32 put_core_ids[] = {};
+
#endif /* __ASM_ARCH_AM62_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/am62a_hardware.h b/arch/arm/mach-k3/include/mach/am62a_hardware.h
index cd61abe0185..f3fd736f31b 100644
--- a/arch/arm/mach-k3/include/mach/am62a_hardware.h
+++ b/arch/arm/mach-k3/include/mach/am62a_hardware.h
@@ -90,8 +90,8 @@
static const u32 put_device_ids[] = {};
-static const u32 put_core_ids[] = {};
-
#endif
+static const u32 put_core_ids[] = {};
+
#endif /* __ASM_ARCH_AM62A_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/am62p_hardware.h b/arch/arm/mach-k3/include/mach/am62p_hardware.h
index 95af5c5c547..a310b52b45d 100644
--- a/arch/arm/mach-k3/include/mach/am62p_hardware.h
+++ b/arch/arm/mach-k3/include/mach/am62p_hardware.h
@@ -141,8 +141,8 @@ static inline int k3_get_a53_max_frequency(void)
static const u32 put_device_ids[] = {};
-static const u32 put_core_ids[] = {};
-
#endif
+static const u32 put_core_ids[] = {};
+
#endif /* __ASM_ARCH_AM62P_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/am64_hardware.h b/arch/arm/mach-k3/include/mach/am64_hardware.h
index 44df887d5df..105b42986de 100644
--- a/arch/arm/mach-k3/include/mach/am64_hardware.h
+++ b/arch/arm/mach-k3/include/mach/am64_hardware.h
@@ -50,19 +50,20 @@
#define AM64X_DEV_RTI8 127
#define AM64X_DEV_RTI9 128
-#define AM64X_DEV_R5FSS0_CORE0 121
-#define AM64X_DEV_R5FSS0_CORE1 122
static const u32 put_device_ids[] = {
AM64X_DEV_RTI9,
AM64X_DEV_RTI8,
};
+#endif
+
+#define AM64X_DEV_R5FSS0_CORE0 121
+#define AM64X_DEV_R5FSS0_CORE1 122
+
static const u32 put_core_ids[] = {
AM64X_DEV_R5FSS0_CORE1,
AM64X_DEV_R5FSS0_CORE0, /* Handle CPU0 after CPU1 */
};
-#endif
-
#endif /* __ASM_ARCH_DRA8_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/am6_hardware.h b/arch/arm/mach-k3/include/mach/am6_hardware.h
index 9913964c46b..8169584a372 100644
--- a/arch/arm/mach-k3/include/mach/am6_hardware.h
+++ b/arch/arm/mach-k3/include/mach/am6_hardware.h
@@ -43,19 +43,20 @@
#define AM6_DEV_MCU_RTI0 134
#define AM6_DEV_MCU_RTI1 135
-#define AM6_DEV_MCU_ARMSS0_CPU0 159
-#define AM6_DEV_MCU_ARMSS0_CPU1 245
static const u32 put_device_ids[] = {
AM6_DEV_MCU_RTI0,
AM6_DEV_MCU_RTI1,
};
+#endif
+
+#define AM6_DEV_MCU_ARMSS0_CPU0 159
+#define AM6_DEV_MCU_ARMSS0_CPU1 245
+
static const u32 put_core_ids[] = {
AM6_DEV_MCU_ARMSS0_CPU1,
AM6_DEV_MCU_ARMSS0_CPU0, /* Handle CPU0 after CPU1 */
};
-#endif
-
#endif /* __ASM_ARCH_AM6_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/j721e_hardware.h b/arch/arm/mach-k3/include/mach/j721e_hardware.h
index 2b5ec771e18..5bef309af0a 100644
--- a/arch/arm/mach-k3/include/mach/j721e_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j721e_hardware.h
@@ -41,19 +41,20 @@
#define J721E_DEV_MCU_RTI0 262
#define J721E_DEV_MCU_RTI1 263
-#define J721E_DEV_MCU_ARMSS0_CPU0 250
-#define J721E_DEV_MCU_ARMSS0_CPU1 251
static const u32 put_device_ids[] = {
J721E_DEV_MCU_RTI0,
J721E_DEV_MCU_RTI1,
};
+#endif
+
+#define J721E_DEV_MCU_ARMSS0_CPU0 250
+#define J721E_DEV_MCU_ARMSS0_CPU1 251
+
static const u32 put_core_ids[] = {
J721E_DEV_MCU_ARMSS0_CPU1,
J721E_DEV_MCU_ARMSS0_CPU0, /* Handle CPU0 after CPU1 */
};
-#endif
-
#endif /* __ASM_ARCH_J721E_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/j721s2_hardware.h b/arch/arm/mach-k3/include/mach/j721s2_hardware.h
index 8daea82a77e..82f076a45e0 100644
--- a/arch/arm/mach-k3/include/mach/j721s2_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j721s2_hardware.h
@@ -41,19 +41,20 @@
#define J721S2_DEV_MCU_RTI0 295
#define J721S2_DEV_MCU_RTI1 296
-#define J721S2_DEV_MCU_ARMSS0_CPU0 284
-#define J721S2_DEV_MCU_ARMSS0_CPU1 285
static const u32 put_device_ids[] = {
J721S2_DEV_MCU_RTI0,
J721S2_DEV_MCU_RTI1,
};
+#endif
+
+#define J721S2_DEV_MCU_ARMSS0_CPU0 284
+#define J721S2_DEV_MCU_ARMSS0_CPU1 285
+
static const u32 put_core_ids[] = {
J721S2_DEV_MCU_ARMSS0_CPU1,
J721S2_DEV_MCU_ARMSS0_CPU0, /* Handle CPU0 after CPU1 */
};
-#endif
-
#endif /* __ASM_ARCH_J721S2_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/j722s_hardware.h b/arch/arm/mach-k3/include/mach/j722s_hardware.h
index 8d0bec22068..0c695134c28 100644
--- a/arch/arm/mach-k3/include/mach/j722s_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j722s_hardware.h
@@ -76,8 +76,8 @@
static const u32 put_device_ids[] = {};
-static const u32 put_core_ids[] = {};
-
#endif
+static const u32 put_core_ids[] = {};
+
#endif /* __ASM_ARCH_J722S_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/j784s4_hardware.h b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
index 0ffe238cdae..29a894baed3 100644
--- a/arch/arm/mach-k3/include/mach/j784s4_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
@@ -41,19 +41,20 @@
#define J784S4_DEV_MCU_RTI0 367
#define J784S4_DEV_MCU_RTI1 368
-#define J784S4_DEV_MCU_ARMSS0_CPU0 346
-#define J784S4_DEV_MCU_ARMSS0_CPU1 347
static const u32 put_device_ids[] = {
J784S4_DEV_MCU_RTI0,
J784S4_DEV_MCU_RTI1,
};
+#endif
+
+#define J784S4_DEV_MCU_ARMSS0_CPU0 346
+#define J784S4_DEV_MCU_ARMSS0_CPU1 347
+
static const u32 put_core_ids[] = {
J784S4_DEV_MCU_ARMSS0_CPU1,
J784S4_DEV_MCU_ARMSS0_CPU0, /* Handle CPU0 after CPU1 */
};
-#endif
-
#endif /* __ASM_ARCH_J784S4_HARDWARE_H */
diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
index 39e6725bb9b..375a1a85945 100644
--- a/arch/arm/mach-k3/include/mach/k3-ddr.h
+++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
@@ -8,10 +8,22 @@
#include <spl.h>
+/* Number of mappable regions in the MMU page table */
+#define K3_MMU_REGIONS_COUNT 32
+
int dram_init(void);
int dram_init_banksize(void);
void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
void fixup_memory_node(struct spl_image_info *spl_image);
+/* Performs MMU memory map fixups at SPL stage */
+int k3_spl_mem_map_init(void);
+
+/*
+ * Modifies the MMU memory map based on DDR size and reserved-memory
+ * nodes in DT
+ */
+int k3_mem_map_init(void);
+
#endif /* _K3_DDR_H_ */
diff --git a/arch/arm/mach-k3/j721e/j721e_init.c b/arch/arm/mach-k3/j721e/j721e_init.c
index f31c20f7ed6..f9af0288cf6 100644
--- a/arch/arm/mach-k3/j721e/j721e_init.c
+++ b/arch/arm/mach-k3/j721e/j721e_init.c
@@ -296,9 +296,9 @@ void do_dt_magic(void)
void board_init_f(ulong dummy)
{
+ int ret;
#if defined(CONFIG_K3_J721E_DDRSS) || defined(CONFIG_K3_LOAD_SYSFW)
struct udevice *dev;
- int ret;
#endif
/*
* Cannot delay this further as there is a chance that
@@ -371,9 +371,20 @@ void board_init_f(ulong dummy)
preloader_console_init();
#endif
+ /* Shutdown MCU_R5 Core 1 in Split mode at A72 SPL Stage */
+ if (IS_ENABLED(CONFIG_ARM64)) {
+ ret = shutdown_mcu_r5_core1();
+ if (ret)
+ printf("Unable to shutdown MCU R5 core 1, %d\n", ret);
+ }
+
/* Output System Firmware version info */
k3_sysfw_print_ver();
+ /* Output DM Firmware version info */
+ if (IS_ENABLED(CONFIG_ARM64))
+ k3_dm_print_ver();
+
/* Perform board detection */
do_board_detect();
diff --git a/arch/arm/mach-k3/j721s2/j721s2_init.c b/arch/arm/mach-k3/j721s2/j721s2_init.c
index 5941fa26a95..eee3d0440ac 100644
--- a/arch/arm/mach-k3/j721s2/j721s2_init.c
+++ b/arch/arm/mach-k3/j721s2/j721s2_init.c
@@ -230,8 +230,19 @@ void k3_spl_init(void)
remove_fwl_configs(navss_cbass0_fwls, ARRAY_SIZE(navss_cbass0_fwls));
}
+ /* Shutdown MCU_R5 Core 1 in Split mode at A72 SPL Stage */
+ if (IS_ENABLED(CONFIG_ARM64)) {
+ ret = shutdown_mcu_r5_core1();
+ if (ret)
+ printf("Unable to shutdown MCU R5 core 1, %d\n", ret);
+ }
+
/* Output System Firmware version info */
k3_sysfw_print_ver();
+
+ /* Output DM Firmware version info */
+ if (IS_ENABLED(CONFIG_ARM64))
+ k3_dm_print_ver();
}
bool check_rom_loaded_sysfw(void)
diff --git a/arch/arm/mach-k3/j722s/j722s_init.c b/arch/arm/mach-k3/j722s/j722s_init.c
index af211377e7c..1180c75f551 100644
--- a/arch/arm/mach-k3/j722s/j722s_init.c
+++ b/arch/arm/mach-k3/j722s/j722s_init.c
@@ -150,6 +150,10 @@ static void k3_spl_init(void)
/* Output System Firmware version info */
k3_sysfw_print_ver();
+
+ /* Output DM Firmware version info */
+ if (IS_ENABLED(CONFIG_ARM64))
+ k3_dm_print_ver();
}
static void k3_mem_init(void)
@@ -162,6 +166,8 @@ static void k3_mem_init(void)
if (ret)
panic("DRAM init failed: %d\n", ret);
}
+
+ spl_enable_cache();
}
static __maybe_unused void enable_mcu_esm_reset(void)
diff --git a/arch/arm/mach-k3/j784s4/j784s4_init.c b/arch/arm/mach-k3/j784s4/j784s4_init.c
index 4e9f823072b..0f11511bda0 100644
--- a/arch/arm/mach-k3/j784s4/j784s4_init.c
+++ b/arch/arm/mach-k3/j784s4/j784s4_init.c
@@ -206,8 +206,19 @@ void k3_spl_init(void)
writel(AUDIO_REFCLK1_DEFAULT, (uintptr_t)CTRL_MMR_CFG0_AUDIO_REFCLK1_CTRL);
+ /* Shutdown MCU_R5 Core 1 in Split mode at A72 SPL Stage */
+ if (IS_ENABLED(CONFIG_ARM64)) {
+ ret = shutdown_mcu_r5_core1();
+ if (ret)
+ printf("Unable to shutdown MCU R5 core 1, %d\n", ret);
+ }
+
/* Output System Firmware version info */
k3_sysfw_print_ver();
+
+ /* Output DM Firmware version info */
+ if (IS_ENABLED(CONFIG_ARM64))
+ k3_dm_print_ver();
}
void k3_mem_init(void)
diff --git a/arch/arm/mach-mediatek/tzcfg.c b/arch/arm/mach-mediatek/tzcfg.c
index 71982ba4d20..c8fe8ac0e9b 100644
--- a/arch/arm/mach-mediatek/tzcfg.c
+++ b/arch/arm/mach-mediatek/tzcfg.c
@@ -173,6 +173,7 @@ phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
int arch_misc_init(void)
{
+ phys_addr_t addr;
struct arm_smccc_res res;
/*
@@ -180,11 +181,14 @@ int arch_misc_init(void)
* there's no need to check the result
*/
arm_smccc_smc(MTK_SIP_GET_BL31_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
- lmb_reserve(res.a1, res.a2, LMB_NOMAP);
+ addr = (phys_addr_t)res.a1;
+ lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &addr, res.a2, LMB_NOMAP);
arm_smccc_smc(MTK_SIP_GET_BL32_REGION, 0, 0, 0, 0, 0, 0, 0, &res);
+ addr = (phys_addr_t)res.a1;
if (!res.a0 && res.a1 && res.a2)
- lmb_reserve(res.a1, res.a2, LMB_NOMAP);
+ lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &addr, res.a2,
+ LMB_NOMAP);
#if IS_ENABLED(CONFIG_CMD_PSTORE)
char cmd[64];
diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c
index 7908f75809c..3eb93c82387 100644
--- a/arch/arm/mach-mvebu/armada8k/cpu.c
+++ b/arch/arm/mach-mvebu/armada8k/cpu.c
@@ -109,5 +109,5 @@ int mmc_get_env_dev(void)
return 1;
}
- return CONFIG_SYS_MMC_ENV_DEV;
+ return CONFIG_ENV_MMC_DEVICE_INDEX;
}
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index d3ed870b169..342933ca509 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -362,7 +362,7 @@ config ROCKCHIP_RK3528
imply SPL_REGMAP
imply SPL_SERIAL
imply SPL_SYSCON
- imply SYS_RELOC_GD_ENV_ADDR
+ imply ENV_RELOC_GD_ENV_ADDR
imply SYSRESET
imply SYSRESET_PSCI if SPL_ATF
help
@@ -446,7 +446,7 @@ config ROCKCHIP_RK3576
imply SPL_REGMAP
imply SPL_SERIAL
imply SPL_SYSCON
- imply SYS_RELOC_GD_ENV_ADDR
+ imply ENV_RELOC_GD_ENV_ADDR
imply SYSRESET
help
The Rockchip RK3576 is a ARM-based SoC with quad-core Cortex-A72 and
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
index 75d6693e28a..2e6bb38b923 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/board.c
@@ -512,8 +512,8 @@ int mmc_get_env_dev(void)
const char *boot_device;
struct udevice *dev;
-#ifdef CONFIG_SYS_MMC_ENV_DEV
- devnum = CONFIG_SYS_MMC_ENV_DEV;
+#ifdef CONFIG_ENV_MMC_DEVICE_INDEX
+ devnum = CONFIG_ENV_MMC_DEVICE_INDEX;
#else
devnum = 0;
#endif
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index 5547d6d054f..ec51ebbbe7f 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -37,6 +37,8 @@
DECLARE_GLOBAL_DATA_PTR;
+enum qcom_boot_source qcom_boot_source __section(".data") = 0;
+
static struct mm_region rbx_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { { 0 } };
struct mm_region *mem_map = rbx_mem_map;
@@ -238,6 +240,12 @@ int board_fdt_blob_setup(void **fdtp)
if (ret < 0)
panic("No valid memory ranges found!\n");
+ /* If we have an external FDT, it can only have come from the Android bootloader. */
+ if (external_valid)
+ qcom_boot_source = QCOM_BOOT_SOURCE_ANDROID;
+ else
+ qcom_boot_source = QCOM_BOOT_SOURCE_XBL;
+
debug("ram_base = %#011lx, ram_size = %#011llx\n",
gd->ram_base, gd->ram_size);
@@ -481,6 +489,23 @@ static void configure_env(void)
qcom_set_serialno();
}
+void qcom_show_boot_source(void)
+{
+ const char *name = "UNKNOWN";
+
+ switch (qcom_boot_source) {
+ case QCOM_BOOT_SOURCE_ANDROID:
+ name = "ABL";
+ break;
+ case QCOM_BOOT_SOURCE_XBL:
+ name = "XBL";
+ break;
+ }
+
+ log_info("U-Boot loaded from %s\n", name);
+ env_set("boot_source", name);
+}
+
void __weak qcom_late_init(void)
{
}
@@ -492,38 +517,56 @@ void __weak qcom_late_init(void)
#define FASTBOOT_BUF_SIZE 0
#endif
-#define addr_alloc(size) lmb_alloc(size, SZ_2M)
+#define lmb_alloc(size, addr) lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
/* Stolen from arch/arm/mach-apple/board.c */
int board_late_init(void)
{
- u32 status = 0;
+ u32 status = 0, fdt_status = 0;
phys_addr_t addr;
struct fdt_header *fdt_blob = (struct fdt_header *)gd->fdt_blob;
/* We need to be fairly conservative here as we support boards with just 1G of TOTAL RAM */
- addr = addr_alloc(SZ_128M);
+ status |= !lmb_alloc(SZ_128M, &addr) ?
+ env_set_hex("loadaddr", addr) : 1;
status |= env_set_hex("kernel_addr_r", addr);
- status |= env_set_hex("loadaddr", addr);
- status |= env_set_hex("ramdisk_addr_r", addr_alloc(SZ_128M));
- status |= env_set_hex("kernel_comp_addr_r", addr_alloc(KERNEL_COMP_SIZE));
- status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
- if (IS_ENABLED(CONFIG_FASTBOOT))
- status |= env_set_hex("fastboot_addr_r", addr_alloc(FASTBOOT_BUF_SIZE));
- status |= env_set_hex("scriptaddr", addr_alloc(SZ_4M));
- status |= env_set_hex("pxefile_addr_r", addr_alloc(SZ_4M));
- addr = addr_alloc(SZ_2M);
- status |= env_set_hex("fdt_addr_r", addr);
-
- if (status)
+ status |= !lmb_alloc(SZ_128M, &addr) ?
+ env_set_hex("ramdisk_addr_r", addr) : 1;
+ status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+ env_set_hex("kernel_comp_addr_r", addr) : 1;
+ status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+ env_set_hex("kernel_comp_size", addr) : 1;
+ status |= !lmb_alloc(SZ_4M, &addr) ?
+ env_set_hex("scriptaddr", addr) : 1;
+ status |= !lmb_alloc(SZ_4M, &addr) ?
+ env_set_hex("pxefile_addr_r", addr) : 1;
+
+ if (IS_ENABLED(CONFIG_FASTBOOT)) {
+ status |= !lmb_alloc(FASTBOOT_BUF_SIZE, &addr) ?
+ env_set_hex("fastboot_addr_r", addr) : 1;
+ /* override loadaddr for memory rich soc */
+ status |= !lmb_alloc(SZ_128M, &addr) ?
+ env_set_hex("loadaddr", addr) : 1;
+ }
+
+ fdt_status |= !lmb_alloc(SZ_2M, &addr) ?
+ env_set_hex("fdt_addr_r", addr) : 1;
+
+ if (status || fdt_status)
log_warning("%s: Failed to set run time variables\n", __func__);
/* By default copy U-Boots FDT, it will be used as a fallback */
- memcpy((void *)addr, (void *)gd->fdt_blob, fdt32_to_cpu(fdt_blob->totalsize));
+ if (fdt_status)
+ log_warning("%s: Failed to reserve memory for copying FDT\n",
+ __func__);
+ else
+ memcpy((void *)addr, (void *)gd->fdt_blob,
+ fdt32_to_cpu(fdt_blob->totalsize));
configure_env();
qcom_late_init();
+ qcom_show_boot_source();
/* Configure the dfu_string for capsule updates */
qcom_configure_capsule_updates();
diff --git a/arch/arm/mach-snapdragon/capsule_update.c b/arch/arm/mach-snapdragon/capsule_update.c
index bf75a9a1b24..4dced4961b6 100644
--- a/arch/arm/mach-snapdragon/capsule_update.c
+++ b/arch/arm/mach-snapdragon/capsule_update.c
@@ -20,22 +20,19 @@
#include "qcom-priv.h"
/*
- * NOTE: for now this implementation only supports the rb3gen2. Supporting other
- * boards that boot in different ways (e.g. chainloaded from ABL) will require
- * additional complexity to properly create the dfu string and fw_images array.
- */
-
-/*
- * To handle different variants like chainloaded U-Boot here we'll need to
- * build the fw_images array dynamically at runtime. It looks like
- * mach-rockchip is a good example for how to do this.
- * Detecting which image types a board uses is TBD, hence for now we only
- * support the one new board that runs U-Boot as its primary bootloader.
+ * To handle different variants like chainloaded U-Boot here we need to
+ * build the fw_images array dynamically at runtime. These are the possible
+ * implementations:
+ *
+ * - Devices with U-Boot on the uefi_a/b partition
+ * - Devices with U-Boot on the boot (a/b) partition
+ * - Devices with U-Boot on the xbl (a/b) partition
+ *
+ * Which partition actually has U-Boot on it is determined based on the
+ * qcom_boot_source variable and additional logic in find_target_partition().
*/
struct efi_fw_image fw_images[] = {
{
- /* U-Boot flashed to the uefi_X partition (e.g. rb3gen2) */
- .fw_name = u"UBOOT_UEFI_PARTITION",
.image_index = 1,
},
};
@@ -47,6 +44,12 @@ struct efi_capsule_update_info update_info = {
.images = fw_images,
};
+enum target_part_type {
+ TARGET_PART_UEFI = 1,
+ TARGET_PART_XBL,
+ TARGET_PART_BOOT,
+};
+
/* LSB first */
struct part_slot_status {
u16: 2;
@@ -57,35 +60,202 @@ struct part_slot_status {
u16 tries_remaining : 4;
};
-static int find_boot_partition(const char *partname, struct blk_desc *blk_dev, char *name)
+enum ab_slot {
+ SLOT_NONE,
+ SLOT_A,
+ SLOT_B,
+};
+
+static enum ab_slot get_part_slot(const char *partname)
+{
+ int len = strlen(partname);
+
+ if (partname[len - 2] != '_')
+ return SLOT_NONE;
+ if (partname[len - 1] == 'a')
+ return SLOT_A;
+ if (partname[len - 1] == 'b')
+ return SLOT_B;
+
+ return SLOT_NONE;
+}
+
+/*
+ * Determine which partition U-Boot is flashed to based on the boot source (ABL/XBL),
+ * the slot status, and prioritizing the uefi partition over xbl if found.
+ */
+static int find_target_partition(int *devnum, enum uclass_id *uclass,
+ enum target_part_type *target_part_type)
{
int ret;
- int partnum;
+ int partnum, uefi_partnum = -1, xbl_partnum = -1;
struct disk_partition info;
struct part_slot_status *slot_status;
+ struct udevice *dev = NULL;
+ struct blk_desc *desc = NULL, *xbl_desc = NULL;
+ uchar ptn_name[32] = { 0 };
+ bool have_ufs = false;
+
+ /*
+ * Check to see if we have UFS storage, if so U-Boot MUST be on it and we can skip
+ * all non-UFS block devices
+ */
+ uclass_foreach_dev_probe(UCLASS_UFS, dev) {
+ have_ufs = true;
+ break;
+ }
- for (partnum = 1;; partnum++) {
- ret = part_get_info(blk_dev, partnum, &info);
- if (ret)
- return ret;
+ uclass_foreach_dev_probe(UCLASS_BLK, dev) {
+ if (device_get_uclass_id(dev) != UCLASS_BLK)
+ continue;
- slot_status = (struct part_slot_status *)&info.type_flags;
- log_io("%16s: Active: %1d, Successful: %1d, Unbootable: %1d, Tries left: %1d\n",
- info.name, slot_status->active,
- slot_status->successful, slot_status->unbootable,
- slot_status->tries_remaining);
+ /* If we have a UFS then don't look at any other block devices */
+ if (have_ufs) {
+ if (device_get_uclass_id(dev->parent->parent) != UCLASS_UFS)
+ continue;
/*
- * FIXME: eventually we'll want to find the active/inactive variant of the partition
- * but on the rb3gen2 these values might all be 0
+ * If we don't have UFS, then U-Boot must be on the eMMC which is always the first
+ * MMC device.
*/
- if (!strncmp(info.name, partname, strlen(partname))) {
- log_debug("Found active %s partition: '%s'!\n", partname, info.name);
- strlcpy(name, info.name, sizeof(info.name));
- return partnum;
+ } else if (dev->parent->seq_ > 0) {
+ continue;
}
+
+ desc = dev_get_uclass_plat(dev);
+ if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
+ continue;
+ for (partnum = 1;; partnum++) {
+ ret = part_get_info(desc, partnum, &info);
+ if (ret)
+ break;
+
+ slot_status = (struct part_slot_status *)&info.type_flags;
+
+ /*
+ * Qualcomm Linux devices have a "uefi" partition, it's A/B but the
+ * flags might not be set so we assume the A partition unless the B
+ * partition is active.
+ */
+ if (!strncmp(info.name, "uefi", strlen("uefi"))) {
+ /*
+ * If U-Boot was chainloaded somehow we can't be flashed to
+ * the uefi partition
+ */
+ if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
+ continue;
+
+ *target_part_type = TARGET_PART_UEFI;
+ /*
+ * Found an active UEFI partition, this is where U-Boot is
+ * flashed.
+ */
+ if (slot_status->active)
+ goto found;
+
+ /* Prefer A slot if it's not marked active */
+ if (get_part_slot(info.name) == SLOT_A) {
+ /*
+ * If we found the A slot after the B slot (both
+ * inactive) then we assume U-Boot is on the A slot.
+ */
+ if (uefi_partnum >= 0)
+ goto found;
+
+ /* Didn't find the B slot yet */
+ uefi_partnum = partnum;
+ strlcpy(ptn_name, info.name, 32);
+ } else {
+ /*
+ * Found inactive B slot after inactive A slot, return
+ * the A slot
+ */
+ if (uefi_partnum >= 0) {
+ partnum = uefi_partnum;
+ goto found;
+ }
+
+ /*
+ * Didn't find the A slot yet. Record that we found the
+ * B slot
+ */
+ uefi_partnum = partnum;
+ strlcpy(ptn_name, info.name, 32);
+ }
+ /* xbl and aboot are effectively the same */
+ } else if ((!strncmp(info.name, "xbl", strlen("xbl")) &&
+ strlen(info.name) == 5) ||
+ !strncmp(info.name, "aboot", strlen("aboot"))) {
+ /*
+ * If U-Boot was booted via ABL, we can't be flashed to the
+ * XBL partition
+ */
+ if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
+ continue;
+
+ /*
+ * ignore xbl partition if we have uefi partitions, U-Boot will
+ * always be on the UEFI partition in this case.
+ */
+ if (*target_part_type == TARGET_PART_UEFI)
+ continue;
+
+ /* Either non-A/B or find the active XBL partition */
+ if (slot_status->active || !get_part_slot(info.name)) {
+ /*
+ * No quick return since we might find a uefi partition
+ * later
+ */
+ xbl_partnum = partnum;
+ *target_part_type = TARGET_PART_XBL;
+ xbl_desc = desc;
+ strlcpy(ptn_name, info.name, 32);
+ }
+
+ /*
+ * No fast return since we might also have a uefi partition which
+ * will take priority.
+ */
+ } else if (!strncmp(info.name, "boot", strlen("boot"))) {
+ /* We can only be flashed to boot if we were chainloaded */
+ if (qcom_boot_source != QCOM_BOOT_SOURCE_ANDROID)
+ continue;
+
+ /*
+ * Either non-A/B or find the active partition. We can return
+ * immediately here since we've narrowed it down to a single option
+ */
+ if (slot_status->active || !get_part_slot(info.name)) {
+ *target_part_type = TARGET_PART_BOOT;
+ goto found;
+ }
+ }
+ }
+ }
+
+ /*
+ * Now we've exhausted all options, if we didn't find a uefi partition
+ * then we are indeed flashed to the xbl partition.
+ */
+ if (*target_part_type == TARGET_PART_XBL) {
+ partnum = xbl_partnum;
+ desc = xbl_desc;
+ goto found;
}
+ /* Found no candidate partitions */
return -1;
+
+found:
+ if (desc) {
+ *devnum = desc->devnum;
+ *uclass = desc->uclass_id;
+ }
+
+ /* info won't match for XBL hence the copy. */
+ log_info("Capsule update target: %s (disk %d:%d)\n",
+ *target_part_type == TARGET_PART_BOOT ? info.name : ptn_name,
+ *devnum, partnum);
+ return partnum;
}
/**
@@ -101,12 +271,10 @@ static int find_boot_partition(const char *partname, struct blk_desc *blk_dev, c
*/
void qcom_configure_capsule_updates(void)
{
- struct blk_desc *desc;
int ret = 0, partnum = -1, devnum;
static char dfu_string[32] = { 0 };
- char name[32]; /* GPT partition name */
- char *partname = "uefi_a";
- struct udevice *dev = NULL;
+ enum target_part_type target_part_type = 0;
+ enum uclass_id dev_uclass;
if (IS_ENABLED(CONFIG_SCSI)) {
/* Scan for SCSI devices */
@@ -117,26 +285,30 @@ void qcom_configure_capsule_updates(void)
}
}
- uclass_foreach_dev_probe(UCLASS_BLK, dev) {
- if (device_get_uclass_id(dev) != UCLASS_BLK)
- continue;
-
- desc = dev_get_uclass_plat(dev);
- if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
- continue;
- devnum = desc->devnum;
- partnum = find_boot_partition(partname, desc,
- name);
- if (partnum >= 0)
- break;
- }
-
+ partnum = find_target_partition(&devnum, &dev_uclass, &target_part_type);
if (partnum < 0) {
log_err("Failed to find boot partition\n");
return;
}
- switch (desc->uclass_id) {
+ /*
+ * Set the fw_name based on the partition type. This causes the GUID to be different
+ * so we will never accidentally flash a U-Boot image intended for XBL to the boot
+ * partition.
+ */
+ switch (target_part_type) {
+ case TARGET_PART_UEFI:
+ fw_images[0].fw_name = u"UBOOT_UEFI_PARTITION";
+ break;
+ case TARGET_PART_XBL:
+ fw_images[0].fw_name = u"UBOOT_XBL_PARTITION";
+ break;
+ case TARGET_PART_BOOT:
+ fw_images[0].fw_name = u"UBOOT_BOOT_PARTITION";
+ break;
+ }
+
+ switch (dev_uclass) {
case UCLASS_SCSI:
snprintf(dfu_string, 32, "scsi %d=u-boot.bin part %d", devnum, partnum);
break;
@@ -144,10 +316,10 @@ void qcom_configure_capsule_updates(void)
snprintf(dfu_string, 32, "mmc 0=u-boot.bin part %d %d", devnum, partnum);
break;
default:
- debug("Unsupported storage uclass: %d\n", desc->uclass_id);
+ debug("Unsupported storage uclass: %d\n", dev_uclass);
return;
}
- log_debug("boot partition is %s, DFU string: '%s'\n", name, dfu_string);
+ log_debug("DFU string: '%s'\n", dfu_string);
update_info.dfu_string = dfu_string;
}
diff --git a/arch/arm/mach-snapdragon/of_fixup.c b/arch/arm/mach-snapdragon/of_fixup.c
index b398c6b7b9f..328c7812f30 100644
--- a/arch/arm/mach-snapdragon/of_fixup.c
+++ b/arch/arm/mach-snapdragon/of_fixup.c
@@ -99,19 +99,6 @@ static int fixup_qcom_dwc3(struct device_node *root, struct device_node *glue_np
return ret;
}
- /*
- * The RB1/2 boards only have a single USB controller and it's muxed between the type-C port
- * and a USB hub. Since we can't do OTG in U-Boot properly we prefer to put it into host mode.
- */
- if (of_device_is_compatible(root, "qcom,qrb4210-rb2", NULL, NULL) ||
- of_device_is_compatible(root, "qcom,qrb2210-rb1", NULL, NULL)) {
- ret = of_write_prop(dwc3, "dr_mode", sizeof("host"), "host");
- if (ret) {
- log_err("Failed to set 'dr_mode' property: %d\n", ret);
- return ret;
- }
- }
-
return 0;
}
diff --git a/arch/arm/mach-snapdragon/qcom-priv.h b/arch/arm/mach-snapdragon/qcom-priv.h
index 4f398e2ba37..b8bf574e8bb 100644
--- a/arch/arm/mach-snapdragon/qcom-priv.h
+++ b/arch/arm/mach-snapdragon/qcom-priv.h
@@ -3,6 +3,20 @@
#ifndef __QCOM_PRIV_H__
#define __QCOM_PRIV_H__
+/**
+ * enum qcom_boot_source - Track where we got loaded from.
+ * Used for capsule update logic.
+ *
+ * @QCOM_BOOT_SOURCE_ANDROID: chainloaded (typically from ABL)
+ * @QCOM_BOOT_SOURCE_XBL: flashed to the XBL or UEFI partition
+ */
+enum qcom_boot_source {
+ QCOM_BOOT_SOURCE_ANDROID = 1,
+ QCOM_BOOT_SOURCE_XBL,
+};
+
+extern enum qcom_boot_source qcom_boot_source;
+
#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
void qcom_configure_capsule_updates(void);
#else
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 17179593913..0a7c029b15a 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -51,7 +51,13 @@ config DRAM_SUN50I_H616
Select this dram controller driver for some sun50i platforms,
like H616.
-if DRAM_SUN50I_H616
+config DRAM_SUN50I_A133
+ bool
+ help
+ Select this dram controller driver for some sun50i platforms,
+ like A133.
+
+if DRAM_SUN50I_H616 || DRAM_SUN50I_A133
config DRAM_SUNXI_DX_ODT
hex "DRAM DX ODT parameter"
help
@@ -73,18 +79,64 @@ config DRAM_SUNXI_ODT_EN
help
ODT EN value from vendor DRAM settings.
+config DRAM_SUNXI_PARA0
+ hex "DRAM PARA0 parameter"
+ depends on DRAM_SUN50I_A133
+ help
+ PARA0 value from vendor DRAM settings.
+
+config DRAM_SUNXI_MR11
+ hex "DRAM MR11 parameter"
+ depends on DRAM_SUN50I_A133
+ default 0x0
+ help
+ MR11 value from vendor DRAM settings.
+
+config DRAM_SUNXI_MR12
+ hex "DRAM MR12 parameter"
+ depends on DRAM_SUN50I_A133
+ default 0x0
+ help
+ MR12 value from vendor DRAM settings.
+
+config DRAM_SUNXI_MR13
+ hex "DRAM MR13 parameter"
+ depends on DRAM_SUN50I_A133
+ default 0x0
+ help
+ MR13 value from vendor DRAM settings.
+
+config DRAM_SUNXI_MR14
+ hex "DRAM MR14 parameter"
+ depends on DRAM_SUN50I_A133
+ default 0x0
+ help
+ MR14 value from vendor DRAM settings.
+
config DRAM_SUNXI_TPR0
hex "DRAM TPR0 parameter"
default 0x0
help
TPR0 value from vendor DRAM settings.
+config DRAM_SUNXI_TPR1
+ hex "DRAM TPR1 parameter"
+ default 0x0
+ help
+ TPR1 value from vendor DRAM settings.
+
config DRAM_SUNXI_TPR2
hex "DRAM TPR2 parameter"
default 0x0
help
TPR2 value from vendor DRAM settings.
+config DRAM_SUNXI_TPR3
+ hex "DRAM TPR3 parameter"
+ default 0x0
+ help
+ TPR3 value from vendor DRAM settings.
+
config DRAM_SUNXI_TPR6
hex "DRAM TPR6 parameter"
default 0x3300c080
@@ -109,6 +161,20 @@ config DRAM_SUNXI_TPR12
help
TPR12 value from vendor DRAM settings.
+config DRAM_SUNXI_TPR13
+ hex "DRAM TPR13 parameter"
+ depends on DRAM_SUN50I_A133
+ default 0x0
+ help
+ TPR13 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR14
+ hex "DRAM TPR14 parameter"
+ depends on DRAM_SUN50I_A133
+ default 0x0
+ help
+ TPR14 value from vendor DRAM settings.
+
choice
prompt "DRAM PHY pin mapping selection"
default DRAM_SUNXI_PHY_ADDR_MAP_0
@@ -116,7 +182,8 @@ choice
config DRAM_SUNXI_PHY_ADDR_MAP_0
bool "DRAM PHY address map 0"
help
- This pin mapping selection should be used by the H313, H616, H618.
+ This pin mapping selection should be used by the H313, H616, H618,
+ and A133, R818 SoCs.
config DRAM_SUNXI_PHY_ADDR_MAP_1
bool "DRAM PHY address map 1"
@@ -153,6 +220,7 @@ config SUNXI_SRAM_ADDRESS
config SUNXI_RVBAR_ADDRESS
hex
depends on ARM64
+ default 0x08100040 if MACH_SUN50I_A133
default 0x09010040 if SUN50I_GEN_H6
default 0x017000a0
---help---
@@ -179,8 +247,8 @@ config SUNXI_RVBAR_ALTERNATIVE
config SUNXI_BL31_BASE
hex
default 0x00044000 if MACH_SUN50I || MACH_SUN50I_H5
- default 0x00104000 if MACH_SUN50I_H6
default 0x40000000 if MACH_SUN50I_H616
+ default 0x00104000 if SUN50I_GEN_H6
default 0x0
help
Address where BL31 (TF-A) is loaded, or zero if BL31 is not used.
@@ -262,7 +330,7 @@ config MACH_SUNXI_H3_H5
# TODO: try out A80's 8GiB DRAM space
config SUNXI_DRAM_MAX_SIZE
hex
- default 0x100000000 if MACH_SUN50I_H616
+ default 0x100000000 if MACH_SUN50I_H616 || MACH_SUN50I_A133
default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6
default 0x80000000
@@ -459,6 +527,10 @@ config MACH_SUN50I_H616
config MACH_SUN50I_A133
bool "sun50i (Allwinner A133)"
+ select ARM64
+ select DRAM_SUN50I_A133
+ select SUN50I_GEN_H6
+ imply OF_UPSTREAM
endchoice
@@ -497,7 +569,7 @@ config ARM_BOOT_HOOK_RMR
This allows both the SPL and the U-Boot proper to be entered in
either mode and switch to AArch64 if needed.
-if SUNXI_DRAM_DW || DRAM_SUN50I_H6 || DRAM_SUN50I_H616
+if SUNXI_DRAM_DW || DRAM_SUN50I_H6 || DRAM_SUN50I_H616 || DRAM_SUN50I_A133
config SUNXI_DRAM_DDR3
bool
@@ -510,6 +582,9 @@ config SUNXI_DRAM_LPDDR3
config SUNXI_DRAM_LPDDR4
bool
+config SUNXI_DRAM_DDR4
+ bool
+
choice
prompt "DRAM Type and Timing"
default SUNXI_DRAM_DDR3_1333 if !MACH_SUN8I_V3S
@@ -518,6 +593,7 @@ choice
config SUNXI_DRAM_DDR3_1333
bool "DDR3 1333"
select SUNXI_DRAM_DDR3
+ depends on !DRAM_SUN50I_A133
---help---
This option is the original only supported memory type, which suits
many H3/H5/A64 boards available now.
@@ -525,6 +601,7 @@ config SUNXI_DRAM_DDR3_1333
config SUNXI_DRAM_LPDDR3_STOCK
bool "LPDDR3 with Allwinner stock configuration"
select SUNXI_DRAM_LPDDR3
+ depends on !DRAM_SUN50I_A133
---help---
This option is the LPDDR3 timing used by the stock boot0 by
Allwinner.
@@ -548,7 +625,7 @@ config SUNXI_DRAM_H6_DDR3_1333
config SUNXI_DRAM_H616_LPDDR3
bool "LPDDR3 DRAM chips on the H616 DRAM controller"
select SUNXI_DRAM_LPDDR3
- depends on DRAM_SUN50I_H616
+ depends on DRAM_SUN50I_H616 || DRAM_SUN50I_A133
help
This option is the LPDDR3 timing used by the stock boot0 by
Allwinner.
@@ -556,7 +633,7 @@ config SUNXI_DRAM_H616_LPDDR3
config SUNXI_DRAM_H616_LPDDR4
bool "LPDDR4 DRAM chips on the H616 DRAM controller"
select SUNXI_DRAM_LPDDR4
- depends on DRAM_SUN50I_H616
+ depends on DRAM_SUN50I_H616 || DRAM_SUN50I_A133
help
This option is the LPDDR4 timing used by the stock boot0 by
Allwinner.
@@ -564,11 +641,27 @@ config SUNXI_DRAM_H616_LPDDR4
config SUNXI_DRAM_H616_DDR3_1333
bool "DDR3-1333 boot0 timings on the H616 DRAM controller"
select SUNXI_DRAM_DDR3
- depends on DRAM_SUN50I_H616
+ depends on DRAM_SUN50I_H616 || DRAM_SUN50I_A133
help
This option is the DDR3 timing used by the boot0 on H616 TV boxes
which use a DDR3-1333 timing.
+config SUNXI_DRAM_A133_DDR4
+ bool "DDR4 boot0 timings on the A133 DRAM controller"
+ select SUNXI_DRAM_DDR4
+ depends on DRAM_SUN50I_A133
+ help
+ This option is the DDR4 timing used by the boot0 on A133 devices
+ which use a DDR4 timing.
+
+config SUNXI_DRAM_A133_LPDDR4
+ bool "LPDDR4 boot0 timings on the A133 DRAM controller"
+ select SUNXI_DRAM_LPDDR4
+ depends on DRAM_SUN50I_A133
+ help
+ This option is the LPDDR4 timing used by the boot0 on A133 devices
+ which use an LPDDR4 timing.
+
config SUNXI_DRAM_DDR2_V3S
bool "DDR2 found in V3s chip"
select SUNXI_DRAM_DDR2
@@ -596,7 +689,7 @@ config DRAM_CLK
MACH_SUN8I_V3S
default 672 if MACH_SUN50I
default 744 if MACH_SUN50I_H6
- default 720 if MACH_SUN50I_H616
+ default 720 if MACH_SUN50I_H616 || MACH_SUN50I_A133
---help---
Set the dram clock speed, valid range 240 - 480 (prior to sun9i),
must be a multiple of 24. For the sun9i (A80), the tested values
@@ -613,7 +706,7 @@ endif
config DRAM_ZQ
int "sunxi dram zq value"
- depends on !MACH_SUN50I_H616
+ depends on !MACH_SUN50I_H616 && !MACH_SUN50I_A133
default 123 if MACH_SUN4I || MACH_SUN5I || MACH_SUN6I || \
MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_A83T
default 127 if MACH_SUN7I
@@ -733,6 +826,7 @@ config SYS_CONFIG_NAME
default "sun50i" if MACH_SUN50I
default "sun50i" if MACH_SUN50I_H6
default "sun50i" if MACH_SUN50I_H616
+ default "sun50i" if MACH_SUN50I_A133
config SYS_BOARD
default "sunxi"
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index a33cd5b0f07..8eff20b77bf 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -45,4 +45,6 @@ obj-$(CONFIG_DRAM_SUN50I_H6) += dram_sun50i_h6.o dram_dw_helpers.o
obj-$(CONFIG_DRAM_SUN50I_H6) += dram_timings/
obj-$(CONFIG_DRAM_SUN50I_H616) += dram_sun50i_h616.o dram_dw_helpers.o
obj-$(CONFIG_DRAM_SUN50I_H616) += dram_timings/
+obj-$(CONFIG_DRAM_SUN50I_A133) += dram_sun50i_a133.o
+obj-$(CONFIG_DRAM_SUN50I_A133) += dram_timings/
endif
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index b1bf51f40c5..08d55b3a0e3 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -137,6 +137,10 @@ static int gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H616_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H616_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN50I_A133)
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN50I_H616_GPH_UART0);
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(10), SUN50I_H616_GPH_UART0);
+ sunxi_gpio_set_pull(SUNXI_GPB(10), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_A83T)
sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_A83T_GPB_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPB(10), SUN8I_A83T_GPB_UART0);
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index 4c522f60810..3f375a51965 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -87,7 +87,8 @@ void clock_set_pll1(unsigned int clk)
/* clk = 24*n/p, p is ignored if clock is >288MHz */
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))
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
+ IS_ENABLED(CONFIG_MACH_SUN50I_A133))
val |= CCM_PLL1_OUT_EN;
if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
val |= CCM_PLL1_OUT_EN | CCM_PLL1_LDO_EN;
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index 310dca06e57..3f4735d4717 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -104,6 +104,8 @@ int print_cpuinfo(void)
puts("CPU: Allwinner H6 (SUN50I)\n");
#elif defined CONFIG_MACH_SUN50I_H616
puts("CPU: Allwinner H616 (SUN50I)\n");
+#elif defined CONFIG_MACH_SUN50I_A133
+ puts("CPU: Allwinner A133 (SUN50I)\n");
#else
#warning Please update cpu_info.c with correct CPU information
puts("CPU: SUNXI Family\n");
diff --git a/arch/arm/mach-sunxi/dram_sun50i_a133.c b/arch/arm/mach-sunxi/dram_sun50i_a133.c
new file mode 100644
index 00000000000..a0fca3738f4
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_sun50i_a133.c
@@ -0,0 +1,1204 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * sun50i A133 platform dram controller driver
+ *
+ * Controller and PHY appear to be quite similar to that of the H616;
+ * however certain offsets, timings, and other details are different enough that
+ * the original code does not work as expected. Some device flags and
+ * calibrations are not yet implemented, and configuration aside from DDR4
+ * have not been tested.
+ *
+ * (C) Copyright 2024 MasterR3C0RD <masterr3c0rd@epochal.quest>
+ *
+ * Uses code from H616 driver, which is
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ */
+
+//#define DEBUG
+
+#include <asm/arch/clock.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/prcm.h>
+#include <asm/io.h>
+#include <init.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <log.h>
+
+#ifdef CONFIG_DRAM_SUNXI_PHY_ADDR_MAP_1
+static const u8 phy_init[] = {
+#ifdef CONFIG_SUNXI_DRAM_DDR3
+ 0x0c, 0x08, 0x19, 0x18, 0x10, 0x06, 0x0a, 0x03, 0x0e,
+ 0x00, 0x0b, 0x05, 0x09, 0x1a, 0x04, 0x13, 0x16, 0x11,
+ 0x01, 0x15, 0x0d, 0x07, 0x12, 0x17, 0x14, 0x02, 0x0f
+#elif CONFIG_SUNXI_DRAM_DDR4
+ 0x19, 0x1a, 0x04, 0x12, 0x09, 0x06, 0x08, 0x0a, 0x16,
+ 0x17, 0x18, 0x0f, 0x0c, 0x13, 0x02, 0x05, 0x01, 0x11,
+ 0x0e, 0x00, 0x0b, 0x07, 0x03, 0x14, 0x15, 0x0d, 0x10
+#elif CONFIG_SUNXI_DRAM_LPDDR3
+ 0x08, 0x03, 0x02, 0x00, 0x18, 0x19, 0x09, 0x01, 0x06,
+ 0x17, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x05, 0x07, 0x1a
+#elif CONFIG_SUNXI_DRAM_LPDDR4
+ 0x01, 0x05, 0x02, 0x00, 0x19, 0x03, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x04, 0x1a
+#endif
+};
+#else
+static const u8 phy_init[] = {
+#ifdef CONFIG_SUNXI_DRAM_DDR3
+ 0x03, 0x19, 0x18, 0x02, 0x10, 0x15, 0x16, 0x07, 0x06,
+ 0x0e, 0x05, 0x08, 0x0d, 0x04, 0x17, 0x1a, 0x13, 0x11,
+ 0x12, 0x14, 0x00, 0x01, 0x0c, 0x0a, 0x09, 0x0b, 0x0f
+#elif CONFIG_SUNXI_DRAM_DDR4
+ 0x13, 0x17, 0x0e, 0x01, 0x06, 0x12, 0x14, 0x07, 0x09,
+ 0x02, 0x0f, 0x00, 0x0d, 0x05, 0x16, 0x0c, 0x0a, 0x11,
+ 0x04, 0x03, 0x18, 0x15, 0x08, 0x10, 0x0b, 0x19, 0x1a
+#elif CONFIG_SUNXI_DRAM_LPDDR3
+ 0x05, 0x06, 0x17, 0x02, 0x19, 0x18, 0x04, 0x07, 0x03,
+ 0x01, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x08, 0x09, 0x00, 0x1a
+#elif CONFIG_SUNXI_DRAM_LPDDR4
+ 0x01, 0x03, 0x02, 0x19, 0x17, 0x00, 0x06, 0x07, 0x08,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
+ 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x18, 0x05, 0x1a
+#endif
+};
+#endif
+
+static void mctl_clk_init(u32 clk)
+{
+ void * const ccm = (void *)SUNXI_CCM_BASE;
+
+ /* Place all DRAM blocks into reset */
+ clrbits_le32(ccm + CCU_H6_MBUS_CFG, MBUS_ENABLE);
+ clrbits_le32(ccm + CCU_H6_MBUS_CFG, MBUS_RESET);
+ clrbits_le32(ccm + CCU_H6_DRAM_GATE_RESET, BIT(GATE_SHIFT));
+ clrbits_le32(ccm + CCU_H6_DRAM_GATE_RESET, BIT(RESET_SHIFT));
+ clrbits_le32(ccm + CCU_H6_PLL5_CFG, CCM_PLL5_CTRL_EN);
+ clrbits_le32(ccm + CCU_H6_DRAM_CLK_CFG, DRAM_MOD_RESET);
+ udelay(5);
+
+ /* Set up PLL5 clock, used for DRAM */
+ clrsetbits_le32(ccm + CCU_H6_PLL5_CFG, 0xff03,
+ CCM_PLL5_CTRL_N((clk * 2) / 24) | CCM_PLL5_CTRL_EN);
+ setbits_le32(ccm + CCU_H6_PLL5_CFG, BIT(24));
+ clrsetbits_le32(ccm + CCU_H6_PLL5_CFG, 0x3,
+ CCM_PLL5_LOCK_EN | CCM_PLL5_CTRL_EN | BIT(30));
+ clrbits_le32(ccm + CCU_H6_PLL5_CFG, 0x3 | BIT(30));
+ mctl_await_completion(ccm + CCU_H6_PLL5_CFG,
+ CCM_PLL5_LOCK, CCM_PLL5_LOCK);
+
+ /* Enable DRAM clock and gate*/
+ clrbits_le32(ccm + CCU_H6_DRAM_CLK_CFG, BIT(24) | BIT(25));
+ clrsetbits_le32(ccm + CCU_H6_DRAM_CLK_CFG, 0x1f, BIT(1) | BIT(0));
+ setbits_le32(ccm + CCU_H6_DRAM_CLK_CFG, DRAM_CLK_UPDATE);
+ setbits_le32(ccm + CCU_H6_DRAM_GATE_RESET, BIT(RESET_SHIFT));
+ setbits_le32(ccm + CCU_H6_DRAM_GATE_RESET, BIT(GATE_SHIFT));
+
+ /* Re-enable MBUS and reset the DRAM module */
+ setbits_le32(ccm + CCU_H6_MBUS_CFG, MBUS_RESET);
+ setbits_le32(ccm + CCU_H6_MBUS_CFG, MBUS_ENABLE);
+ setbits_le32(ccm + CCU_H6_DRAM_CLK_CFG, DRAM_MOD_RESET);
+ udelay(5);
+}
+
+static void mctl_set_odtmap(const struct dram_para *para,
+ const struct dram_config *config)
+{
+ struct sunxi_mctl_ctl_reg *mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ u32 val, temp1, temp2;
+
+ /* Set ODT/rank mappings*/
+ if (config->bus_full_width)
+ writel_relaxed(0x0201, &mctl_ctl->odtmap);
+ else
+ writel_relaxed(0x0303, &mctl_ctl->odtmap);
+
+ switch (para->type) {
+ case SUNXI_DRAM_TYPE_DDR3:
+ val = 0x06000400;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ /* TODO: What's the purpose of these values? */
+ temp1 = para->clk * 7 / 2000;
+ if (para->clk < 400)
+ temp2 = 0x3;
+ else
+ temp2 = 0x4;
+
+ val = 0x400 | (temp2 - temp1) << 16 | temp1 << 24;
+ break;
+ case SUNXI_DRAM_TYPE_DDR4:
+ /* MR4: CS to CMD / ADDR Latency and write preamble */
+ val = 0x400 | (0x000 << 10 & 0x70000) |
+ (((0x0000 >> 12) & 1) + 6) << 24;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR4:
+ val = 0x4000400;
+ break;
+ }
+
+ writel_relaxed(val, &mctl_ctl->odtcfg);
+ /* Documented as ODTCFG_SHADOW */
+ writel_relaxed(val, &mctl_ctl->unk_0x2240);
+ /* Offset's interesting; additional undocumented shadows? */
+ writel_relaxed(val, &mctl_ctl->unk_0x3240);
+ writel_relaxed(val, &mctl_ctl->unk_0x4240);
+}
+
+/*
+ * This function produces address mapping parameters, used internally by the
+ * controller to map address lines to HIF addresses. HIF addresses are word
+ * addresses, not byte addresses;
+ * In other words, DDR address 0x400 maps to HIF address 0x100.
+ *
+ * This implementation sets up a reasonable mapping where HIF address
+ * ordering (LSB->MSB) is as such:
+ * - Bank Groups
+ * - Columns
+ * - Banks
+ * - Rows
+ * - Ranks
+ *
+ * TODO: Handle 1.5GB + 3GB configurations. Info about these is stored in
+ * upper bits of TPR13 after autoscan in boot0, and then some extra logic
+ * happens in the address mapping
+ */
+#define INITIAL_HIF_OFFSET 3
+
+static void mctl_set_addrmap(const struct dram_config *config)
+{
+ struct sunxi_mctl_ctl_reg *mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ u8 bankgrp_bits = config->bankgrps;
+ u8 col_bits = config->cols;
+ u8 bank_bits = config->banks;
+ u8 row_bits = config->rows;
+ u8 rank_bits = config->ranks;
+
+ unsigned int i, hif_offset, hif_bits[6];
+
+ /*
+ * When the bus is half width, we need to adjust address mapping,
+ * as COL[0] will be reallocated as part of the byte address,
+ * offsetting the column address mapping values by 1
+ */
+ if (!config->bus_full_width)
+ col_bits--;
+
+ /* Match boot0's DRAM requirements */
+ if (bankgrp_bits > 2)
+ panic("invalid dram configuration (bankgrps_bits = %d)",
+ bankgrp_bits);
+ if (col_bits < 8 || col_bits > 12)
+ panic("invalid dram configuration (col_bits = %d)", col_bits);
+
+ if (bank_bits < 2 || bank_bits > 3)
+ panic("invalid dram configuration (bank_bits = %d)", bank_bits);
+
+ if (row_bits < 14 || row_bits > 18)
+ panic("invalid dram configuration (row_bits = %d)", row_bits);
+
+ if (rank_bits > 1)
+ panic("invalid dram configuration (rank_bits = %d)", rank_bits);
+
+ /*
+ * Col[0:1] + HIF[0:1] (hardwired), Col[2] = HIF[2] (required)
+ * Thus, we start allocating from HIF[3] onwards
+ */
+ hif_offset = INITIAL_HIF_OFFSET;
+
+ /* BG[bankgrp_bits:0] = HIF[3 + bankgrp_bits:3]*/
+ switch (bankgrp_bits) {
+ case 0:
+ writel_relaxed(ADDRMAP8_BG0_B2(ADDRMAP_DISABLED_1F_B(2)) |
+ ADDRMAP8_BG1_B3(ADDRMAP_DISABLED_1F_B(3)),
+ &mctl_ctl->addrmap[8]);
+ break;
+ case 1:
+ writel_relaxed(ADDRMAP8_BG0_B2(hif_offset) |
+ ADDRMAP8_BG1_B3(ADDRMAP_DISABLED_1F_B(3)),
+ &mctl_ctl->addrmap[8]);
+ break;
+ case 2:
+ writel_relaxed(ADDRMAP8_BG0_B2(hif_offset) |
+ ADDRMAP8_BG1_B3(hif_offset + 1),
+ &mctl_ctl->addrmap[8]);
+ break;
+ default:
+ panic("invalid dram configuration (bankgrp_bits = %d)",
+ bankgrp_bits);
+ }
+
+ hif_offset += bankgrp_bits;
+
+ /* Col[2] = HIF[2], Col[5:3] = HIF[offset + 2:offset] */
+ writel_relaxed(ADDRMAP2_COL2_B2(2) | ADDRMAP2_COL3_B3(hif_offset) |
+ ADDRMAP2_COL4_B4(hif_offset + 1) |
+ ADDRMAP2_COL5_B5(hif_offset + 2),
+ &mctl_ctl->addrmap[2]);
+
+ /* Col[col_bits:6] = HIF[col_bits + offset - 3:offset - 3] */
+ for (i = 6; i < 12; i++) {
+ if (i < col_bits)
+ hif_bits[i - 6] = hif_offset + (i - INITIAL_HIF_OFFSET);
+ else
+ hif_bits[i - 6] = ADDRMAP_DISABLED_1F_B(i);
+ }
+
+ writel_relaxed(ADDRMAP3_COL6_B6(hif_bits[0]) |
+ ADDRMAP3_COL7_B7(hif_bits[1]) |
+ ADDRMAP3_COL8_B8(hif_bits[2]) |
+ ADDRMAP3_COL9_B9(hif_bits[3]),
+ &mctl_ctl->addrmap[3]);
+
+ writel_relaxed(ADDRMAP4_COL10_B10(hif_bits[4]) |
+ ADDRMAP4_COL11_B11(hif_bits[5]),
+ &mctl_ctl->addrmap[4]);
+
+ hif_offset = bankgrp_bits + col_bits;
+
+ /* Bank[bank_bits:0] = HIF[bank_bits + offset:offset] */
+ if (bank_bits == 3)
+ writel_relaxed(ADDRMAP1_BANK0_B2(hif_offset) |
+ ADDRMAP1_BANK1_B3(hif_offset + 1) |
+ ADDRMAP1_BANK2_B4(hif_offset + 2),
+ &mctl_ctl->addrmap[1]);
+ else
+ writel_relaxed(ADDRMAP1_BANK0_B2(hif_offset) |
+ ADDRMAP1_BANK1_B3(hif_offset + 1) |
+ ADDRMAP1_BANK2_B4(ADDRMAP_DISABLED_1F_B(4)),
+ &mctl_ctl->addrmap[1]);
+
+ hif_offset += bank_bits;
+
+ /* Row[11:0] = HIF[11 + offset:offset] */
+ writel_relaxed(ADDRMAP5_ROW0_B6(hif_offset) |
+ ADDRMAP5_ROW1_B7(hif_offset + 1) |
+ ADDRMAP5_ROW2_10_B8(hif_offset + 2) |
+ ADDRMAP5_ROW11_B17(hif_offset + 11),
+ &mctl_ctl->addrmap[5]);
+
+ /*
+ * There's some complexity here because of a special case
+ * in boot0 code that appears to work around a hardware bug.
+ * For (col_bits, row_bits, rank_bits) = (10, 16, 1), we have to
+ * place CS[0] in the position we would normally place ROW[14],
+ * and shift ROW[14] and ROW[15] over by one. Using the bit following
+ * ROW[15], as would be standard here, seems to cause nonsensical
+ * aliasing patterns.
+ *
+ * Aside from this case, mapping is simple:
+ * Row[row_bits:12] = HIF[offset + row_bits:offset + 12]
+ */
+ for (i = 12; i < 18; i++) {
+ if (i >= row_bits)
+ hif_bits[i - 12] = ADDRMAP_DISABLED_0F_B(6 + i);
+ else if (rank_bits != 1 || col_bits != 10 || row_bits != 16 ||
+ i < 14)
+ hif_bits[i - 12] = hif_offset + i;
+ else
+ hif_bits[i - 12] = hif_offset + i + 1;
+ }
+
+ writel_relaxed(ADDRMAP6_ROW12_B18(hif_bits[0]) |
+ ADDRMAP6_ROW13_B19(hif_bits[1]) |
+ ADDRMAP6_ROW14_B20(hif_bits[2]) |
+ ADDRMAP6_ROW15_B21(hif_bits[3]),
+ &mctl_ctl->addrmap[6]);
+
+ writel_relaxed(ADDRMAP7_ROW16_B22(hif_bits[4]) |
+ ADDRMAP7_ROW17_B23(hif_bits[5]),
+ &mctl_ctl->addrmap[7]);
+
+ hif_offset += row_bits;
+
+ /*
+ * Ranks
+ * Most cases: CS[0] = HIF[offset]
+ * Special case (see above): CS[0] = HIF[offset - 2]
+ */
+ if (rank_bits == 0)
+ writel_relaxed(ADDRMAP0_CS0_B6(ADDRMAP_DISABLED_1F_B(6)),
+ &mctl_ctl->addrmap[0]);
+ else if (col_bits == 10 && row_bits == 16)
+ writel_relaxed(ADDRMAP0_CS0_B6(hif_offset - 2),
+ &mctl_ctl->addrmap[0]);
+ else
+ writel_relaxed(ADDRMAP0_CS0_B6(hif_offset),
+ &mctl_ctl->addrmap[0]);
+}
+
+static void mctl_com_init(const struct dram_para *para,
+ const struct dram_config *config)
+{
+ void *const mctl_com = (void *)SUNXI_DRAM_COM_BASE;
+ struct sunxi_mctl_ctl_reg *mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ /* Might control power/reset of DDR-related blocks */
+ clrsetbits_le32(mctl_com + MCTL_COM_UNK_008, BIT(24), BIT(25) | BIT(9));
+
+ /* Unlock mctl_ctl registers */
+ setbits_le32(mctl_com + MCTL_COM_MAER0, BIT(15));
+
+ if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
+ setbits_le32(0x03102ea8, BIT(0));
+
+ clrsetbits_le32(&mctl_ctl->sched[0], 0xff << 8, 0x30 << 8);
+ if (!(para->tpr13 & BIT(28)))
+ clrsetbits_le32(&mctl_ctl->sched[0], 0xf, BIT(0));
+
+ writel_relaxed(0, &mctl_ctl->hwlpctl);
+
+ /* Master settings */
+ u32 mstr_value = MSTR_DEVICECONFIG_X32 |
+ MSTR_ACTIVE_RANKS(config->ranks);
+
+ if (config->bus_full_width)
+ mstr_value |= MSTR_BUSWIDTH_FULL;
+ else
+ mstr_value |= MSTR_BUSWIDTH_HALF;
+
+ /*
+ * Geardown and 2T mode are always enabled here, but is controlled by a flag in boot0;
+ * it has not been a problem so far, but may be suspect if a particular board isn't booting.
+ */
+ switch (para->type) {
+ case SUNXI_DRAM_TYPE_DDR3:
+ mstr_value |= MSTR_DEVICETYPE_DDR3 | MSTR_BURST_LENGTH(8) |
+ MSTR_2TMODE;
+ break;
+ case SUNXI_DRAM_TYPE_DDR4:
+ mstr_value |= MSTR_DEVICETYPE_DDR4 | MSTR_BURST_LENGTH(8) |
+ MSTR_GEARDOWNMODE | MSTR_2TMODE;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ mstr_value |= MSTR_DEVICETYPE_LPDDR3 | MSTR_BURST_LENGTH(8);
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR4:
+ mstr_value |= MSTR_DEVICETYPE_LPDDR4 | MSTR_BURST_LENGTH(16);
+ break;
+ }
+
+ writel_relaxed(mstr_value, &mctl_ctl->mstr);
+
+ mctl_set_odtmap(para, config);
+ mctl_set_addrmap(config);
+ mctl_set_timing_params(para);
+
+ dsb();
+ writel(0, &mctl_ctl->pwrctl);
+
+ /* Disable automatic controller updates + automatic controller update requests */
+ setbits_le32(&mctl_ctl->dfiupd[0], BIT(31) | BIT(30));
+ setbits_le32(&mctl_ctl->zqctl[0], BIT(31) | BIT(30));
+ setbits_le32(&mctl_ctl->unk_0x2180, BIT(31) | BIT(30));
+ setbits_le32(&mctl_ctl->unk_0x3180, BIT(31) | BIT(30));
+ setbits_le32(&mctl_ctl->unk_0x4180, BIT(31) | BIT(30));
+
+ /*
+ * Data bus inversion
+ * Controlled by a flag in boot0, enabled by default here.
+ */
+ if (para->type == SUNXI_DRAM_TYPE_DDR4 ||
+ para->type == SUNXI_DRAM_TYPE_LPDDR4)
+ setbits_le32(&mctl_ctl->dbictl, BIT(2));
+}
+
+static void mctl_drive_odt_config(const struct dram_para *para)
+{
+ u32 val;
+ u64 base;
+ u32 i;
+
+ /* DX drive */
+ for (i = 0; i < 4; i++) {
+ base = SUNXI_DRAM_PHY0_BASE + 0x388 + 0x40 * i;
+ val = (para->dx_dri >> (i * 8)) & 0x1f;
+
+ writel_relaxed(val, base);
+ if (para->type == SUNXI_DRAM_TYPE_LPDDR4) {
+ if (para->tpr3 & 0x1f1f1f1f)
+ val = (para->tpr3 >> (i * 8)) & 0x1f;
+ else
+ val = 4;
+ }
+ writel_relaxed(val, base + 4);
+ }
+
+ /* CA drive */
+ for (i = 0; i < 2; i++) {
+ base = SUNXI_DRAM_PHY0_BASE + 0x340 + 0x8 * i;
+ val = (para->ca_dri >> (i * 8)) & 0x1f;
+
+ writel_relaxed(val, base);
+ writel_relaxed(val, base + 4);
+ }
+
+ /* DX ODT */
+ for (i = 0; i < 4; i++) {
+ base = SUNXI_DRAM_PHY0_BASE + 0x380 + 0x40 * i;
+ val = (para->dx_odt >> (i * 8)) & 0x1f;
+
+ if (para->type == SUNXI_DRAM_TYPE_DDR4 ||
+ para->type == SUNXI_DRAM_TYPE_LPDDR3)
+ writel_relaxed(0, base);
+ else
+ writel_relaxed(val, base);
+
+ if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
+ writel_relaxed(0, base + 4);
+ else
+ writel_relaxed(val, base + 4);
+ }
+ dsb();
+}
+
+static void mctl_phy_ca_bit_delay_compensation(const struct dram_para *para)
+{
+ u32 val, i;
+ u32 *ptr;
+
+ if (para->tpr10 & BIT(31)) {
+ val = para->tpr2;
+ } else {
+ val = ((para->tpr10 << 1) & 0x1e) |
+ ((para->tpr10 << 5) & 0x1e00) |
+ ((para->tpr10 << 9) & 0x1e0000) |
+ ((para->tpr10 << 13) & 0x1e000000);
+
+ if (para->tpr10 >> 29 != 0)
+ val <<= 1;
+ }
+
+ ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x780);
+ for (i = 0; i < 32; i++)
+ writel_relaxed((val >> 8) & 0x3f, &ptr[i]);
+
+ writel_relaxed(val & 0x3f, SUNXI_DRAM_PHY0_BASE + 0x7dc);
+ writel_relaxed(val & 0x3f, SUNXI_DRAM_PHY0_BASE + 0x7e0);
+
+ switch (para->type) {
+ case SUNXI_DRAM_TYPE_DDR3:
+ writel_relaxed((val >> 16) & 0x3f,
+ SUNXI_DRAM_PHY0_BASE + 0x7b8);
+ writel_relaxed((val >> 24) & 0x3f,
+ SUNXI_DRAM_PHY0_BASE + 0x784);
+ break;
+ case SUNXI_DRAM_TYPE_DDR4:
+ writel_relaxed((val >> 16) & 0x3f,
+ SUNXI_DRAM_PHY0_BASE + 0x784);
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ writel_relaxed((val >> 16) & 0x3f,
+ SUNXI_DRAM_PHY0_BASE + 0x788);
+ writel_relaxed((val >> 24) & 0x3f,
+ SUNXI_DRAM_PHY0_BASE + 0x790);
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR4:
+ writel_relaxed((val >> 16) & 0x3f,
+ SUNXI_DRAM_PHY0_BASE + 0x790);
+ writel_relaxed((val >> 24) & 0x3f,
+ SUNXI_DRAM_PHY0_BASE + 0x78c);
+ break;
+ }
+
+ dsb();
+}
+
+static void mctl_phy_init(const struct dram_para *para,
+ const struct dram_config *config)
+{
+ struct sunxi_mctl_ctl_reg *mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+ void *const prcm = (void *)SUNXI_PRCM_BASE;
+ void *const mctl_com = (void *)SUNXI_DRAM_COM_BASE;
+
+ u32 val, val2, i;
+ u32 *ptr;
+
+ /* Disable auto refresh. */
+ setbits_le32(&mctl_ctl->rfshctl3, BIT(0));
+
+ /* Set "phy_dbi_mode" to mark the DFI as implementing DBI functionality */
+ writel_relaxed(0, &mctl_ctl->pwrctl);
+ clrbits_le32(&mctl_ctl->dfimisc, 1);
+ writel_relaxed(0x20, &mctl_ctl->pwrctl);
+
+ /* PHY cold reset */
+ clrsetbits_le32(mctl_com + MCTL_COM_UNK_008, BIT(24), BIT(9));
+ udelay(1);
+ setbits_le32(mctl_com + MCTL_COM_UNK_008, BIT(24));
+
+ /* Not sure what this gates the power of. */
+ clrbits_le32(prcm + CCU_PRCM_SYS_PWROFF_GATING, BIT(4));
+
+ if (para->type == SUNXI_DRAM_TYPE_LPDDR4)
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4, BIT(7));
+
+ /* Note: Similar enumeration of values is used during read training */
+ if (config->bus_full_width)
+ val = 0xf;
+ else
+ val = 0x3;
+
+ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x3c, 0xf, val);
+
+ switch (para->type) {
+ case SUNXI_DRAM_TYPE_DDR3:
+ val = 13;
+ val2 = 9;
+ break;
+ case SUNXI_DRAM_TYPE_DDR4:
+ val = 13;
+ val2 = 10;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ val = 14;
+ val2 = 8;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR4:
+ if (para->tpr13 & BIT(28))
+ val = 22;
+ else
+ val = 20;
+
+ val2 = 10;
+ break;
+ }
+
+ writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x14);
+ writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x35c);
+ writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x368);
+ writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x374);
+ writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x18);
+ writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x360);
+ writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x36c);
+ writel_relaxed(0, SUNXI_DRAM_PHY0_BASE + 0x378);
+ writel_relaxed(val2, SUNXI_DRAM_PHY0_BASE + 0x1c);
+ writel_relaxed(val2, SUNXI_DRAM_PHY0_BASE + 0x364);
+ writel_relaxed(val2, SUNXI_DRAM_PHY0_BASE + 0x370);
+ writel_relaxed(val2, SUNXI_DRAM_PHY0_BASE + 0x37c);
+
+ /* Set up SDQ swizzle */
+ ptr = (u32 *)(SUNXI_DRAM_PHY0_BASE + 0xc0);
+ for (i = 0; i < ARRAY_SIZE(phy_init); i++)
+ writel_relaxed(phy_init[i], &ptr[i]);
+
+ /* Set VREF */
+ val = 0;
+ switch (para->type) {
+ case SUNXI_DRAM_TYPE_DDR3:
+ val = para->tpr6 & 0xff;
+ if (val == 0)
+ val = 0x80;
+ break;
+ case SUNXI_DRAM_TYPE_DDR4:
+ val = (para->tpr6 >> 8) & 0xff;
+ if (val == 0)
+ val = 0x80;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ val = (para->tpr6 >> 16) & 0xff;
+ if (val == 0)
+ val = 0x80;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR4:
+ val = (para->tpr6 >> 24) & 0xff;
+ if (val == 0)
+ val = 0x33;
+ break;
+ }
+ writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x3dc);
+ writel_relaxed(val, SUNXI_DRAM_PHY0_BASE + 0x45c);
+
+ mctl_drive_odt_config(para);
+
+ if (para->tpr10 & TPR10_CA_BIT_DELAY)
+ mctl_phy_ca_bit_delay_compensation(para);
+
+ switch (para->type) {
+ case SUNXI_DRAM_TYPE_DDR3:
+ val = 2;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ val = 3;
+ break;
+ case SUNXI_DRAM_TYPE_DDR4:
+ val = 4;
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR4:
+ val = 5;
+ break;
+ }
+
+ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4, 0x7, val | 8);
+
+ if (para->clk <= 672)
+ writel_relaxed(0xf, SUNXI_DRAM_PHY0_BASE + 0x20);
+
+ if (para->clk > 500) {
+ val = 0;
+ val2 = 0;
+ } else {
+ val = 0x80;
+ val2 = 0x20;
+ }
+
+ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x144, 0x80, val);
+ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, 0xe0, val2);
+
+ dsb();
+ clrbits_le32(mctl_com + MCTL_COM_UNK_008, BIT(9));
+ udelay(1);
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x14c, BIT(3));
+
+ mctl_await_completion((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x180), BIT(2),
+ BIT(2));
+
+ /*
+ * This delay is controlled by a tpr13 flag in boot0; doesn't hurt
+ * to always do it though.
+ */
+ udelay(1000);
+ writel(0x37, SUNXI_DRAM_PHY0_BASE + 0x58);
+
+ setbits_le32(prcm + CCU_PRCM_SYS_PWROFF_GATING, BIT(4));
+}
+
+/* Helpers for updating mode registers */
+static inline void mctl_mr_write(u32 mrctrl0, u32 mrctrl1)
+{
+ struct sunxi_mctl_ctl_reg *mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ writel(mrctrl1, &mctl_ctl->mrctrl1);
+ writel(mrctrl0 | MRCTRL0_MR_WR | MRCTRL0_MR_RANKS_ALL,
+ &mctl_ctl->mrctrl0);
+ mctl_await_completion(&mctl_ctl->mrctrl0, MRCTRL0_MR_WR, 0);
+}
+
+static inline void mctl_mr_write_lpddr4(u8 addr, u8 value)
+{
+ mctl_mr_write(0, MRCTRL1_MR_ADDR(addr) | MRCTRL1_MR_DATA(value));
+}
+
+static inline void mctl_mr_write_lpddr3(u8 addr, u8 value)
+{
+ /* Bit [7:6] are set by boot0, but undocumented */
+ mctl_mr_write(BIT(6) | BIT(7),
+ MRCTRL1_MR_ADDR(addr) | MRCTRL1_MR_DATA(value));
+}
+
+static void mctl_dfi_init(const struct dram_para *para)
+{
+ void *const mctl_com = (void *)SUNXI_DRAM_COM_BASE;
+ struct sunxi_mctl_ctl_reg *mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ /* Unlock DFI registers? */
+ setbits_le32(mctl_com + MCTL_COM_MAER0, BIT(8));
+
+ /* Enable dfi_init_complete signal and trigger PHY init start request */
+ writel_relaxed(0, &mctl_ctl->swctl);
+ setbits_le32(&mctl_ctl->dfimisc, BIT(0));
+ setbits_le32(&mctl_ctl->dfimisc, BIT(5));
+ writel_relaxed(1, &mctl_ctl->swctl);
+ mctl_await_completion(&mctl_ctl->swstat, BIT(0), BIT(0));
+
+ /* Stop sending init request and wait for DFI initialization to complete. */
+ writel_relaxed(0, &mctl_ctl->swctl);
+ clrbits_le32(&mctl_ctl->dfimisc, BIT(5));
+ writel_relaxed(1, &mctl_ctl->swctl);
+ mctl_await_completion(&mctl_ctl->swstat, BIT(0), BIT(0));
+ mctl_await_completion(&mctl_ctl->dfistat, BIT(0), BIT(0));
+
+ /* Enter Software Exit from Self Refresh */
+ writel_relaxed(0, &mctl_ctl->swctl);
+ clrbits_le32(&mctl_ctl->pwrctl, BIT(5));
+ writel_relaxed(1, &mctl_ctl->swctl);
+ mctl_await_completion(&mctl_ctl->swstat, BIT(0), BIT(0));
+ mctl_await_completion(&mctl_ctl->statr, 0x3, 1);
+
+ udelay(200);
+
+ /* Disable dfi_init_complete signal */
+ writel_relaxed(0, &mctl_ctl->swctl);
+ clrbits_le32(&mctl_ctl->dfimisc, BIT(0));
+ writel_relaxed(1, &mctl_ctl->swctl);
+ mctl_await_completion(&mctl_ctl->swstat, BIT(0), BIT(0));
+
+ /* Write mode registers, fixed in the JEDEC spec */
+ switch (para->type) {
+ case SUNXI_DRAM_TYPE_DDR3:
+ mctl_mr_write(MRCTRL0_MR_ADDR(0), 0x1c70); /* MR0 */
+ /*
+ * outbuf en, TDQs dis, write leveling dis, out drv 40 Ohms,
+ * DLL en, Rtt_nom 120 Ohms
+ */
+ mctl_mr_write(MRCTRL0_MR_ADDR(1), 0x40); /* MR1 */
+ /*
+ * full array self-ref, CAS: 8 cyc, SRT w/ norm temp range,
+ * dynamic ODT off
+ */
+ mctl_mr_write(MRCTRL0_MR_ADDR(2), 0x18); /* MR2 */
+ /* predef MPR pattern */
+ mctl_mr_write(MRCTRL0_MR_ADDR(3), 0); /* MR3 */
+ break;
+ case SUNXI_DRAM_TYPE_DDR4:
+ mctl_mr_write(MRCTRL0_MR_ADDR(0), 0x840);
+ mctl_mr_write(MRCTRL0_MR_ADDR(1), 0x601);
+ mctl_mr_write(MRCTRL0_MR_ADDR(2), 0x8);
+ mctl_mr_write(MRCTRL0_MR_ADDR(3), 0);
+ mctl_mr_write(MRCTRL0_MR_ADDR(4), 0);
+ mctl_mr_write(MRCTRL0_MR_ADDR(5), 0x400);
+
+ mctl_mr_write(MRCTRL0_MR_ADDR(6), 0x862 | BIT(7));
+ mctl_mr_write(MRCTRL0_MR_ADDR(6), 0x862 | BIT(7));
+ mctl_mr_write(MRCTRL0_MR_ADDR(6), 0x862 & (~BIT(7)));
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ mctl_mr_write_lpddr3(1, 0xc3); /* MR1: nWR=8, BL8 */
+ mctl_mr_write_lpddr3(2, 0xa); /* MR2: RL=12, WL=6 */
+ mctl_mr_write_lpddr3(3, 0x2); /* MR3: 40 0hms PD/PU */
+ mctl_mr_write_lpddr3(11, para->mr11);
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR4:
+ mctl_mr_write_lpddr4(0, 0); /* MR0 */
+ mctl_mr_write_lpddr4(1, 0x34); /* MR1 */
+ mctl_mr_write_lpddr4(2, 0x1b); /* MR2 */
+ mctl_mr_write_lpddr4(3, 0x33); /* MR3 */
+ mctl_mr_write_lpddr4(4, 0x3); /* MR4 */
+ mctl_mr_write_lpddr4(11, para->mr11);
+ mctl_mr_write_lpddr4(12, para->mr12);
+ mctl_mr_write_lpddr4(13, para->mr13);
+ mctl_mr_write_lpddr4(14, para->mr14);
+ mctl_mr_write_lpddr4(22, para->tpr1);
+ break;
+ }
+
+ writel(0, SUNXI_DRAM_PHY0_BASE + 0x54);
+
+ /* Re-enable controller refresh */
+ writel(0, &mctl_ctl->swctl);
+ clrbits_le32(&mctl_ctl->rfshctl3, BIT(0));
+ writel(1, &mctl_ctl->swctl);
+}
+
+/* Slightly modified from H616 driver */
+static bool mctl_phy_read_calibration(const struct dram_config *config)
+{
+ bool result = true;
+ u32 val, tmp;
+
+ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
+
+ setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+
+ if (config->bus_full_width)
+ val = 0xf;
+ else
+ val = 3;
+
+ while ((readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x184) & val) != val) {
+ if (readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x184) & 0x20) {
+ result = false;
+ break;
+ }
+ }
+
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
+
+ if (config->ranks == 1) {
+ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x10);
+
+ setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+
+ while ((readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x184) & val) !=
+ val) {
+ if (readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x184) &
+ 0x20) {
+ result = false;
+ break;
+ }
+ }
+
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 1);
+ }
+
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30);
+
+ val = readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x274) & 7;
+ tmp = readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x26c) & 7;
+ if (val < tmp)
+ val = tmp;
+ tmp = readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x32c) & 7;
+ if (val < tmp)
+ val = tmp;
+ tmp = readl_relaxed(SUNXI_DRAM_PHY0_BASE + 0x334) & 7;
+ if (val < tmp)
+ val = tmp;
+ clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 0x38, 0x7, (val + 2) & 7);
+
+ setbits_le32(SUNXI_DRAM_PHY0_BASE + 4, 0x20);
+
+ return result;
+}
+
+static inline void mctl_phy_dx_delay1_inner(u32 *base, u32 val1, u32 val2)
+{
+ u32 *ptr = base;
+
+ for (int i = 0; i < 9; i++) {
+ writel_relaxed(val1, ptr);
+ writel_relaxed(val1, ptr + 0x30);
+ ptr += 2;
+ }
+
+ writel_relaxed(val2, ptr + 1);
+ writel_relaxed(val2, ptr + 49);
+ writel_relaxed(val2, ptr);
+ writel_relaxed(val2, ptr + 48);
+}
+
+static inline void mctl_phy_dx_delay0_inner(u32 *base1, u32 *base2, u32 val1,
+ u32 val2)
+{
+ u32 *ptr = base1;
+
+ for (int i = 0; i < 9; i++) {
+ writel_relaxed(val1, ptr);
+ writel_relaxed(val1, ptr + 0x30);
+ ptr += 2;
+ }
+
+ writel_relaxed(val2, base2);
+ writel_relaxed(val2, base2 + 48);
+ writel_relaxed(val2, ptr);
+ writel_relaxed(val2, base2 + 44);
+}
+
+/*
+ * This might be somewhat transferable to H616; whether or not people like
+ * the design is another question
+ */
+static void mctl_phy_dx_delay_compensation(const struct dram_para *para)
+{
+ if (para->tpr10 & TPR10_DX_BIT_DELAY1) {
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
+ setbits_le32(SUNXI_DRAM_PHY0_BASE + 8, BIT(3));
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, BIT(4));
+
+ if (para->type == SUNXI_DRAM_TYPE_DDR4)
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x4, BIT(7));
+
+ mctl_phy_dx_delay1_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x484),
+ para->tpr11 & 0x3f,
+ para->para0 & 0x3f);
+ mctl_phy_dx_delay1_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d8),
+ (para->tpr11 >> 8) & 0x3f,
+ (para->para0 >> 8) & 0x3f);
+ mctl_phy_dx_delay1_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x604),
+ (para->tpr11 >> 16) & 0x3f,
+ (para->para0 >> 16) & 0x3f);
+ mctl_phy_dx_delay1_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x658),
+ (para->tpr11 >> 24) & 0x3f,
+ (para->para0 >> 24) & 0x3f);
+
+ setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, 1);
+ }
+
+ if (para->tpr10 & TPR10_DX_BIT_DELAY0) {
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, BIT(7));
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x190, BIT(2));
+
+ mctl_phy_dx_delay0_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x480),
+ (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x528),
+ para->tpr12 & 0x3f,
+ para->tpr14 & 0x3f);
+
+ mctl_phy_dx_delay0_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x4d4),
+ (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x52c),
+ (para->tpr12 >> 8) & 0x3f,
+ (para->tpr14 >> 8) & 0x3f);
+
+ mctl_phy_dx_delay0_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x600),
+ (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x6a8),
+ (para->tpr12 >> 16) & 0x3f,
+ (para->tpr14 >> 16) & 0x3f);
+
+ mctl_phy_dx_delay0_inner((u32 *)(SUNXI_DRAM_PHY0_BASE + 0x6ac),
+ (u32 *)(SUNXI_DRAM_PHY0_BASE + 0x528),
+ (para->tpr12 >> 24) & 0x3f,
+ (para->tpr14 >> 24) & 0x3f);
+
+ setbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, BIT(7));
+ }
+}
+
+static bool mctl_calibrate_phy(const struct dram_para *para,
+ const struct dram_config *config)
+{
+ struct sunxi_mctl_ctl_reg *mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ int i;
+
+ /* TODO: Implement write levelling */
+ if (para->tpr10 & TPR10_READ_CALIBRATION) {
+ for (i = 0; i < 5; i++)
+ if (mctl_phy_read_calibration(config))
+ break;
+ if (i == 5) {
+ debug("read calibration failed\n");
+ return false;
+ }
+ }
+
+ /* TODO: Implement read training */
+ /* TODO: Implement write training */
+
+ mctl_phy_dx_delay_compensation(para);
+ /* TODO: Implement DFS */
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x60, BIT(0));
+ clrbits_le32(SUNXI_DRAM_PHY0_BASE + 0x54, 7);
+
+ /* Q: Does self-refresh get disabled by a calibration? */
+ writel_relaxed(0, &mctl_ctl->swctl);
+ clrbits_le32(&mctl_ctl->rfshctl3, BIT(1));
+ writel_relaxed(1, &mctl_ctl->swctl);
+ mctl_await_completion(&mctl_ctl->swstat, BIT(0), BIT(0));
+
+ return true;
+}
+
+static bool mctl_core_init(const struct dram_para *para,
+ const struct dram_config *config)
+{
+ mctl_clk_init(para->clk);
+ mctl_com_init(para, config);
+ mctl_phy_init(para, config);
+ mctl_dfi_init(para);
+
+ return mctl_calibrate_phy(para, config);
+}
+
+/* Heavily inspired from H616 driver. */
+static void auto_detect_ranks(const struct dram_para *para,
+ struct dram_config *config)
+{
+ int i;
+
+ config->cols = 9;
+ config->rows = 14;
+ config->banks = 2;
+ config->bankgrps = 0;
+
+ /* Test ranks */
+ for (i = 1; i >= 0; i--) {
+ config->ranks = i;
+ config->bus_full_width = true;
+ debug("Testing ranks = %d, 32-bit bus: ", i);
+ if (mctl_core_init(para, config)) {
+ debug("OK\n");
+ break;
+ }
+
+ config->bus_full_width = false;
+ debug("Testing ranks = %d, 16-bit bus: ", i);
+ if (mctl_core_init(para, config)) {
+ debug("OK\n");
+ break;
+ }
+ }
+
+ if (i < 0)
+ debug("rank testing failed\n");
+}
+
+static void mctl_write_pattern(void)
+{
+ unsigned int i;
+ u32 *ptr, val;
+
+ ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i < 16; ptr++, i++) {
+ if (i & 1)
+ val = ~(ulong)ptr;
+ else
+ val = (ulong)ptr;
+ writel(val, ptr);
+ }
+}
+
+static bool mctl_check_pattern(ulong offset)
+{
+ unsigned int i;
+ u32 *ptr, val;
+
+ ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i < 16; ptr++, i++) {
+ if (i & 1)
+ val = ~(ulong)ptr;
+ else
+ val = (ulong)ptr;
+ if (val != *(ptr + offset / 4))
+ return false;
+ }
+
+ return true;
+}
+
+static void mctl_auto_detect_dram_size(const struct dram_para *para,
+ struct dram_config *config)
+{
+ unsigned int shift;
+ u32 buffer[16];
+
+ /* max config for bankgrps on DDR4, minimum for everything else */
+ config->cols = 8;
+ config->banks = 2;
+ config->rows = 14;
+
+ shift = 1 + config->bus_full_width;
+ if (para->type == SUNXI_DRAM_TYPE_DDR4) {
+ config->bankgrps = 2;
+ mctl_core_init(para, config);
+
+ /* store content so it can be restored later. */
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+ mctl_write_pattern();
+
+ if (mctl_check_pattern(1ULL << (shift + 4)))
+ config->bankgrps = 1;
+
+ /* restore data */
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+ } else {
+ /* No bank groups in (LP)DDR3/LPDDR4 */
+ config->bankgrps = 0;
+ }
+
+ /* reconfigure to make sure all active columns are accessible */
+ config->cols = 12;
+ mctl_core_init(para, config);
+
+ /* store data again as it might be moved */
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+ mctl_write_pattern();
+
+ /*
+ * Detect column address bits. The last number of columns checked
+ * is 11, if that doesn't match, is must be 12, no more checks needed.
+ */
+ shift = 1 + config->bus_full_width + config->bankgrps;
+ for (config->cols = 8; config->cols < 12; config->cols++) {
+ if (mctl_check_pattern(1ULL << (config->cols + shift)))
+ break;
+ }
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+
+ /* reconfigure to make sure that all active banks are accessible */
+ config->banks = 3;
+ mctl_core_init(para, config);
+
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+ mctl_write_pattern();
+
+ /* detect bank bits */
+ shift += config->cols;
+ for (config->banks = 2; config->banks < 3; config->banks++) {
+ if (mctl_check_pattern(1ULL << (config->banks + shift)))
+ break;
+ }
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+
+ /* reconfigure to make sure that all active rows are accessible */
+ config->rows = 18;
+ mctl_core_init(para, config);
+
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+ mctl_write_pattern();
+
+ /* detect row address bits */
+ shift += config->banks;
+ for (config->rows = 14; config->rows < 18; config->rows++) {
+ if (mctl_check_pattern(1ULL << (config->rows + shift)))
+ break;
+ }
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+}
+
+/* Modified from H616 driver to add banks and bank groups */
+static unsigned long calculate_dram_size(const struct dram_config *config)
+{
+ /* Bootrom only uses x32 or x16 bus widths */
+ u8 width = config->bus_full_width ? 4 : 2;
+
+ return (1ULL << (config->cols + config->rows + config->banks +
+ config->bankgrps)) *
+ width * (1ULL << config->ranks);
+}
+
+static const struct dram_para para = {
+ .clk = CONFIG_DRAM_CLK,
+#ifdef CONFIG_SUNXI_DRAM_DDR3
+ .type = SUNXI_DRAM_TYPE_DDR3,
+#elif defined(CONFIG_SUNXI_DRAM_DDR4)
+ .type = SUNXI_DRAM_TYPE_DDR4,
+#elif defined(CONFIG_SUNXI_DRAM_LPDDR3)
+ .type = SUNXI_DRAM_TYPE_LPDDR3,
+#elif defined(CONFIG_SUNXI_DRAM_LPDDR4)
+ .type = SUNXI_DRAM_TYPE_LPDDR4,
+#endif
+ /* TODO: Populate from config */
+ .dx_odt = CONFIG_DRAM_SUNXI_DX_ODT,
+ .dx_dri = CONFIG_DRAM_SUNXI_DX_DRI,
+ .ca_dri = CONFIG_DRAM_SUNXI_CA_DRI,
+ .para0 = CONFIG_DRAM_SUNXI_PARA0,
+ .mr11 = CONFIG_DRAM_SUNXI_MR11,
+ .mr12 = CONFIG_DRAM_SUNXI_MR12,
+ .mr13 = CONFIG_DRAM_SUNXI_MR13,
+ .mr14 = CONFIG_DRAM_SUNXI_MR14,
+ .tpr1 = CONFIG_DRAM_SUNXI_TPR1,
+ .tpr2 = CONFIG_DRAM_SUNXI_TPR2,
+ .tpr3 = CONFIG_DRAM_SUNXI_TPR3,
+ .tpr6 = CONFIG_DRAM_SUNXI_TPR6,
+ .tpr10 = CONFIG_DRAM_SUNXI_TPR10,
+ .tpr11 = CONFIG_DRAM_SUNXI_TPR11,
+ .tpr12 = CONFIG_DRAM_SUNXI_TPR12,
+ .tpr13 = CONFIG_DRAM_SUNXI_TPR13,
+ .tpr14 = CONFIG_DRAM_SUNXI_TPR14,
+};
+
+unsigned long sunxi_dram_init(void)
+{
+ struct dram_config config;
+
+ /* Writing to undocumented SYS_CFG area, according to user manual. */
+ setbits_le32(0x03000160, BIT(8));
+ clrbits_le32(0x03000168, 0x3f);
+
+ auto_detect_ranks(&para, &config);
+ mctl_auto_detect_dram_size(&para, &config);
+
+ if (!mctl_core_init(&para, &config))
+ return 0;
+
+ debug("cols = 2^%d, rows = 2^%d, banks = %d, bank groups = %d, ranks = %d, width = %d\n",
+ config.cols, config.rows, 1U << config.banks,
+ 1U << config.bankgrps, 1U << config.ranks,
+ 16U << config.bus_full_width);
+
+ return calculate_dram_size(&config);
+}
diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile b/arch/arm/mach-sunxi/dram_timings/Makefile
index 5f203419240..4dc1f29fc08 100644
--- a/arch/arm/mach-sunxi/dram_timings/Makefile
+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
@@ -6,3 +6,5 @@ obj-$(CONFIG_SUNXI_DRAM_H6_DDR3_1333) += h6_ddr3_1333.o
obj-$(CONFIG_SUNXI_DRAM_H616_DDR3_1333) += h616_ddr3_1333.o
obj-$(CONFIG_SUNXI_DRAM_H616_LPDDR3) += h616_lpddr3.o
obj-$(CONFIG_SUNXI_DRAM_H616_LPDDR4) += h616_lpddr4_2133.o
+obj-$(CONFIG_SUNXI_DRAM_A133_DDR4) += a133_ddr4.o
+obj-$(CONFIG_SUNXI_DRAM_A133_LPDDR4) += a133_lpddr4.o
diff --git a/arch/arm/mach-sunxi/dram_timings/a133_ddr4.c b/arch/arm/mach-sunxi/dram_timings/a133_ddr4.c
new file mode 100644
index 00000000000..dec208e22df
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/a133_ddr4.c
@@ -0,0 +1,80 @@
+#include <asm/arch/cpu.h>
+#include <asm/arch/dram.h>
+
+void mctl_set_timing_params(const struct dram_para *para)
+{
+ struct sunxi_mctl_ctl_reg *const mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ u8 txsr = 4;
+ u8 tccd = 3;
+ u8 rd2wr = 5;
+ u8 tmrd = 4;
+ u8 tmrw = 0;
+ u8 wrlat = 5;
+ u8 rdlat = 7;
+ u8 wr2pre = 14;
+ u8 dfi_tphy_wrlat = 6;
+ u8 dfi_trddata_en = 10;
+
+ u8 tfaw = ns_to_t(35);
+ u8 trrd = max(ns_to_t(8), 2);
+ u8 txp = max(ns_to_t(6), 2);
+ u8 tmrd_pda = max(ns_to_t(10), 8);
+ u8 trp = ns_to_t(15);
+ u8 trc = ns_to_t(49);
+ u8 wr2rd_s = max(ns_to_t(3), 1) + 7;
+ u8 tras_min = ns_to_t(34);
+ u16 trefi_x32 = ns_to_t(7800) / 32;
+ u16 trfc_min = ns_to_t(350);
+ u16 txs_x32 = ns_to_t(360) / 32;
+ u16 tmod = max(ns_to_t(15), 12);
+ u8 tcke = max(ns_to_t(5), 2);
+ u8 tcksrx = max(ns_to_t(10), 3);
+ u8 txs_abort_x32 = ns_to_t(170) / 32;
+ u8 tras_max = ns_to_t(70200) / 1024;
+
+ u8 rd2pre = (trp < 5 ? 9 - trp : 4);
+ u8 wr2rd = trrd + 7;
+ u8 tckesr = tcke + 1;
+ u8 trcd = trp;
+ u8 trrd_s = txp;
+ u8 tcksre = tcksrx;
+
+ writel(tras_min | tras_max << 8 | tfaw << 16 | wr2pre << 24,
+ &mctl_ctl->dramtmg[0]);
+ writel(trc | rd2pre << 8 | txp << 16, &mctl_ctl->dramtmg[1]);
+ writel(wr2rd | rd2wr << 8 | rdlat << 16 | wrlat << 24,
+ &mctl_ctl->dramtmg[2]);
+ writel(tmod | tmrd << 12 | tmrw << 20, &mctl_ctl->dramtmg[3]);
+ writel(trp | trrd << 8 | tccd << 16 | trcd << 24,
+ &mctl_ctl->dramtmg[4]);
+ writel(tcke | tckesr << 8 | tcksre << 16 | tcksrx << 24,
+ &mctl_ctl->dramtmg[5]);
+ writel((txp + 2) | 0x20 << 16 | 0x20 << 24,
+ &mctl_ctl->dramtmg[6]);
+ writel(txs_x32 | 0x10 << 8 | txs_abort_x32 << 16 | txs_abort_x32 << 24,
+ &mctl_ctl->dramtmg[8]);
+ writel(wr2rd_s | trrd_s << 8 | 0x2 << 16, &mctl_ctl->dramtmg[9]);
+ writel(0xe0c05, &mctl_ctl->dramtmg[10]);
+ writel(0x440c021c, &mctl_ctl->dramtmg[11]);
+ writel(tmrd_pda, &mctl_ctl->dramtmg[12]);
+ writel(0xa100002, &mctl_ctl->dramtmg[13]);
+ writel(txsr, &mctl_ctl->dramtmg[14]);
+
+ clrsetbits_le32(&mctl_ctl->init[0], 0xc0000fff, 1008);
+ writel(0x1f20000, &mctl_ctl->init[1]);
+ clrsetbits_le32(&mctl_ctl->init[2], 0xff0f, 0xd05);
+ writel(0, &mctl_ctl->dfimisc);
+
+ writel(0x840 << 16 | 0x601, &mctl_ctl->init[3]); /* MR0 / MR1 */
+ writel(0x8 << 16 | 0x0, &mctl_ctl->init[4]); /* MR2 / MR3 */
+ writel(0x0 << 16 | 0x400, &mctl_ctl->init[6]); /* MR4 / MR5 */
+ writel(0x826, &mctl_ctl->init[7]); /* MR6 */
+
+ clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+ writel((dfi_tphy_wrlat - 1) | 0x2000000 | (dfi_trddata_en - 1) << 16 |
+ 0x808000, &mctl_ctl->dfitmg0);
+ writel(0x100202, &mctl_ctl->dfitmg1);
+ writel(trfc_min | trefi_x32 << 16, &mctl_ctl->rfshtmg);
+}
diff --git a/arch/arm/mach-sunxi/dram_timings/a133_lpddr4.c b/arch/arm/mach-sunxi/dram_timings/a133_lpddr4.c
new file mode 100644
index 00000000000..1e607381023
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/a133_lpddr4.c
@@ -0,0 +1,102 @@
+#include <asm/arch/cpu.h>
+#include <asm/arch/dram.h>
+
+void mctl_set_timing_params(const struct dram_para *para)
+{
+ struct sunxi_mctl_ctl_reg *const mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ bool tpr13_flag1 = para->tpr13 & BIT(28);
+ bool tpr13_flag2 = para->tpr13 & BIT(3);
+ bool tpr13_flag3 = para->tpr13 & BIT(5);
+
+ u8 tccd = 4;
+ u8 tfaw = ns_to_t(40);
+ u8 trrd = max(ns_to_t(10), 2);
+ u8 trcd = max(ns_to_t(18), 2);
+ u8 trc = ns_to_t(65);
+ u8 txp = max(ns_to_t(8), 2);
+
+ u8 trp = ns_to_t(21);
+ u8 tras_min = ns_to_t(42);
+ u16 trefi_x32 = ns_to_t(3904) / 32;
+ u16 trfc_min = ns_to_t(180);
+ u16 txsr = ns_to_t(190);
+
+ u8 tmrw = max(ns_to_t(14), 5);
+ u8 tmrd = max(ns_to_t(14), 5);
+ u8 tmod = 12;
+ u8 tcke = max(ns_to_t(15), 2);
+ u8 tcksrx = max(ns_to_t(2), 2);
+ u8 tcksre = max(ns_to_t(5), 2);
+ u8 tckesr = max(ns_to_t(15), 2);
+ u8 tras_max = (trefi_x32 * 9) / 32;
+ u8 txs_x32 = 4;
+ u8 txsabort_x32 = 4;
+
+ u8 wrlat = 5;
+ u8 wr2rd_s = 8;
+ u8 trrd_s = 2;
+ u8 tmrd_pda = 8;
+
+ u8 wr2pre = 24;
+ u8 rd2pre = 4;
+ u8 wr2rd = 14 + max(ns_to_t(tpr13_flag1 ? 10 : 12), 4);
+ u8 rd2wr = 17 + ns_to_t(4) - ns_to_t(1);
+ u8 tphy_wrlat = 5;
+
+ u8 rdlat = 10;
+ u8 trddata_en = 17;
+
+ if (tpr13_flag1) {
+ rdlat = 11;
+ trddata_en = 19;
+ }
+
+ writel(tras_min | tras_max << 8 | tfaw << 16 | wr2pre << 24,
+ &mctl_ctl->dramtmg[0]);
+ writel(trc | rd2pre << 8 | txp << 16, &mctl_ctl->dramtmg[1]);
+ writel(wr2rd | rd2wr << 8 | rdlat << 16 | wrlat << 24,
+ &mctl_ctl->dramtmg[2]);
+ writel(tmod | tmrd << 12 | tmrw << 20, &mctl_ctl->dramtmg[3]);
+ writel(trp | trrd << 8 | tccd << 16 | trcd << 24,
+ &mctl_ctl->dramtmg[4]);
+ writel(tcke | tckesr << 8 | tcksre << 16 | tcksrx << 24,
+ &mctl_ctl->dramtmg[5]);
+ writel((txp + 2) | 0x20 << 16 | 0x20 << 24, &mctl_ctl->dramtmg[6]);
+ writel(txs_x32 | 0x10 << 8 | txsabort_x32 << 16 | txsabort_x32 << 24,
+ &mctl_ctl->dramtmg[8]);
+ writel(wr2rd_s | trrd_s << 8 | 0x2 << 16, &mctl_ctl->dramtmg[9]);
+ writel(0xe0c05, &mctl_ctl->dramtmg[10]);
+ writel(0x440c021c, &mctl_ctl->dramtmg[11]);
+ writel(tmrd_pda, &mctl_ctl->dramtmg[12]);
+ writel(0xa100002, &mctl_ctl->dramtmg[13]);
+ writel(txsr, &mctl_ctl->dramtmg[14]);
+
+ clrsetbits_le32(&mctl_ctl->init[0], 0xc0000fff, 1008);
+
+ if (tpr13_flag2)
+ writel(0x420000, &mctl_ctl->init[1]);
+ else
+ writel(0x1f20000, &mctl_ctl->init[1]);
+
+ clrsetbits_le32(&mctl_ctl->init[2], 0xff0f, 0xd05);
+ writel(0, &mctl_ctl->dfimisc);
+
+ writel(0x34 << 16 | 0x1b, &mctl_ctl->init[3]); /* MR1/MR2 */
+ writel(0x33 << 16, &mctl_ctl->init[4]); /* MR3 */
+ writel(para->mr11 << 16 | para->mr12, &mctl_ctl->init[6]);
+ writel(para->tpr1 << 16 | para->mr14, &mctl_ctl->init[7]);
+
+ clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+ if (!tpr13_flag3) {
+ tphy_wrlat -= 1;
+ trddata_en -= 1;
+ }
+
+ writel(tphy_wrlat | trddata_en << 16 | 0x808000 | 0x2000000,
+ &mctl_ctl->dfitmg0);
+ writel(0x100202, &mctl_ctl->dfitmg1);
+
+ writel(trfc_min | trefi_x32 << 16, &mctl_ctl->rfshtmg);
+}
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index b288c65e7fd..8ade6f7b9d1 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -155,10 +155,6 @@ config TARGET_M5282EVB
bool "Support M5282EVB"
select M5282
-config TARGET_ASTRO_MCF5373L
- bool "Support astro_mcf5373l"
- select M5373
-
config TARGET_M53017EVB
bool "Support M53017EVB"
select M53015
@@ -183,7 +179,6 @@ config TARGET_STMARK2
endchoice
source "board/BuS/eb_cpu5282/Kconfig"
-source "board/astro/mcf5373l/Kconfig"
source "board/cobra5272/Kconfig"
source "board/freescale/m5208evbe/Kconfig"
source "board/freescale/m5235evb/Kconfig"
diff --git a/arch/m68k/dts/Makefile b/arch/m68k/dts/Makefile
index 8b354b9c570..c89559be309 100644
--- a/arch/m68k/dts/Makefile
+++ b/arch/m68k/dts/Makefile
@@ -11,7 +11,6 @@ dtb-$(CONFIG_TARGET_M5253DEMO) += M5253DEMO.dtb
dtb-$(CONFIG_TARGET_M5272C3) += M5272C3.dtb
dtb-$(CONFIG_TARGET_M5275EVB) += M5275EVB.dtb
dtb-$(CONFIG_TARGET_M5282EVB) += M5282EVB.dtb
-dtb-$(CONFIG_TARGET_ASTRO_MCF5373L) += astro_mcf5373l.dtb
dtb-$(CONFIG_TARGET_M53017EVB) += M53017EVB.dtb
dtb-$(CONFIG_TARGET_M5329EVB) += M5329AFEE.dtb M5329BFEE.dtb
dtb-$(CONFIG_TARGET_M5373EVB) += M5373EVB.dtb
@@ -21,4 +20,4 @@ dtb-$(CONFIG_TARGET_STMARK2) += stmark2.dtb
include $(srctree)/scripts/Makefile.dts
# Add any required device tree compiler flags here
-DTC_FLAGS += -R 4 -p 0x1000
+DTC_FLAGS += -R 4
diff --git a/arch/m68k/dts/astro_mcf5373l.dts b/arch/m68k/dts/astro_mcf5373l.dts
deleted file mode 100644
index 40f84dd64b6..00000000000
--- a/arch/m68k/dts/astro_mcf5373l.dts
+++ /dev/null
@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2018 Angelo Dureghello <angelo@sysam.it>
- */
-
-/dts-v1/;
-/include/ "mcf537x.dtsi"
-
-/ {
- model = "Astro mcf5373l";
- compatible = "astro,mcf5373l";
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-};
-
-&uart0 {
- bootph-all;
- status = "okay";
-};
-
-&i2c0 {
- clock-frequency = <80000>;
- u-boot,i2c-slave-addr = <0x7f>;
- status = "okay";
-};
diff --git a/arch/microblaze/dts/Makefile b/arch/microblaze/dts/Makefile
index 9be902d3bb1..0f3a7472a67 100644
--- a/arch/microblaze/dts/Makefile
+++ b/arch/microblaze/dts/Makefile
@@ -5,4 +5,4 @@ dtb-y += $(shell echo $(CONFIG_DEFAULT_DEVICE_TREE)).dtb
include $(srctree)/scripts/Makefile.dts
# Add any required device tree compiler flags here
-DTC_FLAGS += -R 4 -p 0x1000
+DTC_FLAGS += -R 4
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 39a4f435a84..4c6322ed1c7 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -118,20 +118,4 @@ struct task_struct;
*/
#define return_address() ({__asm__ __volatile__("":::"$31");__builtin_return_address(0);})
-#ifdef CONFIG_CPU_HAS_PREFETCH
-
-#define ARCH_HAS_PREFETCH
-
-static inline void prefetch(const void *addr)
-{
- __asm__ __volatile__(
- " .set mips4 \n"
- " pref %0, (%1) \n"
- " .set mips0 \n"
- :
- : "i" (Pref_Load), "r" (addr));
-}
-
-#endif
-
#endif /* _ASM_PROCESSOR_H */
diff --git a/arch/nios2/dts/Makefile b/arch/nios2/dts/Makefile
index d77db9762a1..75951164978 100644
--- a/arch/nios2/dts/Makefile
+++ b/arch/nios2/dts/Makefile
@@ -5,4 +5,4 @@ dtb-y += $(CONFIG_DEFAULT_DEVICE_TREE:"%"=%).dtb
include $(srctree)/scripts/Makefile.dts
# Add any required device tree compiler flags here
-DTC_FLAGS += -R 4 -p 0x1000
+DTC_FLAGS += -R 4
diff --git a/arch/powerpc/cpu/mpc85xx/mp.c b/arch/powerpc/cpu/mpc85xx/mp.c
index 8918a401fac..bee6758dc9a 100644
--- a/arch/powerpc/cpu/mpc85xx/mp.c
+++ b/arch/powerpc/cpu/mpc85xx/mp.c
@@ -410,9 +410,9 @@ static void plat_mp_up(unsigned long bootpg, unsigned int pagesize)
void cpu_mp_lmb_reserve(void)
{
- u32 bootpg = determine_mp_bootpg(NULL);
+ phys_addr_t bootpg = determine_mp_bootpg(NULL);
- lmb_reserve(bootpg, 4096, LMB_NONE);
+ lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &bootpg, 4096, LMB_NONE);
}
void setup_mp(void)
diff --git a/arch/powerpc/lib/misc.c b/arch/powerpc/lib/misc.c
index 7e303419624..fc10ae50cf8 100644
--- a/arch/powerpc/lib/misc.c
+++ b/arch/powerpc/lib/misc.c
@@ -36,11 +36,12 @@ int arch_misc_init(void)
size = min(size, (ulong)CFG_SYS_LINUX_LOWMEM_MAX_SIZE);
if (size < bootm_size) {
- ulong base = bootmap_base + size;
+ phys_addr_t base = bootmap_base + size;
printf("WARNING: adjusting available memory from 0x%lx to 0x%llx\n",
size, (unsigned long long)bootm_size);
- lmb_reserve(base, bootm_size - size, LMB_NONE);
+ lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &base,
+ bootm_size - size, LMB_NONE);
}
#ifdef CONFIG_MP
diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile
index cf1872f3fdc..2b10c2d6c01 100644
--- a/arch/riscv/dts/Makefile
+++ b/arch/riscv/dts/Makefile
@@ -19,4 +19,4 @@ dtb-$(CONFIG_TARGET_ASPEED_AST2700_IBEX) += ast2700-ibex.dtb
include $(srctree)/scripts/Makefile.dts
# Add any required device tree compiler flags here
-DTC_FLAGS += -R 4 -p 0x1000
+DTC_FLAGS += -R 4
diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c
index 49236db99c2..6a15c8b0a18 100644
--- a/arch/sandbox/cpu/state.c
+++ b/arch/sandbox/cpu/state.c
@@ -480,7 +480,9 @@ int state_init(void)
state = &main_state;
state->ram_size = CFG_SYS_SDRAM_SIZE;
- state->ram_buf = os_malloc(state->ram_size);
+ state->mmap_addr = os_malloc(state->ram_size + SB_SDRAM_ALIGN);
+ state->ram_buf = (uint8_t *)ALIGN((uintptr_t)state->mmap_addr,
+ SB_SDRAM_ALIGN);
if (!state->ram_buf) {
printf("Out of memory\n");
os_exit(1);
@@ -533,7 +535,7 @@ int state_uninit(void)
trace_set_enabled(0);
os_free(state->state_fdt);
- os_free(state->ram_buf);
+ os_free(state->mmap_addr);
memset(state, '\0', sizeof(*state));
return 0;
diff --git a/arch/sandbox/dts/Makefile b/arch/sandbox/dts/Makefile
index 1c9fb4a4566..0d7b0b80e21 100644
--- a/arch/sandbox/dts/Makefile
+++ b/arch/sandbox/dts/Makefile
@@ -11,4 +11,4 @@ dtb-$(CONFIG_CMD_EXTENSION) += overlay0.dtbo overlay1.dtbo
include $(srctree)/scripts/Makefile.dts
# Add any required device tree compiler flags here
-DTC_FLAGS += -R 4 -p 0x1000
+DTC_FLAGS += -R 4
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index dc21a623106..9dea0980bfc 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -75,6 +75,7 @@ struct sandbox_state {
char **argv; /* Command line arguments */
const char *jumped_fname; /* Jumped from previous U-Boot */
const char *prog_fname; /* U-Boot executable filename */
+ uint8_t *mmap_addr; /* Memory allocated via mmap */
uint8_t *ram_buf; /* Emulated RAM buffer */
unsigned long ram_size; /* Size of RAM buffer */
const char *ram_buf_fname; /* Filename to use for RAM buffer */
diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile
index 9a46726e026..725991e2629 100644
--- a/arch/x86/dts/Makefile
+++ b/arch/x86/dts/Makefile
@@ -24,4 +24,4 @@ dtb-y += bayleybay.dtb \
include $(srctree)/scripts/Makefile.dts
-DTC_FLAGS += -R 4 -p $(if $(CONFIG_EFI_APP),0x8000,0x1000)
+DTC_FLAGS += -R 4