Assorted fixes, refactorings and additions that are ready, and shave
off some load from upcoming series'.

Improves MMC performance on D1/T113 (missed clock divider), enables
eMMC access on the H616 family (never worked, many thanks to Jernej for
the fix!), DRAM detection fixes for the H616 (now reportedly stable).

Some patches for the upcoming Allwinner A133 SoC support: a few
refactorings, plus the DM clock and pinctrl driver. The DRAM init
routines work, but need some more polishing, that also holds back the
actual enablement patch, which will hopefully follow for v2025.07 still.

Also some preparatory patches for the Allwinner A523 SoC support, for
now just to improve the FEL save/restore code. There will be more patches
coming up for this, ideally also in the coming cycle still.

Gitlab CI passed, and I booted that briefly on some boards.
This commit is contained in:
Tom Rini 2025-03-27 08:10:06 -06:00
commit 02d95aaee0
20 changed files with 390 additions and 78 deletions

View file

@ -63,9 +63,12 @@ ENTRY(return_to_fel)
1: wfi 1: wfi
b 1b 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. */ /* AArch32 code to restore the state from fel_stash and return back to FEL. */
back_in_32: 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 0xe5901008 // ldr r1, [r0, #8]
.word 0xe129f001 // msr CPSR_fc, r1 .word 0xe129f001 // msr CPSR_fc, r1
.word 0xf57ff06f // isb .word 0xf57ff06f // isb
@ -77,6 +80,4 @@ back_in_32:
.word 0xee011f10 // mcr 15, 0, r1, cr1, cr0, {0} ; SCTLR .word 0xee011f10 // mcr 15, 0, r1, cr1, cr0, {0} ; SCTLR
.word 0xf57ff06f // isb .word 0xf57ff06f // isb
.word 0xe12fff1e // bx lr ; return to FEL .word 0xe12fff1e // bx lr ; return to FEL
fel_stash_addr:
.word 0x00000000 // receives fel_stash addr, by AA64 code above
ENDPROC(return_to_fel) ENDPROC(return_to_fel)

View file

@ -16,10 +16,11 @@
*/ */
tst x0, x0 // this is "b #0x84" in ARM tst x0, x0 // this is "b #0x84" in ARM
b reset b reset
.space 0x7c .space 0x78
.word fel_stash - .
.word 0xe28f0070 // add r0, pc, #112 // @(fel_stash - .) .word 0xe24f000c // sub r0, pc, #12 // @(fel_stash - .)
.word 0xe59f106c // ldr r1, [pc, #108] // fel_stash - . .word 0xe51f1010 // ldr r1, [pc, #-16] // fel_stash - .
.word 0xe0800001 // add r0, r0, r1 .word 0xe0800001 // add r0, r0, r1
.word 0xe580d000 // str sp, [r0] .word 0xe580d000 // str sp, [r0]
.word 0xe580e004 // str lr, [r0, #4] .word 0xe580e004 // str lr, [r0, #4]
@ -54,7 +55,6 @@
#else #else
.word CONFIG_TEXT_BASE .word CONFIG_TEXT_BASE
#endif #endif
.word fel_stash - .
#else #else
/* normal execution */ /* normal execution */
b reset b reset

View file

@ -457,6 +457,9 @@ config MACH_SUN50I_H616
select SUN50I_GEN_H6 select SUN50I_GEN_H6
imply OF_UPSTREAM imply OF_UPSTREAM
config MACH_SUN50I_A133
bool "sun50i (Allwinner A133)"
endchoice endchoice
# The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33" # 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 config SYS_CLK_FREQ
default 408000000 if MACH_SUNIV 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 816000000 if MACH_SUN50I || MACH_SUN50I_H5
default 1008000000 if MACH_SUN8I
default 1008000000 if MACH_SUN9I
default 888000000 if MACH_SUN50I_H6 default 888000000 if MACH_SUN50I_H6
default 1008000000 if MACH_SUN50I_H616 default 912000000 if MACH_SUN7I
default 1008000000 if MACH_SUN8I_R528 default 1008000000
config SYS_CONFIG_NAME config SYS_CONFIG_NAME
default "suniv" if MACH_SUNIV 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 The used address is "bdaddr" if set, and "ethaddr" with the LSB
flipped elsewise. flipped elsewise.
source "board/sunxi/Kconfig"
endif
config CHIP_DIP_SCAN config CHIP_DIP_SCAN
bool "Enable DIPs detection for CHIP board" bool "Enable DIPs detection for CHIP board"
select SUPPORT_EXTENSION_SCAN select SUPPORT_EXTENSION_SCAN
@ -1143,3 +1136,7 @@ config CHIP_DIP_SCAN
select W1_EEPROM select W1_EEPROM
select W1_EEPROM_DS24XXX select W1_EEPROM_DS24XXX
select CMD_EXTENSION select CMD_EXTENSION
source "board/sunxi/Kconfig"
endif

View file

@ -147,15 +147,20 @@ unsigned int clock_get_pll6(void)
if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) { if (IS_ENABLED(CONFIG_SUNXI_GEN_NCAT2)) {
div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >> div1 = ((rval & CCM_PLL6_CTRL_P0_MASK) >>
CCM_PLL6_CTRL_P0_SHIFT) + 1; CCM_PLL6_CTRL_P0_SHIFT) + 1;
m = 1;
} else { } else {
div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >> div1 = ((rval & CCM_PLL6_CTRL_DIV1_MASK) >>
CCM_PLL6_CTRL_DIV1_SHIFT) + 1; 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; return 24000000U * n / m / div1 / div2;
} }

View file

@ -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"); 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, static void mctl_auto_detect_dram_size(const struct dram_para *para,
struct dram_config *config) struct dram_config *config)
{ {
unsigned int shift; unsigned int shift, cols, rows;
u32 buffer[16];
/* max. config for columns, but not rows */ /* max. config for columns, but not rows */
config->cols = 11; config->cols = 11;
config->rows = 13; config->rows = 13;
mctl_core_init(para, config); 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; shift = config->bus_full_width + 1;
/* detect column address bits */ /* detect column address bits */
for (config->cols = 8; config->cols < 11; config->cols++) { for (cols = 8; cols < 11; cols++) {
if (mctl_mem_matches(1ULL << (config->cols + shift))) if (mctl_check_pattern(1ULL << (cols + shift)))
break; 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 */ /* reconfigure to make sure that all active rows are accessible */
config->rows = 18; config->cols = 8;
config->rows = 17;
mctl_core_init(para, config); 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 */ /* detect row address bits */
shift = config->bus_full_width + 4 + config->cols; shift = config->bus_full_width + 4 + config->cols;
for (config->rows = 13; config->rows < 18; config->rows++) { for (rows = 13; rows < 17; rows++) {
if (mctl_mem_matches(1ULL << (config->rows + shift))) if (mctl_check_pattern(1ULL << (rows + shift)))
break; 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) static unsigned long mctl_calc_size(const struct dram_config *config)

View file

@ -16,33 +16,10 @@
#include <power/pmic.h> #include <power/pmic.h>
#include <asm/arch/pmic_bus.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 #define AXP221_CHIP_ADDR 0x68
#if CONFIG_IS_ENABLED(PMIC_AXP) #if CONFIG_IS_ENABLED(PMIC_AXP)
static struct udevice *pmic; 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 #endif
int pmic_bus_init(void) 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)) if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
return rsb_read(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); 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 #endif
} }
@ -102,7 +79,7 @@ int pmic_bus_write(u8 reg, u8 data)
if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB)) if (IS_ENABLED(CONFIG_SYS_I2C_SUN8I_RSB))
return rsb_write(AXP_PMIC_PRI_RUNTIME_ADDR, reg, data); 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 #endif
} }

View file

@ -16,7 +16,9 @@
@ the machine code must be inserted as verbatim .word statements into the @ the machine code must be inserted as verbatim .word statements into the
@ beginning of the AArch64 U-Boot code. @ beginning of the AArch64 U-Boot code.
@ To get the encoded bytes, use: @ 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 @ ${CROSS_COMPILE}objdump -d rmr_switch.o
@ @
@ The resulting words should be inserted into the U-Boot file at @ The resulting words should be inserted into the U-Boot file at
@ -29,14 +31,40 @@
#include <config.h> #include <config.h>
.text .text
b start32 // this is "tst x0, x0" in AArch64
.word 0x14000047 // this is "b reset" in AArch64
#ifndef CONFIG_SUN50I_GEN_H6 .space 0x78 // gap distance set by the common
ldr r1, =0x017000a0 @ MMIO mapped RVBAR[0] register // 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 #else
ldr r1, =0x09010040 @ MMIO mapped RVBAR[0] register ldr r0, =CONFIG_TEXT_BASE
#endif #endif
ldr r0, =0x57aA7add @ start address, to be replaced str r0, [r1] // store start address in RVBAR
str r0, [r1]
dsb sy dsb sy
isb sy isb sy
mrc 15, 0, r0, cr12, cr0, 2 @ read RMR register mrc 15, 0, r0, cr12, cr0, 2 @ read RMR register

View file

@ -563,7 +563,8 @@ void sunxi_board_init(void)
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \ #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \ defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_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(); power_failed = axp_init();
if (IS_ENABLED(CONFIG_AXP_DISABLE_BOOT_ON_POWERON) && !power_failed) { if (IS_ENABLED(CONFIG_AXP_DISABLE_BOOT_ON_POWERON) && !power_failed) {
@ -581,6 +582,8 @@ void sunxi_board_init(void)
#endif #endif
#ifdef CONFIG_AXP_DCDC2_VOLT #ifdef CONFIG_AXP_DCDC2_VOLT
power_failed |= axp_set_dcdc2(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); power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
#endif #endif
#ifdef CONFIG_AXP_DCDC4_VOLT #ifdef CONFIG_AXP_DCDC4_VOLT

View file

@ -80,11 +80,10 @@ config SPL_MAX_SIZE
default 0x1b000 if AM33XX && !TI_SECURE_DEVICE default 0x1b000 if AM33XX && !TI_SECURE_DEVICE
default 0xec00 if OMAP34XX default 0xec00 if OMAP34XX
default 0x10000 if ARCH_MX6 && !MX6_OCRAM_256KB 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 0xbfa0 if MACH_SUN50I_H616
default 0x7000 if RCAR_GEN3 default 0x7000 if RCAR_GEN3
default 0x5fa0 if SUNXI_SRAM_ADDRESS = 0x0 default 0x5fa0 if SUNXI_SRAM_ADDRESS = 0x0
default 0x7fa0 if ARCH_SUNXI
default 0x10000 if ASPEED_AST2600 default 0x10000 if ASPEED_AST2600
default 0x27000 if IMX8MM && SPL_TEXT_BASE = 0x7E1000 default 0x27000 if IMX8MM && SPL_TEXT_BASE = 0x7E1000
default 0x30000 if ARCH_SC5XX && (SC59X_64 || SC59X) default 0x30000 if ARCH_SC5XX && (SC59X_64 || SC59X)

View file

@ -122,4 +122,11 @@ config CLK_SUN50I_A64
This enables common clock driver support for platforms based This enables common clock driver support for platforms based
on Allwinner A64 SoC. 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 endif # CLK_SUNXI

View file

@ -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_H6_R) += clk_h6_r.o
obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o obj-$(CONFIG_CLK_SUN50I_H616) += clk_h616.o
obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
obj-$(CONFIG_CLK_SUN50I_A100) += clk_a100.o

View file

@ -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),
};

View file

@ -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 h3_ccu_desc;
extern const struct ccu_desc h6_ccu_desc; extern const struct ccu_desc h6_ccu_desc;
extern const struct ccu_desc h616_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 h6_r_ccu_desc;
extern const struct ccu_desc r40_ccu_desc; extern const struct ccu_desc r40_ccu_desc;
extern const struct ccu_desc v3s_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", { .compatible = "allwinner,sun50i-h616-r-ccu",
.data = (ulong)&h6_r_ccu_desc }, .data = (ulong)&h6_r_ccu_desc },
#endif #endif
#ifdef CONFIG_CLK_SUN50I_A100
{ .compatible = "allwinner,sun50i-a100-ccu",
.data = (ulong)&a100_ccu_desc },
#endif
#ifdef CONFIG_CLK_SUNIV_F1C100S #ifdef CONFIG_CLK_SUNIV_F1C100S
{ .compatible = "allwinner,suniv-f1c100s-ccu", { .compatible = "allwinner,suniv-f1c100s-ccu",
.data = (ulong)&f1c100s_ccu_desc }, .data = (ulong)&f1c100s_ccu_desc },

