aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-10-23 09:04:55 -0400
committerTom Rini <trini@konsulko.com>2023-10-23 11:39:33 -0400
commita8f6dab0d41caaa985241d4d79690b8bcef40720 (patch)
tree0bc048489f206164173202cf4c66451b9cfc94da
parentc51f2ea72658a9b5514780b9cf719180d7cdd2cc (diff)
parentfa066df62ed9bfe0aed7749a68457468ad8bcc1c (diff)
downloadu-boot-a8f6dab0d41caaa985241d4d79690b8bcef40720.zip
u-boot-a8f6dab0d41caaa985241d4d79690b8bcef40720.tar.gz
u-boot-a8f6dab0d41caaa985241d4d79690b8bcef40720.tar.bz2
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sunxi
This is mostly about support for the Allwinner R528/T113s SoC, which is reportedly the same die as the Allwinner D1, but with the two Arm Cortex-A7 cores activated instead of the RISC-V one. Using sunxi code outside of arch/arm proved to be difficult, so apart from enabling this Arm SoC, the patches also prepare for more refactoring to get the D1 nicely supported some day: - We get rid of some Kconfig (hard-)coded GPIO pins, responsible for enabling regulators. - The GPIO code is moved out of arch/arm, into drivers/gpio. - Some definitions are moved out of header files under asm/arch. - Some T113s/D1 specific definitions are guarded by a generic Kconfig symbol (CONFIG_SUNXI_GEN_NCAT2). - The DRAM controller initialisation code is located under drivers/ram. - The base SoC .dtsi files are shared (under arch/riscv, as in Linux). Of course there are also the usual new SoC specific patches, like clock and pinmux descriptions, alongside a rework of the pinctrl code, since Allwinner changed the GPIO register layout, for the first time since sunxi's inception. On top of this the PSCI code sees some update, to provide SMP services for R528/T113s boards. Many thanks to Sam for providing this code and staying strong through the review cycles. The final patch enables support for one popular board, I hope to see more DTs and defconfigs contributed in the future! Many thanks to all the various contributors, testers and reviewers, that series was a real team effort!
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/cpu/armv7/Kconfig3
-rw-r--r--arch/arm/cpu/armv7/sunxi/psci.c190
-rw-r--r--arch/arm/cpu/armv7/sunxi/sram.c1
-rw-r--r--arch/arm/cpu/armv8/fel_utils.S1
-rw-r--r--arch/arm/dts/Makefile2
-rw-r--r--arch/arm/dts/axp209.dtsi7
-rw-r--r--arch/arm/dts/sun50i-a64.dtsi3
-rw-r--r--arch/arm/dts/sun50i-h6-pine-h64-model-b.dts2
-rw-r--r--arch/arm/dts/sun50i-h616-orangepi-zero.dtsi134
-rw-r--r--arch/arm/dts/sun50i-h616-orangepi-zero2.dts121
-rw-r--r--arch/arm/dts/sun50i-h616-x96-mate.dts2
-rw-r--r--arch/arm/dts/sun50i-h618-orangepi-zero3.dts94
-rw-r--r--arch/arm/dts/sun5i-r8-chip.dts6
-rw-r--r--arch/arm/dts/sun5i.dtsi11
-rw-r--r--arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts137
-rw-r--r--arch/arm/dts/sun7i-a20-icnova-a20.dtsi62
-rw-r--r--arch/arm/dts/sun8i-a23-a33.dtsi2
-rw-r--r--arch/arm/dts/sun8i-a83t.dtsi2
-rw-r--r--arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts35
-rw-r--r--arch/arm/dts/sun8i-t113s.dtsi59
-rw-r--r--arch/arm/dts/sun8i-v3s.dtsi2
-rw-r--r--arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi126
-rw-r--r--arch/arm/dts/sunxi-u-boot.dtsi7
-rw-r--r--arch/arm/include/asm/arch-sunxi/boot0.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock.h3
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h12
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun4i.h17
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h7
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sun9i.h9
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h39
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpucfg.h67
-rw-r--r--arch/arm/include/asm/arch-sunxi/mmc.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/prcm.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/serial.h32
-rw-r--r--arch/arm/include/asm/arch-sunxi/timer.h2
-rw-r--r--arch/arm/mach-sunxi/Kconfig42
-rw-r--r--arch/arm/mach-sunxi/Makefile2
-rw-r--r--arch/arm/mach-sunxi/board.c31
-rw-r--r--arch/arm/mach-sunxi/clock_sun50i_h6.c45
-rw-r--r--arch/arm/mach-sunxi/cpu_info.c2
-rw-r--r--arch/arm/mach-sunxi/dram_suniv.c2
-rw-r--r--arch/arm/mach-sunxi/gtbus_sun9i.c1
-rw-r--r--arch/arm/mach-sunxi/pinmux.c78
-rw-r--r--arch/arm/mach-sunxi/spl_spi_sunxi.c1
-rw-r--r--arch/arm/mach-sunxi/timer.c1
-rw-r--r--arch/riscv/dts/sunxi-d1-t113.dtsi15
-rw-r--r--arch/riscv/dts/sunxi-d1s-t113.dtsi927
-rw-r--r--board/sunxi/MAINTAINERS5
-rw-r--r--board/sunxi/board.c34
-rw-r--r--board/sunxi/chip.c2
-rw-r--r--common/spl/Kconfig3
-rw-r--r--configs/A10-OLinuXino-Lime_defconfig1
-rw-r--r--configs/A20-OLinuXino-Lime2-eMMC_defconfig1
-rw-r--r--configs/A20-OLinuXino-Lime2_defconfig1
-rw-r--r--configs/A20-OLinuXino-Lime_defconfig1
-rw-r--r--configs/A20-OLinuXino_MICRO-eMMC_defconfig1
-rw-r--r--configs/A20-OLinuXino_MICRO_defconfig1
-rw-r--r--configs/A20-Olimex-SOM-EVB_defconfig1
-rw-r--r--configs/A20-Olimex-SOM204-EVB-eMMC_defconfig1
-rw-r--r--configs/A20-Olimex-SOM204-EVB_defconfig1
-rw-r--r--configs/Bananapi_M2_Ultra_defconfig1
-rw-r--r--configs/Bananapi_defconfig1
-rw-r--r--configs/Bananapro_defconfig1
-rw-r--r--configs/Cubieboard2_defconfig1
-rw-r--r--configs/Cubieboard_defconfig1
-rw-r--r--configs/Cubietruck_defconfig1
-rw-r--r--configs/Itead_Ibox_A20_defconfig1
-rw-r--r--configs/Lamobo_R1_defconfig2
-rw-r--r--configs/Linksprite_pcDuino3_Nano_defconfig1
-rw-r--r--configs/Linksprite_pcDuino3_defconfig1
-rw-r--r--configs/Mele_A1000_defconfig1
-rw-r--r--configs/Orangepi_defconfig1
-rw-r--r--configs/Orangepi_mini_defconfig1
-rw-r--r--configs/Sinovoip_BPI_M3_defconfig1
-rw-r--r--configs/bananapi_m1_plus_defconfig1
-rw-r--r--configs/bananapi_m2_plus_h3_defconfig1
-rw-r--r--configs/bananapi_m2_plus_h5_defconfig1
-rw-r--r--configs/i12-tvbox_defconfig1
-rw-r--r--configs/jesurun_q5_defconfig1
-rw-r--r--configs/mangopi_mq_r_defconfig15
-rw-r--r--configs/mixtile_loftq_defconfig1
-rw-r--r--configs/nanopi_m1_plus_defconfig1
-rw-r--r--configs/nanopi_neo_plus2_defconfig1
-rw-r--r--configs/nanopi_r1s_h5_defconfig1
-rw-r--r--configs/orangepi_pc2_defconfig1
-rw-r--r--configs/orangepi_plus2e_defconfig1
-rw-r--r--configs/orangepi_plus_defconfig3
-rw-r--r--configs/orangepi_win_defconfig1
-rw-r--r--configs/pine_h64_defconfig1
-rw-r--r--configs/zeropi_defconfig1
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/ata/ahci_sunxi.c9
-rw-r--r--drivers/clk/sunxi/Kconfig7
-rw-r--r--drivers/clk/sunxi/Makefile1
-rw-r--r--drivers/clk/sunxi/clk_d1.c84
-rw-r--r--drivers/clk/sunxi/clk_sunxi.c5
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/axp_gpio.c1
-rw-r--r--drivers/gpio/sunxi_gpio.c189
-rw-r--r--drivers/i2c/mvtwsi.c3
-rw-r--r--drivers/i2c/sun6i_p2wi.c2
-rw-r--r--drivers/i2c/sun8i_rsb.c2
-rw-r--r--drivers/mmc/sunxi_mmc.c9
-rw-r--r--drivers/net/sun8i_emac.c7
-rw-r--r--drivers/net/sunxi_emac.c38
-rw-r--r--drivers/pinctrl/sunxi/Kconfig5
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c47
-rw-r--r--drivers/ram/Kconfig3
-rw-r--r--drivers/ram/Makefile3
-rw-r--r--drivers/ram/sunxi/Kconfig60
-rw-r--r--drivers/ram/sunxi/Makefile3
-rw-r--r--drivers/ram/sunxi/dram_sun20i_d1.c1441
-rw-r--r--drivers/ram/sunxi/dram_sun20i_d1.h73
-rw-r--r--drivers/video/hitachi_tx18d42vm_lcd.c1
-rw-r--r--drivers/video/ssd2828.c1
-rw-r--r--drivers/video/sunxi/sunxi_display.c1
-rw-r--r--drivers/video/sunxi/sunxi_lcd.c1
-rw-r--r--include/configs/sunxi-common.h2
-rw-r--r--include/dt-bindings/clock/sun20i-d1-ccu.h158
-rw-r--r--include/dt-bindings/clock/sun20i-d1-r-ccu.h19
-rw-r--r--include/dt-bindings/clock/sun50i-h6-ccu.h2
-rw-r--r--include/dt-bindings/clock/sun50i-h616-ccu.h2
-rw-r--r--include/dt-bindings/clock/sun6i-rtc.h2
-rw-r--r--include/dt-bindings/reset/sun20i-d1-ccu.h79
-rw-r--r--include/dt-bindings/reset/sun20i-d1-r-ccu.h16
-rw-r--r--include/dt-bindings/reset/sun50i-h6-ccu.h2
-rw-r--r--include/dt-bindings/reset/sun50i-h6-r-ccu.h2
-rw-r--r--include/dt-bindings/reset/sun50i-h616-ccu.h2
-rw-r--r--include/sunxi_gpio.h (renamed from arch/arm/include/asm/arch-sunxi/gpio.h)83
131 files changed, 4234 insertions, 594 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 531b081..d812685 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1135,7 +1135,6 @@ config ARCH_SUNXI
select DM_MMC if MMC
select DM_SCSI if SCSI
select DM_SERIAL
- select GPIO_EXTRA_HEADER
select OF_BOARD_SETUP
select OF_CONTROL
select OF_SEPARATE
@@ -1159,6 +1158,8 @@ config ARCH_SUNXI
imply CMD_GPT
imply CMD_UBI if MTD_RAW_NAND
imply DISTRO_DEFAULTS
+ imply DM_REGULATOR
+ imply DM_REGULATOR_FIXED
imply FAT_WRITE
imply FIT
imply OF_LIBFDT_OVERLAY
diff --git a/arch/arm/cpu/armv7/Kconfig b/arch/arm/cpu/armv7/Kconfig
index f015d13..4eb34b7 100644
--- a/arch/arm/cpu/armv7/Kconfig
+++ b/arch/arm/cpu/armv7/Kconfig
@@ -61,8 +61,9 @@ config ARMV7_SECURE_MAX_SIZE
config ARM_GIC_BASE_ADDRESS
hex
depends on ARMV7_NONSEC
- depends on ARCH_EXYNOS5
+ depends on ARCH_EXYNOS5 || MACH_SUN8I_R528
default 0x10480000 if ARCH_EXYNOS5
+ default 0x03020000 if MACH_SUN8I_R528
help
Override the GIC base address if the Arm Cortex defined
CBAR/PERIPHBASE system register holds the wrong value.
diff --git a/arch/arm/cpu/armv7/sunxi/psci.c b/arch/arm/cpu/armv7/sunxi/psci.c
index e1d3638..5cb8cfa 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.c
+++ b/arch/arm/cpu/armv7/sunxi/psci.c
@@ -11,8 +11,6 @@
#include <asm/cache.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/cpucfg.h>
-#include <asm/arch/prcm.h>
#include <asm/armv7.h>
#include <asm/gic.h>
#include <asm/io.h>
@@ -28,6 +26,17 @@
#define GICC_BASE (SUNXI_GIC400_BASE + GIC_CPU_OFFSET_A15)
/*
+ * Offsets into the CPUCFG block applicable to most SUNXIs.
+ */
+#define SUNXI_CPU_RST(cpu) (0x40 + (cpu) * 0x40 + 0x0)
+#define SUNXI_CPU_STATUS(cpu) (0x40 + (cpu) * 0x40 + 0x8)
+#define SUNXI_GEN_CTRL (0x184)
+#define SUNXI_PRIV0 (0x1a4)
+#define SUN7I_CPU1_PWR_CLAMP (0x1b0)
+#define SUN7I_CPU1_PWROFF (0x1b4)
+#define SUNXI_DBG_CTRL1 (0x1e4)
+
+/*
* R40 is different from other single cluster SoCs.
*
* The power clamps are located in the unused space after the per-core
@@ -38,6 +47,24 @@
#define SUN8I_R40_PWR_CLAMP(cpu) (0x120 + (cpu) * 0x4)
#define SUN8I_R40_SRAMC_SOFT_ENTRY_REG0 (0xbc)
+/*
+ * R528 is also different, as it has both cores powered up (but held in reset
+ * state) after the SoC is reset. Like the R40, it uses a "soft" entry point
+ * address register, but unlike the R40, it uses a newer "CPUX" block to manage
+ * CPU state, rather than the older CPUCFG system.
+ */
+#define SUN8I_R528_SOFT_ENTRY (0x1c8)
+#define SUN8I_R528_C0_RST_CTRL (0x0000)
+#define SUN8I_R528_C0_CTRL_REG0 (0x0010)
+#define SUN8I_R528_C0_CPU_STATUS (0x0080)
+
+#define SUN8I_R528_C0_STATUS_STANDBYWFI (16)
+
+/* Only newer cores have this additional IP block. */
+#ifndef SUNXI_R_CPUCFG_BASE
+#define SUNXI_R_CPUCFG_BASE 0
+#endif
+
static void __secure cp15_write_cntp_tval(u32 tval)
{
asm volatile ("mcr p15, 0, %0, c14, c2, 0" : : "r" (tval));
@@ -76,11 +103,8 @@ static void __secure __mdelay(u32 ms)
isb();
}
-static void __secure clamp_release(u32 __maybe_unused *clamp)
+static void __secure clamp_release(u32 *clamp)
{
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
- defined(CONFIG_MACH_SUN8I_H3) || \
- defined(CONFIG_MACH_SUN8I_R40)
u32 tmp = 0x1ff;
do {
tmp >>= 1;
@@ -88,24 +112,54 @@ static void __secure clamp_release(u32 __maybe_unused *clamp)
} while (tmp);
__mdelay(10);
-#endif
}
-static void __secure clamp_set(u32 __maybe_unused *clamp)
+static void __secure clamp_set(u32 *clamp)
{
-#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN7I) || \
- defined(CONFIG_MACH_SUN8I_H3) || \
- defined(CONFIG_MACH_SUN8I_R40)
writel(0xff, clamp);
-#endif
}
-static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
- int cpu)
+static void __secure sunxi_cpu_set_entry(int __always_unused cpu, void *entry)
+{
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
+ writel((u32)entry,
+ SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ writel((u32)entry,
+ SUNXI_R_CPUCFG_BASE + SUN8I_R528_SOFT_ENTRY);
+ } else {
+ writel((u32)entry, SUNXI_CPUCFG_BASE + SUNXI_PRIV0);
+ }
+}
+
+static void __secure sunxi_cpu_set_power(int cpu, bool on)
{
+ u32 *clamp = NULL;
+ u32 *pwroff;
+
+ /* sun7i (A20) is different from other single cluster SoCs */
+ if (IS_ENABLED(CONFIG_MACH_SUN7I)) {
+ clamp = (void *)SUNXI_CPUCFG_BASE + SUN7I_CPU1_PWR_CLAMP;
+ pwroff = (void *)SUNXI_CPUCFG_BASE + SUN7I_CPU1_PWROFF;
+ cpu = 0;
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R40)) {
+ clamp = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWR_CLAMP(cpu);
+ pwroff = (void *)SUNXI_CPUCFG_BASE + SUN8I_R40_PWROFF;
+ } else if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ /* R528 leaves both cores powered up, manages them via reset */
+ return;
+ } else {
+ if (IS_ENABLED(CONFIG_MACH_SUN6I) ||
+ IS_ENABLED(CONFIG_MACH_SUN8I_H3))
+ clamp = (void *)SUNXI_PRCM_BASE + 0x140 + cpu * 0x4;
+
+ pwroff = (void *)SUNXI_PRCM_BASE + 0x100;
+ }
+
if (on) {
/* Release power clamp */
- clamp_release(clamp);
+ if (clamp)
+ clamp_release(clamp);
/* Clear power gating */
clrbits_le32(pwroff, BIT(cpu));
@@ -114,82 +168,80 @@ static void __secure sunxi_power_switch(u32 *clamp, u32 *pwroff, bool on,
setbits_le32(pwroff, BIT(cpu));
/* Activate power clamp */
- clamp_set(clamp);
+ if (clamp)
+ clamp_set(clamp);
}
}
-#ifdef CONFIG_MACH_SUN8I_R40
-/* secondary core entry address is programmed differently on R40 */
-static void __secure sunxi_set_entry_address(void *entry)
+static void __secure sunxi_cpu_set_reset(int cpu, bool reset)
{
- writel((u32)entry,
- SUNXI_SRAMC_BASE + SUN8I_R40_SRAMC_SOFT_ENTRY_REG0);
-}
-#else
-static void __secure sunxi_set_entry_address(void *entry)
-{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ if (reset)
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_RST_CTRL,
+ BIT(cpu));
+ else
+ setbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_RST_CTRL,
+ BIT(cpu));
+
+ return;
+ }
- writel((u32)entry, &cpucfg->priv0);
+ writel(reset ? 0b00 : 0b11, SUNXI_CPUCFG_BASE + SUNXI_CPU_RST(cpu));
}
-#endif
-#ifdef CONFIG_MACH_SUN7I
-/* sun7i (A20) is different from other single cluster SoCs */
-static void __secure sunxi_cpu_set_power(int __always_unused cpu, bool on)
+static void __secure sunxi_cpu_set_locking(int cpu, bool lock)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ /* Not required on R528 */
+ return;
+ }
- sunxi_power_switch(&cpucfg->cpu1_pwr_clamp, &cpucfg->cpu1_pwroff,
- on, 0);
+ if (lock)
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_DBG_CTRL1, BIT(cpu));
+ else
+ setbits_le32(SUNXI_CPUCFG_BASE + SUNXI_DBG_CTRL1, BIT(cpu));
}
-#elif defined CONFIG_MACH_SUN8I_R40
-static void __secure sunxi_cpu_set_power(int cpu, bool on)
+
+static bool __secure sunxi_cpu_poll_wfi(int cpu)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ return !!(readl(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_CPU_STATUS) &
+ BIT(SUN8I_R528_C0_STATUS_STANDBYWFI + cpu));
+ }
- sunxi_power_switch((void *)cpucfg + SUN8I_R40_PWR_CLAMP(cpu),
- (void *)cpucfg + SUN8I_R40_PWROFF,
- on, cpu);
+ return !!(readl(SUNXI_CPUCFG_BASE + SUNXI_CPU_STATUS(cpu)) & BIT(2));
}
-#else /* ! CONFIG_MACH_SUN7I && ! CONFIG_MACH_SUN8I_R40 */
-static void __secure sunxi_cpu_set_power(int cpu, bool on)
+
+static void __secure sunxi_cpu_invalidate_cache(int cpu)
{
- struct sunxi_prcm_reg *prcm =
- (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528)) {
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUN8I_R528_C0_CTRL_REG0,
+ BIT(cpu));
+ return;
+ }
- sunxi_power_switch(&prcm->cpu_pwr_clamp[cpu], &prcm->cpu_pwroff,
- on, cpu);
+ clrbits_le32(SUNXI_CPUCFG_BASE + SUNXI_GEN_CTRL, BIT(cpu));
}
-#endif /* CONFIG_MACH_SUN7I */
-void __secure sunxi_cpu_power_off(u32 cpuid)
+static void __secure sunxi_cpu_power_off(u32 cpuid)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
u32 cpu = cpuid & 0x3;
/* Wait for the core to enter WFI */
- while (1) {
- if (readl(&cpucfg->cpu[cpu].status) & BIT(2))
- break;
+ while (!sunxi_cpu_poll_wfi(cpu))
__mdelay(1);
- }
/* Assert reset on target CPU */
- writel(0, &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, true);
/* Lock CPU (Disable external debug access) */
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ sunxi_cpu_set_locking(cpu, true);
/* Power down CPU */
sunxi_cpu_set_power(cpuid, false);
- /* Unlock CPU (Disable external debug access) */
- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ /* Unlock CPU (Reenable external debug access) */
+ sunxi_cpu_set_locking(cpu, false);
}
static u32 __secure cp15_read_scr(void)
@@ -246,33 +298,31 @@ out:
int __secure psci_cpu_on(u32 __always_unused unused, u32 mpidr, u32 pc,
u32 context_id)
{
- struct sunxi_cpucfg_reg *cpucfg =
- (struct sunxi_cpucfg_reg *)SUNXI_CPUCFG_BASE;
u32 cpu = (mpidr & 0x3);
/* store target PC and context id */
psci_save(cpu, pc, context_id);
/* Set secondary core power on PC */
- sunxi_set_entry_address(&psci_cpu_entry);
+ sunxi_cpu_set_entry(cpu, &psci_cpu_entry);
/* Assert reset on target CPU */
- writel(0, &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, true);
/* Invalidate L1 cache */
- clrbits_le32(&cpucfg->gen_ctrl, BIT(cpu));
+ sunxi_cpu_invalidate_cache(cpu);
/* Lock CPU (Disable external debug access) */
- clrbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ sunxi_cpu_set_locking(cpu, true);
/* Power up target CPU */
sunxi_cpu_set_power(cpu, true);
/* De-assert reset on target CPU */
- writel(BIT(1) | BIT(0), &cpucfg->cpu[cpu].rst);
+ sunxi_cpu_set_reset(cpu, false);
- /* Unlock CPU (Disable external debug access) */
- setbits_le32(&cpucfg->dbg_ctrl1, BIT(cpu));
+ /* Unlock CPU (Reenable external debug access) */
+ sunxi_cpu_set_locking(cpu, false);
return ARM_PSCI_RET_SUCCESS;
}
diff --git a/arch/arm/cpu/armv7/sunxi/sram.c b/arch/arm/cpu/armv7/sunxi/sram.c
index 28564c2..28ff6a1 100644
--- a/arch/arm/cpu/armv7/sunxi/sram.c
+++ b/arch/arm/cpu/armv7/sunxi/sram.c
@@ -12,6 +12,7 @@
#include <common.h>
#include <init.h>
#include <asm/io.h>
+#include <asm/arch/cpu.h>
void sunxi_sram_init(void)
{
diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 2fe38a1..939869b 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -10,6 +10,7 @@
#include <config.h>
#include <asm/system.h>
#include <linux/linkage.h>
+#include <asm/arch/cpu.h>
/*
* We don't overwrite save_boot_params() here, to save the FEL state upon
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 4569483..3a9b365 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -776,6 +776,8 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \
sun8i-s3-pinecube.dtb \
sun8i-v3-sl631-imx179.dtb \
sun8i-v3s-licheepi-zero.dtb
+dtb-$(CONFIG_MACH_SUN8I_R528) += \
+ sun8i-t113s-mangopi-mq-r-t113.dtb
dtb-$(CONFIG_MACH_SUN50I_H5) += \
sun50i-h5-bananapi-m2-plus.dtb \
sun50i-h5-emlid-neutis-n5-devboard.dtb \
diff --git a/arch/arm/dts/axp209.dtsi b/arch/arm/dts/axp209.dtsi
index ca240cd..469d0f7 100644
--- a/arch/arm/dts/axp209.dtsi
+++ b/arch/arm/dts/axp209.dtsi
@@ -48,6 +48,13 @@
* http://dl.linux-sunxi.org/AXP/AXP209%20Datasheet%20v1.0_cn.pdf
*/
+/ {
+ pmic-temp {
+ compatible = "iio-hwmon";
+ io-channels = <&axp_adc 4>; /* Internal temperature */
+ };
+};
+
&axp209 {
compatible = "x-powers,axp209";
interrupt-controller;
diff --git a/arch/arm/dts/sun50i-a64.dtsi b/arch/arm/dts/sun50i-a64.dtsi
index 135762b..2240eae 100644
--- a/arch/arm/dts/sun50i-a64.dtsi
+++ b/arch/arm/dts/sun50i-a64.dtsi
@@ -93,6 +93,7 @@
L2: l2-cache {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
};
};
@@ -407,7 +408,7 @@
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
clock-names = "ahb", "tcon-ch0";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
reset-names = "lcd", "lvds";
diff --git a/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts b/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts
index 686f58e..b710f1a 100644
--- a/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts
+++ b/arch/arm/dts/sun50i-h6-pine-h64-model-b.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2019 Corentin LABBE <clabbe@baylibre.com>
*/
diff --git a/arch/arm/dts/sun50i-h616-orangepi-zero.dtsi b/arch/arm/dts/sun50i-h616-orangepi-zero.dtsi
new file mode 100644
index 0000000..15290e6
--- /dev/null
+++ b/arch/arm/dts/sun50i-h616-orangepi-zero.dtsi
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ *
+ * DT nodes common between Orange Pi Zero 2 and Orange Pi Zero 3.
+ * Excludes PMIC nodes and properties, since they are different between the two.
+ */
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ ethernet0 = &emac0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
+ default-state = "on";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
+ };
+ };
+
+ reg_vcc5v: vcc5v {
+ /* board wide 5V supply directly from the USB-C socket */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ reg_usb1_vbus: regulator-usb1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&reg_vcc5v>;
+ enable-active-high;
+ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */
+ };
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+/* USB 2 & 3 are on headers only. */
+
+&emac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ allwinner,rx-delay-ps = <3100>;
+ allwinner,tx-delay-ps = <700>;
+ status = "okay";
+};
+
+&mdio0 {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&mmc0 {
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>;
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&usbotg {
+ /*
+ * PHY0 pins are connected to a USB-C socket, but a role switch
+ * is not implemented: both CC pins are pulled to GND.
+ * The VBUS pins power the device, so a fixed peripheral mode
+ * is the best choice.
+ * The board can be powered via GPIOs, in this case port0 *can*
+ * act as a host (with a cable/adapter ignoring CC), as VBUS is
+ * then provided by the GPIOs. Any user of this setup would
+ * need to adjust the DT accordingly: dr_mode set to "host",
+ * enabling OHCI0 and EHCI0.
+ */
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun50i-h616-orangepi-zero2.dts b/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
index cb8600d..d83852e 100644
--- a/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
+++ b/arch/arm/dts/sun50i-h616-orangepi-zero2.dts
@@ -1,99 +1,23 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2020 Arm Ltd.
*/
/dts-v1/;
-#include "sun50i-h616.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/leds/common.h>
+#include "sun50i-h616-orangepi-zero.dtsi"
/ {
model = "OrangePi Zero2";
compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616";
-
- aliases {
- ethernet0 = &emac0;
- serial0 = &uart0;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- leds {
- compatible = "gpio-leds";
-
- led-0 {
- function = LED_FUNCTION_POWER;
- color = <LED_COLOR_ID_RED>;
- gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
- default-state = "on";
- };
-
- led-1 {
- function = LED_FUNCTION_STATUS;
- color = <LED_COLOR_ID_GREEN>;
- gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
- };
- };
-
- reg_vcc5v: vcc5v {
- /* board wide 5V supply directly from the USB-C socket */
- compatible = "regulator-fixed";
- regulator-name = "vcc-5v";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- regulator-always-on;
- };
-
- reg_usb1_vbus: regulator-usb1-vbus {
- compatible = "regulator-fixed";
- regulator-name = "usb1-vbus";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- vin-supply = <&reg_vcc5v>;
- enable-active-high;
- gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */
- };
};
-&ehci1 {
- status = "okay";
-};
-
-/* USB 2 & 3 are on headers only. */
-
&emac0 {
- pinctrl-names = "default";
- pinctrl-0 = <&ext_rgmii_pins>;
- phy-mode = "rgmii";
- phy-handle = <&ext_rgmii_phy>;
phy-supply = <&reg_dcdce>;
- allwinner,rx-delay-ps = <3100>;
- allwinner,tx-delay-ps = <700>;
- status = "okay";
-};
-
-&mdio0 {
- ext_rgmii_phy: ethernet-phy@1 {
- compatible = "ethernet-phy-ieee802.3-c22";
- reg = <1>;
- };
};
&mmc0 {
vmmc-supply = <&reg_dcdce>;
- cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
- bus-width = <4>;
- status = "okay";
-};
-
-&ohci1 {
- status = "okay";
};
&r_rsb {
@@ -211,44 +135,3 @@
vcc-ph-supply = <&reg_aldo1>;
vcc-pi-supply = <&reg_aldo1>;
};
-
-&spi0 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>;
-
- flash@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "jedec,spi-nor";
- reg = <0>;
- spi-max-frequency = <40000000>;
- };
-};
-
-&uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_ph_pins>;
- status = "okay";
-};
-
-&usbotg {
- /*
- * PHY0 pins are connected to a USB-C socket, but a role switch
- * is not implemented: both CC pins are pulled to GND.
- * The VBUS pins power the device, so a fixed peripheral mode
- * is the best choice.
- * The board can be powered via GPIOs, in this case port0 *can*
- * act as a host (with a cable/adapter ignoring CC), as VBUS is
- * then provided by the GPIOs. Any user of this setup would
- * need to adjust the DT accordingly: dr_mode set to "host",
- * enabling OHCI0 and EHCI0.
- */
- dr_mode = "peripheral";
- status = "okay";
-};
-
-&usbphy {
- usb1_vbus-supply = <&reg_usb1_vbus>;
- status = "okay";
-};
diff --git a/arch/arm/dts/sun50i-h616-x96-mate.dts b/arch/arm/dts/sun50i-h616-x96-mate.dts
index 07424c2..959b6fd 100644
--- a/arch/arm/dts/sun50i-h616-x96-mate.dts
+++ b/arch/arm/dts/sun50i-h616-x96-mate.dts
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (C) 2021 Arm Ltd.
*/
diff --git a/arch/arm/dts/sun50i-h618-orangepi-zero3.dts b/arch/arm/dts/sun50i-h618-orangepi-zero3.dts
new file mode 100644
index 0000000..00fe28c
--- /dev/null
+++ b/arch/arm/dts/sun50i-h618-orangepi-zero3.dts
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616-orangepi-zero.dtsi"
+
+/ {
+ model = "OrangePi Zero3";
+ compatible = "xunlong,orangepi-zero3", "allwinner,sun50i-h618";
+};
+
+&emac0 {
+ phy-supply = <&reg_dldo1>;
+};
+
+&ext_rgmii_phy {
+ motorcomm,clk-out-frequency-hz = <125000000>;
+};
+
+&mmc0 {
+ /*
+ * The schematic shows the card detect pin wired up to PF6, via an
+ * inverter, but it just doesn't work.
+ */
+ broken-cd;
+ vmmc-supply = <&reg_dldo1>;
+};
+
+&r_i2c {
+ status = "okay";
+
+ axp313: pmic@36 {
+ compatible = "x-powers,axp313a";
+ reg = <0x36>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ interrupt-parent = <&pio>;
+ interrupts = <2 9 IRQ_TYPE_LEVEL_LOW>; /* PC9 */
+
+ vin1-supply = <&reg_vcc5v>;
+ vin2-supply = <&reg_vcc5v>;
+ vin3-supply = <&reg_vcc5v>;
+
+ regulators {
+ /* Supplies VCC-PLL, so needs to be always on. */
+ reg_aldo1: aldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc1v8";
+ };
+
+ /* Supplies VCC-IO, so needs to be always on. */
+ reg_dldo1: dldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc3v3";
+ };
+
+ reg_dcdc1: dcdc1 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <990000>;
+ regulator-name = "vdd-gpu-sys";
+ };
+
+ reg_dcdc2: dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-cpu";
+ };
+
+ reg_dcdc3: dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-name = "vdd-dram";
+ };
+ };
+ };
+};
+
+&pio {
+ vcc-pc-supply = <&reg_dldo1>;
+ vcc-pf-supply = <&reg_dldo1>;
+ vcc-pg-supply = <&reg_aldo1>;
+ vcc-ph-supply = <&reg_dldo1>;
+ vcc-pi-supply = <&reg_dldo1>;
+};
diff --git a/arch/arm/dts/sun5i-r8-chip.dts b/arch/arm/dts/sun5i-r8-chip.dts
index fd37bd1..4192c23 100644
--- a/arch/arm/dts/sun5i-r8-chip.dts
+++ b/arch/arm/dts/sun5i-r8-chip.dts
@@ -255,6 +255,12 @@
pinctrl-0 = <&uart3_pg_pins>,
<&uart3_cts_rts_pg_pins>;
status = "okay";
+
+ bluetooth {
+ compatible = "realtek,rtl8723bs-bt";
+ device-wake-gpios = <&axp_gpio 3 GPIO_ACTIVE_HIGH>;
+ host-wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
+ };
};
&usb_otg {
diff --git a/arch/arm/dts/sun5i.dtsi b/arch/arm/dts/sun5i.dtsi
index 250d6b8..d7c7b45 100644
--- a/arch/arm/dts/sun5i.dtsi
+++ b/arch/arm/dts/sun5i.dtsi
@@ -286,7 +286,7 @@
clock-names = "ahb",
"tcon-ch0",
"tcon-ch1";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
status = "disabled";
@@ -517,6 +517,15 @@
bias-pull-up;
};
+ /omit-if-no-ref/
+ mmc2_4bit_pe_pins: mmc2-4bit-pe-pins {
+ pins = "PE4", "PE5", "PE6", "PE7",
+ "PE8", "PE9";
+ function = "mmc2";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
mmc2_8bit_pins: mmc2-8bit-pins {
pins = "PC6", "PC7", "PC8", "PC9",
"PC10", "PC11", "PC12", "PC13",
diff --git a/arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts b/arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts
new file mode 100644
index 0000000..577ead1
--- /dev/null
+++ b/arch/arm/dts/sun7i-a20-icnova-a20-adb4006.dts
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+// Copyright (C) 2023 In-Circuit GmbH
+
+/dts-v1/;
+
+#include "sun7i-a20-icnova-a20.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "In-Circuit ICnova A20 ADB4006";
+ compatible = "incircuit,icnova-a20-adb4006", "incircuit,icnova-a20",
+ "allwinner,sun7i-a20";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ hdmi-connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_YELLOW>;
+ gpios = <&pio 7 21 GPIO_ACTIVE_HIGH>; /* PH21 */
+ default-state = "on";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_HEARTBEAT;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>; /* PH20 */
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
+
+&ahci {
+ target-supply = <&reg_ahci_5v>;
+ status = "okay";
+};
+
+&codec {
+ status = "okay";
+};
+
+&de {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>; /* PH1 */
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&otg_sram {
+ status = "okay";
+};
+
+&reg_ahci_5v {
+ status = "okay";
+};
+
+&ac_power_supply {
+ status = "okay";
+};
+
+&reg_usb1_vbus {
+ status = "okay";
+};
+
+&reg_usb2_vbus {
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pb_pins>;
+ status = "okay";
+};
+
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+ usb0_vbus_det-gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ usb2_vbus-supply = <&reg_usb2_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sun7i-a20-icnova-a20.dtsi b/arch/arm/dts/sun7i-a20-icnova-a20.dtsi
new file mode 100644
index 0000000..46616c6
--- /dev/null
+++ b/arch/arm/dts/sun7i-a20-icnova-a20.dtsi
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+// Copyright (C) 2023 In-Circuit GmbH
+
+#include "sun7i-a20.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&cpu0 {
+ cpu-supply = <&reg_dcdc2>;
+};
+
+&gmac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_mii_pins>;
+ phy-handle = <&phy1>;
+ phy-mode = "mii";
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ axp209: pmic@34 {
+ reg = <0x34>;
+ interrupt-parent = <&nmi_intc>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+#include "axp209.dtsi"
+
+&reg_dcdc2 {
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo1 {
+ regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-name = "avcc";
+};
diff --git a/arch/arm/dts/sun8i-a23-a33.dtsi b/arch/arm/dts/sun8i-a23-a33.dtsi
index 84c6d93..a0cac96 100644
--- a/arch/arm/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/dts/sun8i-a23-a33.dtsi
@@ -190,7 +190,7 @@
clock-names = "ahb",
"tcon-ch0",
"lvds-alt";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_LCD>,
<&ccu RST_BUS_LVDS>;
diff --git a/arch/arm/dts/sun8i-a83t.dtsi b/arch/arm/dts/sun8i-a83t.dtsi
index 9c07660..cc40622 100644
--- a/arch/arm/dts/sun8i-a83t.dtsi
+++ b/arch/arm/dts/sun8i-a83t.dtsi
@@ -456,7 +456,7 @@
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_TCON0>, <&ccu CLK_TCON0>;
clock-names = "ahb", "tcon-ch0";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_TCON0>, <&ccu RST_BUS_LVDS>;
reset-names = "lcd", "lvds";
diff --git a/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
new file mode 100644
index 0000000..8b3a753
--- /dev/null
+++ b/arch/arm/dts/sun8i-t113s-mangopi-mq-r-t113.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/dts-v1/;
+
+#include "sun8i-t113s.dtsi"
+#include "sunxi-d1s-t113-mangopi-mq-r.dtsi"
+
+/ {
+ model = "MangoPi MQ-R-T113";
+ compatible = "widora,mangopi-mq-r-t113", "allwinner,sun8i-t113s";
+
+ aliases {
+ ethernet0 = &rtl8189ftv;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vcc_core>;
+};
+
+&cpu1 {
+ cpu-supply = <&reg_vcc_core>;
+};
+
+&mmc1 {
+ rtl8189ftv: wifi@1 {
+ reg = <1>;
+ interrupt-parent = <&pio>;
+ interrupts = <6 10 IRQ_TYPE_LEVEL_LOW>; /* PG10 = WL_WAKE_AP */
+ interrupt-names = "host-wake";
+ };
+};
diff --git a/arch/arm/dts/sun8i-t113s.dtsi b/arch/arm/dts/sun8i-t113s.dtsi
new file mode 100644
index 0000000..b94b691
--- /dev/null
+++ b/arch/arm/dts/sun8i-t113s.dtsi
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+
+#define SOC_PERIPHERAL_IRQ(nr) GIC_SPI nr
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <../../riscv/dts/sunxi-d1s-t113.dtsi>
+#include <../../riscv/dts/sunxi-d1-t113.dtsi>
+
+/ {
+ interrupt-parent = <&gic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0>;
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <1>;
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ };
+ };
+
+ gic: interrupt-controller@1c81000 {
+ compatible = "arm,gic-400";
+ reg = <0x03021000 0x1000>,
+ <0x03022000 0x2000>,
+ <0x03024000 0x2000>,
+ <0x03026000 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+};
diff --git a/arch/arm/dts/sun8i-v3s.dtsi b/arch/arm/dts/sun8i-v3s.dtsi
index b001251..3b9a282 100644
--- a/arch/arm/dts/sun8i-v3s.dtsi
+++ b/arch/arm/dts/sun8i-v3s.dtsi
@@ -191,7 +191,7 @@
<&ccu CLK_TCON0>;
clock-names = "ahb",
"tcon-ch0";
- clock-output-names = "tcon-pixel-clock";
+ clock-output-names = "tcon-data-clock";
#clock-cells = <0>;
resets = <&ccu RST_BUS_TCON0>;
reset-names = "lcd";
diff --git a/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
new file mode 100644
index 0000000..a415c4a
--- /dev/null
+++ b/arch/arm/dts/sunxi-d1s-t113-mangopi-mq-r.dtsi
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2022 Arm Ltd.
+/*
+ * Common peripherals and configurations for MangoPi MQ-R boards.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ serial3 = &uart3;
+ };
+
+ chosen {
+ stdout-path = "serial3:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ color = <LED_COLOR_ID_BLUE>;
+ function = LED_FUNCTION_STATUS;
+ gpios = <&pio 3 22 GPIO_ACTIVE_LOW>; /* PD22 */
+ };
+ };
+
+ /* board wide 5V supply directly from the USB-C socket */
+ reg_vcc5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ };
+
+ /* SY8008 DC/DC regulator on the board */
+ reg_3v3: regulator-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&reg_vcc5v>;
+ };
+
+ /* SY8008 DC/DC regulator on the board, also supplying VDD-SYS */
+ reg_vcc_core: regulator-core {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-core";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ vin-supply = <&reg_vcc5v>;
+ };
+
+ /* XC6206 LDO on the board */
+ reg_avdd2v8: regulator-avdd {
+ compatible = "regulator-fixed";
+ regulator-name = "avdd2v8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ vin-supply = <&reg_3v3>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */
+ };
+};
+
+&dcxo {
+ clock-frequency = <24000000>;
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-0 = <&mmc0_pins>;
+ pinctrl-names = "default";
+ vmmc-supply = <&reg_3v3>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-0 = <&mmc1_pins>;
+ pinctrl-names = "default";
+ vmmc-supply = <&reg_3v3>;
+ non-removable;
+ bus-width = <4>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&pio {
+ vcc-pb-supply = <&reg_3v3>;
+ vcc-pd-supply = <&reg_3v3>;
+ vcc-pe-supply = <&reg_avdd2v8>;
+ vcc-pf-supply = <&reg_3v3>;
+ vcc-pg-supply = <&reg_3v3>;
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pb_pins>;
+ status = "okay";
+};
+
+/* The USB-C socket has its CC pins pulled to GND, so is hardwired as a UFP. */
+&usb_otg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_vcc5v>;
+ status = "okay";
+};
diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi
index af419c7..a0c8abb 100644
--- a/arch/arm/dts/sunxi-u-boot.dtsi
+++ b/arch/arm/dts/sunxi-u-boot.dtsi
@@ -23,6 +23,13 @@
};
};
+/* Let U-Boot be the firmware layer that controls the watchdog. */
+#ifdef CONFIG_MACH_SUN8I_R528
+&wdt {
+ status = "okay";
+};
+#endif
+
&binman {
u-boot-sunxi-with-spl {
filename = "u-boot-sunxi-with-spl.bin";
diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 30f5680..cad25c5 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -3,6 +3,8 @@
* Configuration settings for the Allwinner A64 (sun50i) CPU
*/
+#include <asm/arch/cpu.h>
+
#if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
/* reserve space for BOOT0 header information */
b reset
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 2cfd540..fcc8966 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -9,6 +9,7 @@
#define _SUNXI_CLOCK_H
#include <linux/types.h>
+#include <asm/arch/cpu.h>
#define CLK_GATE_OPEN 0x1
#define CLK_GATE_CLOSE 0x0
@@ -16,7 +17,7 @@
/* clock control module regs definition */
#if defined(CONFIG_MACH_SUN8I_A83T)
#include <asm/arch/clock_sun8i_a83t.h>
-#elif defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
#include <asm/arch/clock_sun50i_h6.h>
#elif defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \
defined(CONFIG_MACH_SUN50I) || defined(CONFIG_MACH_SUNIV)
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 37df441..a84a57e 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -228,6 +228,7 @@ struct sunxi_ccm_reg {
/* pll1 bit field */
#define CCM_PLL1_CTRL_EN BIT(31)
+#define CCM_PLL1_LDO_EN BIT(30)
#define CCM_PLL1_LOCK_EN BIT(29)
#define CCM_PLL1_LOCK BIT(28)
#define CCM_PLL1_OUT_EN BIT(27)
@@ -248,6 +249,8 @@ struct sunxi_ccm_reg {
#define CCM_PLL6_CTRL_EN BIT(31)
#define CCM_PLL6_LOCK_EN BIT(29)
#define CCM_PLL6_LOCK BIT(28)
+#define CCM_PLL6_CTRL_P0_SHIFT 16
+#define CCM_PLL6_CTRL_P0_MASK (0x7 << CCM_PLL6_CTRL_P0_SHIFT)
#define CCM_PLL6_CTRL_N_SHIFT 8
#define CCM_PLL6_CTRL_N_MASK (0xff << CCM_PLL6_CTRL_N_SHIFT)
#define CCM_PLL6_CTRL_DIV1_SHIFT 0
@@ -263,7 +266,7 @@ struct sunxi_ccm_reg {
#define CCM_CPU_AXI_AXI_MASK 0x3
#define CCM_CPU_AXI_DEFAULT_FACTORS 0x301
-#ifdef CONFIG_MACH_SUN50I_H6
+#ifdef CONFIG_MACH_SUN50I_H6 /* H6 */
#define CCM_PLL6_DEFAULT 0xa0006300
/* psi_ahb1_ahb2 bit field */
@@ -274,7 +277,7 @@ struct sunxi_ccm_reg {
/* apb1 bit field */
#define CCM_APB1_DEFAULT 0x03000102
-#elif CONFIG_MACH_SUN50I_H616
+#elif CONFIG_MACH_SUN50I_H616 /* H616 */
#define CCM_PLL6_DEFAULT 0xa8003100
/* psi_ahb1_ahb2 bit field */
@@ -285,6 +288,11 @@ struct sunxi_ccm_reg {
/* apb1 bit field */
#define CCM_APB1_DEFAULT 0x03000102
+#elif CONFIG_MACH_SUN8I_R528 /* R528 */
+#define CCM_PLL6_DEFAULT 0xe8216300
+#define CCM_PSI_AHB1_AHB2_DEFAULT 0x03000002
+//#define CCM_AHB3_DEFAULT 0x03000002
+#define CCM_APB1_DEFAULT 0x03000102
#endif
/* apb2 bit field */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index b08f202..768c657 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -10,6 +10,8 @@
#include <asm/arch/cpu_sun9i.h>
#elif defined(CONFIG_SUN50I_GEN_H6)
#include <asm/arch/cpu_sun50i_h6.h>
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#include <asm/arch/cpu_sunxi_ncat2.h>
#else
#include <asm/arch/cpu_sun4i.h>
#endif
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index f7ecc79..3daee2f 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -91,7 +91,6 @@
#define SUNXI_CCM_BASE 0x01c20000
#define SUNXI_INTC_BASE 0x01c20400
-#define SUNXI_PIO_BASE 0x01c20800
#define SUNXI_TIMER_BASE 0x01c20c00
#ifndef CONFIG_SUNXI_GEN_SUN6I
#define SUNXI_PWM_BASE 0x01c20e00
@@ -129,20 +128,6 @@ defined(CONFIG_MACH_SUN50I)
#define SUNXI_CPUCFG_BASE 0x01c25c00
#endif
-#ifdef CONFIG_MACH_SUNIV
-#define SUNXI_UART0_BASE 0x01c25000
-#define SUNXI_UART1_BASE 0x01c25400
-#define SUNXI_UART2_BASE 0x01c25800
-#else
-#define SUNXI_UART0_BASE 0x01c28000
-#define SUNXI_UART1_BASE 0x01c28400
-#define SUNXI_UART2_BASE 0x01c28800
-#endif
-#define SUNXI_UART3_BASE 0x01c28c00
-#define SUNXI_UART4_BASE 0x01c29000
-#define SUNXI_UART5_BASE 0x01c29400
-#define SUNXI_UART6_BASE 0x01c29800
-#define SUNXI_UART7_BASE 0x01c29c00
#define SUNXI_PS2_0_BASE 0x01c2a000
#define SUNXI_PS2_1_BASE 0x01c2a400
@@ -209,8 +194,6 @@ defined(CONFIG_MACH_SUN50I)
#endif
#define SUNXI_R_TWI_BASE 0x01f02400
-#define SUNXI_R_UART_BASE 0x01f02800
-#define SUNXI_R_PIO_BASE 0x01f02c00
#define SUN6I_P2WI_BASE 0x01f03400
#define SUNXI_RSB_BASE 0x01f03400
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
index d9cf8ae..15ee092 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun50i_h6.h
@@ -22,7 +22,6 @@
#define SUNXI_SIDC_BASE 0x03006000
#define SUNXI_SID_BASE 0x03006200
#define SUNXI_TIMER_BASE 0x03009000
-#define SUNXI_PIO_BASE 0x0300B000
#define SUNXI_PSI_BASE 0x0300C000
#define SUNXI_GIC400_BASE 0x03020000
@@ -43,10 +42,6 @@
#define SUNXI_DRAM_PHY0_BASE 0x04800000
#endif
-#define SUNXI_UART0_BASE 0x05000000
-#define SUNXI_UART1_BASE 0x05000400
-#define SUNXI_UART2_BASE 0x05000800
-#define SUNXI_UART3_BASE 0x05000C00
#define SUNXI_TWI0_BASE 0x05002000
#define SUNXI_TWI1_BASE 0x05002400
#define SUNXI_TWI2_BASE 0x05002800
@@ -68,8 +63,6 @@
#define SUNXI_R_CPUCFG_BASE 0x07000400
#define SUNXI_PRCM_BASE 0x07010000
#define SUNXI_R_WDOG_BASE 0x07020400
-#define SUNXI_R_PIO_BASE 0x07022000
-#define SUNXI_R_UART_BASE 0x07080000
#define SUNXI_R_TWI_BASE 0x07081400
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
index 9c2d11b..2bf2675 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun9i.h
@@ -81,18 +81,11 @@
/* APB0 Module */
#define SUNXI_CCM_BASE (REGS_APB0_BASE + 0x0000)
#define SUNXI_CCMMODULE_BASE (REGS_APB0_BASE + 0x0400)
-#define SUNXI_PIO_BASE (REGS_APB0_BASE + 0x0800)
#define SUNXI_TIMER_BASE (REGS_APB0_BASE + 0x0C00)
#define SUNXI_PWM_BASE (REGS_APB0_BASE + 0x1400)
#define SUNXI_LRADC_BASE (REGS_APB0_BASE + 0x1800)
/* APB1 Module */
-#define SUNXI_UART0_BASE (REGS_APB1_BASE + 0x0000)
-#define SUNXI_UART1_BASE (REGS_APB1_BASE + 0x0400)
-#define SUNXI_UART2_BASE (REGS_APB1_BASE + 0x0800)
-#define SUNXI_UART3_BASE (REGS_APB1_BASE + 0x0C00)
-#define SUNXI_UART4_BASE (REGS_APB1_BASE + 0x1000)
-#define SUNXI_UART5_BASE (REGS_APB1_BASE + 0x1400)
#define SUNXI_TWI0_BASE (REGS_APB1_BASE + 0x2800)
#define SUNXI_TWI1_BASE (REGS_APB1_BASE + 0x2C00)
#define SUNXI_TWI2_BASE (REGS_APB1_BASE + 0x3000)
@@ -101,8 +94,6 @@
/* RCPUS Module */
#define SUNXI_PRCM_BASE (REGS_RCPUS_BASE + 0x1400)
-#define SUNXI_R_UART_BASE (REGS_RCPUS_BASE + 0x2800)
-#define SUNXI_R_PIO_BASE (REGS_RCPUS_BASE + 0x2c00)
#define SUNXI_RSB_BASE (REGS_RCPUS_BASE + 0x3400)
/* Misc. */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
new file mode 100644
index 0000000..908a582
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sunxi_ncat2.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2022 Arm Limited
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_CPU_SUNXI_NCAT2_H
+#define _SUNXI_CPU_SUNXI_NCAT2_H
+
+#define SUNXI_CCM_BASE 0x02001000
+#define SUNXI_TIMER_BASE 0x02050000
+
+#define SUNXI_TWI0_BASE 0x02502000
+#define SUNXI_TWI1_BASE 0x02502400
+#define SUNXI_TWI2_BASE 0x02502800
+#define SUNXI_TWI3_BASE 0x02502C00
+
+#define SUNXI_SRAMC_BASE 0x03000000
+/* SID address space starts at 0x03006000, but e-fuse is at offset 0x200 */
+#define SUNXI_SIDC_BASE 0x03006000
+#define SUNXI_SID_BASE 0x03006200
+#define SUNXI_GIC400_BASE 0x03020000
+
+#define SUNXI_MMC0_BASE 0x04020000
+#define SUNXI_MMC1_BASE 0x04021000
+#define SUNXI_MMC2_BASE 0x04022000
+
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_PRCM_BASE 0x07010000
+
+#define SUNXI_CPUCFG_BASE 0x09010000
+
+#ifndef __ASSEMBLY__
+void sunxi_board_init(void);
+void sunxi_reset(void);
+int sunxi_get_sid(unsigned int *sid);
+#endif
+
+#endif /* _SUNXI_CPU_SUNXI_NCAT2_H */
diff --git a/arch/arm/include/asm/arch-sunxi/cpucfg.h b/arch/arm/include/asm/arch-sunxi/cpucfg.h
deleted file mode 100644
index 4aaebe0..0000000
--- a/arch/arm/include/asm/arch-sunxi/cpucfg.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Sunxi A31 CPUCFG register definition.
- *
- * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com
- */
-
-#ifndef _SUNXI_CPUCFG_H
-#define _SUNXI_CPUCFG_H
-
-#include <linux/compiler.h>
-#include <linux/types.h>
-
-#ifndef __ASSEMBLY__
-
-struct __packed sunxi_cpucfg_cpu {
- u32 rst; /* base + 0x0 */
- u32 ctrl; /* base + 0x4 */
- u32 status; /* base + 0x8 */
- u8 res[0x34]; /* base + 0xc */
-};
-
-struct __packed sunxi_cpucfg_reg {
- u8 res0[0x40]; /* 0x000 */
- struct sunxi_cpucfg_cpu cpu[4]; /* 0x040 */
- u8 res1[0x44]; /* 0x140 */
- u32 gen_ctrl; /* 0x184 */
- u32 l2_status; /* 0x188 */
- u8 res2[0x4]; /* 0x18c */
- u32 event_in; /* 0x190 */
- u8 res3[0xc]; /* 0x194 */
- u32 super_standy_flag; /* 0x1a0 */
- u32 priv0; /* 0x1a4 */
- u32 priv1; /* 0x1a8 */
- u8 res4[0x4]; /* 0x1ac */
- u32 cpu1_pwr_clamp; /* 0x1b0 sun7i only */
- u32 cpu1_pwroff; /* 0x1b4 sun7i only */
- u8 res5[0x2c]; /* 0x1b8 */
- u32 dbg_ctrl1; /* 0x1e4 */
- u8 res6[0x18]; /* 0x1e8 */
- u32 idle_cnt0_low; /* 0x200 */
- u32 idle_cnt0_high; /* 0x204 */
- u32 idle_cnt0_ctrl; /* 0x208 */
- u8 res8[0x4]; /* 0x20c */
- u32 idle_cnt1_low; /* 0x210 */
- u32 idle_cnt1_high; /* 0x214 */
- u32 idle_cnt1_ctrl; /* 0x218 */
- u8 res9[0x4]; /* 0x21c */
- u32 idle_cnt2_low; /* 0x220 */
- u32 idle_cnt2_high; /* 0x224 */
- u32 idle_cnt2_ctrl; /* 0x228 */
- u8 res10[0x4]; /* 0x22c */
- u32 idle_cnt3_low; /* 0x230 */
- u32 idle_cnt3_high; /* 0x234 */
- u32 idle_cnt3_ctrl; /* 0x238 */
- u8 res11[0x4]; /* 0x23c */
- u32 idle_cnt4_low; /* 0x240 */
- u32 idle_cnt4_high; /* 0x244 */
- u32 idle_cnt4_ctrl; /* 0x248 */
- u8 res12[0x34]; /* 0x24c */
- u32 cnt64_ctrl; /* 0x280 */
- u32 cnt64_low; /* 0x284 */
- u32 cnt64_high; /* 0x288 */
-};
-
-#endif /* __ASSEMBLY__ */
-#endif /* _SUNXI_CPUCFG_H */
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
index 5daacf1..8ed3e04 100644
--- a/arch/arm/include/asm/arch-sunxi/mmc.h
+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
@@ -45,7 +45,7 @@ struct sunxi_mmc {
u32 chda; /* 0x90 */
u32 cbda; /* 0x94 */
u32 res2[26];
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
u32 res3[17];
u32 samp_dl;
u32 res4[46];
diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
index 5106076..c5418cf 100644
--- a/arch/arm/include/asm/arch-sunxi/prcm.h
+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
@@ -9,7 +9,7 @@
#define _SUNXI_PRCM_H
/* prcm regs definition */
-#if defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
#include <asm/arch/prcm_sun50i.h>
#else
#include <asm/arch/prcm_sun6i.h>
diff --git a/arch/arm/include/asm/arch-sunxi/serial.h b/arch/arm/include/asm/arch-sunxi/serial.h
new file mode 100644
index 0000000..9386287
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/serial.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * hardcoded UART base addresses for early SPL use
+ *
+ * Copyright (c) 2022 Arm Ltd.
+ */
+
+#ifndef SUNXI_SERIAL_MEMMAP_H
+#define SUNXI_SERIAL_MEMMAP_H
+
+#if defined(CONFIG_MACH_SUN9I)
+#define SUNXI_UART0_BASE 0x07000000
+#define SUNXI_R_UART_BASE 0x08002800
+#elif defined(CONFIG_SUN50I_GEN_H6)
+#define SUNXI_UART0_BASE 0x05000000
+#define SUNXI_R_UART_BASE 0x07080000
+#elif defined(CONFIG_MACH_SUNIV)
+#define SUNXI_UART0_BASE 0x01c25000
+#define SUNXI_R_UART_BASE 0
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#define SUNXI_UART0_BASE 0x02500000
+#define SUNXI_R_UART_BASE 0 // 0x07080000 (?>
+#else
+#define SUNXI_UART0_BASE 0x01c28000
+#define SUNXI_R_UART_BASE 0x01f02800
+#endif
+
+#define SUNXI_UART1_BASE (SUNXI_UART0_BASE + 0x400)
+#define SUNXI_UART2_BASE (SUNXI_UART0_BASE + 0x800)
+#define SUNXI_UART3_BASE (SUNXI_UART0_BASE + 0xc00)
+
+#endif /* SUNXI_SERIAL_MEMMAP_H */
diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
index bb5626d..e17db85 100644
--- a/arch/arm/include/asm/arch-sunxi/timer.h
+++ b/arch/arm/include/asm/arch-sunxi/timer.h
@@ -76,7 +76,7 @@ struct sunxi_timer_reg {
struct sunxi_tgp tgp[4];
u8 res5[8];
u32 cpu_cfg;
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
u8 res3[16];
struct sunxi_wdog wdog[5]; /* We have 5 watchdogs */
#endif
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 9d5df2c..40ca7d7 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -121,7 +121,7 @@ config AXP_PMIC_BUS
config SUNXI_SRAM_ADDRESS
hex
default 0x10000 if MACH_SUN9I || MACH_SUN50I || MACH_SUN50I_H5
- default 0x20000 if SUN50I_GEN_H6
+ default 0x20000 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
default 0x0
---help---
Older Allwinner SoCs have their mask boot ROM mapped just below 4GB,
@@ -183,6 +183,14 @@ config SUN50I_GEN_H6
Select this for sunxi SoCs which have H6 like peripherals, clocks
and memory map.
+config SUNXI_GEN_NCAT2
+ bool
+ select MMC_SUNXI_HAS_NEW_MODE
+ select SUPPORT_SPL
+ ---help---
+ Select this for sunxi SoCs which have D1 like peripherals, clocks
+ and memory map.
+
config SUNXI_DRAM_DW
bool
---help---
@@ -338,6 +346,19 @@ config MACH_SUN8I_R40
select SUNXI_DRAM_DW_32BIT
imply SPL_SYS_I2C_LEGACY
+config MACH_SUN8I_R528
+ bool "sun8i (Allwinner R528)"
+ select CPU_V7A
+ select CPU_V7_HAS_NONSEC
+ select CPU_V7_HAS_VIRT
+ select ARCH_SUPPORT_PSCI
+ select SPL_ARMV7_SET_CORTEX_SMPEN
+ select SUNXI_GEN_NCAT2
+ select SUNXI_NEW_PINCTRL
+ select MMC_SUNXI_HAS_NEW_MODE
+ select SUPPORT_SPL
+ select DRAM_SUN20I_D1
+
config MACH_SUN8I_V3S
bool "sun8i (Allwinner V3/V3s/S3/S3L)"
select CPU_V7A
@@ -648,6 +669,7 @@ config SYS_CLK_FREQ
default 1008000000 if MACH_SUN9I
default 888000000 if MACH_SUN50I_H6
default 1008000000 if MACH_SUN50I_H616
+ default 1008000000 if MACH_SUN8I_R528
config SYS_CONFIG_NAME
default "suniv" if MACH_SUNIV
@@ -656,6 +678,7 @@ config SYS_CONFIG_NAME
default "sun6i" if MACH_SUN6I
default "sun7i" if MACH_SUN7I
default "sun8i" if MACH_SUN8I
+ default "sun8i" if MACH_SUN8I_R528
default "sun9i" if MACH_SUN9I
default "sun50i" if MACH_SUN50I
default "sun50i" if MACH_SUN50I_H6
@@ -695,13 +718,6 @@ config OLD_SUNXI_KERNEL_COMPAT
Set this to enable various workarounds for old kernels, this results in
sub-optimal settings for newer kernels, only enable if needed.
-config MACPWR
- string "MAC power pin"
- default ""
- help
- Set the pin used to power the MAC. This takes a string in the format
- understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
-
config MMC1_PINS_PH
bool "Pins for mmc1 are on Port H"
depends on MACH_SUN4I || MACH_SUN7I || MACH_SUN8I_R40
@@ -811,6 +827,7 @@ config VIDEO_SUNXI
depends on !MACH_SUN9I
depends on !MACH_SUN50I
depends on !SUN50I_GEN_H6
+ depends on !SUNXI_GEN_NCAT2
select VIDEO
select DISPLAY
imply VIDEO_DT_SIMPLEFB
@@ -1008,14 +1025,6 @@ config VIDEO_LCD_TL059WV5C0
endchoice
-config SATAPWR
- string "SATA power pin"
- default ""
- help
- Set the pins used to power the SATA. This takes a string in the
- format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of
- port H.
-
config GMAC_TX_DELAY
int "GMAC Transmit Clock Delay Chain"
default 0
@@ -1032,6 +1041,7 @@ config SPL_STACK_R_ADDR
default 0x2fe00000 if MACH_SUN9I
default 0x4fe00000 if MACH_SUN50I
default 0x4fe00000 if SUN50I_GEN_H6
+ default 0x4fe00000 if SUNXI_GEN_NCAT2
config SPL_SPI_SUNXI
bool "Support for SPI Flash on Allwinner SoCs in SPL"
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 58f807c..1d4c70e 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -10,7 +10,6 @@ obj-y += board.o
obj-y += clock.o
obj-y += cpu_info.o
obj-y += dram_helpers.o
-obj-y += pinmux.o
obj-$(CONFIG_SUN6I_PRCM) += prcm.o
obj-$(CONFIG_AXP_PMIC_BUS) += pmic_bus.o
obj-$(CONFIG_MACH_SUNIV) += clock_sun6i.o
@@ -26,6 +25,7 @@ obj-$(CONFIG_MACH_SUN8I) += clock_sun6i.o
endif
obj-$(CONFIG_MACH_SUN9I) += clock_sun9i.o gtbus_sun9i.o
obj-$(CONFIG_SUN50I_GEN_H6) += clock_sun50i_h6.o
+obj-$(CONFIG_SUNXI_GEN_NCAT2) += clock_sun50i_h6.o
ifndef CONFIG_ARM64
obj-y += timer.o
endif
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index 78597ad..c2fadf7 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -17,6 +17,7 @@
#include <i2c.h>
#include <serial.h>
#include <spl.h>
+#include <sunxi_gpio.h>
#include <asm/cache.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -146,6 +147,10 @@ static int gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPH(12), SUN9I_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(13), SUN9I_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(13), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_R528)
+ sunxi_gpio_set_cfgpin(SUNXI_GPE(2), 6);
+ sunxi_gpio_set_cfgpin(SUNXI_GPE(3), 6);
+ sunxi_gpio_set_pull(SUNXI_GPE(3), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUNIV)
sunxi_gpio_set_cfgpin(SUNXI_GPA(2), SUNIV_GPE_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPA(3), SUNIV_GPE_UART0);
@@ -162,6 +167,10 @@ static int gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN8I_GPB_UART2);
sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN8I_GPB_UART2);
sunxi_gpio_set_pull(SUNXI_GPB(1), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 4 && defined(CONFIG_MACH_SUN8I_R528)
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(6), 7);
+ sunxi_gpio_set_cfgpin(SUNXI_GPB(7), 7);
+ sunxi_gpio_set_pull(SUNXI_GPB(7), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_MACH_SUN8I)
sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
@@ -175,13 +184,19 @@ static int gpio_init(void)
#error Unsupported console port number. Please fix pin mux settings in board.c
#endif
-#ifdef CONFIG_SUN50I_GEN_H6
- /* Update PIO power bias configuration by copy hardware detected value */
- val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
- writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
- val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
- writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
-#endif
+ /*
+ * Update PIO power bias configuration by copying the hardware
+ * detected value.
+ */
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+ IS_ENABLED(CONFIG_SUN50I_GEN_NCAT2)) {
+ val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+ writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+ }
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6)) {
+ val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+ writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+ }
return 0;
}
@@ -480,7 +495,7 @@ void reset_cpu(void)
/* sun5i sometimes gets stuck without this */
writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
}
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
#if defined(CONFIG_MACH_SUN50I_H6)
/* WDOG is broken for some H6 rev. use the R_WDOG instead */
static const struct sunxi_wdog *wdog =
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index 7926394..bea91c7 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -18,8 +18,11 @@ void clock_init_safe(void)
setbits_le32(&prcm->res_cal_ctrl, 2);
}
- clrbits_le32(&prcm->res_cal_ctrl, 1);
- setbits_le32(&prcm->res_cal_ctrl, 1);
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616) ||
+ IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
+ clrbits_le32(&prcm->res_cal_ctrl, 1);
+ setbits_le32(&prcm->res_cal_ctrl, 1);
+ }
if (IS_ENABLED(CONFIG_MACH_SUN50I_H6)) {
/* set key field for ldo enable */
@@ -38,7 +41,9 @@ void clock_init_safe(void)
CCM_CPU_AXI_DEFAULT_FACTORS);
writel(CCM_PSI_AHB1_AHB2_DEFAULT, &ccm->psi_ahb1_ahb2_cfg);
+#ifdef CCM_AHB3_DEFAULT
writel(CCM_AHB3_DEFAULT, &ccm->ahb3_cfg);
+#endif
writel(CCM_APB1_DEFAULT, &ccm->apb1_cfg);
/*
@@ -86,11 +91,13 @@ void clock_set_pll1(unsigned int clk)
writel(val, &ccm->cpu_axi_cfg);
/* clk = 24*n/p, p is ignored if clock is >288MHz */
- writel(CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2 |
-#ifdef CONFIG_MACH_SUN50I_H616
- CCM_PLL1_OUT_EN |
-#endif
- CCM_PLL1_CTRL_N(clk / 24000000), &ccm->pll1_cfg);
+ val = CCM_PLL1_CTRL_EN | CCM_PLL1_LOCK_EN | CCM_PLL1_CLOCK_TIME_2;
+ val |= CCM_PLL1_CTRL_N(clk / 24000000);
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H616))
+ val |= CCM_PLL1_OUT_EN;
+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
+ val |= CCM_PLL1_OUT_EN | CCM_PLL1_LDO_EN;
+ writel(val, &ccm->pll1_cfg);
while (!(readl(&ccm->pll1_cfg) & CCM_PLL1_LOCK)) {}
/* Switch CPU to PLL1 */
@@ -105,16 +112,26 @@ unsigned int clock_get_pll6(void)
{
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
- int m = IS_ENABLED(CONFIG_MACH_SUN50I_H6) ? 4 : 2;
-
uint32_t rval = readl(&ccm->pll6_cfg);
int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
- int div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
- CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
int div2 = ((rval & CCM_PLL6_CTRL_DIV2_MASK) >>
- CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
- /* The register defines PLL6-2X or PLL6-4X, not plain PLL6 */
- return 24000000 / m * n / div1 / div2;
+ CCM_PLL6_CTRL_DIV2_SHIFT) + 1;
+ int div1, m;
+
+ if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
+ div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
+ CCM_PLL6_CTRL_P0_SHIFT) + 1;
+ m = 1;
+ } else {
+ div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
+ CCM_PLL6_CTRL_DIV1_SHIFT) + 1;
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+ m = 4;
+ else
+ m = 2;
+ }
+
+ return 24000000U * n / m / div1 / div2;
}
int clock_twi_onoff(int port, int state)
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index 7eef178..7fecc3b 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -93,6 +93,8 @@ int print_cpuinfo(void)
printf("CPU: Allwinner R40 (SUN8I %04x)\n", sunxi_get_sram_id());
#elif defined CONFIG_MACH_SUN8I_V3S
printf("CPU: Allwinner V3s (SUN8I %04x)\n", sunxi_get_sram_id());
+#elif defined CONFIG_MACH_SUN8I_R528
+ puts("CPU: Allwinner R528 (SUN8I)\n");
#elif defined CONFIG_MACH_SUN9I
puts("CPU: Allwinner A80 (SUN9I)\n");
#elif defined CONFIG_MACH_SUN50I
diff --git a/arch/arm/mach-sunxi/dram_suniv.c b/arch/arm/mach-sunxi/dram_suniv.c
index 3aa3ce7..9e583e1 100644
--- a/arch/arm/mach-sunxi/dram_suniv.c
+++ b/arch/arm/mach-sunxi/dram_suniv.c
@@ -13,10 +13,10 @@
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/dram.h>
-#include <asm/arch/gpio.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <hang.h>
+#include <sunxi_gpio.h>
#define SDR_T_CAS (0x2)
#define SDR_T_RAS (0x8)
diff --git a/arch/arm/mach-sunxi/gtbus_sun9i.c b/arch/arm/mach-sunxi/gtbus_sun9i.c
index cf011c4..5624621 100644
--- a/arch/arm/mach-sunxi/gtbus_sun9i.c
+++ b/arch/arm/mach-sunxi/gtbus_sun9i.c
@@ -8,6 +8,7 @@
#include <common.h>
#include <asm/io.h>
+#include <asm/arch/cpu.h>
#include <asm/arch/gtbus_sun9i.h>
#include <asm/arch/sys_proto.h>
diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
deleted file mode 100644
index c95fcee..0000000
--- a/arch/arm/mach-sunxi/pinmux.c
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * (C) Copyright 2007-2011
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Tom Cubie <tangliang@allwinnertech.com>
- */
-
-#include <common.h>
-#include <asm/io.h>
-#include <asm/arch/gpio.h>
-
-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-{
- u32 index = GPIO_CFG_INDEX(bank_offset);
- u32 offset = GPIO_CFG_OFFSET(bank_offset);
-
- clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
-}
-
-void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- sunxi_gpio_set_cfgbank(pio, pin, val);
-}
-
-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
-{
- u32 index = GPIO_CFG_INDEX(bank_offset);
- u32 offset = GPIO_CFG_OFFSET(bank_offset);
- u32 cfg;
-
- cfg = readl(&pio->cfg[index]);
- cfg >>= offset;
-
- return cfg & 0xf;
-}
-
-int sunxi_gpio_get_cfgpin(u32 pin)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- return sunxi_gpio_get_cfgbank(pio, pin);
-}
-
-void sunxi_gpio_set_drv(u32 pin, u32 val)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- sunxi_gpio_set_drv_bank(pio, pin, val);
-}
-
-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
-{
- u32 index = GPIO_DRV_INDEX(bank_offset);
- u32 offset = GPIO_DRV_OFFSET(bank_offset);
-
- clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
-}
-
-void sunxi_gpio_set_pull(u32 pin, u32 val)
-{
- u32 bank = GPIO_BANK(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
-
- sunxi_gpio_set_pull_bank(pio, pin, val);
-}
-
-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
-{
- u32 index = GPIO_PULL_INDEX(bank_offset);
- u32 offset = GPIO_PULL_OFFSET(bank_offset);
-
- clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
-}
diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c
index 81159cf..c2410dd 100644
--- a/arch/arm/mach-sunxi/spl_spi_sunxi.c
+++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c
@@ -13,6 +13,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/libfdt.h>
+#include <sunxi_gpio.h>
#ifdef CONFIG_SPL_OS_BOOT
#error CONFIG_SPL_OS_BOOT is not supported yet
diff --git a/arch/arm/mach-sunxi/timer.c b/arch/arm/mach-sunxi/timer.c
index fc9d419..9a6f6c0 100644
--- a/arch/arm/mach-sunxi/timer.c
+++ b/arch/arm/mach-sunxi/timer.c
@@ -10,6 +10,7 @@
#include <time.h>
#include <asm/global_data.h>
#include <asm/io.h>
+#include <asm/arch/cpu.h>
#include <asm/arch/timer.h>
#include <linux/delay.h>
diff --git a/arch/riscv/dts/sunxi-d1-t113.dtsi b/arch/riscv/dts/sunxi-d1-t113.dtsi
new file mode 100644
index 0000000..b715612
--- /dev/null
+++ b/arch/riscv/dts/sunxi-d1-t113.dtsi
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+/ {
+ soc {
+ dsp_wdt: watchdog@1700400 {
+ compatible = "allwinner,sun20i-d1-wdt";
+ reg = <0x1700400 0x20>;
+ interrupts = <SOC_PERIPHERAL_IRQ(122) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ status = "reserved";
+ };
+ };
+};
diff --git a/arch/riscv/dts/sunxi-d1s-t113.dtsi b/arch/riscv/dts/sunxi-d1s-t113.dtsi
new file mode 100644
index 0000000..822f022
--- /dev/null
+++ b/arch/riscv/dts/sunxi-d1s-t113.dtsi
@@ -0,0 +1,927 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2021-2022 Samuel Holland <samuel@sholland.org>
+
+#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun8i-de2.h>
+#include <dt-bindings/clock/sun8i-tcon-top.h>
+#include <dt-bindings/clock/sun20i-d1-ccu.h>
+#include <dt-bindings/clock/sun20i-d1-r-ccu.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/reset/sun8i-de2.h>
+#include <dt-bindings/reset/sun20i-d1-ccu.h>
+#include <dt-bindings/reset/sun20i-d1-r-ccu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ dcxo: dcxo-clk {
+ compatible = "fixed-clock";
+ clock-output-names = "dcxo";
+ #clock-cells = <0>;
+ };
+
+ de: display-engine {
+ compatible = "allwinner,sun20i-d1-display-engine";
+ allwinner,pipelines = <&mixer0>, <&mixer1>;
+ status = "disabled";
+ };
+
+ soc {
+ compatible = "simple-bus";
+ ranges;
+ dma-noncoherent;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pio: pinctrl@2000000 {
+ compatible = "allwinner,sun20i-d1-pinctrl";
+ reg = <0x2000000 0x800>;
+ interrupts = <SOC_PERIPHERAL_IRQ(69) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(71) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(73) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(75) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(77) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(79) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_APB0>,
+ <&dcxo>,
+ <&rtc CLK_OSC32K>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ interrupt-controller;
+ #gpio-cells = <3>;
+ #interrupt-cells = <3>;
+
+ /omit-if-no-ref/
+ can0_pins: can0-pins {
+ pins = "PB2", "PB3";
+ function = "can0";
+ };
+
+ /omit-if-no-ref/
+ can1_pins: can1-pins {
+ pins = "PB4", "PB5";
+ function = "can1";
+ };
+
+ /omit-if-no-ref/
+ clk_pg11_pin: clk-pg11-pin {
+ pins = "PG11";
+ function = "clk";
+ };
+
+ /omit-if-no-ref/
+ dsi_4lane_pins: dsi-4lane-pins {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+ "PD6", "PD7", "PD8", "PD9";
+ drive-strength = <30>;
+ function = "dsi";
+ };
+
+ /omit-if-no-ref/
+ lcd_rgb666_pins: lcd-rgb666-pins {
+ pins = "PD0", "PD1", "PD2", "PD3", "PD4", "PD5",
+ "PD6", "PD7", "PD8", "PD9", "PD10", "PD11",
+ "PD12", "PD13", "PD14", "PD15", "PD16", "PD17",
+ "PD18", "PD19", "PD20", "PD21";
+ function = "lcd0";
+ };
+
+ /omit-if-no-ref/
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
+ function = "mmc0";
+ };
+
+ /omit-if-no-ref/
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5";
+ function = "mmc1";
+ };
+
+ /omit-if-no-ref/
+ mmc2_pins: mmc2-pins {
+ pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7";
+ function = "mmc2";
+ };
+
+ /omit-if-no-ref/
+ rgmii_pe_pins: rgmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9",
+ "PE11", "PE12", "PE13", "PE14", "PE15";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ rmii_pe_pins: rmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ spi0_pins: spi0-pins {
+ pins = "PC2", "PC3", "PC4", "PC5";
+ function = "spi0";
+ };
+
+ /omit-if-no-ref/
+ uart1_pg6_pins: uart1-pg6-pins {
+ pins = "PG6", "PG7";
+ function = "uart1";
+ };
+
+ /omit-if-no-ref/
+ uart1_pg8_rts_cts_pins: uart1-pg8-rts-cts-pins {
+ pins = "PG8", "PG9";
+ function = "uart1";
+ };
+
+ /omit-if-no-ref/
+ uart3_pb_pins: uart3-pb-pins {
+ pins = "PB6", "PB7";
+ function = "uart3";
+ };
+ };
+
+ ccu: clock-controller@2001000 {
+ compatible = "allwinner,sun20i-d1-ccu";
+ reg = <0x2001000 0x1000>;
+ clocks = <&dcxo>,
+ <&rtc CLK_OSC32K>,
+ <&rtc CLK_IOSC>;
+ clock-names = "hosc", "losc", "iosc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ gpadc: adc@2009000 {
+ compatible = "allwinner,sun20i-d1-gpadc";
+ reg = <0x2009000 0x400>;
+ clocks = <&ccu CLK_BUS_GPADC>;
+ resets = <&ccu RST_BUS_GPADC>;
+ interrupts = <SOC_PERIPHERAL_IRQ(57) IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ #io-channel-cells = <1>;
+ };
+
+ dmic: dmic@2031000 {
+ compatible = "allwinner,sun20i-d1-dmic",
+ "allwinner,sun50i-h6-dmic";
+ reg = <0x2031000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(24) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMIC>,
+ <&ccu CLK_DMIC>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_DMIC>;
+ dmas = <&dma 8>;
+ dma-names = "rx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ i2s1: i2s@2033000 {
+ compatible = "allwinner,sun20i-d1-i2s",
+ "allwinner,sun50i-r329-i2s";
+ reg = <0x2033000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(27) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S1>,
+ <&ccu CLK_I2S1>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S1>;
+ dmas = <&dma 4>, <&dma 4>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ i2s2: i2s@2034000 {
+ compatible = "allwinner,sun20i-d1-i2s",
+ "allwinner,sun50i-r329-i2s";
+ reg = <0x2034000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(28) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S2>,
+ <&ccu CLK_I2S2>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S2>;
+ dmas = <&dma 5>, <&dma 5>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ timer: timer@2050000 {
+ compatible = "allwinner,sun20i-d1-timer",
+ "allwinner,sun8i-a23-timer";
+ reg = <0x2050000 0xa0>;
+ interrupts = <SOC_PERIPHERAL_IRQ(59) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(60) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo>;
+ };
+
+ wdt: watchdog@20500a0 {
+ compatible = "allwinner,sun20i-d1-wdt-reset",
+ "allwinner,sun20i-d1-wdt";
+ reg = <0x20500a0 0x20>;
+ interrupts = <SOC_PERIPHERAL_IRQ(63) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ status = "reserved";
+ };
+
+ uart0: serial@2500000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500000 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(2) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART0>;
+ resets = <&ccu RST_BUS_UART0>;
+ dmas = <&dma 14>, <&dma 14>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart1: serial@2500400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500400 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(3) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART1>;
+ resets = <&ccu RST_BUS_UART1>;
+ dmas = <&dma 15>, <&dma 15>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart2: serial@2500800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500800 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(4) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART2>;
+ resets = <&ccu RST_BUS_UART2>;
+ dmas = <&dma 16>, <&dma 16>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart3: serial@2500c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500c00 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(5) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART3>;
+ resets = <&ccu RST_BUS_UART3>;
+ dmas = <&dma 17>, <&dma 17>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart4: serial@2501000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2501000 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(6) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART4>;
+ resets = <&ccu RST_BUS_UART4>;
+ dmas = <&dma 18>, <&dma 18>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ uart5: serial@2501400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2501400 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <SOC_PERIPHERAL_IRQ(7) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART5>;
+ resets = <&ccu RST_BUS_UART5>;
+ dmas = <&dma 19>, <&dma 19>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c0: i2c@2502000 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(9) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ dmas = <&dma 43>, <&dma 43>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@2502400 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502400 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(10) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ dmas = <&dma 44>, <&dma 44>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@2502800 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502800 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(11) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ dmas = <&dma 45>, <&dma 45>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c@2502c00 {
+ compatible = "allwinner,sun20i-d1-i2c",
+ "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502c00 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(12) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C3>;
+ resets = <&ccu RST_BUS_I2C3>;
+ dmas = <&dma 46>, <&dma 46>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ can0: can@2504000 {
+ compatible = "allwinner,sun20i-d1-can";
+ reg = <0x02504000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(21) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CAN0>;
+ resets = <&ccu RST_BUS_CAN0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&can0_pins>;
+ status = "disabled";
+ };
+
+ can1: can@2504400 {
+ compatible = "allwinner,sun20i-d1-can";
+ reg = <0x02504400 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(22) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CAN1>;
+ resets = <&ccu RST_BUS_CAN1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&can1_pins>;
+ status = "disabled";
+ };
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun20i-d1-system-control";
+ reg = <0x3000000 0x1000>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ dma: dma-controller@3002000 {
+ compatible = "allwinner,sun20i-d1-dma";
+ reg = <0x3002000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(50) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+ clock-names = "bus", "mbus";
+ resets = <&ccu RST_BUS_DMA>;
+ dma-channels = <16>;
+ dma-requests = <48>;
+ #dma-cells = <1>;
+ };
+
+ sid: efuse@3006000 {
+ compatible = "allwinner,sun20i-d1-sid";
+ reg = <0x3006000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ crypto: crypto@3040000 {
+ compatible = "allwinner,sun20i-d1-crypto";
+ reg = <0x3040000 0x800>;
+ interrupts = <SOC_PERIPHERAL_IRQ(52) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CE>,
+ <&ccu CLK_CE>,
+ <&ccu CLK_MBUS_CE>,
+ <&rtc CLK_IOSC>;
+ clock-names = "bus", "mod", "ram", "trng";
+ resets = <&ccu RST_BUS_CE>;
+ };
+
+ mbus: dram-controller@3102000 {
+ compatible = "allwinner,sun20i-d1-mbus";
+ reg = <0x3102000 0x1000>,
+ <0x3103000 0x1000>;
+ reg-names = "mbus", "dram";
+ interrupts = <SOC_PERIPHERAL_IRQ(43) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_MBUS>,
+ <&ccu CLK_DRAM>,
+ <&ccu CLK_BUS_DRAM>;
+ clock-names = "mbus", "dram", "bus";
+ dma-ranges = <0 0x40000000 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interconnect-cells = <1>;
+ };
+
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4020000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(40) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ cap-sd-highspeed;
+ max-frequency = <150000000>;
+ no-mmc;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4021000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(41) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ cap-sd-highspeed;
+ max-frequency = <150000000>;
+ no-mmc;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun20i-d1-emmc",
+ "allwinner,sun50i-a100-emmc";
+ reg = <0x4022000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(42) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ cap-mmc-highspeed;
+ max-frequency = <150000000>;
+ mmc-ddr-1_8v;
+ mmc-ddr-3_3v;
+ no-sd;
+ no-sdio;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi0: spi@4025000 {
+ compatible = "allwinner,sun20i-d1-spi",
+ "allwinner,sun50i-r329-spi";
+ reg = <0x04025000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(15) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 22>, <&dma 22>;
+ dma-names = "rx", "tx";
+ resets = <&ccu RST_BUS_SPI0>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@4026000 {
+ compatible = "allwinner,sun20i-d1-spi-dbi",
+ "allwinner,sun50i-r329-spi-dbi",
+ "allwinner,sun50i-r329-spi";
+ reg = <0x04026000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(16) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ dmas = <&dma 23>, <&dma 23>;
+ dma-names = "rx", "tx";
+ resets = <&ccu RST_BUS_SPI1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ usb_otg: usb@4100000 {
+ compatible = "allwinner,sun20i-d1-musb",
+ "allwinner,sun8i-a33-musb";
+ reg = <0x4100000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(29) IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ extcon = <&usbphy 0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ usbphy: phy@4100400 {
+ compatible = "allwinner,sun20i-d1-usb-phy";
+ reg = <0x4100400 0x100>,
+ <0x4101800 0x100>,
+ <0x4200800 0x100>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1";
+ clocks = <&dcxo>,
+ <&dcxo>;
+ clock-names = "usb0_phy",
+ "usb1_phy";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>;
+ reset-names = "usb0_reset",
+ "usb1_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@4101000 {
+ compatible = "allwinner,sun20i-d1-ehci",
+ "generic-ehci";
+ reg = <0x4101000 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(30) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_BUS_EHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>,
+ <&ccu RST_BUS_EHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@4101400 {
+ compatible = "allwinner,sun20i-d1-ohci",
+ "generic-ohci";
+ reg = <0x4101400 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(31) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci1: usb@4200000 {
+ compatible = "allwinner,sun20i-d1-ehci",
+ "generic-ehci";
+ reg = <0x4200000 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(33) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_BUS_EHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>,
+ <&ccu RST_BUS_EHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@4200400 {
+ compatible = "allwinner,sun20i-d1-ohci",
+ "generic-ohci";
+ reg = <0x4200400 0x100>;
+ interrupts = <SOC_PERIPHERAL_IRQ(34) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ emac: ethernet@4500000 {
+ compatible = "allwinner,sun20i-d1-emac",
+ "allwinner,sun50i-a64-emac";
+ reg = <0x4500000 0x10000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(46) IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ syscon = <&syscon>;
+ status = "disabled";
+
+ mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ display_clocks: clock-controller@5000000 {
+ compatible = "allwinner,sun20i-d1-de2-clk",
+ "allwinner,sun50i-h5-de2-clk";
+ reg = <0x5000000 0x10000>;
+ clocks = <&ccu CLK_BUS_DE>, <&ccu CLK_DE>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_DE>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ mixer0: mixer@5100000 {
+ compatible = "allwinner,sun20i-d1-de2-mixer-0";
+ reg = <0x5100000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER0>,
+ <&display_clocks CLK_MIXER0>;
+ clock-names = "bus", "mod";
+ resets = <&display_clocks RST_MIXER0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer0_out: port@1 {
+ reg = <1>;
+
+ mixer0_out_tcon_top_mixer0: endpoint {
+ remote-endpoint = <&tcon_top_mixer0_in_mixer0>;
+ };
+ };
+ };
+ };
+
+ mixer1: mixer@5200000 {
+ compatible = "allwinner,sun20i-d1-de2-mixer-1";
+ reg = <0x5200000 0x100000>;
+ clocks = <&display_clocks CLK_BUS_MIXER1>,
+ <&display_clocks CLK_MIXER1>;
+ clock-names = "bus", "mod";
+ resets = <&display_clocks RST_MIXER1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mixer1_out: port@1 {
+ reg = <1>;
+
+ mixer1_out_tcon_top_mixer1: endpoint {
+ remote-endpoint = <&tcon_top_mixer1_in_mixer1>;
+ };
+ };
+ };
+ };
+
+ dsi: dsi@5450000 {
+ compatible = "allwinner,sun20i-d1-mipi-dsi",
+ "allwinner,sun50i-a100-mipi-dsi";
+ reg = <0x5450000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&tcon_top CLK_TCON_TOP_DSI>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ phys = <&dphy>;
+ phy-names = "dphy";
+ status = "disabled";
+
+ port {
+ dsi_in_tcon_lcd0: endpoint {
+ remote-endpoint = <&tcon_lcd0_out_dsi>;
+ };
+ };
+ };
+
+ dphy: phy@5451000 {
+ compatible = "allwinner,sun20i-d1-mipi-dphy",
+ "allwinner,sun50i-a100-mipi-dphy";
+ reg = <0x5451000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_MIPI_DSI>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ #phy-cells = <0>;
+ };
+
+ tcon_top: tcon-top@5460000 {
+ compatible = "allwinner,sun20i-d1-tcon-top";
+ reg = <0x5460000 0x1000>;
+ clocks = <&ccu CLK_BUS_DPSS_TOP>,
+ <&ccu CLK_TCON_TV>,
+ <&ccu CLK_TVE>,
+ <&ccu CLK_TCON_LCD0>;
+ clock-names = "bus", "tcon-tv0", "tve0", "dsi";
+ clock-output-names = "tcon-top-tv0", "tcon-top-dsi";
+ resets = <&ccu RST_BUS_DPSS_TOP>;
+ #clock-cells = <1>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_in: port@0 {
+ reg = <0>;
+
+ tcon_top_mixer0_in_mixer0: endpoint {
+ remote-endpoint = <&mixer0_out_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer0_out: port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer0_out_tcon_lcd0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer0>;
+ };
+
+ tcon_top_mixer0_out_tcon_tv0: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer0>;
+ };
+ };
+
+ tcon_top_mixer1_in: port@2 {
+ reg = <2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer1_in_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&mixer1_out_tcon_top_mixer1>;
+ };
+ };
+
+ tcon_top_mixer1_out: port@3 {
+ reg = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_top_mixer1_out_tcon_lcd0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_lcd0_in_tcon_top_mixer1>;
+ };
+
+ tcon_top_mixer1_out_tcon_tv0: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&tcon_tv0_in_tcon_top_mixer1>;
+ };
+ };
+
+ tcon_top_hdmi_in: port@4 {
+ reg = <4>;
+
+ tcon_top_hdmi_in_tcon_tv0: endpoint {
+ remote-endpoint = <&tcon_tv0_out_tcon_top_hdmi>;
+ };
+ };
+
+ tcon_top_hdmi_out: port@5 {
+ reg = <5>;
+ };
+ };
+ };
+
+ tcon_lcd0: lcd-controller@5461000 {
+ compatible = "allwinner,sun20i-d1-tcon-lcd";
+ reg = <0x5461000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(90) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_LCD0>,
+ <&ccu CLK_TCON_LCD0>;
+ clock-names = "ahb", "tcon-ch0";
+ clock-output-names = "tcon-pixel-clock";
+ resets = <&ccu RST_BUS_TCON_LCD0>,
+ <&ccu RST_BUS_LVDS0>;
+ reset-names = "lcd", "lvds";
+ #clock-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_in: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_lcd0>;
+ };
+
+ tcon_lcd0_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_lcd0>;
+ };
+ };
+
+ tcon_lcd0_out: port@1 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_lcd0_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_tcon_lcd0>;
+ };
+ };
+ };
+ };
+
+ tcon_tv0: lcd-controller@5470000 {
+ compatible = "allwinner,sun20i-d1-tcon-tv";
+ reg = <0x5470000 0x1000>;
+ interrupts = <SOC_PERIPHERAL_IRQ(91) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_TCON_TV>,
+ <&tcon_top CLK_TCON_TOP_TV0>;
+ clock-names = "ahb", "tcon-ch1";
+ resets = <&ccu RST_BUS_TCON_TV>;
+ reset-names = "lcd";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv0_in: port@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon_tv0_in_tcon_top_mixer0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&tcon_top_mixer0_out_tcon_tv0>;
+ };
+
+ tcon_tv0_in_tcon_top_mixer1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&tcon_top_mixer1_out_tcon_tv0>;
+ };
+ };
+
+ tcon_tv0_out: port@1 {
+ reg = <1>;
+
+ tcon_tv0_out_tcon_top_hdmi: endpoint {
+ remote-endpoint = <&tcon_top_hdmi_in_tcon_tv0>;
+ };
+ };
+ };
+ };
+
+ ppu: power-controller@7001000 {
+ compatible = "allwinner,sun20i-d1-ppu";
+ reg = <0x7001000 0x1000>;
+ clocks = <&r_ccu CLK_BUS_R_PPU>;
+ resets = <&r_ccu RST_BUS_R_PPU>;
+ #power-domain-cells = <1>;
+ };
+
+ r_ccu: clock-controller@7010000 {
+ compatible = "allwinner,sun20i-d1-r-ccu";
+ reg = <0x7010000 0x400>;
+ clocks = <&dcxo>,
+ <&rtc CLK_OSC32K>,
+ <&rtc CLK_IOSC>,
+ <&ccu CLK_PLL_PERIPH0_DIV3>;
+ clock-names = "hosc", "losc", "iosc", "pll-periph";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ rtc: rtc@7090000 {
+ compatible = "allwinner,sun20i-d1-rtc",
+ "allwinner,sun50i-r329-rtc";
+ reg = <0x7090000 0x400>;
+ interrupts = <SOC_PERIPHERAL_IRQ(144) IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_BUS_R_RTC>,
+ <&dcxo>,
+ <&r_ccu CLK_R_AHB>;
+ clock-names = "bus", "hosc", "ahb";
+ #clock-cells = <1>;
+ };
+ };
+};
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 98bbd2d..4bbe3f6 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -291,6 +291,11 @@ M: Aleksei Mamlin <mamlinav@gmail.com>
S: Maintained
F: configs/Marsboard_A10_defconfig
+MANGOPI MQ-R BOARD
+M: Andre Przywara <andre.przywara@arm.com>
+S: Maintained
+F: configs/mangopi_mq_r_defconfig
+
MELE I7 BOARD
M: Marcus Cooper <codekipper@gmail.com>
S: Maintained
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index ebaa943..39ecbe9 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -38,6 +38,7 @@
#include <asm/armv7.h>
#endif
#include <asm/gpio.h>
+#include <sunxi_gpio.h>
#include <asm/io.h>
#include <u-boot/crc.h>
#include <env_internal.h>
@@ -187,7 +188,7 @@ enum env_location env_get_location(enum env_operation op, int prio)
/* add board specific code here */
int board_init(void)
{
- __maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
+ __maybe_unused int id_pfr1, ret;
gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
@@ -224,29 +225,6 @@ int board_init(void)
if (ret)
return ret;
- /* strcmp() would look better, but doesn't get optimised away. */
- if (CONFIG_SATAPWR[0]) {
- satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
- if (satapwr_pin >= 0) {
- gpio_request(satapwr_pin, "satapwr");
- gpio_direction_output(satapwr_pin, 1);
-
- /*
- * Give the attached SATA device time to power-up
- * to avoid link timeouts
- */
- mdelay(500);
- }
- }
-
- if (CONFIG_MACPWR[0]) {
- macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
- if (macpwr_pin >= 0) {
- gpio_request(macpwr_pin, "macpwr");
- gpio_direction_output(macpwr_pin, 1);
- }
- }
-
#if CONFIG_IS_ENABLED(DM_I2C)
/*
* Temporary workaround for enabling I2C clocks until proper sunxi DM
@@ -254,7 +232,6 @@ int board_init(void)
*/
i2c_init_board();
#endif
-
eth_init_board();
return 0;
@@ -482,6 +459,13 @@ static void mmc_pinmux_setup(int sdc)
sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
sunxi_gpio_set_drv(pin, 2);
}
+#elif defined(CONFIG_MACH_SUN8I_R528)
+ /* SDC2: PC2-PC7 */
+ for (pin = SUNXI_GPC(2); pin <= SUNXI_GPC(7); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
#else
puts("ERROR: No pinmux setup defined for MMC2!\n");
#endif
diff --git a/board/sunxi/chip.c b/board/sunxi/chip.c
index cde04be..eeee631 100644
--- a/board/sunxi/chip.c
+++ b/board/sunxi/chip.c
@@ -12,7 +12,7 @@
#include <w1-eeprom.h>
#include <dm/device-internal.h>
-#include <asm/arch/gpio.h>
+#include <sunxi_gpio.h>
#include <extension_board.h>
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6bc4066..25cd18a 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -265,7 +265,7 @@ config SPL_TEXT_BASE
default 0x402F0400 if AM33XX
default 0x40301350 if OMAP54XX
default 0x10060 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN9I
- default 0x20060 if SUN50I_GEN_H6
+ default 0x20060 if SUN50I_GEN_H6 || SUNXI_GEN_NCAT2
default 0x00060 if ARCH_SUNXI
default 0xfffc0000 if ARCH_ZYNQMP
default 0x0
@@ -371,6 +371,7 @@ config SPL_STACK
default 0x91ffb8 if ARCH_MX6 && !MX6_OCRAM_256KB
default 0x118000 if MACH_SUN50I_H6
default 0x58000 if MACH_SUN50I_H616
+ default 0x40000 if MACH_SUN8I_R528
default 0x54000 if MACH_SUN50I || MACH_SUN50I_H5
default 0x18000 if MACH_SUN9I
default 0x8000 if ARCH_SUNXI
diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index df4fdfa..57e91d0 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=480
CONFIG_DRAM_EMR1=4
CONFIG_SYS_CLK_FREQ=912000000
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
index be49e93..44770ff 100644
--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_SPL_SPI_SUNXI=y
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index 43cd28c..e10660c 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 7c77f38..4ed666a 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino_MICRO-eMMC_defconfig b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
index 0211699..ca5869f 100644
--- a/configs/A20-OLinuXino_MICRO-eMMC_defconfig
+++ b/configs/A20-OLinuXino_MICRO-eMMC_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_I2C1_ENABLE=y
CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index 895e8db..db4270f 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_I2C1_ENABLE=y
CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-Olimex-SOM-EVB_defconfig b/configs/A20-Olimex-SOM-EVB_defconfig
index 5bcc9f9..ac90047 100644
--- a/configs/A20-Olimex-SOM-EVB_defconfig
+++ b/configs/A20-Olimex-SOM-EVB_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="PH5"
-CONFIG_SATAPWR="PC3"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
index e588109..00a9814 100644
--- a/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB-eMMC_defconfig
@@ -8,7 +8,6 @@ CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_GMAC_TX_DELAY=4
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
index 592a79a..f4ae3ae 100644
--- a/configs/A20-Olimex-SOM204-EVB_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB_defconfig
@@ -7,7 +7,6 @@ CONFIG_DRAM_CLK=384
CONFIG_USB0_VBUS_PIN="PC17"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_I2C1_ENABLE=y
-CONFIG_SATAPWR="PC3"
CONFIG_GMAC_TX_DELAY=4
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Bananapi_M2_Ultra_defconfig b/configs/Bananapi_M2_Ultra_defconfig
index a5fe76a..2cc7bbb 100644
--- a/configs/Bananapi_M2_Ultra_defconfig
+++ b/configs/Bananapi_M2_Ultra_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-r40-bananapi-m2-ultra"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_R40=y
CONFIG_DRAM_CLK=576
-CONFIG_MACPWR="PA17"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB1_VBUS_PIN="PH23"
CONFIG_USB2_VBUS_PIN="PH23"
diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
index 6c2a1f6..f4910ba 100644
--- a/configs/Bananapi_defconfig
+++ b/configs/Bananapi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_VIDEO_COMPOSITE=y
CONFIG_GMAC_TX_DELAY=3
CONFIG_AHCI=y
diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
index 94fd747..02be897 100644
--- a/configs/Bananapro_defconfig
+++ b/configs/Bananapro_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapro"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_USB1_VBUS_PIN="PH0"
CONFIG_USB2_VBUS_PIN="PH1"
CONFIG_VIDEO_COMPOSITE=y
diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
index 0c23368..ef4f11b 100644
--- a/configs/Cubieboard2_defconfig
+++ b/configs/Cubieboard2_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-cubieboard2"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
index 71743f7..ab3f65a 100644
--- a/configs/Cubieboard_defconfig
+++ b/configs/Cubieboard_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-cubieboard"
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig
index 184f305..184143d 100644
--- a/configs/Cubietruck_defconfig
+++ b/configs/Cubietruck_defconfig
@@ -8,7 +8,6 @@ CONFIG_USB0_VBUS_PIN="PH17"
CONFIG_USB0_VBUS_DET="PH22"
CONFIG_USB0_ID_DET="PH19"
CONFIG_VIDEO_VGA=y
-CONFIG_SATAPWR="PH12"
CONFIG_GMAC_TX_DELAY=1
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
index 5d05f33..d03fa62 100644
--- a/configs/Itead_Ibox_A20_defconfig
+++ b/configs/Itead_Ibox_A20_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-itead-ibox"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
-CONFIG_SATAPWR="PB8"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Lamobo_R1_defconfig b/configs/Lamobo_R1_defconfig
index 5294608..66f57ab 100644
--- a/configs/Lamobo_R1_defconfig
+++ b/configs/Lamobo_R1_defconfig
@@ -4,8 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-lamobo-r1"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
-CONFIG_SATAPWR="PB3"
CONFIG_GMAC_TX_DELAY=4
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
index e3e30a4..9eb9a918 100644
--- a/configs/Linksprite_pcDuino3_Nano_defconfig
+++ b/configs/Linksprite_pcDuino3_Nano_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=408
CONFIG_DRAM_ZQ=122
CONFIG_USB1_VBUS_PIN="PH11"
-CONFIG_SATAPWR="PH2"
CONFIG_GMAC_TX_DELAY=3
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
index 1fda0db..7db10e6 100644
--- a/configs/Linksprite_pcDuino3_defconfig
+++ b/configs/Linksprite_pcDuino3_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=480
CONFIG_DRAM_ZQ=122
-CONFIG_SATAPWR="PH2"
CONFIG_AHCI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig
index f5b6d90..9ac2e48 100644
--- a/configs/Mele_A1000_defconfig
+++ b/configs/Mele_A1000_defconfig
@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-a1000"
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
-CONFIG_MACPWR="PH15"
CONFIG_VIDEO_VGA=y
CONFIG_VIDEO_COMPOSITE=y
CONFIG_AHCI=y
diff --git a/configs/Orangepi_defconfig b/configs/Orangepi_defconfig
index c89a9a1..53edf52 100644
--- a/configs/Orangepi_defconfig
+++ b/configs/Orangepi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_USB1_VBUS_PIN="PH26"
CONFIG_USB2_VBUS_PIN="PH22"
CONFIG_VIDEO_VGA=y
diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
index fe9ce80..ccf3267 100644
--- a/configs/Orangepi_mini_defconfig
+++ b/configs/Orangepi_mini_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-orangepi-mini"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_MMC_SUNXI_SLOT_EXTRA=3
CONFIG_USB1_VBUS_PIN="PH26"
CONFIG_USB2_VBUS_PIN="PH22"
diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
index 5642e52..ad41dbd 100644
--- a/configs/Sinovoip_BPI_M3_defconfig
+++ b/configs/Sinovoip_BPI_M3_defconfig
@@ -12,7 +12,6 @@ CONFIG_USB0_VBUS_PIN="AXP0-VBUS-ENABLE"
CONFIG_USB0_ID_DET="PH11"
CONFIG_USB1_VBUS_PIN="PD24"
CONFIG_AXP_GPIO=y
-CONFIG_SATAPWR="PD25"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_CONSOLE_MUX=y
CONFIG_PHY_REALTEK=y
diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
index 0fbb619..a432a01 100644
--- a/configs/bananapi_m1_plus_defconfig
+++ b/configs/bananapi_m1_plus_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-bananapi-m1-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=432
-CONFIG_MACPWR="PH23"
CONFIG_VIDEO_COMPOSITE=y
CONFIG_GMAC_TX_DELAY=3
CONFIG_AHCI=y
diff --git a/configs/bananapi_m2_plus_h3_defconfig b/configs/bananapi_m2_plus_h3_defconfig
index 26ced59..a8f9b50 100644
--- a/configs/bananapi_m2_plus_h3_defconfig
+++ b/configs/bananapi_m2_plus_h3_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/bananapi_m2_plus_h5_defconfig b/configs/bananapi_m2_plus_h5_defconfig
index fb6c945..1634f62 100644
--- a/configs/bananapi_m2_plus_h5_defconfig
+++ b/configs/bananapi_m2_plus_h5_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-bananapi-m2-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
index 257dd89..37f0f53 100644
--- a/configs/i12-tvbox_defconfig
+++ b/configs/i12-tvbox_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-i12-tvbox"
CONFIG_SPL=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
-CONFIG_MACPWR="PH21"
CONFIG_VIDEO_COMPOSITE=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/jesurun_q5_defconfig b/configs/jesurun_q5_defconfig
index 0ff666b..c99be7c 100644
--- a/configs/jesurun_q5_defconfig
+++ b/configs/jesurun_q5_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-jesurun-q5"
CONFIG_SPL=y
CONFIG_MACH_SUN4I=y
CONFIG_DRAM_CLK=312
-CONFIG_MACPWR="PH19"
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_VIDEO_COMPOSITE=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
diff --git a/configs/mangopi_mq_r_defconfig b/configs/mangopi_mq_r_defconfig
new file mode 100644
index 0000000..66ae639
--- /dev/null
+++ b/configs/mangopi_mq_r_defconfig
@@ -0,0 +1,15 @@
+CONFIG_ARM=y
+CONFIG_ARCH_SUNXI=y
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-t113s-mangopi-mq-r-t113"
+CONFIG_SPL=y
+CONFIG_MACH_SUN8I_R528=y
+CONFIG_DRAM_CLK=792
+CONFIG_DRAM_ZQ=8092667
+CONFIG_SUNXI_MINIMUM_DRAM_MB=128
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_DRAM_SUNXI_ODT_EN=0
+CONFIG_DRAM_SUNXI_TPR0=0x004a2195
+CONFIG_DRAM_SUNXI_TPR11=0x340000
+CONFIG_DRAM_SUNXI_TPR12=0x46
+CONFIG_DRAM_SUNXI_TPR13=0x34000100
+CONFIG_CONS_INDEX=4
diff --git a/configs/mixtile_loftq_defconfig b/configs/mixtile_loftq_defconfig
index 0e4cdc4..2f92228 100644
--- a/configs/mixtile_loftq_defconfig
+++ b/configs/mixtile_loftq_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31-mixtile-loftq"
CONFIG_SPL=y
CONFIG_MACH_SUN6I=y
CONFIG_DRAM_ZQ=251
-CONFIG_MACPWR="PA21"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB1_VBUS_PIN="PH24"
CONFIG_USB2_VBUS_PIN=""
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index 76655d7..078e98b 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=408
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
index 924ff38..85ff31c 100644
--- a/configs/nanopi_neo_plus2_defconfig
+++ b/configs/nanopi_neo_plus2_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=408
CONFIG_DRAM_ZQ=3881977
# CONFIG_DRAM_ODT_EN is not set
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/nanopi_r1s_h5_defconfig b/configs/nanopi_r1s_h5_defconfig
index 27cf172..2a6f94a 100644
--- a/configs/nanopi_r1s_h5_defconfig
+++ b/configs/nanopi_r1s_h5_defconfig
@@ -6,7 +6,6 @@ CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=672
CONFIG_DRAM_ZQ=3881977
# CONFIG_DRAM_ODT_EN is not set
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
index 777af8c..fb6fbaf 100644
--- a/configs/orangepi_pc2_defconfig
+++ b/configs/orangepi_pc2_defconfig
@@ -5,7 +5,6 @@ CONFIG_SPL=y
CONFIG_MACH_SUN50I_H5=y
CONFIG_DRAM_CLK=672
CONFIG_DRAM_ZQ=3881977
-CONFIG_MACPWR="PD6"
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
index 138a6a7..5e2cbc4 100644
--- a/configs/orangepi_plus2e_defconfig
+++ b/configs/orangepi_plus2e_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus2e"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
index 76de72a..092ce77 100644
--- a/configs/orangepi_plus_defconfig
+++ b/configs/orangepi_plus_defconfig
@@ -4,10 +4,8 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=672
-CONFIG_MACPWR="PD6"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB1_VBUS_PIN="PG13"
-CONFIG_SATAPWR="PG11"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL_I2C=y
CONFIG_SPL_SYS_I2C_LEGACY=y
@@ -16,3 +14,4 @@ CONFIG_SUN8I_EMAC=y
CONFIG_SY8106A_POWER=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
+CONFIG_USB3_VBUS_PIN="PG11"
diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
index df11ad8..3ddaf05 100644
--- a/configs/orangepi_win_defconfig
+++ b/configs/orangepi_win_defconfig
@@ -3,7 +3,6 @@ CONFIG_ARCH_SUNXI=y
CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win"
CONFIG_SPL=y
CONFIG_MACH_SUN50I=y
-CONFIG_MACPWR="PD14"
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPI_FLASH_WINBOND=y
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 6dac609..4712b8e 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-pine-h64"
CONFIG_SPL=y
CONFIG_MACH_SUN50I_H6=y
CONFIG_SUNXI_DRAM_H6_LPDDR3=y
-CONFIG_MACPWR="PC16"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB3_VBUS_PIN="PL5"
CONFIG_SPL_SPI_SUNXI=y
diff --git a/configs/zeropi_defconfig b/configs/zeropi_defconfig
index 11f3715..7901bff 100644
--- a/configs/zeropi_defconfig
+++ b/configs/zeropi_defconfig
@@ -4,7 +4,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-zeropi"
CONFIG_SPL=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=408
-CONFIG_MACPWR="PD6"
# CONFIG_VIDEO_DE2 is not set
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_CONSOLE_MUX=y
diff --git a/drivers/Makefile b/drivers/Makefile
index 74f940a..bf73b77 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_$(SPL_)ALTERA_SDRAM) += ddr/altera/
obj-$(CONFIG_ARCH_IMX8M) += ddr/imx/imx8m/
obj-$(CONFIG_IMX8ULP_DRAM) += ddr/imx/imx8ulp/
obj-$(CONFIG_ARCH_IMX9) += ddr/imx/imx9/
+obj-$(CONFIG_DRAM_SUN20I_D1) += ram/
obj-$(CONFIG_SPL_DM_RESET) += reset/
obj-$(CONFIG_SPL_MUSB_NEW) += usb/musb-new/
obj-$(CONFIG_SPL_USB_GADGET) += usb/gadget/
diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c
index 94a3379..9064774 100644
--- a/drivers/ata/ahci_sunxi.c
+++ b/drivers/ata/ahci_sunxi.c
@@ -7,6 +7,7 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <linux/delay.h>
+#include <power/regulator.h>
#define AHCI_PHYCS0R 0x00c0
#define AHCI_PHYCS1R 0x00c4
@@ -74,6 +75,7 @@ static int sunxi_ahci_phy_init(u8 *reg_base)
static int sunxi_sata_probe(struct udevice *dev)
{
+ struct udevice *reg_dev;
ulong base;
u8 *reg;
int ret;
@@ -89,6 +91,13 @@ static int sunxi_sata_probe(struct udevice *dev)
debug("%s: Failed to init phy (err=%d)\n", __func__, ret);
return ret;
}
+
+ ret = device_get_supply_regulator(dev, "target-supply", &reg_dev);
+ if (ret == 0) {
+ regulator_set_enable(reg_dev, true);
+ mdelay(500);
+ }
+
ret = ahci_probe_scsi(dev, base);
if (ret) {
debug("%s: Failed to probe (err=%d)\n", __func__, ret);
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index bf11fad..8bdc094 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -87,6 +87,13 @@ config CLK_SUN8I_H3
This enables common clock driver support for platforms based
on Allwinner H3/H5 SoC.
+config CLK_SUN20I_D1
+ bool "Clock driver for Allwinner D1"
+ default MACH_SUN8I_R528
+ help
+ This enables common clock driver support for platforms based
+ on Allwinner D1 SoC.
+
config CLK_SUN50I_H6
bool "Clock driver for Allwinner H6"
default MACH_SUN50I_H6
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 895da02..90a2774 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
obj-$(CONFIG_CLK_SUN9I_A80) += clk_a80.o
obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
+obj-$(CONFIG_CLK_SUN20I_D1) += clk_d1.o
obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
obj-$(CONFIG_CLK_SUN50I_H6_R) += clk_h6_r.o
obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
diff --git a/drivers/clk/sunxi/clk_d1.c b/drivers/clk/sunxi/clk_d1.c
new file mode 100644
index 0000000..9dae761
--- /dev/null
+++ b/drivers/clk/sunxi/clk_d1.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/sun20i-d1-ccu.h>
+#include <dt-bindings/reset/sun20i-d1-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate d1_gates[] = {
+ [CLK_APB0] = GATE_DUMMY,
+
+ [CLK_BUS_MMC0] = GATE(0x84c, BIT(0)),
+ [CLK_BUS_MMC1] = GATE(0x84c, BIT(1)),
+ [CLK_BUS_MMC2] = GATE(0x84c, BIT(2)),
+ [CLK_BUS_UART0] = GATE(0x90c, BIT(0)),
+ [CLK_BUS_UART1] = GATE(0x90c, BIT(1)),
+ [CLK_BUS_UART2] = GATE(0x90c, BIT(2)),
+ [CLK_BUS_UART3] = GATE(0x90c, BIT(3)),
+ [CLK_BUS_UART4] = GATE(0x90c, BIT(4)),
+ [CLK_BUS_UART5] = GATE(0x90c, BIT(5)),
+ [CLK_BUS_I2C0] = GATE(0x91c, BIT(0)),
+ [CLK_BUS_I2C1] = GATE(0x91c, BIT(1)),
+ [CLK_BUS_I2C2] = GATE(0x91c, BIT(2)),
+ [CLK_BUS_I2C3] = GATE(0x91c, BIT(3)),
+ [CLK_SPI0] = GATE(0x940, BIT(31)),
+ [CLK_SPI1] = GATE(0x944, BIT(31)),
+ [CLK_BUS_SPI0] = GATE(0x96c, BIT(0)),
+ [CLK_BUS_SPI1] = GATE(0x96c, BIT(1)),
+
+ [CLK_BUS_EMAC] = GATE(0x97c, BIT(0)),
+
+ [CLK_USB_OHCI0] = GATE(0xa70, BIT(31)),
+ [CLK_USB_OHCI1] = GATE(0xa74, BIT(31)),
+ [CLK_BUS_OHCI0] = GATE(0xa8c, BIT(0)),
+ [CLK_BUS_OHCI1] = GATE(0xa8c, BIT(1)),
+ [CLK_BUS_EHCI0] = GATE(0xa8c, BIT(4)),
+ [CLK_BUS_EHCI1] = GATE(0xa8c, BIT(5)),
+ [CLK_BUS_OTG] = GATE(0xa8c, BIT(8)),
+ [CLK_BUS_LRADC] = GATE(0xa9c, BIT(0)),
+
+ [CLK_RISCV] = GATE(0xd04, BIT(31)),
+};
+
+static struct ccu_reset d1_resets[] = {
+ [RST_BUS_MMC0] = RESET(0x84c, BIT(16)),
+ [RST_BUS_MMC1] = RESET(0x84c, BIT(17)),
+ [RST_BUS_MMC2] = RESET(0x84c, BIT(18)),
+ [RST_BUS_UART0] = RESET(0x90c, BIT(16)),
+ [RST_BUS_UART1] = RESET(0x90c, BIT(17)),
+ [RST_BUS_UART2] = RESET(0x90c, BIT(18)),
+ [RST_BUS_UART3] = RESET(0x90c, BIT(19)),
+ [RST_BUS_UART4] = RESET(0x90c, BIT(20)),
+ [RST_BUS_UART5] = RESET(0x90c, BIT(21)),
+ [RST_BUS_I2C0] = RESET(0x91c, BIT(16)),
+ [RST_BUS_I2C1] = RESET(0x91c, BIT(17)),
+ [RST_BUS_I2C2] = RESET(0x91c, BIT(18)),
+ [RST_BUS_I2C3] = RESET(0x91c, BIT(19)),
+ [RST_BUS_SPI0] = RESET(0x96c, BIT(16)),
+ [RST_BUS_SPI1] = RESET(0x96c, BIT(17)),
+
+ [RST_BUS_EMAC] = RESET(0x97c, BIT(16)),
+
+ [RST_USB_PHY0] = RESET(0xa70, BIT(30)),
+ [RST_USB_PHY1] = RESET(0xa74, BIT(30)),
+ [RST_BUS_OHCI0] = RESET(0xa8c, BIT(16)),
+ [RST_BUS_OHCI1] = RESET(0xa8c, BIT(17)),
+ [RST_BUS_EHCI0] = RESET(0xa8c, BIT(20)),
+ [RST_BUS_EHCI1] = RESET(0xa8c, BIT(21)),
+ [RST_BUS_OTG] = RESET(0xa8c, BIT(24)),
+ [RST_BUS_LRADC] = RESET(0xa9c, BIT(16)),
+};
+
+const struct ccu_desc d1_ccu_desc = {
+ .gates = d1_gates,
+ .resets = d1_resets,
+ .num_gates = ARRAY_SIZE(d1_gates),
+ .num_resets = ARRAY_SIZE(d1_resets),
+};
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
index ec02a2d..1782cff 100644
--- a/drivers/clk/sunxi/clk_sunxi.c
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -118,6 +118,7 @@ extern const struct ccu_desc a64_ccu_desc;
extern const struct ccu_desc a80_ccu_desc;
extern const struct ccu_desc a80_mmc_clk_desc;
extern const struct ccu_desc a83t_ccu_desc;
+extern const struct ccu_desc d1_ccu_desc;
extern const struct ccu_desc f1c100s_ccu_desc;
extern const struct ccu_desc h3_ccu_desc;
extern const struct ccu_desc h6_ccu_desc;
@@ -195,6 +196,10 @@ static const struct udevice_id sunxi_clk_ids[] = {
{ .compatible = "allwinner,sun50i-h5-ccu",
.data = (ulong)&h3_ccu_desc },
#endif
+#ifdef CONFIG_CLK_SUN20I_D1
+ { .compatible = "allwinner,sun20i-d1-ccu",
+ .data = (ulong)&d1_ccu_desc },
+#endif
#ifdef CONFIG_CLK_SUN50I_H6
{ .compatible = "allwinner,sun50i-h6-ccu",
.data = (ulong)&h6_ccu_desc },
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 74baa98..ba42b07 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -372,6 +372,13 @@ config SUNXI_GPIO
help
Support the GPIO device in Allwinner SoCs.
+config SUNXI_NEW_PINCTRL
+ bool
+ depends on SUNXI_GPIO
+ ---help---
+ The Allwinner D1 and other new SoCs use a different register map
+ for the GPIO block, which we need to know about in the SPL.
+
config XILINX_GPIO
bool "Xilinx GPIO driver"
depends on DM_GPIO
diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c
index 4967219..af66316 100644
--- a/drivers/gpio/axp_gpio.c
+++ b/drivers/gpio/axp_gpio.c
@@ -14,6 +14,7 @@
#include <dm/lists.h>
#include <dm/root.h>
#include <errno.h>
+#include <sunxi_gpio.h>
static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val);
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index f0b42e4..e4463a2 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -17,37 +17,165 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <dt-bindings/gpio/gpio.h>
+#include <sunxi_gpio.h>
-#if !CONFIG_IS_ENABLED(DM_GPIO)
-static int sunxi_gpio_output(u32 pin, u32 val)
+/*
+ * =======================================================================
+ * Low level GPIO/pin controller access functions, to be shared by non-DM
+ * SPL code and the DM pinctrl/GPIO drivers.
+ * The functions ending in "bank" take a base pointer to a GPIO bank, and
+ * the pin offset is relative to that bank.
+ * The functions without "bank" in their name take a linear GPIO number,
+ * covering all ports, and starting at 0 for PortA.
+ * =======================================================================
+ */
+
+#define GPIO_BANK(pin) ((pin) >> 5)
+#define GPIO_NUM(pin) ((pin) & 0x1f)
+
+#define GPIO_CFG_REG_OFFSET 0x00
+#define GPIO_CFG_INDEX(pin) (((pin) & 0x1f) >> 3)
+#define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1f) & 0x7) << 2)
+
+#define GPIO_DAT_REG_OFFSET 0x10
+
+#define GPIO_DRV_REG_OFFSET 0x14
+
+/* Newer SoCs use a slightly different register layout */
+#ifdef CONFIG_SUNXI_NEW_PINCTRL
+/* pin drive strength: 4 bits per pin */
+#define GPIO_DRV_INDEX(pin) ((pin) / 8)
+#define GPIO_DRV_OFFSET(pin) (((pin) % 8) * 4)
+
+#define GPIO_PULL_REG_OFFSET 0x24
+
+#else /* older generation pin controllers */
+/* pin drive strength: 2 bits per pin */
+#define GPIO_DRV_INDEX(pin) ((pin) / 16)
+#define GPIO_DRV_OFFSET(pin) (((pin) % 16) * 2)
+
+#define GPIO_PULL_REG_OFFSET 0x1c
+#endif
+
+#define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
+#define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+
+static void* BANK_TO_GPIO(int bank)
+{
+ void *pio_base;
+
+ if (bank < SUNXI_GPIO_L) {
+ pio_base = (void *)(uintptr_t)SUNXI_PIO_BASE;
+ } else {
+ pio_base = (void *)(uintptr_t)SUNXI_R_PIO_BASE;
+ bank -= SUNXI_GPIO_L;
+ }
+
+ return pio_base + bank * SUNXI_PINCTRL_BANK_SIZE;
+}
+
+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
+{
+ u32 index = GPIO_CFG_INDEX(pin_offset);
+ u32 offset = GPIO_CFG_OFFSET(pin_offset);
+
+ clrsetbits_le32(bank_base + GPIO_CFG_REG_OFFSET + index * 4,
+ 0xfU << offset, val << offset);
+}
+
+void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
{
- u32 dat;
u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+ void *pio = BANK_TO_GPIO(bank);
- dat = readl(&pio->dat);
- if (val)
- dat |= 0x1 << num;
- else
- dat &= ~(0x1 << num);
+ sunxi_gpio_set_cfgbank(pio, GPIO_NUM(pin), val);
+}
+
+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset)
+{
+ u32 index = GPIO_CFG_INDEX(pin_offset);
+ u32 offset = GPIO_CFG_OFFSET(pin_offset);
+ u32 cfg;
- writel(dat, &pio->dat);
+ cfg = readl(bank_base + GPIO_CFG_REG_OFFSET + index * 4);
+ cfg >>= offset;
- return 0;
+ return cfg & 0xf;
+}
+
+int sunxi_gpio_get_cfgpin(u32 pin)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *bank_base = BANK_TO_GPIO(bank);
+
+ return sunxi_gpio_get_cfgbank(bank_base, GPIO_NUM(pin));
+}
+
+static void sunxi_gpio_set_value_bank(void *bank_base, int pin, bool set)
+{
+ u32 mask = 1U << pin;
+
+ clrsetbits_le32(bank_base + GPIO_DAT_REG_OFFSET,
+ set ? 0 : mask, set ? mask : 0);
+}
+
+static int sunxi_gpio_get_value_bank(void *bank_base, int pin)
+{
+ return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & (1U << pin));
+}
+
+void sunxi_gpio_set_drv(u32 pin, u32 val)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *bank_base = BANK_TO_GPIO(bank);
+
+ sunxi_gpio_set_drv_bank(bank_base, GPIO_NUM(pin), val);
+}
+
+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val)
+{
+ u32 index = GPIO_DRV_INDEX(pin_offset);
+ u32 offset = GPIO_DRV_OFFSET(pin_offset);
+
+ clrsetbits_le32(bank_base + GPIO_DRV_REG_OFFSET + index * 4,
+ 0x3U << offset, val << offset);
+}
+
+void sunxi_gpio_set_pull(u32 pin, u32 val)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *bank_base = BANK_TO_GPIO(bank);
+
+ sunxi_gpio_set_pull_bank(bank_base, GPIO_NUM(pin), val);
}
-static int sunxi_gpio_input(u32 pin)
+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val)
+{
+ u32 index = GPIO_PULL_INDEX(pin_offset);
+ u32 offset = GPIO_PULL_OFFSET(pin_offset);
+
+ clrsetbits_le32(bank_base + GPIO_PULL_REG_OFFSET + index * 4,
+ 0x3U << offset, val << offset);
+}
+
+
+/* =========== Non-DM code, used by the SPL. ============ */
+
+#if !CONFIG_IS_ENABLED(DM_GPIO)
+static void sunxi_gpio_set_value(u32 pin, bool set)
{
- u32 dat;
u32 bank = GPIO_BANK(pin);
- u32 num = GPIO_NUM(pin);
- struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+ void *pio = BANK_TO_GPIO(bank);
+
+ sunxi_gpio_set_value_bank(pio, GPIO_NUM(pin), set);
+}
- dat = readl(&pio->dat);
- dat >>= num;
+static int sunxi_gpio_get_value(u32 pin)
+{
+ u32 bank = GPIO_BANK(pin);
+ void *pio = BANK_TO_GPIO(bank);
- return dat & 0x1;
+ return sunxi_gpio_get_value_bank(pio, GPIO_NUM(pin));
}
int gpio_request(unsigned gpio, const char *label)
@@ -70,18 +198,21 @@ int gpio_direction_input(unsigned gpio)
int gpio_direction_output(unsigned gpio, int value)
{
sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
+ sunxi_gpio_set_value(gpio, value);
- return sunxi_gpio_output(gpio, value);
+ return 0;
}
int gpio_get_value(unsigned gpio)
{
- return sunxi_gpio_input(gpio);
+ return sunxi_gpio_get_value(gpio);
}
int gpio_set_value(unsigned gpio, int value)
{
- return sunxi_gpio_output(gpio, value);
+ sunxi_gpio_set_value(gpio, value);
+
+ return 0;
}
int sunxi_name_to_gpio(const char *name)
@@ -106,7 +237,9 @@ int sunxi_name_to_gpio(const char *name)
return -1;
return group * 32 + pin;
}
-#endif /* DM_GPIO */
+#endif /* !DM_GPIO */
+
+/* =========== DM code, used by U-Boot proper. ============ */
#if CONFIG_IS_ENABLED(DM_GPIO)
/* TODO(sjg@chromium.org): Remove this function and use device tree */
@@ -131,13 +264,8 @@ int sunxi_name_to_gpio(const char *name)
static int sunxi_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct sunxi_gpio_plat *plat = dev_get_plat(dev);
- u32 num = GPIO_NUM(offset);
- unsigned dat;
-
- dat = readl(&plat->regs->dat);
- dat >>= num;
- return dat & 0x1;
+ return sunxi_gpio_get_value_bank(plat->regs, offset);
}
static int sunxi_gpio_get_function(struct udevice *dev, unsigned offset)
@@ -175,9 +303,8 @@ static int sunxi_gpio_set_flags(struct udevice *dev, unsigned int offset,
if (flags & GPIOD_IS_OUT) {
u32 value = !!(flags & GPIOD_IS_OUT_ACTIVE);
- u32 num = GPIO_NUM(offset);
- clrsetbits_le32(&plat->regs->dat, 1 << num, value << num);
+ sunxi_gpio_set_value_bank(plat->regs, offset, value);
sunxi_gpio_set_cfgbank(plat->regs, offset, SUNXI_GPIO_OUTPUT);
} else if (flags & GPIOD_IS_IN) {
u32 pull = 0;
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 14cdb0f..c38330f 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -124,7 +124,8 @@ enum mvtwsi_ctrl_register_fields {
* on other platforms, it is a normal r/w bit, which is cleared by writing 0.
*/
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || \
+ defined(CONFIG_SUNXI_GEN_NCAT2)
#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000008
#else
#define MVTWSI_CONTROL_CLEAR_IFLG 0x00000000
diff --git a/drivers/i2c/sun6i_p2wi.c b/drivers/i2c/sun6i_p2wi.c
index d221323..b8e07a5 100644
--- a/drivers/i2c/sun6i_p2wi.c
+++ b/drivers/i2c/sun6i_p2wi.c
@@ -20,10 +20,10 @@
#include <errno.h>
#include <i2c.h>
#include <reset.h>
+#include <sunxi_gpio.h>
#include <time.h>
#include <asm/io.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/p2wi.h>
#include <asm/arch/prcm.h>
#include <asm/arch/sys_proto.h>
diff --git a/drivers/i2c/sun8i_rsb.c b/drivers/i2c/sun8i_rsb.c
index 47fa05b..f36f2c7 100644
--- a/drivers/i2c/sun8i_rsb.c
+++ b/drivers/i2c/sun8i_rsb.c
@@ -14,10 +14,10 @@
#include <dm.h>
#include <errno.h>
#include <i2c.h>
+#include <sunxi_gpio.h>
#include <reset.h>
#include <time.h>
#include <asm/arch/cpu.h>
-#include <asm/arch/gpio.h>
#include <asm/arch/prcm.h>
#include <asm/arch/rsb.h>
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 23bc7da..4d6351b 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -27,6 +27,7 @@
#include <asm/arch/cpu.h>
#include <asm/arch/mmc.h>
#include <linux/delay.h>
+#include <sunxi_gpio.h>
#ifndef CCM_MMC_CTRL_MODE_SEL_NEW
#define CCM_MMC_CTRL_MODE_SEL_NEW 0
@@ -56,6 +57,7 @@ static bool sunxi_mmc_can_calibrate(void)
return IS_ENABLED(CONFIG_MACH_SUN50I) ||
IS_ENABLED(CONFIG_MACH_SUN50I_H5) ||
IS_ENABLED(CONFIG_SUN50I_GEN_H6) ||
+ IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2) ||
IS_ENABLED(CONFIG_MACH_SUN8I_R40);
}
@@ -190,7 +192,7 @@ static int mmc_config_clock(struct sunxi_mmc_priv *priv, struct mmc *mmc)
rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
writel(rval, &priv->reg->clkcr);
-#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
/* A64 supports calibration of delays on MMC controller and we
* have to set delay of zero before starting calibration.
* Allwinner BSP driver sets a delay only in the case of
@@ -543,7 +545,7 @@ struct mmc *sunxi_mmc_init(int sdc_no)
/* config ahb clock */
debug("init mmc %d clock and io\n", sdc_no);
-#if !defined(CONFIG_SUN50I_GEN_H6)
+#if !defined(CONFIG_SUN50I_GEN_H6) && !defined(CONFIG_SUNXI_GEN_NCAT2)
setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
#ifdef CONFIG_SUNXI_GEN_SUN6I
@@ -618,7 +620,7 @@ static unsigned get_mclk_offset(void)
if (IS_ENABLED(CONFIG_MACH_SUN9I_A80))
return 0x410;
- if (IS_ENABLED(CONFIG_SUN50I_GEN_H6))
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2))
return 0x830;
return 0x88;
@@ -705,6 +707,7 @@ static const struct udevice_id sunxi_mmc_ids[] = {
{ .compatible = "allwinner,sun50i-h6-emmc" },
{ .compatible = "allwinner,sun50i-a100-mmc" },
{ .compatible = "allwinner,sun50i-a100-emmc" },
+ { .compatible = "allwinner,sun20i-d1-mmc" },
{ /* sentinel */ }
};
diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c
index 04c3274..4ba9ee1 100644
--- a/drivers/net/sun8i_emac.c
+++ b/drivers/net/sun8i_emac.c
@@ -29,6 +29,7 @@
#include <net.h>
#include <reset.h>
#include <wait_bit.h>
+#include <power/regulator.h>
#define MDIO_CMD_MII_BUSY BIT(0)
#define MDIO_CMD_MII_WRITE BIT(1)
@@ -170,6 +171,7 @@ struct emac_eth_dev {
#if CONFIG_IS_ENABLED(DM_GPIO)
struct gpio_desc reset_gpio;
#endif
+ struct udevice *phy_reg;
};
@@ -720,6 +722,9 @@ static int sun8i_emac_eth_probe(struct udevice *dev)
sun8i_emac_set_syscon(sun8i_pdata, priv);
+ if (priv->phy_reg)
+ regulator_set_enable(priv->phy_reg, true);
+
sun8i_mdio_init(dev->name, dev);
priv->bus = miiphy_get_dev_by_name(dev->name);
@@ -829,6 +834,8 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev)
priv->sysctl_reg = (void *)syscon_base + priv->variant->syscon_offset;
+ device_get_supply_regulator(dev, "phy-supply", &priv->phy_reg);
+
pdata->phy_interface = -1;
priv->phyaddr = -1;
priv->use_internal_phy = false;
diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c
index 4c90d4b..f546ad1 100644
--- a/drivers/net/sunxi_emac.c
+++ b/drivers/net/sunxi_emac.c
@@ -17,6 +17,7 @@
#include <net.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
+#include <power/regulator.h>
/* EMAC register */
struct emac_regs {
@@ -165,6 +166,7 @@ struct emac_eth_dev {
struct phy_device *phydev;
int link_printed;
uchar rx_buf[EMAC_RX_BUFSIZE];
+ struct udevice *phy_reg;
};
struct emac_rxhdr {
@@ -572,6 +574,9 @@ static int sunxi_emac_eth_probe(struct udevice *dev)
if (ret)
return ret;
+ if (priv->phy_reg)
+ regulator_set_enable(priv->phy_reg, true);
+
return sunxi_emac_init_phy(priv, dev);
}
@@ -585,9 +590,42 @@ static const struct eth_ops sunxi_emac_eth_ops = {
static int sunxi_emac_eth_of_to_plat(struct udevice *dev)
{
struct eth_pdata *pdata = dev_get_plat(dev);
+ struct emac_eth_dev *priv = dev_get_priv(dev);
+ struct ofnode_phandle_args args;
+ ofnode phy_node, mdio_node;
+ int ret;
pdata->iobase = dev_read_addr(dev);
+ phy_node = dev_get_phy_node(dev);
+ if (!ofnode_valid(phy_node)) {
+ dev_err(dev, "failed to get PHY node\n");
+ return -ENOENT;
+ }
+ /*
+ * The PHY regulator is in the MDIO node, not the EMAC or PHY node.
+ * U-Boot does not have (and does not need) a device driver for the
+ * MDIO device, so just "pass through" that DT node to get to the
+ * regulator phandle.
+ * The PHY regulator is optional, though: ignore if we cannot find
+ * a phy-supply property.
+ */
+ mdio_node = ofnode_get_parent(phy_node);
+ ret= ofnode_parse_phandle_with_args(mdio_node, "phy-supply", NULL, 0, 0,
+ &args);
+ if (ret && ret != -ENOENT) {
+ dev_err(dev, "failed to get PHY supply node\n");
+ return ret;
+ }
+ if (!ret) {
+ ret = uclass_get_device_by_ofnode(UCLASS_REGULATOR, args.node,
+ &priv->phy_reg);
+ if (ret) {
+ dev_err(dev, "failed to get PHY regulator node\n");
+ return ret;
+ }
+ }
+
return 0;
}
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 77da908..cbd6179 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -124,4 +124,9 @@ config PINCTRL_SUN50I_H616_R
default MACH_SUN50I_H616
select PINCTRL_SUNXI
+config PINCTRL_SUN20I_D1
+ bool "Support for the Allwinner D1/R528 PIO"
+ default MACH_SUN8I_R528
+ select PINCTRL_SUNXI
+
endif
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index e510218..bdf6360 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -7,6 +7,7 @@
#include <dm/pinctrl.h>
#include <errno.h>
#include <malloc.h>
+#include <sunxi_gpio.h>
#include <asm/gpio.h>
@@ -35,7 +36,7 @@ struct sunxi_pinctrl_desc {
};
struct sunxi_pinctrl_plat {
- struct sunxi_gpio __iomem *base;
+ void __iomem *base;
};
static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
@@ -86,8 +87,8 @@ static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
sunxi_pinctrl_get_function_name(dev, func_selector),
desc->functions[func_selector].mux);
- sunxi_gpio_set_cfgbank(plat->base + bank, pin,
- desc->functions[func_selector].mux);
+ sunxi_gpio_set_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE,
+ pin, desc->functions[func_selector].mux);
return 0;
}
@@ -102,7 +103,7 @@ static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
uint bank, uint pin, uint bias)
{
- struct sunxi_gpio *regs = &plat->base[bank];
+ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
sunxi_gpio_set_pull_bank(regs, pin, bias);
@@ -112,7 +113,7 @@ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
uint bank, uint pin, uint drive)
{
- struct sunxi_gpio *regs = &plat->base[bank];
+ void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
if (drive < 10 || drive > 40)
return -EINVAL;
@@ -148,7 +149,7 @@ static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
int pin = pin_selector % SUNXI_GPIOS_PER_BANK;
- int mux = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
+ int mux = sunxi_gpio_get_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE, pin);
switch (mux) {
case SUNXI_GPIO_INPUT:
@@ -206,7 +207,7 @@ static int sunxi_pinctrl_bind(struct udevice *dev)
if (!gpio_plat)
return -ENOMEM;
- gpio_plat->regs = plat->base + i;
+ gpio_plat->regs = plat->base + i * SUNXI_PINCTRL_BANK_SIZE;
gpio_plat->bank_name[0] = 'P';
gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
gpio_plat->bank_name[2] = '\0';
@@ -597,6 +598,32 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_r_pinctrl_desc =
.num_banks = 3,
};
+static const struct sunxi_pinctrl_function sun20i_d1_pinctrl_functions[] = {
+ { "emac", 8 }, /* PE0-PE15 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 4 }, /* PB10-PB11 */
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC2-PC7 */
+ { "spi0", 2 }, /* PC2-PC7 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2,PF4 */
+#else
+ { "uart0", 6 }, /* PB0-PB1, PB8-PB9, PE2-PE3 */
+#endif
+ { "uart1", 2 }, /* PG6-PG7 */
+ { "uart2", 7 }, /* PB0-PB1 */
+ { "uart3", 7 }, /* PB6-PB7 */
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun20i_d1_pinctrl_desc = {
+ .functions = sun20i_d1_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun20i_d1_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 7,
+};
+
static const struct sunxi_pinctrl_function sun50i_a64_pinctrl_functions[] = {
{ "emac", 4 }, /* PD8-PD23 */
{ "gpio_in", 0 },
@@ -862,6 +889,12 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
.data = (ulong)&sun9i_a80_r_pinctrl_desc,
},
#endif
+#ifdef CONFIG_PINCTRL_SUN20I_D1
+ {
+ .compatible = "allwinner,sun20i-d1-pinctrl",
+ .data = (ulong)&sun20i_d1_pinctrl_desc,
+ },
+#endif
#ifdef CONFIG_PINCTRL_SUN50I_A64
{
.compatible = "allwinner,sun50i-a64-pinctrl",
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig
index bf99964..5b07e92 100644
--- a/drivers/ram/Kconfig
+++ b/drivers/ram/Kconfig
@@ -109,8 +109,9 @@ config IMXRT_SDRAM
source "drivers/ram/aspeed/Kconfig"
source "drivers/ram/cadence/Kconfig"
+source "drivers/ram/octeon/Kconfig"
source "drivers/ram/rockchip/Kconfig"
source "drivers/ram/sifive/Kconfig"
source "drivers/ram/stm32mp1/Kconfig"
-source "drivers/ram/octeon/Kconfig"
source "drivers/ram/starfive/Kconfig"
+source "drivers/ram/sunxi/Kconfig"
diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile
index 6eb1a24..985990a 100644
--- a/drivers/ram/Makefile
+++ b/drivers/ram/Makefile
@@ -23,6 +23,9 @@ obj-$(CONFIG_RAM_SIFIVE) += sifive/
ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SPL_STARFIVE_DDR) += starfive/
endif
+
+obj-$(CONFIG_DRAM_SUN20I_D1) += sunxi/
+
obj-$(CONFIG_ARCH_OCTEON) += octeon/
obj-$(CONFIG_ARCH_RMOBILE) += renesas/
diff --git a/drivers/ram/sunxi/Kconfig b/drivers/ram/sunxi/Kconfig
new file mode 100644
index 0000000..1775cb0
--- /dev/null
+++ b/drivers/ram/sunxi/Kconfig
@@ -0,0 +1,60 @@
+config DRAM_SUN20I_D1
+ bool
+ depends on ARCH_SUNXI
+ help
+ This enables support for the DRAM controller driver covering
+ the Allwinner D1/R528/T113s SoCs.
+
+if DRAM_SUN20I_D1
+
+config DRAM_SUNXI_ODT_EN
+ hex "DRAM ODT EN parameter"
+ help
+ ODT EN value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR0
+ hex "DRAM TPR0 parameter"
+ help
+ TPR0 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR11
+ hex "DRAM TPR11 parameter"
+ help
+ TPR11 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR12
+ hex "DRAM TPR12 parameter"
+ help
+ TPR12 value from vendor DRAM settings.
+
+config DRAM_SUNXI_TPR13
+ hex "DRAM TPR13 parameter"
+ help
+ TPR13 value from vendor DRAM settings. It tells which features
+ should be configured.
+
+choice
+ prompt "DRAM chip type"
+ default SUNXI_DRAM_TYPE_DDR3 if DRAM_SUN20I_D1
+
+config SUNXI_DRAM_TYPE_DDR2
+ bool "DDR2 chips"
+
+config SUNXI_DRAM_TYPE_DDR3
+ bool "DDR3 chips"
+
+config SUNXI_DRAM_TYPE_LPDDR2
+ bool "LPDDR2 chips"
+
+config SUNXI_DRAM_TYPE_LPDDR3
+ bool "LPDDR3 chips"
+endchoice
+
+config SUNXI_DRAM_TYPE
+ int
+ default 2 if SUNXI_DRAM_TYPE_DDR2
+ default 3 if SUNXI_DRAM_TYPE_DDR3
+ default 6 if SUNXI_DRAM_TYPE_LPDDR2
+ default 7 if SUNXI_DRAM_TYPE_LPDDR3
+
+endif
diff --git a/drivers/ram/sunxi/Makefile b/drivers/ram/sunxi/Makefile
new file mode 100644
index 0000000..86ea0b9
--- /dev/null
+++ b/drivers/ram/sunxi/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_DRAM_SUN20I_D1) += dram_sun20i_d1.o
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.c b/drivers/ram/sunxi/dram_sun20i_d1.c
new file mode 100644
index 0000000..3837928
--- /dev/null
+++ b/drivers/ram/sunxi/dram_sun20i_d1.c
@@ -0,0 +1,1441 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Allwinner D1/D1s/R528/T113-sx DRAM initialisation
+ *
+ * As usual there is no documentation for the memory controller or PHY IP
+ * used here. The baseline of this code was lifted from awboot[1], which
+ * seems to be based on some form of de-compilation of some original Allwinner
+ * code bits (with a GPL2 license tag from the very beginning).
+ * This version here is a reworked version, to match the U-Boot coding style
+ * and style of the other Allwinner DRAM drivers.
+ *
+ * [1] https://github.com/szemzoa/awboot.git
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#ifdef CONFIG_RAM
+ #include <dm.h>
+ #include <ram.h>
+#endif
+#include <linux/delay.h>
+
+#include "dram_sun20i_d1.h"
+
+#ifndef SUNXI_SID_BASE
+#define SUNXI_SID_BASE 0x3006200
+#endif
+
+#ifndef SUNXI_CCM_BASE
+#define SUNXI_CCM_BASE 0x2001000
+#endif
+
+static void sid_read_ldoB_cal(const dram_para_t *para)
+{
+ uint32_t reg;
+
+ reg = (readl(SUNXI_SID_BASE + 0x1c) & 0xff00) >> 8;
+
+ if (reg == 0)
+ return;
+
+ switch (para->dram_type) {
+ case SUNXI_DRAM_TYPE_DDR2:
+ break;
+ case SUNXI_DRAM_TYPE_DDR3:
+ if (reg > 0x20)
+ reg -= 0x16;
+ break;
+ default:
+ reg = 0;
+ break;
+ }
+
+ clrsetbits_le32(0x3000150, 0xff00, reg << 8);
+}
+
+static void dram_voltage_set(const dram_para_t *para)
+{
+ int vol;
+
+ switch (para->dram_type) {
+ case SUNXI_DRAM_TYPE_DDR2:
+ vol = 47;
+ break;
+ case SUNXI_DRAM_TYPE_DDR3:
+ vol = 25;
+ break;
+ default:
+ vol = 0;
+ break;
+ }
+
+ clrsetbits_le32(0x3000150, 0x20ff00, vol << 8);
+
+ udelay(1);
+
+ sid_read_ldoB_cal(para);
+}
+
+static void dram_enable_all_master(void)
+{
+ writel(~0, 0x3102020);
+ writel(0xff, 0x3102024);
+ writel(0xffff, 0x3102028);
+ udelay(10);
+}
+
+static void dram_disable_all_master(void)
+{
+ writel(1, 0x3102020);
+ writel(0, 0x3102024);
+ writel(0, 0x3102028);
+ udelay(10);
+}
+
+static void eye_delay_compensation(const dram_para_t *para)
+{
+ uint32_t delay;
+ unsigned long ptr;
+
+ // DATn0IOCR, n = 0...7
+ delay = (para->dram_tpr11 & 0xf) << 9;
+ delay |= (para->dram_tpr12 & 0xf) << 1;
+ for (ptr = 0x3103310; ptr < 0x3103334; ptr += 4)
+ setbits_le32(ptr, delay);
+
+ // DATn1IOCR, n = 0...7
+ delay = (para->dram_tpr11 & 0xf0) << 5;
+ delay |= (para->dram_tpr12 & 0xf0) >> 3;
+ for (ptr = 0x3103390; ptr != 0x31033b4; ptr += 4)
+ setbits_le32(ptr, delay);
+
+ // PGCR0: assert AC loopback FIFO reset
+ clrbits_le32(0x3103100, 0x04000000);
+
+ // ??
+
+ delay = (para->dram_tpr11 & 0xf0000) >> 7;
+ delay |= (para->dram_tpr12 & 0xf0000) >> 15;
+ setbits_le32(0x3103334, delay);
+ setbits_le32(0x3103338, delay);
+
+ delay = (para->dram_tpr11 & 0xf00000) >> 11;
+ delay |= (para->dram_tpr12 & 0xf00000) >> 19;
+ setbits_le32(0x31033b4, delay);
+ setbits_le32(0x31033b8, delay);
+
+ setbits_le32(0x310333c, (para->dram_tpr11 & 0xf0000) << 9);
+ setbits_le32(0x31033bc, (para->dram_tpr11 & 0xf00000) << 5);
+
+ // PGCR0: release AC loopback FIFO reset
+ setbits_le32(0x3103100, BIT(26));
+
+ udelay(1);
+
+ delay = (para->dram_tpr10 & 0xf0) << 4;
+ for (ptr = 0x3103240; ptr != 0x310327c; ptr += 4)
+ setbits_le32(ptr, delay);
+ for (ptr = 0x3103228; ptr != 0x3103240; ptr += 4)
+ setbits_le32(ptr, delay);
+
+ setbits_le32(0x3103218, (para->dram_tpr10 & 0x0f) << 8);
+ setbits_le32(0x310321c, (para->dram_tpr10 & 0x0f) << 8);
+
+ setbits_le32(0x3103280, (para->dram_tpr10 & 0xf00) >> 4);
+}
+
+/*
+ * Main purpose of the auto_set_timing routine seems to be to calculate all
+ * timing settings for the specific type of sdram used. Read together with
+ * an sdram datasheet for context on the various variables.
+ */
+static void mctl_set_timing_params(const dram_para_t *para,
+ const dram_config_t *config)
+{
+ /* DRAM_TPR0 */
+ u8 tccd = 2;
+ u8 tfaw;
+ u8 trrd;
+ u8 trcd;
+ u8 trc;
+
+ /* DRAM_TPR1 */
+ u8 txp;
+ u8 twtr;
+ u8 trtp = 4;
+ u8 twr;
+ u8 trp;
+ u8 tras;
+
+ /* DRAM_TPR2 */
+ u16 trefi;
+ u16 trfc;
+
+ u8 tcksrx;
+ u8 tckesr;
+ u8 trd2wr;
+ u8 twr2rd;
+ u8 trasmax;
+ u8 twtp;
+ u8 tcke;
+ u8 tmod;
+ u8 tmrd;
+ u8 tmrw;
+
+ u8 tcl;
+ u8 tcwl;
+ u8 t_rdata_en;
+ u8 wr_latency;
+
+ u32 mr0;
+ u32 mr1;
+ u32 mr2;
+ u32 mr3;
+
+ u32 tdinit0;
+ u32 tdinit1;
+ u32 tdinit2;
+ u32 tdinit3;
+
+ switch (para->dram_type) {
+ case SUNXI_DRAM_TYPE_DDR2:
+ /* DRAM_TPR0 */
+ tfaw = ns_to_t(50);
+ trrd = ns_to_t(10);
+ trcd = ns_to_t(20);
+ trc = ns_to_t(65);
+
+ /* DRAM_TPR1 */
+ txp = 2;
+ twtr = ns_to_t(8);
+ twr = ns_to_t(15);
+ trp = ns_to_t(15);
+ tras = ns_to_t(45);
+
+ /* DRAM_TRP2 */
+ trfc = ns_to_t(328);
+ trefi = ns_to_t(7800) / 32;
+
+ trasmax = CONFIG_DRAM_CLK / 30;
+ if (CONFIG_DRAM_CLK < 409) {
+ t_rdata_en = 1;
+ tcl = 3;
+ mr0 = 0x06a3;
+ } else {
+ t_rdata_en = 2;
+ tcl = 4;
+ mr0 = 0x0e73;
+ }
+ tmrd = 2;
+ twtp = twr + 5;
+ tcksrx = 5;
+ tckesr = 4;
+ trd2wr = 4;
+ tcke = 3;
+ tmod = 12;
+ wr_latency = 1;
+ tmrw = 0;
+ twr2rd = twtr + 5;
+ tcwl = 0;
+
+ mr1 = para->dram_mr1;
+ mr2 = 0;
+ mr3 = 0;
+
+ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
+ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
+ tdinit2 = 200 * CONFIG_DRAM_CLK + 1;
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
+
+ break;
+ case SUNXI_DRAM_TYPE_DDR3:
+ trfc = ns_to_t(350);
+ trefi = ns_to_t(7800) / 32 + 1; // XXX
+
+ twtr = ns_to_t(8) + 2; // + 2 ? XXX
+ /* Only used by trd2wr calculation, which gets discard below */
+// twr = max(ns_to_t(15), 2);
+ trrd = max(ns_to_t(10), 2);
+ txp = max(ns_to_t(10), 2);
+
+ if (CONFIG_DRAM_CLK <= 800) {
+ tfaw = ns_to_t(50);
+ trcd = ns_to_t(15);
+ trp = ns_to_t(15);
+ trc = ns_to_t(53);
+ tras = ns_to_t(38);
+
+ mr0 = 0x1c70;
+ mr2 = 0x18;
+ tcl = 6;
+ wr_latency = 2;
+ tcwl = 4;
+ t_rdata_en = 4;
+ } else {
+ tfaw = ns_to_t(35);
+ trcd = ns_to_t(14);
+ trp = ns_to_t(14);
+ trc = ns_to_t(48);
+ tras = ns_to_t(34);
+
+ mr0 = 0x1e14;
+ mr2 = 0x20;
+ tcl = 7;
+ wr_latency = 3;
+ tcwl = 5;
+ t_rdata_en = 5;
+ }
+
+ trasmax = CONFIG_DRAM_CLK / 30;
+ twtp = tcwl + 2 + twtr; // WL+BL/2+tWTR
+ /* Gets overwritten below */
+// trd2wr = tcwl + 2 + twr; // WL+BL/2+tWR
+ twr2rd = tcwl + twtr; // WL+tWTR
+
+ tdinit0 = 500 * CONFIG_DRAM_CLK + 1; // 500 us
+ tdinit1 = 360 * CONFIG_DRAM_CLK / 1000 + 1; // 360 ns
+ tdinit2 = 200 * CONFIG_DRAM_CLK + 1; // 200 us
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1; // 1 us
+
+ mr1 = para->dram_mr1;
+ mr3 = 0;
+ tcke = 3;
+ tcksrx = 5;
+ tckesr = 4;
+ if (((config->dram_tpr13 & 0xc) == 0x04) || CONFIG_DRAM_CLK < 912)
+ trd2wr = 5;
+ else
+ trd2wr = 6;
+
+ tmod = 12;
+ tmrd = 4;
+ tmrw = 0;
+
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR2:
+ tfaw = max(ns_to_t(50), 4);
+ trrd = max(ns_to_t(10), 1);
+ trcd = max(ns_to_t(24), 2);
+ trc = ns_to_t(70);
+ txp = ns_to_t(8);
+ if (txp < 2) {
+ txp++;
+ twtr = 2;
+ } else {
+ twtr = txp;
+ }
+ twr = max(ns_to_t(15), 2);
+ trp = ns_to_t(17);
+ tras = ns_to_t(42);
+ trefi = ns_to_t(3900) / 32;
+ trfc = ns_to_t(210);
+
+ trasmax = CONFIG_DRAM_CLK / 60;
+ mr3 = para->dram_mr3;
+ twtp = twr + 5;
+ mr2 = 6;
+ mr1 = 5;
+ tcksrx = 5;
+ tckesr = 5;
+ trd2wr = 10;
+ tcke = 2;
+ tmod = 5;
+ tmrd = 5;
+ tmrw = 3;
+ tcl = 4;
+ wr_latency = 1;
+ t_rdata_en = 1;
+
+ tdinit0 = 200 * CONFIG_DRAM_CLK + 1;
+ tdinit1 = 100 * CONFIG_DRAM_CLK / 1000 + 1;
+ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
+ twr2rd = twtr + 5;
+ tcwl = 2;
+ mr1 = 195;
+ mr0 = 0;
+
+ break;
+ case SUNXI_DRAM_TYPE_LPDDR3:
+ tfaw = max(ns_to_t(50), 4);
+ trrd = max(ns_to_t(10), 1);
+ trcd = max(ns_to_t(24), 2);
+ trc = ns_to_t(70);
+ twtr = max(ns_to_t(8), 2);
+ twr = max(ns_to_t(15), 2);
+ trp = ns_to_t(17);
+ tras = ns_to_t(42);
+ trefi = ns_to_t(3900) / 32;
+ trfc = ns_to_t(210);
+ txp = twtr;
+
+ trasmax = CONFIG_DRAM_CLK / 60;
+ if (CONFIG_DRAM_CLK < 800) {
+ tcwl = 4;
+ wr_latency = 3;
+ t_rdata_en = 6;
+ mr2 = 12;
+ } else {
+ tcwl = 3;
+ tcke = 6;
+ wr_latency = 2;
+ t_rdata_en = 5;
+ mr2 = 10;
+ }
+ twtp = tcwl + 5;
+ tcl = 7;
+ mr3 = para->dram_mr3;
+ tcksrx = 5;
+ tckesr = 5;
+ trd2wr = 13;
+ tcke = 3;
+ tmod = 12;
+ tdinit0 = 400 * CONFIG_DRAM_CLK + 1;
+ tdinit1 = 500 * CONFIG_DRAM_CLK / 1000 + 1;
+ tdinit2 = 11 * CONFIG_DRAM_CLK + 1;
+ tdinit3 = 1 * CONFIG_DRAM_CLK + 1;
+ tmrd = 5;
+ tmrw = 5;
+ twr2rd = tcwl + twtr + 5;
+ mr1 = 195;
+ mr0 = 0;
+
+ break;
+ default:
+ trfc = 128;
+ trp = 6;
+ trefi = 98;
+ txp = 10;
+ twr = 8;
+ twtr = 3;
+ tras = 14;
+ tfaw = 16;
+ trc = 20;
+ trcd = 6;
+ trrd = 3;
+
+ twr2rd = 8;
+ tcksrx = 4;
+ tckesr = 3;
+ trd2wr = 4;
+ trasmax = 27;
+ twtp = 12;
+ tcke = 2;
+ tmod = 6;
+ tmrd = 2;
+ tmrw = 0;
+ tcwl = 3;
+ tcl = 3;
+ wr_latency = 1;
+ t_rdata_en = 1;
+ mr3 = 0;
+ mr2 = 0;
+ mr1 = 0;
+ mr0 = 0;
+ tdinit3 = 0;
+ tdinit2 = 0;
+ tdinit1 = 0;
+ tdinit0 = 0;
+
+ break;
+ }
+
+ /* Set mode registers */
+ writel(mr0, 0x3103030);
+ writel(mr1, 0x3103034);
+ writel(mr2, 0x3103038);
+ writel(mr3, 0x310303c);
+ /* TODO: dram_odt_en is either 0x0 or 0x1, so right shift looks weird */
+ writel((para->dram_odt_en >> 4) & 0x3, 0x310302c);
+
+ /* Set dram timing DRAMTMG0 - DRAMTMG5 */
+ writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | (tras << 0),
+ 0x3103058);
+ writel((txp << 16) | (trtp << 8) | (trc << 0),
+ 0x310305c);
+ writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | (twr2rd << 0),
+ 0x3103060);
+ writel((tmrw << 16) | (tmrd << 12) | (tmod << 0),
+ 0x3103064);
+ writel((trcd << 24) | (tccd << 16) | (trrd << 8) | (trp << 0),
+ 0x3103068);
+ writel((tcksrx << 24) | (tcksrx << 16) | (tckesr << 8) | (tcke << 0),
+ 0x310306c);
+
+ /* Set dual rank timing */
+ clrsetbits_le32(0x3103078, 0xf000ffff,
+ (CONFIG_DRAM_CLK < 800) ? 0xf0006610 : 0xf0007610);
+
+ /* Set phy interface time PITMG0, PTR3, PTR4 */
+ writel((0x2 << 24) | (t_rdata_en << 16) | BIT(8) | (wr_latency << 0),
+ 0x3103080);
+ writel(((tdinit0 << 0) | (tdinit1 << 20)), 0x3103050);
+ writel(((tdinit2 << 0) | (tdinit3 << 20)), 0x3103054);
+
+ /* Set refresh timing and mode */
+ writel((trefi << 16) | (trfc << 0), 0x3103090);
+ writel((trefi << 15) & 0x0fff0000, 0x3103094);
+}
+
+// Purpose of this routine seems to be to initialize the PLL driving
+// the MBUS and sdram.
+//
+static int ccu_set_pll_ddr_clk(int index, const dram_para_t *para,
+ const dram_config_t *config)
+{
+ unsigned int val, clk, n;
+
+ if (config->dram_tpr13 & BIT(6))
+ clk = para->dram_tpr9;
+ else
+ clk = para->dram_clk;
+
+ // set VCO clock divider
+ n = (clk * 2) / 24;
+
+ val = readl(SUNXI_CCM_BASE + 0x10);
+ val &= ~0x0007ff03; // clear dividers
+ val |= (n - 1) << 8; // set PLL division
+ val |= BIT(31) | BIT(30); // enable PLL and LDO
+ writel(val | BIT(29), SUNXI_CCM_BASE + 0x10);
+
+ // wait for PLL to lock
+ while ((readl(SUNXI_CCM_BASE + 0x10) & BIT(28)) == 0)
+ ;
+
+ udelay(20);
+
+ // enable PLL output
+ setbits_le32(SUNXI_CCM_BASE + 0x0, BIT(27));
+
+ // turn clock gate on
+ val = readl(SUNXI_CCM_BASE + 0x800);
+ val &= ~0x03000303; // select DDR clk source, n=1, m=1
+ val |= BIT(31); // turn clock on
+ writel(val, SUNXI_CCM_BASE + 0x800);
+
+ return n * 24;
+}
+
+/* Set up the PLL and clock gates for the DRAM controller and MBUS clocks. */
+static void mctl_sys_init(const dram_para_t *para, const dram_config_t *config)
+{
+ // assert MBUS reset
+ clrbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
+
+ // turn off sdram clock gate, assert sdram reset
+ clrbits_le32(SUNXI_CCM_BASE + 0x80c, 0x10001);
+ clrsetbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(30), BIT(27));
+ udelay(10);
+
+ // set ddr pll clock
+ ccu_set_pll_ddr_clk(0, para, config);
+ udelay(100);
+ dram_disable_all_master();
+
+ // release sdram reset
+ setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(16));
+
+ // release MBUS reset
+ setbits_le32(SUNXI_CCM_BASE + 0x540, BIT(30));
+ setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(30));
+
+ udelay(5);
+
+ // turn on sdram clock gate
+ setbits_le32(SUNXI_CCM_BASE + 0x80c, BIT(0));
+
+ // turn dram clock gate on, trigger sdr clock update
+ setbits_le32(SUNXI_CCM_BASE + 0x800, BIT(31) | BIT(27));
+ udelay(5);
+
+ // mCTL clock enable
+ writel(0x8000, 0x310300c);
+ udelay(10);
+}
+
+// The main purpose of this routine seems to be to copy an address configuration
+// from the dram_para1 and dram_para2 fields to the PHY configuration registers
+// (0x3102000, 0x3102004).
+//
+static void mctl_com_init(const dram_para_t *para, const dram_config_t *config)
+{
+ uint32_t val, width;
+ unsigned long ptr;
+ int i;
+
+ // purpose ??
+ clrsetbits_le32(0x3102008, 0x3f00, 0x2000);
+
+ // set SDRAM type and word width
+ val = readl(0x3102000) & ~0x00fff000;
+ val |= (para->dram_type & 0x7) << 16; // DRAM type
+ val |= (~config->dram_para2 & 0x1) << 12; // DQ width
+ val |= BIT(22); // ??
+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
+ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
+ val |= BIT(19); // type 6 and 7 must use 1T
+ } else {
+ if (config->dram_tpr13 & BIT(5))
+ val |= BIT(19);
+ }
+ writel(val, 0x3102000);
+
+ // init rank / bank / row for single/dual or two different ranks
+ if ((config->dram_para2 & BIT(8)) &&
+ ((config->dram_para2 & 0xf000) != 0x1000))
+ width = 32;
+ else
+ width = 16;
+
+ ptr = 0x3102000;
+ for (i = 0; i < width; i += 16) {
+ val = readl(ptr) & 0xfffff000;
+
+ val |= (config->dram_para2 >> 12) & 0x3; // rank
+ val |= ((config->dram_para1 >> (i + 12)) << 2) & 0x4; // bank - 2
+ val |= (((config->dram_para1 >> (i + 4)) - 1) << 4) & 0xff; // row - 1
+
+ // convert from page size to column addr width - 3
+ switch ((config->dram_para1 >> i) & 0xf) {
+ case 8: val |= 0xa00; break;
+ case 4: val |= 0x900; break;
+ case 2: val |= 0x800; break;
+ case 1: val |= 0x700; break;
+ default: val |= 0x600; break;
+ }
+ writel(val, ptr);
+ ptr += 4;
+ }
+
+ // set ODTMAP based on number of ranks in use
+ val = (readl(0x3102000) & 0x1) ? 0x303 : 0x201;
+ writel(val, 0x3103120);
+
+ // set mctl reg 3c4 to zero when using half DQ
+ if (config->dram_para2 & BIT(0))
+ writel(0, 0x31033c4);
+
+ // purpose ??
+ if (para->dram_tpr4) {
+ setbits_le32(0x3102000, (para->dram_tpr4 & 0x3) << 25);
+ setbits_le32(0x3102004, (para->dram_tpr4 & 0x7fc) << 10);
+ }
+}
+
+static const uint8_t ac_remapping_tables[][22] = {
+ [0] = { 0 },
+ [1] = { 1, 9, 3, 7, 8, 18, 4, 13, 5, 6, 10,
+ 2, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [2] = { 4, 9, 3, 7, 8, 18, 1, 13, 2, 6, 10,
+ 5, 14, 12, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [3] = { 1, 7, 8, 12, 10, 18, 4, 13, 5, 6, 3,
+ 2, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [4] = { 4, 12, 10, 7, 8, 18, 1, 13, 2, 6, 3,
+ 5, 9, 0, 0, 0, 21, 17, 20, 19, 11, 22 },
+ [5] = { 13, 2, 7, 9, 12, 19, 5, 1, 6, 3, 4,
+ 8, 10, 0, 0, 0, 21, 22, 18, 17, 11, 20 },
+ [6] = { 3, 10, 7, 13, 9, 11, 1, 2, 4, 6, 8,
+ 5, 12, 0, 0, 0, 20, 1, 0, 21, 22, 17 },
+ [7] = { 3, 2, 4, 7, 9, 1, 17, 12, 18, 14, 13,
+ 8, 15, 6, 10, 5, 19, 22, 16, 21, 20, 11 },
+};
+
+/*
+ * This routine chooses one of several remapping tables for 22 lines.
+ * It is unclear which lines are being remapped. It seems to pick
+ * table cfg7 for the Nezha board.
+ */
+static void mctl_phy_ac_remapping(const dram_para_t *para,
+ const dram_config_t *config)
+{
+ const uint8_t *cfg;
+ uint32_t fuse, val;
+
+ /*
+ * It is unclear whether the LPDDRx types don't need any remapping,
+ * or whether the original code just didn't provide tables.
+ */
+ if (para->dram_type != SUNXI_DRAM_TYPE_DDR2 &&
+ para->dram_type != SUNXI_DRAM_TYPE_DDR3)
+ return;
+
+ fuse = (readl(SUNXI_SID_BASE + 0x28) & 0xf00) >> 8;
+ debug("DDR efuse: 0x%x\n", fuse);
+
+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR2) {
+ if (fuse == 15)
+ return;
+ cfg = ac_remapping_tables[6];
+ } else {
+ if (config->dram_tpr13 & 0xc0000) {
+ cfg = ac_remapping_tables[7];
+ } else {
+ switch (fuse) {
+ case 8: cfg = ac_remapping_tables[2]; break;
+ case 9: cfg = ac_remapping_tables[3]; break;
+ case 10: cfg = ac_remapping_tables[5]; break;
+ case 11: cfg = ac_remapping_tables[4]; break;
+ default:
+ case 12: cfg = ac_remapping_tables[1]; break;
+ case 13:
+ case 14: cfg = ac_remapping_tables[0]; break;
+ }
+ }
+ }
+
+ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
+ (cfg[1] << 10) | (cfg[0] << 5);
+ writel(val, 0x3102500);
+
+ val = (cfg[10] << 25) | (cfg[9] << 20) | (cfg[8] << 15) |
+ (cfg[ 7] << 10) | (cfg[6] << 5) | cfg[5];
+ writel(val, 0x3102504);
+
+ val = (cfg[15] << 20) | (cfg[14] << 15) | (cfg[13] << 10) |
+ (cfg[12] << 5) | cfg[11];
+ writel(val, 0x3102508);
+
+ val = (cfg[21] << 25) | (cfg[20] << 20) | (cfg[19] << 15) |
+ (cfg[18] << 10) | (cfg[17] << 5) | cfg[16];
+ writel(val, 0x310250c);
+
+ val = (cfg[4] << 25) | (cfg[3] << 20) | (cfg[2] << 15) |
+ (cfg[1] << 10) | (cfg[0] << 5) | 1;
+ writel(val, 0x3102500);
+}
+
+// Init the controller channel. The key part is placing commands in the main
+// command register (PIR, 0x3103000) and checking command status (PGSR0, 0x3103010).
+//
+static unsigned int mctl_channel_init(unsigned int ch_index,
+ const dram_para_t *para,
+ const dram_config_t *config)
+{
+ unsigned int val, dqs_gating_mode;
+
+ dqs_gating_mode = (config->dram_tpr13 & 0xc) >> 2;
+
+ // set DDR clock to half of CPU clock
+ clrsetbits_le32(0x310200c, 0xfff, (para->dram_clk / 2) - 1);
+
+ // MRCTRL0 nibble 3 undocumented
+ clrsetbits_le32(0x3103108, 0xf00, 0x300);
+
+ if (para->dram_odt_en)
+ val = 0;
+ else
+ val = BIT(5);
+
+ // DX0GCR0
+ if (para->dram_clk > 672)
+ clrsetbits_le32(0x3103344, 0xf63e, val);
+ else
+ clrsetbits_le32(0x3103344, 0xf03e, val);
+
+ // DX1GCR0
+ if (para->dram_clk > 672) {
+ setbits_le32(0x3103344, 0x400);
+ clrsetbits_le32(0x31033c4, 0xf63e, val);
+ } else {
+ clrsetbits_le32(0x31033c4, 0xf03e, val);
+ }
+
+ // 0x3103208 undocumented
+ setbits_le32(0x3103208, BIT(1));
+
+ eye_delay_compensation(para);
+
+ // set PLL SSCG ?
+ val = readl(0x3103108);
+ if (dqs_gating_mode == 1) {
+ clrsetbits_le32(0x3103108, 0xc0, 0);
+ clrbits_le32(0x31030bc, 0x107);
+ } else if (dqs_gating_mode == 2) {
+ clrsetbits_le32(0x3103108, 0xc0, 0x80);
+
+ clrsetbits_le32(0x31030bc, 0x107,
+ (((config->dram_tpr13 >> 16) & 0x1f) - 2) | 0x100);
+ clrsetbits_le32(0x310311c, BIT(31), BIT(27));
+ } else {
+ clrbits_le32(0x3103108, 0x40);
+ udelay(10);
+ setbits_le32(0x3103108, 0xc0);
+ }
+
+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR2 ||
+ para->dram_type == SUNXI_DRAM_TYPE_LPDDR3) {
+ if (dqs_gating_mode == 1)
+ clrsetbits_le32(0x310311c, 0x080000c0, 0x80000000);
+ else
+ clrsetbits_le32(0x310311c, 0x77000000, 0x22000000);
+ }
+
+ clrsetbits_le32(0x31030c0, 0x0fffffff,
+ (config->dram_para2 & BIT(12)) ? 0x03000001 : 0x01000007);
+
+ if (readl(0x70005d4) & BIT(16)) {
+ clrbits_le32(0x7010250, 0x2);
+ udelay(10);
+ }
+
+ // Set ZQ config
+ clrsetbits_le32(0x3103140, 0x3ffffff,
+ (para->dram_zq & 0x00ffffff) | BIT(25));
+
+ // Initialise DRAM controller
+ if (dqs_gating_mode == 1) {
+ //writel(0x52, 0x3103000); // prep PHY reset + PLL init + z-cal
+ writel(0x53, 0x3103000); // Go
+
+ while ((readl(0x3103010) & 0x1) == 0) {
+ } // wait for IDONE
+ udelay(10);
+
+ // 0x520 = prep DQS gating + DRAM init + d-cal
+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
+ writel(0x5a0, 0x3103000); // + DRAM reset
+ else
+ writel(0x520, 0x3103000);
+ } else {
+ if ((readl(0x70005d4) & (1 << 16)) == 0) {
+ // prep DRAM init + PHY reset + d-cal + PLL init + z-cal
+ if (para->dram_type == SUNXI_DRAM_TYPE_DDR3)
+ writel(0x1f2, 0x3103000); // + DRAM reset
+ else
+ writel(0x172, 0x3103000);
+ } else {
+ // prep PHY reset + d-cal + z-cal
+ writel(0x62, 0x3103000);
+ }
+ }
+
+ setbits_le32(0x3103000, 0x1); // GO
+
+ udelay(10);
+ while ((readl(0x3103010) & 0x1) == 0) {
+ } // wait for IDONE
+
+ if (readl(0x70005d4) & BIT(16)) {
+ clrsetbits_le32(0x310310c, 0x06000000, 0x04000000);
+ udelay(10);
+
+ setbits_le32(0x3103004, 0x1);
+
+ while ((readl(0x3103018) & 0x7) != 0x3) {
+ }
+
+ clrbits_le32(0x7010250, 0x1);
+ udelay(10);
+
+ clrbits_le32(0x3103004, 0x1);
+
+ while ((readl(0x3103018) & 0x7) != 0x1) {
+ }
+
+ udelay(15);
+
+ if (dqs_gating_mode == 1) {
+ clrbits_le32(0x3103108, 0xc0);
+ clrsetbits_le32(0x310310c, 0x06000000, 0x02000000);
+ udelay(1);
+ writel(0x401, 0x3103000);
+
+ while ((readl(0x3103010) & 0x1) == 0) {
+ }
+ }
+ }
+
+ // Check for training error
+ if (readl(0x3103010) & BIT(20)) {
+ printf("ZQ calibration error, check external 240 ohm resistor\n");
+ return 0;
+ }
+
+ // STATR = Zynq STAT? Wait for status 'normal'?
+ while ((readl(0x3103018) & 0x1) == 0) {
+ }
+
+ setbits_le32(0x310308c, BIT(31));
+ udelay(10);
+ clrbits_le32(0x310308c, BIT(31));
+ udelay(10);
+ setbits_le32(0x3102014, BIT(31));
+ udelay(10);
+
+ clrbits_le32(0x310310c, 0x06000000);
+
+ if (dqs_gating_mode == 1)
+ clrsetbits_le32(0x310311c, 0xc0, 0x40);
+
+ return 1;
+}
+
+static unsigned int calculate_rank_size(uint32_t regval)
+{
+ unsigned int bits;
+
+ bits = (regval >> 8) & 0xf; /* page size - 3 */
+ bits += (regval >> 4) & 0xf; /* row width - 1 */
+ bits += (regval >> 2) & 0x3; /* bank count - 2 */
+ bits -= 14; /* 1MB = 20 bits, minus above 6 = 14 */
+
+ return 1U << bits;
+}
+
+/*
+ * The below routine reads the dram config registers and extracts
+ * the number of address bits in each rank available. It then calculates
+ * total memory size in MB.
+ */
+static unsigned int DRAMC_get_dram_size(void)
+{
+ uint32_t val;
+ unsigned int size;
+
+ val = readl(0x3102000); /* MC_WORK_MODE0 */
+ size = calculate_rank_size(val);
+ if ((val & 0x3) == 0) /* single rank? */
+ return size;
+
+ val = readl(0x3102004); /* MC_WORK_MODE1 */
+ if ((val & 0x3) == 0) /* two identical ranks? */
+ return size * 2;
+
+ /* add sizes of both ranks */
+ return size + calculate_rank_size(val);
+}
+
+/*
+ * The below routine reads the command status register to extract
+ * DQ width and rank count. This follows the DQS training command in
+ * channel_init. If error bit 22 is reset, we have two ranks and full DQ.
+ * If there was an error, figure out whether it was half DQ, single rank,
+ * or both. Set bit 12 and 0 in dram_para2 with the results.
+ */
+static int dqs_gate_detect(dram_config_t *config)
+{
+ uint32_t dx0, dx1;
+
+ if ((readl(0x3103010) & BIT(22)) == 0) {
+ config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
+ debug("dual rank and full DQ\n");
+
+ return 1;
+ }
+
+ dx0 = (readl(0x3103348) & 0x3000000) >> 24;
+ if (dx0 == 0) {
+ config->dram_para2 = (config->dram_para2 & ~0xf) | 0x1001;
+ debug("dual rank and half DQ\n");
+
+ return 1;
+ }
+
+ if (dx0 == 2) {
+ dx1 = (readl(0x31033c8) & 0x3000000) >> 24;
+ if (dx1 == 2) {
+ config->dram_para2 = config->dram_para2 & ~0xf00f;
+ debug("single rank and full DQ\n");
+ } else {
+ config->dram_para2 = (config->dram_para2 & ~0xf00f) | BIT(0);
+ debug("single rank and half DQ\n");
+ }
+
+ return 1;
+ }
+
+ if ((config->dram_tpr13 & BIT(29)) == 0)
+ return 0;
+
+ debug("DX0 state: %d\n", dx0);
+ debug("DX1 state: %d\n", dx1);
+
+ return 0;
+}
+
+static int dramc_simple_wr_test(unsigned int mem_mb, int len)
+{
+ unsigned int offs = (mem_mb / 2) << 18; // half of memory size
+ unsigned int patt1 = 0x01234567;
+ unsigned int patt2 = 0xfedcba98;
+ unsigned int *addr, v1, v2, i;
+
+ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i != len; i++, addr++) {
+ writel(patt1 + i, (unsigned long)addr);
+ writel(patt2 + i, (unsigned long)(addr + offs));
+ }
+
+ addr = (unsigned int *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i != len; i++) {
+ v1 = readl((unsigned long)(addr + i));
+ v2 = patt1 + i;
+ if (v1 != v2) {
+ printf("DRAM: simple test FAIL\n");
+ printf("%x != %x at address %p\n", v1, v2, addr + i);
+ return 1;
+ }
+ v1 = readl((unsigned long)(addr + offs + i));
+ v2 = patt2 + i;
+ if (v1 != v2) {
+ printf("DRAM: simple test FAIL\n");
+ printf("%x != %x at address %p\n", v1, v2, addr + offs + i);
+ return 1;
+ }
+ }
+
+ debug("DRAM: simple test OK\n");
+ return 0;
+}
+
+// Set the Vref mode for the controller
+//
+static void mctl_vrefzq_init(const dram_para_t *para, const dram_config_t *config)
+{
+ if (config->dram_tpr13 & BIT(17))
+ return;
+
+ clrsetbits_le32(0x3103110, 0x7f7f7f7f, para->dram_tpr5);
+
+ // IOCVR1
+ if ((config->dram_tpr13 & BIT(16)) == 0)
+ clrsetbits_le32(0x3103114, 0x7f, para->dram_tpr6 & 0x7f);
+}
+
+// Perform an init of the controller. This is actually done 3 times. The first
+// time to establish the number of ranks and DQ width. The second time to
+// establish the actual ram size. The third time is final one, with the final
+// settings.
+//
+static int mctl_core_init(const dram_para_t *para, const dram_config_t *config)
+{
+ mctl_sys_init(para, config);
+
+ mctl_vrefzq_init(para, config);
+
+ mctl_com_init(para, config);
+
+ mctl_phy_ac_remapping(para, config);
+
+ mctl_set_timing_params(para, config);
+
+ return mctl_channel_init(0, para, config);
+}
+
+/*
+ * This routine sizes a DRAM device by cycling through address lines and
+ * figuring out if they are connected to a real address line, or if the
+ * address is a mirror.
+ * First the column and bank bit allocations are set to low values (2 and 9
+ * address lines). Then a maximum allocation (16 lines) is set for rows and
+ * this is tested.
+ * Next the BA2 line is checked. This seems to be placed above the column,
+ * BA0-1 and row addresses. Finally, the column address is allocated 13 lines
+ * and these are tested. The results are placed in dram_para1 and dram_para2.
+ */
+
+static uint32_t get_payload(bool odd, unsigned long int ptr)
+{
+ if (odd)
+ return (uint32_t)ptr;
+ else
+ return ~((uint32_t)ptr);
+}
+
+static int auto_scan_dram_size(const dram_para_t *para, dram_config_t *config)
+{
+ unsigned int rval, i, j, rank, maxrank, offs;
+ unsigned int shft;
+ unsigned long ptr, mc_work_mode, chk;
+
+ if (mctl_core_init(para, config) == 0) {
+ printf("DRAM initialisation error : 0\n");
+ return 0;
+ }
+
+ maxrank = (config->dram_para2 & 0xf000) ? 2 : 1;
+ mc_work_mode = 0x3102000;
+ offs = 0;
+
+ /* write test pattern */
+ for (i = 0, ptr = CFG_SYS_SDRAM_BASE; i < 64; i++, ptr += 4)
+ writel(get_payload(i & 0x1, ptr), ptr);
+
+ for (rank = 0; rank < maxrank;) {
+ /* set row mode */
+ clrsetbits_le32(mc_work_mode, 0xf0c, 0x6f0);
+ udelay(1);
+
+ // Scan per address line, until address wraps (i.e. see shadow)
+ for (i = 11; i < 17; i++) {
+ chk = CFG_SYS_SDRAM_BASE + (1U << (i + 11));
+ ptr = CFG_SYS_SDRAM_BASE;
+ for (j = 0; j < 64; j++) {
+ if (readl(chk) != get_payload(j & 0x1, ptr))
+ break;
+ ptr += 4;
+ chk += 4;
+ }
+ if (j == 64)
+ break;
+ }
+ if (i > 16)
+ i = 16;
+ debug("rank %d row = %d\n", rank, i);
+
+ /* Store rows in para 1 */
+ shft = offs + 4;
+ rval = config->dram_para1;
+ rval &= ~(0xff << shft);
+ rval |= i << shft;
+ config->dram_para1 = rval;
+
+ if (rank == 1) /* Set bank mode for rank0 */
+ clrsetbits_le32(0x3102000, 0xffc, 0x6a4);
+
+ /* Set bank mode for current rank */
+ clrsetbits_le32(mc_work_mode, 0xffc, 0x6a4);
+ udelay(1);
+
+ // Test if bit A23 is BA2 or mirror XXX A22?
+ chk = CFG_SYS_SDRAM_BASE + (1U << 22);
+ ptr = CFG_SYS_SDRAM_BASE;
+ for (i = 0, j = 0; i < 64; i++) {
+ if (readl(chk) != get_payload(i & 1, ptr)) {
+ j = 1;
+ break;
+ }
+ ptr += 4;
+ chk += 4;
+ }
+
+ debug("rank %d bank = %d\n", rank, (j + 1) << 2); /* 4 or 8 */
+
+ /* Store banks in para 1 */
+ shft = 12 + offs;
+ rval = config->dram_para1;
+ rval &= ~(0xf << shft);
+ rval |= j << shft;
+ config->dram_para1 = rval;
+
+ if (rank == 1) /* Set page mode for rank0 */
+ clrsetbits_le32(0x3102000, 0xffc, 0xaa0);
+
+ /* Set page mode for current rank */
+ clrsetbits_le32(mc_work_mode, 0xffc, 0xaa0);
+ udelay(1);
+
+ // Scan per address line, until address wraps (i.e. see shadow)
+ for (i = 9; i < 14; i++) {
+ chk = CFG_SYS_SDRAM_BASE + (1U << i);
+ ptr = CFG_SYS_SDRAM_BASE;
+ for (j = 0; j < 64; j++) {
+ if (readl(chk) != get_payload(j & 1, ptr))
+ break;
+ ptr += 4;
+ chk += 4;
+ }
+ if (j == 64)
+ break;
+ }
+ if (i > 13)
+ i = 13;
+
+ unsigned int pgsize = (i == 9) ? 0 : (1 << (i - 10));
+ debug("rank %d page size = %d KB\n", rank, pgsize);
+
+ /* Store page size */
+ shft = offs;
+ rval = config->dram_para1;
+ rval &= ~(0xf << shft);
+ rval |= pgsize << shft;
+ config->dram_para1 = rval;
+
+ // Move to next rank
+ rank++;
+ if (rank != maxrank) {
+ if (rank == 1) {
+ /* MC_WORK_MODE */
+ clrsetbits_le32(0x3202000, 0xffc, 0x6f0);
+
+ /* MC_WORK_MODE2 */
+ clrsetbits_le32(0x3202004, 0xffc, 0x6f0);
+ }
+ /* store rank1 config in upper half of para1 */
+ offs += 16;
+ mc_work_mode += 4; /* move to MC_WORK_MODE2 */
+ }
+ }
+ if (maxrank == 2) {
+ config->dram_para2 &= 0xfffff0ff;
+ /* note: rval is equal to para->dram_para1 here */
+ if ((rval & 0xffff) == (rval >> 16)) {
+ debug("rank1 config same as rank0\n");
+ } else {
+ config->dram_para2 |= BIT(8);
+ debug("rank1 config different from rank0\n");
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * This routine sets up parameters with dqs_gating_mode equal to 1 and two
+ * ranks enabled. It then configures the core and tests for 1 or 2 ranks and
+ * full or half DQ width. It then resets the parameters to the original values.
+ * dram_para2 is updated with the rank and width findings.
+ */
+static int auto_scan_dram_rank_width(const dram_para_t *para,
+ dram_config_t *config)
+{
+ unsigned int s1 = config->dram_tpr13;
+ unsigned int s2 = config->dram_para1;
+
+ config->dram_para1 = 0x00b000b0;
+ config->dram_para2 = (config->dram_para2 & ~0xf) | BIT(12);
+
+ /* set DQS probe mode */
+ config->dram_tpr13 = (config->dram_tpr13 & ~0x8) | BIT(2) | BIT(0);
+
+ mctl_core_init(para, config);
+
+ if (readl(0x3103010) & BIT(20))
+ return 0;
+
+ if (dqs_gate_detect(config) == 0)
+ return 0;
+
+ config->dram_tpr13 = s1;
+ config->dram_para1 = s2;
+
+ return 1;
+}
+
+/*
+ * This routine determines the SDRAM topology. It first establishes the number
+ * of ranks and the DQ width. Then it scans the SDRAM address lines to establish
+ * the size of each rank. It then updates dram_tpr13 to reflect that the sizes
+ * are now known: a re-init will not repeat the autoscan.
+ */
+static int auto_scan_dram_config(const dram_para_t *para,
+ dram_config_t *config)
+{
+ if (((config->dram_tpr13 & BIT(14)) == 0) &&
+ (auto_scan_dram_rank_width(para, config) == 0)) {
+ printf("ERROR: auto scan dram rank & width failed\n");
+ return 0;
+ }
+
+ if (((config->dram_tpr13 & BIT(0)) == 0) &&
+ (auto_scan_dram_size(para, config) == 0)) {
+ printf("ERROR: auto scan dram size failed\n");
+ return 0;
+ }
+
+ if ((config->dram_tpr13 & BIT(15)) == 0)
+ config->dram_tpr13 |= BIT(14) | BIT(13) | BIT(1) | BIT(0);
+
+ return 1;
+}
+
+static int init_DRAM(int type, const dram_para_t *para)
+{
+ dram_config_t config = {
+ .dram_para1 = 0x000010d2,
+ .dram_para2 = 0,
+ .dram_tpr13 = CONFIG_DRAM_SUNXI_TPR13,
+ };
+ u32 rc, mem_size_mb;
+
+ debug("DRAM BOOT DRIVE INFO: %s\n", "V0.24");
+ debug("DRAM CLK = %d MHz\n", para->dram_clk);
+ debug("DRAM Type = %d (2:DDR2,3:DDR3)\n", para->dram_type);
+ if ((para->dram_odt_en & 0x1) == 0)
+ debug("DRAMC read ODT off\n");
+ else
+ debug("DRAMC ZQ value: 0x%x\n", para->dram_zq);
+
+ /* Test ZQ status */
+ if (config.dram_tpr13 & BIT(16)) {
+ debug("DRAM only have internal ZQ\n");
+ setbits_le32(0x3000160, BIT(8));
+ writel(0, 0x3000168);
+ udelay(10);
+ } else {
+ clrbits_le32(0x3000160, 0x3);
+ writel(config.dram_tpr13 & BIT(16), 0x7010254);
+ udelay(10);
+ clrsetbits_le32(0x3000160, 0x108, BIT(1));
+ udelay(10);
+ setbits_le32(0x3000160, BIT(0));
+ udelay(20);
+ debug("ZQ value = 0x%x\n", readl(0x300016c));
+ }
+
+ dram_voltage_set(para);
+
+ /* Set SDRAM controller auto config */
+ if ((config.dram_tpr13 & BIT(0)) == 0) {
+ if (auto_scan_dram_config(para, &config) == 0) {
+ printf("auto_scan_dram_config() FAILED\n");
+ return 0;
+ }
+ }
+
+ /* report ODT */
+ rc = para->dram_mr1;
+ if ((rc & 0x44) == 0)
+ debug("DRAM ODT off\n");
+ else
+ debug("DRAM ODT value: 0x%x\n", rc);
+
+ /* Init core, final run */
+ if (mctl_core_init(para, &config) == 0) {
+ printf("DRAM initialisation error: 1\n");
+ return 0;
+ }
+
+ /* Get SDRAM size */
+ /* TODO: who ever puts a negative number in the top half? */
+ rc = config.dram_para2;
+ if (rc & BIT(31)) {
+ rc = (rc >> 16) & ~BIT(15);
+ } else {
+ rc = DRAMC_get_dram_size();
+ debug("DRAM: size = %dMB\n", rc);
+ config.dram_para2 = (config.dram_para2 & 0xffffU) | rc << 16;
+ }
+ mem_size_mb = rc;
+
+ /* Purpose ?? */
+ if (config.dram_tpr13 & BIT(30)) {
+ rc = para->dram_tpr8;
+ if (rc == 0)
+ rc = 0x10000200;
+ writel(rc, 0x31030a0);
+ writel(0x40a, 0x310309c);
+ setbits_le32(0x3103004, BIT(0));
+ debug("Enable Auto SR\n");
+ } else {
+ clrbits_le32(0x31030a0, 0xffff);
+ clrbits_le32(0x3103004, 0x1);
+ }
+
+ /* Purpose ?? */
+ if (config.dram_tpr13 & BIT(9)) {
+ clrsetbits_le32(0x3103100, 0xf000, 0x5000);
+ } else {
+ if (para->dram_type != SUNXI_DRAM_TYPE_LPDDR2)
+ clrbits_le32(0x3103100, 0xf000);
+ }
+
+ setbits_le32(0x3103140, BIT(31));
+
+ /* CHECK: is that really writing to a different register? */
+ if (config.dram_tpr13 & BIT(8))
+ writel(readl(0x3103140) | 0x300, 0x31030b8);
+
+ if (config.dram_tpr13 & BIT(16))
+ clrbits_le32(0x3103108, BIT(13));
+ else
+ setbits_le32(0x3103108, BIT(13));
+
+ /* Purpose ?? */
+ if (para->dram_type == SUNXI_DRAM_TYPE_LPDDR3)
+ clrsetbits_le32(0x310307c, 0xf0000, 0x1000);
+
+ dram_enable_all_master();
+ if (config.dram_tpr13 & BIT(28)) {
+ if ((readl(0x70005d4) & BIT(16)) ||
+ dramc_simple_wr_test(mem_size_mb, 4096))
+ return 0;
+ }
+
+ return mem_size_mb;
+}
+
+static const dram_para_t para = {
+ .dram_clk = CONFIG_DRAM_CLK,
+ .dram_type = CONFIG_SUNXI_DRAM_TYPE,
+ .dram_zq = CONFIG_DRAM_ZQ,
+ .dram_odt_en = CONFIG_DRAM_SUNXI_ODT_EN,
+ .dram_mr0 = 0x1c70,
+ .dram_mr1 = 0x42,
+ .dram_mr2 = 0x18,
+ .dram_mr3 = 0,
+ .dram_tpr0 = 0x004a2195,
+ .dram_tpr1 = 0x02423190,
+ .dram_tpr2 = 0x0008b061,
+ .dram_tpr3 = 0xb4787896, // unused
+ .dram_tpr4 = 0,
+ .dram_tpr5 = 0x48484848,
+ .dram_tpr6 = 0x00000048,
+ .dram_tpr7 = 0x1620121e, // unused
+ .dram_tpr8 = 0,
+ .dram_tpr9 = 0, // clock?
+ .dram_tpr10 = 0,
+ .dram_tpr11 = CONFIG_DRAM_SUNXI_TPR11,
+ .dram_tpr12 = CONFIG_DRAM_SUNXI_TPR12,
+};
+
+unsigned long sunxi_dram_init(void)
+{
+ return init_DRAM(0, &para) * 1024UL * 1024;
+};
+
+#ifdef CONFIG_RAM /* using the driver model */
+struct sunxi_ram_priv {
+ size_t size;
+};
+
+static int sunxi_ram_probe(struct udevice *dev)
+{
+ struct sunxi_ram_priv *priv = dev_get_priv(dev);
+ unsigned long dram_size;
+
+ debug("%s: %s: probing\n", __func__, dev->name);
+
+ dram_size = sunxi_dram_init();
+ if (!dram_size) {
+ printf("DRAM init failed\n");
+ return -ENODEV;
+ }
+
+ priv->size = dram_size;
+
+ return 0;
+}
+
+static int sunxi_ram_get_info(struct udevice *dev, struct ram_info *info)
+{
+ struct sunxi_ram_priv *priv = dev_get_priv(dev);
+
+ debug("%s: %s: getting info\n", __func__, dev->name);
+
+ info->base = CFG_SYS_SDRAM_BASE;
+ info->size = priv->size;
+
+ return 0;
+}
+
+static struct ram_ops sunxi_ram_ops = {
+ .get_info = sunxi_ram_get_info,
+};
+
+static const struct udevice_id sunxi_ram_ids[] = {
+ { .compatible = "allwinner,sun20i-d1-mbus" },
+ { }
+};
+
+U_BOOT_DRIVER(sunxi_ram) = {
+ .name = "sunxi_ram",
+ .id = UCLASS_RAM,
+ .of_match = sunxi_ram_ids,
+ .ops = &sunxi_ram_ops,
+ .probe = sunxi_ram_probe,
+ .priv_auto = sizeof(struct sunxi_ram_priv),
+};
+#endif /* CONFIG_RAM (using driver model) */
diff --git a/drivers/ram/sunxi/dram_sun20i_d1.h b/drivers/ram/sunxi/dram_sun20i_d1.h
new file mode 100644
index 0000000..91383f6
--- /dev/null
+++ b/drivers/ram/sunxi/dram_sun20i_d1.h
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * D1/R528/T113 DRAM controller register and constant defines
+ *
+ * (C) Copyright 2022 Arm Ltd.
+ * Based on H6 and H616 header, which are:
+ * (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ */
+
+#ifndef _SUNXI_DRAM_SUN20I_D1_H
+#define _SUNXI_DRAM_SUN20I_D1_H
+
+enum sunxi_dram_type {
+ SUNXI_DRAM_TYPE_DDR2 = 2,
+ SUNXI_DRAM_TYPE_DDR3 = 3,
+ SUNXI_DRAM_TYPE_LPDDR2 = 6,
+ SUNXI_DRAM_TYPE_LPDDR3 = 7,
+};
+
+/*
+ * This structure contains a mixture of fixed configuration settings,
+ * variables that are used at runtime to communicate settings between
+ * different stages and functions, and unused values.
+ * This is copied from Allwinner's boot0 data structure, which can be
+ * found at offset 0x38 in any boot0 binary. To allow matching up some
+ * board specific settings, this struct is kept compatible, even though
+ * we don't need all members in our code.
+ */
+typedef struct dram_para {
+ /* normal configuration */
+ const u32 dram_clk;
+ const u32 dram_type;
+ const u32 dram_zq;
+ const u32 dram_odt_en;
+
+ /* timing configuration */
+ const u32 dram_mr0;
+ const u32 dram_mr1;
+ const u32 dram_mr2;
+ const u32 dram_mr3;
+ const u32 dram_tpr0; //DRAMTMG0
+ const u32 dram_tpr1; //DRAMTMG1
+ const u32 dram_tpr2; //DRAMTMG2
+ const u32 dram_tpr3; //DRAMTMG3
+ const u32 dram_tpr4; //DRAMTMG4
+ const u32 dram_tpr5; //DRAMTMG5
+ const u32 dram_tpr6; //DRAMTMG8
+ const u32 dram_tpr7;
+ const u32 dram_tpr8;
+ const u32 dram_tpr9;
+ const u32 dram_tpr10;
+ const u32 dram_tpr11;
+ const u32 dram_tpr12;
+} dram_para_t;
+
+typedef struct dram_config {
+ /* control configuration */
+ u32 dram_para1;
+ u32 dram_para2;
+ /* contains a bitfield of DRAM setup settings */
+ u32 dram_tpr13;
+} dram_config_t;
+
+static inline int ns_to_t(int nanoseconds)
+{
+ const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
+
+ return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
+}
+
+#endif /* _SUNXI_DRAM_SUN20I_D1_H */
diff --git a/drivers/video/hitachi_tx18d42vm_lcd.c b/drivers/video/hitachi_tx18d42vm_lcd.c
index 87c4d27..95984fe 100644
--- a/drivers/video/hitachi_tx18d42vm_lcd.c
+++ b/drivers/video/hitachi_tx18d42vm_lcd.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <asm/gpio.h>
+#include <sunxi_gpio.h>
#include <errno.h>
/*
diff --git a/drivers/video/ssd2828.c b/drivers/video/ssd2828.c
index 4cdcbe7..948f5e7 100644
--- a/drivers/video/ssd2828.c
+++ b/drivers/video/ssd2828.c
@@ -12,7 +12,6 @@
#include <common.h>
#include <malloc.h>
#include <mipi_display.h>
-#include <asm/arch/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index 9110a48..8da44a1 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -31,6 +31,7 @@
#include <malloc.h>
#include <video.h>
#include <dm/uclass-internal.h>
+#include <sunxi_gpio.h>
#include "../videomodes.h"
#include "../anx9804.h"
#include "../hitachi_tx18d42vm_lcd.h"
diff --git a/drivers/video/sunxi/sunxi_lcd.c b/drivers/video/sunxi/sunxi_lcd.c
index 8b9c3b2..7a01cc3 100644
--- a/drivers/video/sunxi/sunxi_lcd.c
+++ b/drivers/video/sunxi/sunxi_lcd.c
@@ -17,6 +17,7 @@
#include <asm/arch/lcdc.h>
#include <asm/global_data.h>
#include <asm/gpio.h>
+#include <sunxi_gpio.h>
struct sunxi_lcd_priv {
struct display_timing timing;
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index d2d70f0..b8ca77d 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -12,7 +12,6 @@
#ifndef _SUNXI_COMMON_CONFIG_H
#define _SUNXI_COMMON_CONFIG_H
-#include <asm/arch/cpu.h>
#include <linux/stringify.h>
/* Serial & console */
@@ -24,6 +23,7 @@
#define CFG_SYS_NS16550_CLK 24000000
#endif
#if !CONFIG_IS_ENABLED(DM_SERIAL)
+#include <asm/arch/serial.h>
# define CFG_SYS_NS16550_COM1 SUNXI_UART0_BASE
# define CFG_SYS_NS16550_COM2 SUNXI_UART1_BASE
# define CFG_SYS_NS16550_COM3 SUNXI_UART2_BASE
diff --git a/include/dt-bindings/clock/sun20i-d1-ccu.h b/include/dt-bindings/clock/sun20i-d1-ccu.h
new file mode 100644
index 0000000..fdbfb40
--- /dev/null
+++ b/include/dt-bindings/clock/sun20i-d1-ccu.h
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
+#define _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_
+
+#define CLK_PLL_CPUX 0
+#define CLK_PLL_DDR0 1
+#define CLK_PLL_PERIPH0_4X 2
+#define CLK_PLL_PERIPH0_2X 3
+#define CLK_PLL_PERIPH0_800M 4
+#define CLK_PLL_PERIPH0 5
+#define CLK_PLL_PERIPH0_DIV3 6
+#define CLK_PLL_VIDEO0_4X 7
+#define CLK_PLL_VIDEO0_2X 8
+#define CLK_PLL_VIDEO0 9
+#define CLK_PLL_VIDEO1_4X 10
+#define CLK_PLL_VIDEO1_2X 11
+#define CLK_PLL_VIDEO1 12
+#define CLK_PLL_VE 13
+#define CLK_PLL_AUDIO0_4X 14
+#define CLK_PLL_AUDIO0_2X 15
+#define CLK_PLL_AUDIO0 16
+#define CLK_PLL_AUDIO1 17
+#define CLK_PLL_AUDIO1_DIV2 18
+#define CLK_PLL_AUDIO1_DIV5 19
+#define CLK_CPUX 20
+#define CLK_CPUX_AXI 21
+#define CLK_CPUX_APB 22
+#define CLK_PSI_AHB 23
+#define CLK_APB0 24
+#define CLK_APB1 25
+#define CLK_MBUS 26
+#define CLK_DE 27
+#define CLK_BUS_DE 28
+#define CLK_DI 29
+#define CLK_BUS_DI 30
+#define CLK_G2D 31
+#define CLK_BUS_G2D 32
+#define CLK_CE 33
+#define CLK_BUS_CE 34
+#define CLK_VE 35
+#define CLK_BUS_VE 36
+#define CLK_BUS_DMA 37
+#define CLK_BUS_MSGBOX0 38
+#define CLK_BUS_MSGBOX1 39
+#define CLK_BUS_MSGBOX2 40
+#define CLK_BUS_SPINLOCK 41
+#define CLK_BUS_HSTIMER 42
+#define CLK_AVS 43
+#define CLK_BUS_DBG 44
+#define CLK_BUS_PWM 45
+#define CLK_BUS_IOMMU 46
+#define CLK_DRAM 47
+#define CLK_MBUS_DMA 48
+#define CLK_MBUS_VE 49
+#define CLK_MBUS_CE 50
+#define CLK_MBUS_TVIN 51
+#define CLK_MBUS_CSI 52
+#define CLK_MBUS_G2D 53
+#define CLK_MBUS_RISCV 54
+#define CLK_BUS_DRAM 55
+#define CLK_MMC0 56
+#define CLK_MMC1 57
+#define CLK_MMC2 58
+#define CLK_BUS_MMC0 59
+#define CLK_BUS_MMC1 60
+#define CLK_BUS_MMC2 61
+#define CLK_BUS_UART0 62
+#define CLK_BUS_UART1 63
+#define CLK_BUS_UART2 64
+#define CLK_BUS_UART3 65
+#define CLK_BUS_UART4 66
+#define CLK_BUS_UART5 67
+#define CLK_BUS_I2C0 68
+#define CLK_BUS_I2C1 69
+#define CLK_BUS_I2C2 70
+#define CLK_BUS_I2C3 71
+#define CLK_SPI0 72
+#define CLK_SPI1 73
+#define CLK_BUS_SPI0 74
+#define CLK_BUS_SPI1 75
+#define CLK_EMAC_25M 76
+#define CLK_BUS_EMAC 77
+#define CLK_IR_TX 78
+#define CLK_BUS_IR_TX 79
+#define CLK_BUS_GPADC 80
+#define CLK_BUS_THS 81
+#define CLK_I2S0 82
+#define CLK_I2S1 83
+#define CLK_I2S2 84
+#define CLK_I2S2_ASRC 85
+#define CLK_BUS_I2S0 86
+#define CLK_BUS_I2S1 87
+#define CLK_BUS_I2S2 88
+#define CLK_SPDIF_TX 89
+#define CLK_SPDIF_RX 90
+#define CLK_BUS_SPDIF 91
+#define CLK_DMIC 92
+#define CLK_BUS_DMIC 93
+#define CLK_AUDIO_DAC 94
+#define CLK_AUDIO_ADC 95
+#define CLK_BUS_AUDIO 96
+#define CLK_USB_OHCI0 97
+#define CLK_USB_OHCI1 98
+#define CLK_BUS_OHCI0 99
+#define CLK_BUS_OHCI1 100
+#define CLK_BUS_EHCI0 101
+#define CLK_BUS_EHCI1 102
+#define CLK_BUS_OTG 103
+#define CLK_BUS_LRADC 104
+#define CLK_BUS_DPSS_TOP 105
+#define CLK_HDMI_24M 106
+#define CLK_HDMI_CEC_32K 107
+#define CLK_HDMI_CEC 108
+#define CLK_BUS_HDMI 109
+#define CLK_MIPI_DSI 110
+#define CLK_BUS_MIPI_DSI 111
+#define CLK_TCON_LCD0 112
+#define CLK_BUS_TCON_LCD0 113
+#define CLK_TCON_TV 114
+#define CLK_BUS_TCON_TV 115
+#define CLK_TVE 116
+#define CLK_BUS_TVE_TOP 117
+#define CLK_BUS_TVE 118
+#define CLK_TVD 119
+#define CLK_BUS_TVD_TOP 120
+#define CLK_BUS_TVD 121
+#define CLK_LEDC 122
+#define CLK_BUS_LEDC 123
+#define CLK_CSI_TOP 124
+#define CLK_CSI_MCLK 125
+#define CLK_BUS_CSI 126
+#define CLK_TPADC 127
+#define CLK_BUS_TPADC 128
+#define CLK_BUS_TZMA 129
+#define CLK_DSP 130
+#define CLK_BUS_DSP_CFG 131
+#define CLK_RISCV 132
+#define CLK_RISCV_AXI 133
+#define CLK_BUS_RISCV_CFG 134
+#define CLK_FANOUT_24M 135
+#define CLK_FANOUT_12M 136
+#define CLK_FANOUT_16M 137
+#define CLK_FANOUT_25M 138
+#define CLK_FANOUT_32K 139
+#define CLK_FANOUT_27M 140
+#define CLK_FANOUT_PCLK 141
+#define CLK_FANOUT0 142
+#define CLK_FANOUT1 143
+#define CLK_FANOUT2 144
+#define CLK_BUS_CAN0 145
+#define CLK_BUS_CAN1 146
+
+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ */
diff --git a/include/dt-bindings/clock/sun20i-d1-r-ccu.h b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
new file mode 100644
index 0000000..f95c170
--- /dev/null
+++ b/include/dt-bindings/clock/sun20i-d1-r-ccu.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_
+
+#define CLK_R_AHB 0
+
+#define CLK_BUS_R_TIMER 2
+#define CLK_BUS_R_TWD 3
+#define CLK_BUS_R_PPU 4
+#define CLK_R_IR_RX 5
+#define CLK_BUS_R_IR_RX 6
+#define CLK_BUS_R_RTC 7
+#define CLK_BUS_R_CPUCFG 8
+
+#endif /* _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ */
diff --git a/include/dt-bindings/clock/sun50i-h6-ccu.h b/include/dt-bindings/clock/sun50i-h6-ccu.h
index a1545cd..ef9123d 100644
--- a/include/dt-bindings/clock/sun50i-h6-ccu.h
+++ b/include/dt-bindings/clock/sun50i-h6-ccu.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
*/
diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h
index 1191aca..6f8f01e 100644
--- a/include/dt-bindings/clock/sun50i-h616-ccu.h
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2020 Arm Ltd.
*/
diff --git a/include/dt-bindings/clock/sun6i-rtc.h b/include/dt-bindings/clock/sun6i-rtc.h
index c845493..3bd3aa3 100644
--- a/include/dt-bindings/clock/sun6i-rtc.h
+++ b/include/dt-bindings/clock/sun6i-rtc.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
#ifndef _DT_BINDINGS_CLK_SUN6I_RTC_H_
#define _DT_BINDINGS_CLK_SUN6I_RTC_H_
diff --git a/include/dt-bindings/reset/sun20i-d1-ccu.h b/include/dt-bindings/reset/sun20i-d1-ccu.h
new file mode 100644
index 0000000..79e52ac
--- /dev/null
+++ b/include/dt-bindings/reset/sun20i-d1-ccu.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
+#define _DT_BINDINGS_RST_SUN20I_D1_CCU_H_
+
+#define RST_MBUS 0
+#define RST_BUS_DE 1
+#define RST_BUS_DI 2
+#define RST_BUS_G2D 3
+#define RST_BUS_CE 4
+#define RST_BUS_VE 5
+#define RST_BUS_DMA 6
+#define RST_BUS_MSGBOX0 7
+#define RST_BUS_MSGBOX1 8
+#define RST_BUS_MSGBOX2 9
+#define RST_BUS_SPINLOCK 10
+#define RST_BUS_HSTIMER 11
+#define RST_BUS_DBG 12
+#define RST_BUS_PWM 13
+#define RST_BUS_DRAM 14
+#define RST_BUS_MMC0 15
+#define RST_BUS_MMC1 16
+#define RST_BUS_MMC2 17
+#define RST_BUS_UART0 18
+#define RST_BUS_UART1 19
+#define RST_BUS_UART2 20
+#define RST_BUS_UART3 21
+#define RST_BUS_UART4 22
+#define RST_BUS_UART5 23
+#define RST_BUS_I2C0 24
+#define RST_BUS_I2C1 25
+#define RST_BUS_I2C2 26
+#define RST_BUS_I2C3 27
+#define RST_BUS_SPI0 28
+#define RST_BUS_SPI1 29
+#define RST_BUS_EMAC 30
+#define RST_BUS_IR_TX 31
+#define RST_BUS_GPADC 32
+#define RST_BUS_THS 33
+#define RST_BUS_I2S0 34
+#define RST_BUS_I2S1 35
+#define RST_BUS_I2S2 36
+#define RST_BUS_SPDIF 37
+#define RST_BUS_DMIC 38
+#define RST_BUS_AUDIO 39
+#define RST_USB_PHY0 40
+#define RST_USB_PHY1 41
+#define RST_BUS_OHCI0 42
+#define RST_BUS_OHCI1 43
+#define RST_BUS_EHCI0 44
+#define RST_BUS_EHCI1 45
+#define RST_BUS_OTG 46
+#define RST_BUS_LRADC 47
+#define RST_BUS_DPSS_TOP 48
+#define RST_BUS_HDMI_SUB 49
+#define RST_BUS_HDMI_MAIN 50
+#define RST_BUS_MIPI_DSI 51
+#define RST_BUS_TCON_LCD0 52
+#define RST_BUS_TCON_TV 53
+#define RST_BUS_LVDS0 54
+#define RST_BUS_TVE 55
+#define RST_BUS_TVE_TOP 56
+#define RST_BUS_TVD 57
+#define RST_BUS_TVD_TOP 58
+#define RST_BUS_LEDC 59
+#define RST_BUS_CSI 60
+#define RST_BUS_TPADC 61
+#define RST_DSP 62
+#define RST_BUS_DSP_CFG 63
+#define RST_BUS_DSP_DBG 64
+#define RST_BUS_RISCV_CFG 65
+#define RST_BUS_CAN0 66
+#define RST_BUS_CAN1 67
+
+#endif /* _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun20i-d1-r-ccu.h b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
new file mode 100644
index 0000000..e20babc
--- /dev/null
+++ b/include/dt-bindings/reset/sun20i-d1-r-ccu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2021 Samuel Holland <samuel@sholland.org>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_
+
+#define RST_BUS_R_TIMER 0
+#define RST_BUS_R_TWD 1
+#define RST_BUS_R_PPU 2
+#define RST_BUS_R_IR_RX 3
+#define RST_BUS_R_RTC 4
+#define RST_BUS_R_CPUCFG 5
+
+#endif /* _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h6-ccu.h b/include/dt-bindings/reset/sun50i-h6-ccu.h
index 81106f4..d038ddf 100644
--- a/include/dt-bindings/reset/sun50i-h6-ccu.h
+++ b/include/dt-bindings/reset/sun50i-h6-ccu.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
*/
diff --git a/include/dt-bindings/reset/sun50i-h6-r-ccu.h b/include/dt-bindings/reset/sun50i-h6-r-ccu.h
index 7950e79..d541ade 100644
--- a/include/dt-bindings/reset/sun50i-h6-r-ccu.h
+++ b/include/dt-bindings/reset/sun50i-h6-r-ccu.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
*/
diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
index cb6285a..1bd8bb0 100644
--- a/include/dt-bindings/reset/sun50i-h616-ccu.h
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (C) 2020 Arm Ltd.
*/
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/include/sunxi_gpio.h
index 6eaeece..db3742c 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/include/sunxi_gpio.h
@@ -3,13 +3,29 @@
* (C) Copyright 2007-2012
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
* Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Definitions that are shared between the Allwinner pinctrl and GPIO drivers,
+ * also used by some non-DM SPL code directly.
*/
#ifndef _SUNXI_GPIO_H
#define _SUNXI_GPIO_H
#include <linux/types.h>
-#include <asm/arch/cpu.h>
+
+#if defined(CONFIG_MACH_SUN9I)
+#define SUNXI_PIO_BASE 0x06000800
+#define SUNXI_R_PIO_BASE 0x08002c00
+#elif defined(CONFIG_SUN50I_GEN_H6)
+#define SUNXI_PIO_BASE 0x0300b000
+#define SUNXI_R_PIO_BASE 0x07022000
+#elif defined(CONFIG_SUNXI_GEN_NCAT2)
+#define SUNXI_PIO_BASE 0x02000000
+#define SUNXI_R_PIO_BASE 0x07022000
+#else
+#define SUNXI_PIO_BASE 0x01c20800
+#define SUNXI_R_PIO_BASE 0x01f02c00
+#endif
/*
* sunxi has 9 banks of gpio, they are:
@@ -29,13 +45,6 @@
#define SUNXI_GPIO_I 8
/*
- * This defines the number of GPIO banks for the _main_ GPIO controller.
- * You should fix up the padding in struct sunxi_gpio_reg below if you
- * change this.
- */
-#define SUNXI_GPIO_BANKS 9
-
-/*
* sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
* at a different register offset.
*
@@ -52,47 +61,9 @@
#define SUNXI_GPIO_M 12
#define SUNXI_GPIO_N 13
-struct sunxi_gpio {
- u32 cfg[4];
- u32 dat;
- u32 drv[2];
- u32 pull[2];
-};
-
-/* gpio interrupt control */
-struct sunxi_gpio_int {
- u32 cfg[3];
- u32 ctl;
- u32 sta;
- u32 deb; /* interrupt debounce */
-};
-
-struct sunxi_gpio_reg {
- struct sunxi_gpio gpio_bank[SUNXI_GPIO_BANKS];
- u8 res[0xbc];
- struct sunxi_gpio_int gpio_int;
-};
-
#define SUN50I_H6_GPIO_POW_MOD_SEL 0x340
#define SUN50I_H6_GPIO_POW_MOD_VAL 0x348
-#define BANK_TO_GPIO(bank) (((bank) < SUNXI_GPIO_L) ? \
- &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
- &((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
-
-#define GPIO_BANK(pin) ((pin) >> 5)
-#define GPIO_NUM(pin) ((pin) & 0x1f)
-
-#define GPIO_CFG_INDEX(pin) (((pin) & 0x1f) >> 3)
-#define GPIO_CFG_OFFSET(pin) ((((pin) & 0x1f) & 0x7) << 2)
-
-#define GPIO_DRV_INDEX(pin) (((pin) & 0x1f) >> 4)
-#define GPIO_DRV_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-
-#define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
-#define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
-
-/* GPIO bank sizes */
#define SUNXI_GPIOS_PER_BANK 32
#define SUNXI_GPIO_NEXT(__gpio) \
@@ -133,7 +104,6 @@ enum sunxi_gpio_number {
/* GPIO pin function config */
#define SUNXI_GPIO_INPUT 0
#define SUNXI_GPIO_OUTPUT 1
-#define SUNXI_GPIO_DISABLE 7
#define SUN8I_H3_GPA_UART0 2
#define SUN8I_H3_GPA_UART2 2
@@ -202,6 +172,14 @@ enum sunxi_gpio_number {
#define SUN9I_GPN_R_RSB 3
+#ifdef CONFIG_SUNXI_NEW_PINCTRL
+ #define SUNXI_PINCTRL_BANK_SIZE 0x30
+ #define SUNXI_GPIO_DISABLE 0xf
+#else
+ #define SUNXI_PINCTRL_BANK_SIZE 0x24
+ #define SUNXI_GPIO_DISABLE 0x7
+#endif
+
/* GPIO pin pull-up/down config */
#define SUNXI_GPIO_PULL_DISABLE 0
#define SUNXI_GPIO_PULL_UP 1
@@ -213,18 +191,19 @@ enum sunxi_gpio_number {
#define SUNXI_GPIO_AXP0_GPIO_COUNT 6
struct sunxi_gpio_plat {
- struct sunxi_gpio *regs;
+ void *regs;
char bank_name[3];
};
-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
+/* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */
+void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
+int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
int sunxi_gpio_get_cfgpin(u32 pin);
void sunxi_gpio_set_drv(u32 pin, u32 val);
-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
+void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
void sunxi_gpio_set_pull(u32 pin, u32 val);
-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val);
+void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val);
int sunxi_name_to_gpio(const char *name);
#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO