summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-01-26 09:09:16 -0600
committerTom Rini <[email protected]>2026-01-26 09:09:16 -0600
commitc08da5d03c2a0b72e81a11ff7ca507e3a6414db3 (patch)
tree4f56e067e2aaf15c440a4685cd3ae2987119e477
parent0ffca1dff1e8960b5920dfc3164e0fcd5892b961 (diff)
parent8805aa120ca5341ca14d8f7f2311f7a85d57a5f9 (diff)
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sunxi
Some improvements for some boards' DRAM setup, to allow boards with "odd" DRAM sizes (1.5GB or 3GB), and to support the T113-s4 with double the co-packaged DRAM. Support for a new board (X96Q TV box), and a fix for the DT name prefix. Also we support the new AXP318W PMIC, which is used on new boards with the A733 SoC. There are some preliminary support patches for this SoC, but they are not quite ready yet - though maybe I push some uncontroversial ones a bit later still.
-rw-r--r--arch/arm/include/asm/arch-sunxi/dram.h1
-rw-r--r--arch/arm/mach-sunxi/dram_dw_helpers.c22
-rw-r--r--arch/arm/mach-sunxi/dram_helpers.c12
-rw-r--r--board/sunxi/MAINTAINERS5
-rw-r--r--board/sunxi/board.c5
-rw-r--r--configs/x96q_defconfig27
-rw-r--r--drivers/power/Kconfig10
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/axp_spl.c20
-rw-r--r--drivers/power/pmic/axp.c1
-rw-r--r--drivers/power/regulator/axp_regulator.c50
-rw-r--r--drivers/ram/sunxi/dram_sun20i_d1.c10
-rw-r--r--drivers/ram/sunxi/dram_sun20i_d1.h11
-rw-r--r--include/axp_pmic.h1
14 files changed, 174 insertions, 2 deletions
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
index 0eccb1e6c28..59e2e980bfa 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -45,5 +45,6 @@ unsigned long sunxi_dram_init(void);
void mctl_await_completion(u32 *reg, u32 mask, u32 val);
bool mctl_mem_matches(u32 offset);
bool mctl_mem_matches_base(u32 offset, ulong base);
+bool mctl_check_memory(phys_addr_t addr);
#endif /* _SUNXI_DRAM_H */
diff --git a/arch/arm/mach-sunxi/dram_dw_helpers.c b/arch/arm/mach-sunxi/dram_dw_helpers.c
index 24767354935..d2af2d57fde 100644
--- a/arch/arm/mach-sunxi/dram_dw_helpers.c
+++ b/arch/arm/mach-sunxi/dram_dw_helpers.c
@@ -143,8 +143,28 @@ void mctl_auto_detect_dram_size(const struct dram_para *para,
unsigned long mctl_calc_size(const struct dram_config *config)
{
+ unsigned long size;
u8 width = config->bus_full_width ? 4 : 2;
/* 8 banks */
- return (1ULL << (config->cols + config->rows + 3)) * width * config->ranks;
+ size = (1ULL << (config->cols + config->rows + 3)) * width *
+ config->ranks;
+
+ /*
+ * There are boards with non-power-of-2 sized DRAM chips, like 1.5GB
+ * or 3GB. They are detected as the larger power-of-2 (2GB and 4GB),
+ * so test the last quarter for being able to store values.
+ */
+ if (!mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3)) {
+ if (mctl_check_memory(CFG_SYS_SDRAM_BASE + size / 4 * 3 - 64)) {
+ size = (size / 4) * 3;
+ debug("capping memory at %ld MB\n", size >> 20);
+ } else {
+ printf("DRAM test failure at address 0x%lx\n",
+ CFG_SYS_SDRAM_BASE + size / 4 * 3 - 64);
+ return 0;
+ }
+ }
+
+ return size;
}
diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c
index 83dbe4ca98f..376b7d14f86 100644
--- a/arch/arm/mach-sunxi/dram_helpers.c
+++ b/arch/arm/mach-sunxi/dram_helpers.c
@@ -62,3 +62,15 @@ bool mctl_mem_matches(u32 offset)
return mctl_mem_matches_base(offset, CFG_SYS_SDRAM_BASE);
}
#endif
+
+bool mctl_check_memory(phys_addr_t addr)
+{
+ uint32_t orig, val;
+
+ orig = readl(addr);
+ writel(~orig, addr);
+ val = readl(addr);
+ writel(orig, addr);
+
+ return ~orig == val;
+}
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index c52e8a34c85..775d0f7ae83 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -611,6 +611,11 @@ M: Andre Przywara <[email protected]>
S: Maintained
F: configs/x96_mate_defconfig
+X96Q TV BOX
+M: J. Neuschäfer <[email protected]>
+S: Maintained
+F: configs/x96q_defconfig
+
X96Q PRO+ TV BOX
M: Andre Przywara <[email protected]>
S: Maintained
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 2929bc17f08..e9e3fb9a571 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -834,9 +834,12 @@ int misc_init_r(void)
/* Set fdtfile to match the FIT configuration chosen in SPL. */
spl_dt_name = get_spl_dt_name();
if (spl_dt_name) {
- char *prefix = IS_ENABLED(CONFIG_ARM64) ? "allwinner/" : "";
+ const char *prefix = "";
char str[64];
+ if (IS_ENABLED(CONFIG_ARM64) && !IS_ENABLED(CONFIG_OF_UPSTREAM))
+ prefix = "allwinner/";
+
snprintf(str, sizeof(str), "%s%s.dtb", prefix, spl_dt_name);
env_set("fdtfile", str);
}
diff --git a/configs/x96q_defconfig b/configs/x96q_defconfig
new file mode 100644
index 00000000000..59f01aae4eb
--- /dev/null
+++ b/configs/x96q_defconfig
@@ -0,0 +1,27 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="allwinner/sun50i-h313-x96q"
+CONFIG_DRAM_CLK=600
+CONFIG_SPL=y
+CONFIG_DRAM_SUNXI_DX_ODT=0x03030303
+CONFIG_DRAM_SUNXI_DX_DRI=0x0e0e0e0e
+CONFIG_DRAM_SUNXI_CA_DRI=0x1f12
+CONFIG_DRAM_SUNXI_TPR0=0xc0001002
+CONFIG_DRAM_SUNXI_TPR2=0x00000100
+CONFIG_DRAM_SUNXI_TPR10=0x002f0107
+CONFIG_DRAM_SUNXI_TPR11=0xddddcccc
+CONFIG_DRAM_SUNXI_TPR12=0xeddc7665
+CONFIG_MACH_SUN50I_H616=y
+CONFIG_SUNXI_DRAM_H616_DDR3_1333=y
+CONFIG_MMC_SUNXI_SLOT_EXTRA=2
+CONFIG_R_I2C_ENABLE=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPL_I2C=y
+CONFIG_SPL_SYS_I2C_LEGACY=y
+CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_SYS_I2C_SPEED=400000
+CONFIG_SUPPORT_EMMC_BOOT=y
+CONFIG_SUN8I_EMAC=y
+CONFIG_AXP305_POWER=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index d17337c0c3f..1b06d8a66c7 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -58,6 +58,7 @@ choice
default AXP209_POWER if MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
default AXP221_POWER if MACH_SUN6I || MACH_SUN8I_A23 || MACH_SUN8I_A33 || MACH_SUN8I_R40
default AXP818_POWER if MACH_SUN8I_A83T
+ default AXP318W_POWER if MACH_SUN60I_A733
default SUNXI_NO_PMIC if MACH_SUNXI_H3_H5 || MACH_SUN50I || MACH_SUN8I_V3S
config SUNXI_NO_PMIC
@@ -140,6 +141,14 @@ config AXP818_POWER
Say y here to enable support for the axp818 pmic found on
A83T dev board.
+config AXP318W_POWER
+ bool "axp318w pmic support"
+ select AXP_PMIC_BUS
+ select CMD_POWEROFF
+ ---help---
+ Select this to enable support for the AXP318W PMIC found on some
+ A733 boards.
+
config SY8106A_POWER
bool "SY8106A pmic support"
depends on MACH_SUNXI_H3_H5
@@ -154,6 +163,7 @@ config AXP_I2C_ADDRESS
depends on ARCH_SUNXI && !SUNXI_NO_PMIC
default 0x36 if AXP305_POWER
default 0x36 if AXP313_POWER
+ default 0x36 if AXP318W_POWER
default 0x30 if AXP152_POWER
default 0x34
---help---
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 3363191fdc8..1a54898c874 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_AXP152_POWER) += axp152.o
obj-$(CONFIG_AXP209_POWER) += axp209.o
obj-$(CONFIG_AXP305_POWER) += axp_spl.o
obj-$(CONFIG_AXP313_POWER) += axp_spl.o
+obj-$(CONFIG_AXP318W_POWER) += axp_spl.o
obj-$(CONFIG_AXP717_POWER) += axp_spl.o
obj-$(CONFIG_AXP809_POWER) += axp809.o
obj-$(CONFIG_AXP818_POWER) += axp818.o
diff --git a/drivers/power/axp_spl.c b/drivers/power/axp_spl.c
index 7c51a9b3dfb..0162ef5e4cc 100644
--- a/drivers/power/axp_spl.c
+++ b/drivers/power/axp_spl.c
@@ -67,6 +67,26 @@ static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
#define AXP_SHUTDOWN_REG 0x1a
#define AXP_SHUTDOWN_MASK BIT(7)
+#elif defined(CONFIG_AXP318W_POWER) /* AXP318W */
+
+static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
+ { 0x10, BIT(0), 0x12, 0x1f, 1000, 3400, 100, NA },
+ { 0x10, BIT(1), 0x13, 0x7f, 500, 1540, 10, 70 },
+ { 0x10, BIT(2), 0x14, 0x7f, 500, 1540, 10, 70 },
+ { 0x10, BIT(3), 0x15, 0x7f, 500, 1540, 10, 70 },
+ { 0x10, BIT(4), 0x16, 0x7f, 500, 1540, 10, 70 },
+ { 0x10, BIT(5), 0x17, 0x7f, 500, 1540, 10, 70 },
+ { 0x10, BIT(6), 0x18, 0x7f, 500, 1840, 10, 70 },
+ { 0x10, BIT(7), 0x19, 0x7f, 500, 1840, 10, 70 },
+ { 0x11, BIT(0), 0x1a, 0x7f, 500, 1840, 10, 70 },
+};
+
+#define AXP_CHIP_VERSION 0
+#define AXP_CHIP_VERSION_MASK 0
+#define AXP_CHIP_ID 0
+#define AXP_SHUTDOWN_REG 0x55
+#define AXP_SHUTDOWN_MASK BIT(7)
+
#elif defined(CONFIG_AXP305_POWER) /* AXP305 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
diff --git a/drivers/power/pmic/axp.c b/drivers/power/pmic/axp.c
index 1204ec00f8d..7d8348b0769 100644
--- a/drivers/power/pmic/axp.c
+++ b/drivers/power/pmic/axp.c
@@ -95,6 +95,7 @@ static const struct udevice_id axp_pmic_ids[] = {
{ .compatible = "x-powers,axp806", .data = AXP806_ID },
{ .compatible = "x-powers,axp809", .data = AXP809_ID },
{ .compatible = "x-powers,axp813", .data = AXP813_ID },
+ { .compatible = "x-powers,axp318w", .data = AXP318_ID },
{ }
};
diff --git a/drivers/power/regulator/axp_regulator.c b/drivers/power/regulator/axp_regulator.c
index 7794a4f5d92..16d3a8f7f90 100644
--- a/drivers/power/regulator/axp_regulator.c
+++ b/drivers/power/regulator/axp_regulator.c
@@ -189,6 +189,55 @@ static const struct axp_regulator_plat axp313_regulators[] = {
{ }
};
+ /*
+ * Only two level step tuning is implemented for DCDC6, 8, 9
+ * so the voltage below is not support in this driver
+ * DCDC6: 20 (v1.8 - 2.4v), 40 (2.44v - 2.76v)
+ * DCDC8,9: 100 (1.9v - 3.4v)
+ */
+static const struct axp_regulator_plat axp318_regulators[] = {
+ { "dcdc1", 0x10, BIT(0), 0x12, 0x1f, 1000, 3400, 100, NA },
+ { "dcdc2", 0x10, BIT(1), 0x13, 0x7f, 500, 1540, 10, 70 },
+ { "dcdc3", 0x10, BIT(2), 0x14, 0x7f, 500, 1540, 10, 70 },
+ { "dcdc4", 0x10, BIT(3), 0x15, 0x7f, 500, 1540, 10, 70 },
+ { "dcdc5", 0x10, BIT(4), 0x16, 0x7f, 500, 1540, 10, 70 },
+ { "dcdc6", 0x10, BIT(5), 0x17, 0x7f, 500, 1540, 10, 70 },
+ { "dcdc7", 0x10, BIT(6), 0x18, 0x7f, 500, 1840, 10, 70 },
+ { "dcdc8", 0x10, BIT(7), 0x19, 0x7f, 500, 1840, 10, 70 },
+ { "dcdc9", 0x11, BIT(0), 0x1a, 0x7f, 500, 1840, 10, 70 },
+ { "aldo1", 0x20, BIT(0), 0x24, 0x1f, 500, 3400, 100, NA },
+ { "aldo2", 0x20, BIT(1), 0x25, 0x1f, 500, 3400, 100, NA },
+ { "aldo3", 0x20, BIT(2), 0x26, 0x1f, 500, 3400, 100, NA },
+ { "aldo4", 0x20, BIT(3), 0x27, 0x1f, 500, 3400, 100, NA },
+ { "aldo5", 0x20, BIT(4), 0x28, 0x1f, 500, 3400, 100, NA },
+ { "aldo6", 0x20, BIT(5), 0x29, 0x1f, 500, 3400, 100, NA },
+ { "bldo1", 0x20, BIT(6), 0x2a, 0x1f, 500, 3400, 100, NA },
+ { "bldo2", 0x20, BIT(7), 0x2b, 0x1f, 500, 3400, 100, NA },
+ { "bldo3", 0x21, BIT(0), 0x2c, 0x1f, 500, 3400, 100, NA },
+ { "bldo4", 0x21, BIT(1), 0x2d, 0x1f, 500, 3400, 100, NA },
+ { "bldo5", 0x21, BIT(2), 0x2e, 0x1f, 500, 3400, 100, NA },
+ { "cldo1", 0x21, BIT(3), 0x2f, 0x1f, 500, 3400, 100, NA },
+ { "cldo2", 0x21, BIT(4), 0x30, 0x1f, 500, 3400, 100, NA },
+ { "cldo3", 0x21, BIT(5), 0x31, 0x1f, 500, 3400, 100, NA },
+ { "cldo4", 0x21, BIT(6), 0x32, 0x1f, 500, 3400, 100, NA },
+ { "cldo5", 0x21, BIT(7), 0x33, 0x1f, 500, 3400, 100, NA },
+ { "dldo1", 0x22, BIT(0), 0x34, 0x1f, 500, 3400, 100, NA },
+ { "dldo2", 0x22, BIT(1), 0x35, 0x1f, 500, 3400, 100, NA },
+ { "dldo3", 0x22, BIT(2), 0x36, 0x1f, 500, 3400, 100, NA },
+ { "dldo4", 0x22, BIT(3), 0x37, 0x1f, 500, 3400, 100, NA },
+ { "dldo5", 0x22, BIT(4), 0x38, 0x1f, 500, 3400, 100, NA },
+ { "dldo6", 0x22, BIT(5), 0x39, 0x1f, 500, 3400, 100, NA },
+ { "eldo1", 0x22, BIT(6), 0x3a, 0x1f, 500, 1500, 25, NA },
+ { "eldo2", 0x22, BIT(7), 0x3b, 0x1f, 500, 1500, 25, NA },
+ { "eldo3", 0x23, BIT(0), 0x3c, 0x1f, 500, 1500, 25, NA },
+ { "eldo4", 0x23, BIT(1), 0x3d, 0x1f, 500, 1500, 25, NA },
+ { "eldo5", 0x23, BIT(2), 0x3e, 0x1f, 500, 1500, 25, NA },
+ { "eldo6", 0x23, BIT(3), 0x3f, 0x1f, 500, 1500, 25, NA },
+ { "swout1", 0x11, BIT(3), NA, NA, NA, NA, NA, NA },
+ { "swout2", 0x11, BIT(4), NA, NA, NA, NA, NA, NA },
+ { }
+};
+
/*
* The "dcdc2" regulator has another range, beyond 1.54V up to 3.4V, in
* steps of 100mV. We cannot model this easily, but also don't need that,
@@ -318,6 +367,7 @@ static const struct axp_regulator_plat *const axp_regulators[] = {
[AXP221_ID] = axp22x_regulators,
[AXP223_ID] = axp22x_regulators,
[AXP313_ID] = axp313_regulators,
+ [AXP318_ID] = axp318_regulators,
[AXP323_ID] = axp313_regulators,
[AXP717_ID] = axp717_regulators,
[AXP803_ID] = axp803_regulators,
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
index a1794032f3b..79cf0a51e47 100644
--- a/drivers/ram/sunxi/dram_sun20i_d1.c
+++ b/drivers/ram/sunxi/dram_sun20i_d1.c
@@ -54,6 +54,11 @@ static void sid_read_ldoB_cal(const dram_para_t *para)
clrsetbits_le32(0x3000150, 0xff00, reg << 8);
}
+static uint32_t sid_read_soc_chipid(void)
+{
+ return readl(SUNXI_SID_BASE + 0x00) & 0xffff;
+}
+
static void dram_voltage_set(const dram_para_t *para)
{
int vol;
@@ -663,6 +668,11 @@ static void mctl_phy_ac_remapping(const dram_para_t *para,
fuse = (readl(SUNXI_SID_BASE + 0x28) & 0xf00) >> 8;
debug("DDR efuse: 0x%x\n", fuse);
+ debug("SoC Chip ID: 0x%08x\n", sid_read_soc_chipid());
+
+ /* No remapping needed on T113-s4 with 256MB co-packaged DRAM */
+ if (sid_read_soc_chipid() == SUNXI_CHIPID_T113M4020DC0)
+ return;
if (para->dram_type == SUNXI_DRAM_TYPE_DDR2) {
if (fuse == 15)
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.h b/drivers/ram/sunxi/dram_sun20i_d1.h
index 91383f6cf10..83ae7eb36cd 100644
--- a/drivers/ram/sunxi/dram_sun20i_d1.h
+++ b/drivers/ram/sunxi/dram_sun20i_d1.h
@@ -20,6 +20,17 @@ enum sunxi_dram_type {
};
/*
+ * Chip-IDs taken from
+ * https://github.com/ua1arn/hftrx/blob/25d8cb9e4cfe1d7d0e4a2f641025c88a9ec5e758/inc/clocks.h#L250
+ */
+enum sunxi_soc_chipid {
+ SUNXI_CHIPID_F133A = 0x5C00,
+ SUNXI_CHIPID_D1S = 0x5E00,
+ SUNXI_CHIPID_T113S3 = 0x6000,
+ SUNXI_CHIPID_T113M4020DC0 = 0x7200,
+};
+
+/*
* This structure contains a mixture of fixed configuration settings,
* variables that are used at runtime to communicate settings between
* different stages and functions, and unused values.
diff --git a/include/axp_pmic.h b/include/axp_pmic.h
index 1806a7270a0..2f547da74c2 100644
--- a/include/axp_pmic.h
+++ b/include/axp_pmic.h
@@ -39,6 +39,7 @@ enum {
AXP806_ID,
AXP809_ID,
AXP813_ID,
+ AXP318_ID,
};
int axp_set_dcdc1(unsigned int mvolt);