View file

@ -92,6 +92,13 @@ static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
pll = CCM_MMC_CTRL_PLL6; pll = CCM_MMC_CTRL_PLL6;
pll_hz = clock_get_pll6(); pll_hz = clock_get_pll6();
#endif #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; div = pll_hz / hz;
@ -442,6 +449,26 @@ out:
return error; 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 */ /* non-DM code here is used by the (ARM) SPL only */
#if !CONFIG_IS_ENABLED(DM_MMC) #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; struct sunxi_mmc_priv *priv = mmc->priv;
/* Reset controller */ sunxi_mmc_reset(priv->reg);
writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
udelay(1000);
return 0; return 0;
} }
@ -684,9 +709,7 @@ static int sunxi_mmc_probe(struct udevice *dev)
upriv->mmc = &plat->mmc; upriv->mmc = &plat->mmc;
/* Reset controller */ sunxi_mmc_reset(priv->reg);
writel(SUNXI_MMC_GCTRL_RESET, &priv->reg->gctrl);
udelay(1000);
return 0; return 0;
} }

View file

@ -37,7 +37,9 @@ struct sunxi_mmc {
u32 res0; /* 0x54 reserved */ u32 res0; /* 0x54 reserved */
u32 a12a; /* 0x58 Auto command 12 argument */ u32 a12a; /* 0x58 Auto command 12 argument */
u32 ntsr; /* 0x5c New timing set register */ 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 dmac; /* 0x80 internal DMA control */
u32 dlba; /* 0x84 internal DMA descr list base address */ u32 dlba; /* 0x84 internal DMA descr list base address */
u32 idst; /* 0x88 internal DMA status */ u32 idst; /* 0x88 internal DMA status */
@ -46,7 +48,8 @@ struct sunxi_mmc {
u32 cbda; /* 0x94 */ u32 cbda; /* 0x94 */
u32 res2[26]; u32 res2[26];
#if defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6) || defined(CONFIG_SUNXI_GEN_NCAT2) #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 samp_dl;
u32 res4[46]; u32 res4[46];
#endif #endif
@ -57,6 +60,7 @@ struct sunxi_mmc {
#define SUNXI_MMC_CLK_ENABLE (0x1 << 16) #define SUNXI_MMC_CLK_ENABLE (0x1 << 16)
#define SUNXI_MMC_CLK_DIVIDER_MASK (0xff) #define SUNXI_MMC_CLK_DIVIDER_MASK (0xff)
#define SUNXI_MMC_GCTRL 0x000
#define SUNXI_MMC_GCTRL_SOFT_RESET (0x1 << 0) #define SUNXI_MMC_GCTRL_SOFT_RESET (0x1 << 0)
#define SUNXI_MMC_GCTRL_FIFO_RESET (0x1 << 1) #define SUNXI_MMC_GCTRL_FIFO_RESET (0x1 << 1)
#define SUNXI_MMC_GCTRL_DMA_RESET (0x1 << 2) #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_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_RESET (0x1 << 0)
#define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1) #define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1)
#define SUNXI_MMC_IDMAC_ENABLE (0x1 << 7) #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_CLK_GATE (1 << 16)
#define SUNXI_MMC_COMMON_RESET (1 << 18) #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) #define SUNXI_MMC_CAL_DL_SW_EN (0x1 << 7)
#endif /* _SUNXI_MMC_H */ #endif /* _SUNXI_MMC_H */

View file

@ -124,6 +124,16 @@ config PINCTRL_SUN50I_H616_R
default MACH_SUN50I_H616 default MACH_SUN50I_H616
select PINCTRL_SUNXI 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 config PINCTRL_SUN20I_D1
bool "Support for the Allwinner D1/R528 PIO" bool "Support for the Allwinner D1/R528 PIO"
default MACH_SUN8I_R528 default MACH_SUN8I_R528

View file

@ -774,6 +774,41 @@ static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc
.num_banks = 1, .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[] = { static const struct udevice_id sunxi_pinctrl_ids[] = {
#ifdef CONFIG_PINCTRL_SUNIV_F1C100S #ifdef CONFIG_PINCTRL_SUNIV_F1C100S
{ {
@ -936,6 +971,18 @@ static const struct udevice_id sunxi_pinctrl_ids[] = {
.compatible = "allwinner,sun50i-h616-r-pinctrl", .compatible = "allwinner,sun50i-h616-r-pinctrl",
.data = (ulong)&sun50i_h616_r_pinctrl_desc, .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 #endif
{} {}
}; };

View file

@ -116,6 +116,12 @@ config AXP717_POWER
---help--- ---help---
Select this to enable support for the AXP717 PMIC found on some boards. 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 config AXP809_POWER
bool "axp809 pmic support" bool "axp809 pmic support"
depends on MACH_SUN9I depends on MACH_SUN9I
@ -142,10 +148,20 @@ config SY8106A_POWER
endchoice 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 config AXP_DCDC1_VOLT
int "axp pmic dcdc1 voltage" int "axp pmic dcdc1 voltage"
depends on AXP221_POWER || AXP809_POWER || AXP818_POWER depends on AXP221_POWER || AXP809_POWER || AXP818_POWER || AXP803_POWER
default 3300 if AXP818_POWER || MACH_SUN8I_R40 default 3300 if AXP818_POWER || MACH_SUN8I_R40 || AXP803_POWER
default 3000 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I default 3000 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
---help--- ---help---
Set the voltage (mV) to program the axp pmic dcdc1 at, set to 0 to 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 config AXP_DCDC2_VOLT
int "axp pmic dcdc2 voltage" 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 900 if AXP818_POWER
default 1400 if AXP152_POWER || AXP209_POWER default 1400 if AXP152_POWER || AXP209_POWER
default 1000 if AXP313_POWER default 1000 if AXP313_POWER
default 1000 if AXP717_POWER default 1000 if AXP717_POWER
default 1000 if AXP803_POWER
default 1200 if MACH_SUN6I default 1200 if MACH_SUN6I
default 1100 if MACH_SUN8I default 1100 if MACH_SUN8I
default 0 if MACH_SUN9I default 0 if MACH_SUN9I
@ -219,7 +236,7 @@ config AXP_DCDC4_VOLT
config AXP_DCDC5_VOLT config AXP_DCDC5_VOLT
int "axp pmic dcdc5 voltage" 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 default 1500 if MACH_SUN6I || MACH_SUN8I || MACH_SUN9I
---help--- ---help---
Set the voltage (mV) to program the axp pmic dcdc5 at, set to 0 to Set the voltage (mV) to program the axp pmic dcdc5 at, set to 0 to

View file

@ -17,6 +17,7 @@ obj-$(CONFIG_AXP313_POWER) += axp_spl.o
obj-$(CONFIG_AXP717_POWER) += axp_spl.o obj-$(CONFIG_AXP717_POWER) += axp_spl.o
obj-$(CONFIG_AXP809_POWER) += axp809.o obj-$(CONFIG_AXP809_POWER) += axp809.o
obj-$(CONFIG_AXP818_POWER) += axp818.o obj-$(CONFIG_AXP818_POWER) += axp818.o
obj-$(CONFIG_AXP803_POWER) += axp_spl.o
endif endif
obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o obj-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
obj-$(CONFIG_SY8106A_POWER) += sy8106a.o obj-$(CONFIG_SY8106A_POWER) += sy8106a.o

View file

@ -36,6 +36,23 @@ static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {
#define AXP_SHUTDOWN_REG 0x27 #define AXP_SHUTDOWN_REG 0x27
#define AXP_SHUTDOWN_MASK BIT(0) #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 */ #elif defined(CONFIG_AXP313_POWER) /* AXP313 */
static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = { static const struct axp_reg_desc_spl axp_spl_dcdc_regulators[] = {