summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);