summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv8/fel_utils.S7
-rw-r--r--arch/arm/include/asm/arch-sunxi/boot0.h8
-rw-r--r--arch/arm/mach-sunxi/Kconfig21
-rw-r--r--arch/arm/mach-sunxi/clock_sun50i_h6.c15
-rw-r--r--arch/arm/mach-sunxi/dram_sun50i_h616.c74
-rw-r--r--arch/arm/mach-sunxi/pmic_bus.c27
-rw-r--r--arch/arm/mach-sunxi/rmr_switch.S40
-rw-r--r--board/sunxi/board.c5
-rw-r--r--common/spl/Kconfig3
-rw-r--r--drivers/clk/sunxi/Kconfig7
-rw-r--r--drivers/clk/sunxi/Makefile1
-rw-r--r--drivers/clk/sunxi/clk_a100.c102
-rw-r--r--drivers/clk/sunxi/clk_sunxi.c5
-rw-r--r--drivers/mmc/sunxi_mmc.c35
-rw-r--r--drivers/mmc/sunxi_mmc.h18
-rw-r--r--drivers/pinctrl/sunxi/Kconfig10
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c47
-rw-r--r--drivers/power/Kconfig25
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/axp_spl.c17
20 files changed, 390 insertions, 78 deletions
diff --git a/arch/arm/cpu/armv8/fel_utils.S b/arch/arm/cpu/armv8/fel_utils.S
index 939869b9ffa..f7707acdf1a 100644
--- a/arch/arm/cpu/armv8/fel_utils.S
+++ b/arch/arm/cpu/armv8/fel_utils.S
@@ -63,9 +63,12 @@ ENTRY(return_to_fel)
1: wfi
b 1b
+fel_stash_addr: // must immediately precede back_in_32:
+ .word 0x00000000 // receives fel_stash addr, by AA64 code above
+
/* AArch32 code to restore the state from fel_stash and return back to FEL. */
back_in_32:
- .word 0xe59f0028 // ldr r0, [pc, #40] ; load fel_stash address
+ .word 0xe51f000c // ldr r0, [pc, #-12] ; load fel_stash address
.word 0xe5901008 // ldr r1, [r0, #8]
.word 0xe129f001 // msr CPSR_fc, r1
.word 0xf57ff06f // isb
@@ -77,6 +80,4 @@ back_in_32:
.word 0xee011f10 // mcr 15, 0, r1, cr1, cr0, {0} ; SCTLR
.word 0xf57ff06f // isb
.word 0xe12fff1e // bx lr ; return to FEL
-fel_stash_addr:
- .word 0x00000000 // receives fel_stash addr, by AA64 code above
ENDPROC(return_to_fel)
diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 6b2bb5a4586..24c81391d58 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -16,10 +16,11 @@
*/
tst x0, x0 // this is "b #0x84" in ARM
b reset
- .space 0x7c
+ .space 0x78
+ .word fel_stash - .
- .word 0xe28f0070 // add r0, pc, #112 // @(fel_stash - .)
- .word 0xe59f106c // ldr r1, [pc, #108] // fel_stash - .
+ .word 0xe24f000c // sub r0, pc, #12 // @(fel_stash - .)
+ .word 0xe51f1010 // ldr r1, [pc, #-16] // fel_stash - .
.word 0xe0800001 // add r0, r0, r1
.word 0xe580d000 // str sp, [r0]
.word 0xe580e004 // str lr, [r0, #4]
@@ -54,7 +55,6 @@
#else
.word CONFIG_TEXT_BASE
#endif
- .word fel_stash - .
#else
/* normal execution */
b reset
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index ba1b1541437..ab432390d3c 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -457,6 +457,9 @@ config MACH_SUN50I_H616
select SUN50I_GEN_H6
imply OF_UPSTREAM
+config MACH_SUN50I_A133
+ bool "sun50i (Allwinner A133)"
+
endchoice
# The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33"
@@ -713,16 +716,10 @@ endif
config SYS_CLK_FREQ
default 408000000 if MACH_SUNIV
- default 1008000000 if MACH_SUN4I
- default 1008000000 if MACH_SUN5I
- default 1008000000 if MACH_SUN6I
- default 912000000 if MACH_SUN7I
default 816000000 if MACH_SUN50I || MACH_SUN50I_H5
- default 1008000000 if MACH_SUN8I
- default 1008000000 if MACH_SUN9I
default 888000000 if MACH_SUN50I_H6
- default 1008000000 if MACH_SUN50I_H616
- default 1008000000 if MACH_SUN8I_R528
+ default 912000000 if MACH_SUN7I
+ default 1008000000
config SYS_CONFIG_NAME
default "suniv" if MACH_SUNIV
@@ -1131,10 +1128,6 @@ config BLUETOOTH_DT_DEVICE_FIXUP
The used address is "bdaddr" if set, and "ethaddr" with the LSB
flipped elsewise.
-source "board/sunxi/Kconfig"
-
-endif
-
config CHIP_DIP_SCAN
bool "Enable DIPs detection for CHIP board"
select SUPPORT_EXTENSION_SCAN
@@ -1143,3 +1136,7 @@ config CHIP_DIP_SCAN
select W1_EEPROM
select W1_EEPROM_DS24XXX
select CMD_EXTENSION
+
+source "board/sunxi/Kconfig"
+
+endif
diff --git a/arch/arm/mach-sunxi/clock_sun50i_h6.c b/arch/arm/mach-sunxi/clock_sun50i_h6.c
index b424a7893ea..359513d1669 100644
--- a/arch/arm/mach-sunxi/clock_sun50i_h6.c
+++ b/arch/arm/mach-sunxi/clock_sun50i_h6.c
@@ -147,15 +147,20 @@ unsigned int clock_get_pll6(void)
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;
}
+ /*
+ * The factors encoded in the register describe the doubled clock
+ * frequency, expect for the H6, where it's the quadrupled frequency.
+ * Compensate for that here.
+ */
+ if (IS_ENABLED(CONFIG_MACH_SUN50I_H6))
+ m = 4;
+ else
+ m = 2;
+
return 24000000U * n / m / div1 / div2;
}
diff --git a/arch/arm/mach-sunxi/dram_sun50i_h616.c b/arch/arm/mach-sunxi/dram_sun50i_h616.c
index b3554cc64bf..cd9d321a018 100644
--- a/arch/arm/mach-sunxi/dram_sun50i_h616.c
+++ b/arch/arm/mach-sunxi/dram_sun50i_h616.c
@@ -1360,36 +1360,94 @@ static void mctl_auto_detect_rank_width(const struct dram_para *para,
panic("This DRAM setup is currently not supported.\n");
}
+static void mctl_write_pattern(void)
+{
+ unsigned int i;
+ u32 *ptr, val;
+
+ ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i < 16; ptr++, i++) {
+ if (i & 1)
+ val = ~(ulong)ptr;
+ else
+ val = (ulong)ptr;
+ writel(val, ptr);
+ }
+}
+
+static bool mctl_check_pattern(ulong offset)
+{
+ unsigned int i;
+ u32 *ptr, val;
+
+ ptr = (u32 *)CFG_SYS_SDRAM_BASE;
+ for (i = 0; i < 16; ptr++, i++) {
+ if (i & 1)
+ val = ~(ulong)ptr;
+ else
+ val = (ulong)ptr;
+ if (val != *(ptr + offset / 4))
+ return false;
+ }
+
+ return true;
+}
+
static void mctl_auto_detect_dram_size(const struct dram_para *para,
struct dram_config *config)
{
- unsigned int shift;
+ unsigned int shift, cols, rows;
+ u32 buffer[16];
/* max. config for columns, but not rows */
config->cols = 11;
config->rows = 13;
mctl_core_init(para, config);
+ /*
+ * Store content so it can be restored later. This is important
+ * if controller was already initialized and holds any data
+ * which is important for restoring system.
+ */
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+
+ mctl_write_pattern();
+
shift = config->bus_full_width + 1;
/* detect column address bits */
- for (config->cols = 8; config->cols < 11; config->cols++) {
- if (mctl_mem_matches(1ULL << (config->cols + shift)))
+ for (cols = 8; cols < 11; cols++) {
+ if (mctl_check_pattern(1ULL << (cols + shift)))
break;
}
- debug("detected %u columns\n", config->cols);
+ debug("detected %u columns\n", cols);
+
+ /* restore data */
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
/* reconfigure to make sure that all active rows are accessible */
- config->rows = 18;
+ config->cols = 8;
+ config->rows = 17;
mctl_core_init(para, config);
+ /* store data again as it might be moved */
+ memcpy(buffer, (u32 *)CFG_SYS_SDRAM_BASE, sizeof(buffer));
+
+ mctl_write_pattern();
+
/* detect row address bits */
shift = config->bus_full_width + 4 + config->cols;
- for (config->rows = 13; config->rows < 18; config->rows++) {
- if (mctl_mem_matches(1ULL << (config->rows + shift)))
+ for (rows = 13; rows < 17; rows++) {
+ if (mctl_check_pattern(1ULL << (rows + shift)))
break;
}
- debug("detected %u rows\n", config->rows);
+ debug("detected %u rows\n", rows);
+
+ /* restore data again */
+ memcpy((u32 *)CFG_SYS_SDRAM_BASE, buffer, sizeof(buffer));
+
+ config->cols = cols;
+ config->rows = rows;
}
static unsigned long mctl_calc_size(const struct dram_config *config)
diff --git a/arch/arm/mach-sunxi/pmic_bus.c b/arch/arm/mach-sunxi/pmic_bus.c
index 8e19324c8ac..c77dc538456 100644
--- a/arch/arm/mach-sunxi/pmic_bus.c
+++ b/arch/arm/mach-sunxi/pmic_bus.c
@@ -16,33 +16,10 @@
#include <power/pmic.h>
#include <asm/arch/pmic_bus.h>
-#define AXP152_I2C_ADDR 0x30
-
-#define AXP209_I2C_ADDR 0x34
-#define AXP717_I2C_ADDR 0x34
-
-#define AXP305_I2C_ADDR 0x36
-#define AXP313_I2C_ADDR 0x36
-
#define AXP221_CHIP_ADDR 0x68
#if CONFIG_IS_ENABLED(PMIC_AXP)
static struct udevice *pmic;
-#else
-static int pmic_i2c_address(void)
-{
- if (IS_ENABLED(CONFIG_AXP152_POWER))
- return AXP152_I2C_ADDR;
- if (IS_ENABLED(CONFIG_AXP305_POWER))
- return AXP305_I2C_ADDR;
- if (IS_ENABLED(CONFIG_AXP313_POWER))
- return AXP313_I2C_ADDR;
- if (IS_ENABLED(CONFIG_AXP717_POWER))
- return AXP717_I2C_ADDR;
-
- /* Other AXP2xx and AXP8xx variants */
- return AXP209_I2C_ADDR;
-}
#endif
int pmic_bus_init(void)
@@ -88,7 +65,7 @@ int pmic_bus_read(u8 reg, u8 *data)
if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data);
- return i2c_read(pmic_i2c_address(), reg, 1, data, 1);
+ return i2c_read(CONFIG_AXP_I2C_ADDRESS, reg, 1, data, 1);
#endif
}
@@ -102,7 +79,7 @@ int pmic_bus_write(u8 reg, u8 data)
if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data);
- return i2c_write(pmic_i2c_address(), reg, 1, &data, 1);
+ return i2c_write(CONFIG_AXP_I2C_ADDRESS, reg, 1, &data, 1);
#endif
}
diff --git a/arch/arm/mach-sunxi/rmr_switch.S b/arch/arm/mach-sunxi/rmr_switch.S
index 33e55d49686..422007c985b 100644
--- a/arch/arm/mach-sunxi/rmr_switch.S
+++ b/arch/arm/mach-sunxi/rmr_switch.S
@@ -16,7 +16,9 @@
@ the machine code must be inserted as verbatim .word statements into the
@ beginning of the AArch64 U-Boot code.
@ To get the encoded bytes, use:
-@ ${CROSS_COMPILE}gcc -c -o rmr_switch.o rmr_switch.S
+@ ${CROSS_COMPILE}gcc -c -Iinclude -Iarch/arm/include \
+@ -D__ASSEMBLY__ -DCONFIG_ARM64 \
+@ -o rmr_switch.o arch/arm/mach-sunxi/rmr_switch.S
@ ${CROSS_COMPILE}objdump -d rmr_switch.o
@
@ The resulting words should be inserted into the U-Boot file at
@@ -29,14 +31,40 @@
#include <config.h>
.text
+ b start32 // this is "tst x0, x0" in AArch64
+ .word 0x14000047 // this is "b reset" in AArch64
-#ifndef CONFIG_SUN50I_GEN_H6
- ldr r1, =0x017000a0 @ MMIO mapped RVBAR[0] register
+ .space 0x78 // gap distance set by the common
+ // encoding of the first instruction
+fel_stash_addr:
+ .word fel_stash - . // distance to fel_stash buffer
+
+start32:
+ adr r0, fel_stash_addr // absolute location of fel_stash_addr
+ ldr r1, fel_stash_addr // distance to actual fel_stash
+ add r0, r0, r1 // real address of fel_stash
+
+ /* save the current state as needed by the BROM for a later return */
+ str sp, [r0]
+ str lr, [r0, #4]
+ mrs lr, CPSR
+ str lr, [r0, #8]
+ mrc p15, 0, lr, cr1, cr0, 0 // SCTLR
+ str lr, [r0, #12]
+ mrc p15, 0, lr, cr12, cr0, 0 // VBAR
+ str lr, [r0, #16]
+
+ ldr r1, =CONFIG_SUNXI_RVBAR_ADDRESS
+ ldr r0, =SUNXI_SRAMC_BASE
+ ldr r0, [r0, #36] // SRAM_VER_REG
+ ands r0, r0, #0xff
+ ldrne r1, =CONFIG_SUNXI_RVBAR_ALTERNATIVE
+#ifdef CONFIG_XPL_BUILD
+ ldr r0, =CONFIG_SPL_TEXT_BASE
#else
- ldr r1, =0x09010040 @ MMIO mapped RVBAR[0] register
+ ldr r0, =CONFIG_TEXT_BASE
#endif
- ldr r0, =0x57aA7add @ start address, to be replaced
- str r0, [r1]
+ str r0, [r1] // store start address in RVBAR
dsb sy
isb sy
mrc 15, 0, r0, cr12, cr0, 2 @ read RMR register
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index c7a2205ed61..ac9cefc6eac 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -563,7 +563,8 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER || \
- defined CONFIG_AXP313_POWER || defined CONFIG_AXP717_POWER
+ defined CONFIG_AXP313_POWER || defined CONFIG_AXP717_POWER || \
+ defined CONFIG_AXP803_POWER
power_failed = axp_init();
if (IS_ENABLED(CONFIG_AXP_DISABLE_BOOT_ON_POWERON) && !power_failed) {
@@ -581,6 +582,8 @@ void sunxi_board_init(void)
#endif
#ifdef CONFIG_AXP_DCDC2_VOLT
power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
+#endif
+#ifdef CONFIG_AXP_DCDC3_VOLT
power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
#endif
#ifdef CONFIG_AXP_DCDC4_VOLT
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 97f542fcc8a..36dd064c25a 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -80,11 +80,10 @@ config SPL_MAX_SIZE
default 0x1b000 if AM33XX && !TI_SECURE_DEVICE
default 0xec00 if OMAP34XX
default 0x10000 if ARCH_MX6 && !MX6_OCRAM_256KB
- default 0x7fa0 if SUNXI_SRAM_ADDRESS = 0x10000
- default 0x7fa0 if SUNXI_SRAM_ADDRESS = 0x20000 && !MACH_SUN50I_H616
default 0xbfa0 if MACH_SUN50I_H616
default 0x7000 if RCAR_GEN3
default 0x5fa0 if SUNXI_SRAM_ADDRESS = 0x0
+ default 0x7fa0 if ARCH_SUNXI
default 0x10000 if ASPEED_AST2600
default 0x27000 if IMX8MM && SPL_TEXT_BASE = 0x7E1000
default 0x30000 if ARCH_SC5XX && (SC59X_64 || SC59X)
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index 8bdc0944896..f44db76c182 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -122,4 +122,11 @@ config CLK_SUN50I_A64
This enables common clock driver support for platforms based
on Allwinner A64 SoC.
+config CLK_SUN50I_A100
+ bool "Clock driver for Allwinner A100/A133"
+ default MACH_SUN50I_A133
+ help
+ This enables common clock driver support for platforms based
+ on Allwinner A100/A133 SoCs.
+
endif # CLK_SUNXI
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 90a277489dc..7ff71c756e0 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -24,3 +24,4 @@ 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
obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
+obj-$(CONFIG_CLK_SUN50I_A100) += clk_a100.o
diff --git a/drivers/clk/sunxi/clk_a100.c b/drivers/clk/sunxi/clk_a100.c
new file mode 100644
index 00000000000..b641feb8612
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a100.c
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2023-2024 Arm Ltd.
+ */
+
+#include <clk/sunxi.h>
+#include <dt-bindings/clock/sun50i-a100-ccu.h>
+#include <dt-bindings/reset/sun50i-a100-ccu.h>
+#include <linux/bitops.h>
+
+static struct ccu_clk_gate a100_gates[] = {
+ [CLK_PLL_PERIPH0] = GATE(0x020, BIT(31) | BIT(27)),
+
+ [CLK_APB1] = GATE_DUMMY,
+
+ [CLK_DE] = GATE(0x600, BIT(31)),
+ [CLK_BUS_DE] = GATE(0x60c, BIT(0)),
+
+ [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_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_SPI2] = GATE(0x948, BIT(31)),
+
+ [CLK_BUS_SPI0] = GATE(0x96c, BIT(0)),
+ [CLK_BUS_SPI1] = GATE(0x96c, BIT(1)),
+ [CLK_BUS_SPI2] = GATE(0x96c, BIT(2)),
+
+ [CLK_BUS_EMAC] = GATE(0x97c, BIT(0)),
+
+ [CLK_USB_PHY0] = GATE(0xa70, BIT(29)),
+ [CLK_USB_OHCI0] = GATE(0xa70, BIT(31)),
+
+ [CLK_USB_PHY1] = GATE(0xa74, BIT(29)),
+ [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_TCON_LCD] = GATE(0xb60, BIT(31)),
+ [CLK_BUS_TCON_LCD] = GATE(0xb7c, BIT(0)),
+};
+
+static struct ccu_reset a100_resets[] = {
+ [RST_BUS_DE] = RESET(0x60c, BIT(16)),
+
+ [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_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_SPI2] = RESET(0x96c, BIT(18)),
+
+ [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_TCON_LCD] = RESET(0xb7c, BIT(16)),
+};
+
+const struct ccu_desc a100_ccu_desc = {
+ .gates = a100_gates,
+ .resets = a100_resets,
+ .num_gates = ARRAY_SIZE(a100_gates),
+ .num_resets = ARRAY_SIZE(a100_resets),
+};
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
index 2ef4f45dacf..e0765cbc6dc 100644
--- a/drivers/clk/sunxi/clk_sunxi.c
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -122,6 +122,7 @@ extern const struct ccu_desc f1c100s_ccu_desc;
extern const struct ccu_desc h3_ccu_desc;
extern const struct ccu_desc h6_ccu_desc;
extern const struct ccu_desc h616_ccu_desc;
+extern const struct ccu_desc a100_ccu_desc;
extern const struct ccu_desc h6_r_ccu_desc;
extern const struct ccu_desc r40_ccu_desc;
extern const struct ccu_desc v3s_ccu_desc;
@@ -215,6 +216,10 @@ static const struct udevice_id sunxi_clk_ids[] = {
{ .compatible = "allwinner,sun50i-h616-r-ccu",
.data = (ulong)&h6_r_ccu_desc },
#endif
+#ifdef CONFIG_CLK_SUN50I_A100
+ { .compatible = "allwinner,sun50i-a100-ccu",
+ .data = (ulong)&a100_ccu_desc },
+#endif
#ifdef CONFIG_CLK_SUNIV_F1C100S
{ .compatible = "allwinner,suniv-f1c100s-ccu",
.data = (ulong)&f1c100s_ccu_desc },
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index 0b56d1405be..951e6acd34d 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -92,6 +92,13 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
pll = CCM_MMC_CTRL_PLL6;
pll_hz = clock_get_pll6();
#endif
+ /*
+ * On the D1/R528/T113 mux source 1 refers to PLL_PERIPH0(1x),
+ * like for the older SoCs. However we still have the hidden
+ * divider of 2x, so compensate for that here.
+ */
+ if (IS_ENABLED(CONFIG_MACH_SUN8I_R528))
+ pll_hz /= 2;
}
div = pll_hz / hz;
@@ -442,6 +449,26 @@ out:
return error;
}
+static void sunxi_mmc_reset(void *regs)
+{
+ /* Reset controller */
+ writel(SUNXI_MMC_GCTRL_RESET, regs + SUNXI_MMC_GCTRL);
+ udelay(1000);
+
+ if (IS_ENABLED(CONFIG_SUN50I_GEN_H6) || IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
+ /* Reset card */
+ writel(SUNXI_MMC_HWRST_ASSERT, regs + SUNXI_MMC_HWRST);
+ udelay(10);
+ writel(SUNXI_MMC_HWRST_DEASSERT, regs + SUNXI_MMC_HWRST);
+ udelay(300);
+
+ /* Setup FIFO R/W threshold. Needed on H616. */
+ writel(SUNXI_MMC_THLDC_READ_THLD(512) |
+ SUNXI_MMC_THLDC_WRITE_EN |
+ SUNXI_MMC_THLDC_READ_EN, regs + SUNXI_MMC_THLDC);
+ }
+}
+
/* non-DM code here is used by the (ARM) SPL only */
#if !CONFIG_IS_ENABLED(DM_MMC)
@@ -489,9 +516,7 @@ static int sunxi_mmc_core_init(struct mmc *mmc)
{
struct sunxi_mmc_priv *priv = mmc->priv;
- /* Reset controller */
- writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
- udelay(1000);
+ sunxi_mmc_reset(priv->reg);
return 0;
}
@@ -684,9 +709,7 @@ static int sunxi_mmc_probe(struct udevice *dev)
upriv->mmc = &plat->mmc;
- /* Reset controller */
- writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
- udelay(1000);
+ sunxi_mmc_reset(priv->reg);
return 0;
}
diff --git a/drivers/mmc/sunxi_mmc.h b/drivers/mmc/sunxi_mmc.h
index f4ae5a790c8..71865160319 100644
--- a/drivers/mmc/sunxi_mmc.h
+++ b/drivers/mmc/sunxi_mmc.h
@@ -37,7 +37,9 @@ struct sunxi_mmc {
u32 res0; /* 0x54 reserved */
u32 a12a; /* 0x58 Auto command 12 argument */
u32 ntsr; /* 0x5c New timing set register */
- u32 res1[8];
+ u32 res1[6];
+ u32 hwrst; /* 0x78 Hardware Reset */
+ u32 res5;
u32 dmac; /* 0x80 internal DMA control */
u32 dlba; /* 0x84 internal DMA descr list base address */
u32 idst; /* 0x88 internal DMA status */
@@ -46,7 +48,8 @@ struct sunxi_mmc {
u32 cbda; /* 0x94 */
u32 res2[26];
#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2)
- u32 res3[17];
+ u32 thldc; /* 0x100 Threshold control */
+ u32 res3[16];
u32 samp_dl;
u32 res4[46];
#endif
@@ -57,6 +60,7 @@ struct sunxi_mmc {
#define SUNXI_MMC_CLK_ENABLE (0x1 << 16)
#define SUNXI_MMC_CLK_DIVIDER_MASK (0xff)
+#define SUNXI_MMC_GCTRL 0x000
#define SUNXI_MMC_GCTRL_SOFT_RESET (0x1 << 0)
#define SUNXI_MMC_GCTRL_FIFO_RESET (0x1 << 1)
#define SUNXI_MMC_GCTRL_DMA_RESET (0x1 << 2)
@@ -123,6 +127,10 @@ struct sunxi_mmc {
#define SUNXI_MMC_NTSR_MODE_SEL_NEW (0x1 << 31)
+#define SUNXI_MMC_HWRST 0x078
+#define SUNXI_MMC_HWRST_ASSERT (0x0 << 0)
+#define SUNXI_MMC_HWRST_DEASSERT (0x1 << 0)
+
#define SUNXI_MMC_IDMAC_RESET (0x1 << 0)
#define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1)
#define SUNXI_MMC_IDMAC_ENABLE (0x1 << 7)
@@ -133,6 +141,12 @@ struct sunxi_mmc {
#define SUNXI_MMC_COMMON_CLK_GATE (1 << 16)
#define SUNXI_MMC_COMMON_RESET (1 << 18)
+#define SUNXI_MMC_THLDC 0x100
+#define SUNXI_MMC_THLDC_READ_EN (0x1 << 0)
+#define SUNXI_MMC_THLDC_BSY_CLR_INT_EN (0x1 << 1)
+#define SUNXI_MMC_THLDC_WRITE_EN (0x1 << 2)
+#define SUNXI_MMC_THLDC_READ_THLD(x) (((x) & 0xfff) << 16)
+
#define SUNXI_MMC_CAL_DL_SW_EN (0x1 << 7)
#endif /* _SUNXI_MMC_H */
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index cbd61795986..65e8192a99a 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -124,6 +124,16 @@ config PINCTRL_SUN50I_H616_R
default MACH_SUN50I_H616
select PINCTRL_SUNXI
+config PINCTRL_SUN50I_A100
+ bool "Support for the Allwinner A100/A133 PIO"
+ default MACH_SUN50I_A133
+ select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_A100_R
+ bool "Support for the Allwinner A100/A133 R-PIO"
+ default MACH_SUN50I_A133
+ select PINCTRL_SUNXI
+
config PINCTRL_SUN20I_D1
bool "Support for the Allwinner D1/R528 PIO"
default MACH_SUN8I_R528
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 37ea93715d1..c38edf7d4f5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -774,6 +774,41 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc
.num_banks = 1,
};
+static const struct sunxi_pinctrl_function sun50i_a100_pinctrl_functions[] = {
+ { "emac0", 5 }, /* PH0-PH16 */
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 }, /* PF0-PF5 */
+ { "mmc1", 2 }, /* PG0-PG5 */
+ { "mmc2", 3 }, /* PC0-PC16 */
+ { "spi0", 4 }, /* PC2-PC4, PC7, PC12, PC15-PC16 */
+#if IS_ENABLED(CONFIG_UART0_PORT_F)
+ { "uart0", 3 }, /* PF2-PF4 */
+#else
+ { "uart0", 2 }, /* PB9-PB10 */
+#endif
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a100_pinctrl_desc = {
+ .functions = sun50i_a100_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_a100_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_A,
+ .num_banks = 8,
+};
+
+static const struct sunxi_pinctrl_function sun50i_a100_r_pinctrl_functions[] = {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c0", 2 },
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a100_r_pinctrl_desc = {
+ .functions = sun50i_a100_r_pinctrl_functions,
+ .num_functions = ARRAY_SIZE(sun50i_a100_r_pinctrl_functions),
+ .first_bank = SUNXI_GPIO_L,
+ .num_banks = 1,
+};
+
static const struct udevice_id sunxi_pinctrl_ids[] = {
#ifdef CONFIG_PINCTRL_SUNIV_F1C100S
{
@@ -937,6 +972,18 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
.data = (ulong)&sun50i_h616_r_pinctrl_desc,
},
#endif
+#ifdef CONFIG_PINCTRL_SUN50I_A100
+ {
+ .compatible = "allwinner,sun50i-a100-pinctrl",
+ .data = (ulong)&sun50i_a100_pinctrl_desc,
+ },
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_A100_R
+ {
+ .compatible = "allwinner,sun50i-a100-r-pinctrl",
+ .data = (ulong)&sun50i_a100_r_pinctrl_desc,
+ },
+#endif
{}
};
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 4b81aeb7497..eed65058e66 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -116,6 +116,12 @@ config AXP717_POWER
---help---
Select this to enable support for the AXP717 PMIC found on some boards.
+config AXP803_POWER
+ bool "AXP803 PMIC support"
+ select AXP_PMIC_BUS
+ ---help---
+ Select this to enable support for the AXP803 PMIC found on some boards.
+
config AXP809_POWER
bool "axp809 pmic support"
depends on MACH_SUN9I
@@ -142,10 +148,20 @@ config SY8106A_POWER
endchoice
+config AXP_I2C_ADDRESS
+ hex "AXP PMIC I2C address"
+ depends on ARCH_SUNXI && !SUNXI_NO_PMIC
+ default 0x36 if AXP305_POWER
+ default 0x36 if AXP313_POWER
+ default 0x30 if AXP152_POWER
+ default 0x34
+ ---help---
+ I2C address of the AXP PMIC, used for the SPL only.
+
config AXP_DCDC1_VOLT
int "axp pmic dcdc1 voltage"
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
- default 3300 if AXP818_POWER || MACH_SUN8I_R40
+ depends on AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP803_POWER
+ default 3300 if AXP818_POWER || MACH_SUN8I_R40 || AXP803_POWER
default 3000 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic dcdc1 at, set to 0 to
@@ -158,11 +174,12 @@ config AXP_DCDC1_VOLT
config AXP_DCDC2_VOLT
int "axp pmic dcdc2 voltage"
- depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER || AXP717_POWER
+ depends on AXP152_POWER || AXP209_POWER || AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP313_POWER || AXP717_POWER || AXP803_POWER
default 900 if AXP818_POWER
default 1400 if AXP152_POWER || AXP209_POWER
default 1000 if AXP313_POWER
default 1000 if AXP717_POWER
+ default 1000 if AXP803_POWER
default 1200 if MACH_SUN6I
default 1100 if MACH_SUN8I
default 0 if MACH_SUN9I
@@ -219,7 +236,7 @@ config AXP_DCDC4_VOLT
config AXP_DCDC5_VOLT
int "axp pmic dcdc5 voltage"
- depends on AXP221_POWER || AXP809_POWER || AXP818_POWER
+ depends on AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP803_POWER
default 1500 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
---help---
Set the voltage (mV) to program the axp pmic dcdc5 at, set to 0 to
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 3f4d56f5139..3363191fdc8 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_AXP313_POWER) += axp_spl.o
obj-$(CONFIG_AXP717_POWER) += axp_spl.o
obj-$(CONFIG_AXP809_POWER) += axp809.o
obj-$(CONFIG_AXP818_POWER) += axp818.o
+obj-$(CONFIG_AXP803_POWER) += axp_spl.o
endif
obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
obj-$(CONFIG_SY8106A_POWER) += sy8106a.o
diff --git a/drivers/power/axp_spl.c b/drivers/power/axp_spl.c
index 3c86eb20ab4..7c51a9b3dfb 100644
--- a/drivers/power/axp_spl.c
+++ b/drivers/power/axp_spl.c
@@ -36,6 +36,23 @@ static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
#define AXP_SHUTDOWN_REG 0x27
#define AXP_SHUTDOWN_MASK BIT(0)
+#elif defined(CONFIG_AXP803_POWER) /* AXP803 */
+
+static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
+ { 0x10, BIT(0), 0x20, 0x1f, 1600, 3400, 100, NA },
+ { 0x10, BIT(1), 0x21, 0x7f, 500, 1300, 10, 70 },
+ { 0x10, BIT(2), 0x22, 0x7f, 500, 1300, 10, 70 },
+ { 0x10, BIT(3), 0x23, 0x7f, 500, 1300, 10, 70 },
+ { 0x10, BIT(4), 0x24, 0x7f, 800, 1840, 10, 32 },
+ { 0x10, BIT(5), 0x25, 0x7f, 600, 1520, 10, 50 },
+};
+
+#define AXP_CHIP_VERSION 0x3
+#define AXP_CHIP_VERSION_MASK 0xcf
+#define AXP_CHIP_ID 0x41
+#define AXP_SHUTDOWN_REG 0x32
+#define AXP_SHUTDOWN_MASK BIT(7)
+
#elif defined(CONFIG_AXP313_POWER) /* AXP313 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {