Commit d0f2fbb8 authored by Icenowy Zheng's avatar Icenowy Zheng Committed by Andre Przywara
Browse files

uart0-helloworld-sdboot: add support for H6



Allwinner H6 SoC has a totally different memory map and different clock
control unit with other SoCs.

Add support for it in uart0-helloworld-sdboot.

To avoid writing blindly into the device MMIO area first (for triggering
the SRAM version register), we query the known content of some GIC register
to verify we are looking at an H6 memory map.
Signed-off-by: default avatarIcenowy Zheng <icenowy@aosc.io>
Signed-off-by: default avatarAndre Przywara <osp@andrep.de>
parent 4acf2a92
......@@ -61,6 +61,11 @@ typedef unsigned int u32;
#define AW_CCM_BASE 0x01c20000
#define AW_SRAMCTRL_BASE 0x01c00000
#define H6_UART0_BASE 0x05000000
#define H6_PIO_BASE 0x0300B000
#define H6_CCM_BASE 0x03001000
#define H6_SRAMCTRL_BASE 0x03000000
/*****************************************************************************
* GPIO code, borrowed from U-Boot *
*****************************************************************************/
......@@ -140,6 +145,7 @@ enum sunxi_gpio_number {
#define SUN8I_H3_GPA_UART0 (2)
#define SUN8I_V3S_GPB_UART0 (3)
#define SUN50I_H5_GPA_UART0 (2)
#define SUN50I_H6_GPH_UART0 (2)
#define SUN50I_A64_GPB_UART0 (4)
#define SUNXI_GPF_UART0 (4)
......@@ -230,9 +236,13 @@ int gpio_direction_output(unsigned gpio, int value)
* *
* Allwinner A10s and A13 are using the same SoC type id, but they can be *
* differentiated using a certain part of the SID register. *
* *
* Allwinner H6 has its memory map totally reworked, but the SRAM controller *
* remains similar; the base of it is moved to 0x03000000. *
*****************************************************************************/
#define VER_REG (AW_SRAMCTRL_BASE + 0x24)
#define H6_VER_REG (H6_SRAMCTRL_BASE + 0x24)
#define SUN4I_SID_BASE 0x01C23800
#define SUN8I_SID_BASE 0x01C14000
......@@ -268,8 +278,21 @@ void soc_detection_init(void)
if (((midr >> 4) & 0xFFF) == 0xC0F) {
soc_id = 0x1639; /* ARM Cortex-A15, so likely Allwinner A80 */
} else {
set_wbit(VER_REG, 1 << 15);
soc_id = readl(VER_REG) >> 16;
u32 reg;
/*
* This register is GICD_IIDR on H6, but unmapped according to
* other known SoCs' user manuals.
*/
reg = readl(0x03021008);
if ((reg & 0xfff) == 0x43b) /* Found GICv2 here, so it's a H6 */
reg = H6_VER_REG;
else
reg = VER_REG;
set_wbit(reg, 1 << 15);
soc_id = readl(reg) >> 16;
}
}
......@@ -281,6 +304,7 @@ void soc_detection_init(void)
#define soc_is_a80() (soc_id == 0x1639)
#define soc_is_a64() (soc_id == 0x1689)
#define soc_is_h5() (soc_id == 0x1718)
#define soc_is_h6() (soc_id == 0x1728)
#define soc_is_r40() (soc_id == 0x1701)
#define soc_is_v3s() (soc_id == 0x1681)
......@@ -336,7 +360,11 @@ int soc_is_h3(void)
#define APB2_GATE_UART_SHIFT (16)
#define APB2_RESET_UART_SHIFT (16)
void clock_init_uart(void)
#define H6_UART_GATE_RESET (H6_CCM_BASE + 0x90C)
#define H6_UART_GATE_SHIFT (0)
#define H6_UART_RESET_SHIFT (16)
void clock_init_uart_legacy(void)
{
/* Open the clock gate for UART0 */
set_wbit(APB2_GATE, 1 << (APB2_GATE_UART_SHIFT + CONFIG_CONS_INDEX - 1));
......@@ -344,6 +372,22 @@ void clock_init_uart(void)
set_wbit(APB2_RESET, 1 << (APB2_RESET_UART_SHIFT + CONFIG_CONS_INDEX - 1));
}
void clock_init_uart_h6(void)
{
/* Open the clock gate for UART0 */
set_wbit(H6_UART_GATE_RESET, 1 << (H6_UART_GATE_SHIFT + CONFIG_CONS_INDEX - 1));
/* Deassert UART0 reset */
set_wbit(H6_UART_GATE_RESET, 1 << (H6_UART_RESET_SHIFT + CONFIG_CONS_INDEX - 1));
}
void clock_init_uart(void)
{
if (soc_is_h6())
clock_init_uart_h6();
else
clock_init_uart_legacy();
}
/*****************************************************************************
* UART0 pins muxing is different for different SoC variants. *
* Allwinner A13 is a bit special, because there are no dedicated UART0 pins *
......@@ -384,6 +428,10 @@ void gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPA(4), SUN50I_H5_GPA_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPA(5), SUN50I_H5_GPA_UART0);
sunxi_gpio_set_pull(SUNXI_GPA(5), SUNXI_GPIO_PULL_UP);
} else if (soc_is_h6()) {
sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H6_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H6_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
} else if (soc_is_v3s()) {
sunxi_gpio_set_cfgpin(SUNXI_GPB(8), SUN8I_V3S_GPB_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_V3S_GPB_UART0);
......@@ -464,6 +512,8 @@ int get_boot_device(void)
u32 *spl_signature = (void *)0x4;
if (soc_is_a64() || soc_is_a80() || soc_is_h5())
spl_signature = (void *)0x10004;
if (soc_is_h6())
spl_signature = (void *)0x20004;
/* Check the eGON.BT0 magic in the SPL header */
if (spl_signature[0] != 0x4E4F4765 || spl_signature[1] != 0x3054422E)
......@@ -480,8 +530,13 @@ int get_boot_device(void)
void bases_init(void)
{
pio_base = SUNXI_PIO_BASE;
uart0_base = SUNXI_UART0_BASE;
if (soc_is_h6()) {
pio_base = H6_PIO_BASE;
uart0_base = H6_UART0_BASE;
} else {
pio_base = SUNXI_PIO_BASE;
uart0_base = SUNXI_UART0_BASE;
}
}
int main(void)
......@@ -510,6 +565,8 @@ int main(void)
uart0_puts("Allwinner H3!\n");
else if (soc_is_h5())
uart0_puts("Allwinner H5!\n");
else if (soc_is_h6())
uart0_puts("Allwinner H6!\n");
else if (soc_is_r40())
uart0_puts("Allwinner R40!\n");
else if (soc_is_v3s())
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment