diff --git a/uart0-helloworld-sdboot.c b/uart0-helloworld-sdboot.c index 875e139..2c509cf 100644 --- a/uart0-helloworld-sdboot.c +++ b/uart0-helloworld-sdboot.c @@ -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())