From 46a8f2ae6e3d4c0b0ae090c6751fadcf133bebf0 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 23 Aug 2024 20:13:35 +0100 Subject: [PATCH] uart0-helloworld-sdboot: add clock data to the SoC table To make the UART work, we have to open the clock gate and de-assert the reset for the UART0 peripheral. This is currently done by calling one of four functions, even though there are actually only two different ways: - Older SoCs need to set a bit in the APB1/2 bus clock register, and the same bit in the respective reset register. - Newer SoCs combines both the clock and the reset gate in one register, so it's only one write, setting two bits. Add a flag to the table to choose between the two methods for each SoC. The offsets for these clock registers are very stable, but the CCU base address changed a bit over time, so split this up and put the base address separately into the table. For the latest SoCs, the "new" clock structure is combined with an updated GPIO IP, and the Allwinner BSP calls this SoC generation "NCAT2". Add a symbolic name for this already, so we can mark those SoCs now, and add the respective GPIO flag later when this gets added. Signed-off-by: Andre Przywara --- uart0-helloworld-sdboot.c | 145 +++++++++++++++----------------------- 1 file changed, 55 insertions(+), 90 deletions(-) diff --git a/uart0-helloworld-sdboot.c b/uart0-helloworld-sdboot.c index caf6a90..78fd33e 100644 --- a/uart0-helloworld-sdboot.c +++ b/uart0-helloworld-sdboot.c @@ -170,55 +170,60 @@ enum sunxi_gpio_number { #define BIT(x) (1U << (x)) #define FLAG_VAR0 0 #define FLAG_VAR1 BIT(0) +#define FLAG_NEW_CLOCK BIT(3) +#define FLAG_UART_ON_APB1 BIT(4) + +#define FLAG_NCAT2 FLAG_NEW_CLOCK static const struct soc_info { u16 soc_id; char soc_name[10]; + u32 ccu_base; u32 uart0_base; u8 flags; } soc_table[] = { - { 0x1623, "A10", + { 0x1623, "A10", AW_CCM_BASE, SUNXI_UART0_BASE, }, - { 0x1625, "A10s", + { 0x1625, "A10s", AW_CCM_BASE, SUNXI_UART0_BASE, FLAG_VAR0 }, - { 0x1625, "A13", + { 0x1625, "A13", AW_CCM_BASE, SUNXI_UART0_BASE, FLAG_VAR1 }, - { 0x1633, "A31/A31s", + { 0x1633, "A31/A31s", AW_CCM_BASE, SUNXI_UART0_BASE, }, - { 0x1651, "A20", + { 0x1651, "A20", AW_CCM_BASE, SUNXI_UART0_BASE, }, - { 0x1663, "F1C100s", - SUNIV_UART0_BASE, }, - { 0x1689, "A64", + { 0x1663, "F1C100s", AW_CCM_BASE, + SUNIV_UART0_BASE, FLAG_UART_ON_APB1 }, + { 0x1689, "A64", AW_CCM_BASE, SUNXI_UART0_BASE, }, - { 0x1680, "H2+", + { 0x1680, "H2+", AW_CCM_BASE, SUNXI_UART0_BASE, FLAG_VAR1 }, - { 0x1680, "H3", + { 0x1680, "H3", AW_CCM_BASE, SUNXI_UART0_BASE, FLAG_VAR0 }, - { 0x1681, "V3s", + { 0x1681, "V3s", AW_CCM_BASE, SUNXI_UART0_BASE, }, - { 0x1701, "R40", + { 0x1701, "R40", AW_CCM_BASE, SUNXI_UART0_BASE, }, - { 0x1708, "T7", - H6_UART0_BASE, }, - { 0x1718, "H5", + { 0x1708, "T7", H6_CCM_BASE, + H6_UART0_BASE, FLAG_NEW_CLOCK }, + { 0x1718, "H5", AW_CCM_BASE, SUNXI_UART0_BASE, }, - { 0x1719, "A63", - H6_UART0_BASE, }, - { 0x1721, "V5", - H6_UART0_BASE, }, - { 0x1728, "H6", - H6_UART0_BASE, }, - { 0x1817, "V831", - H6_UART0_BASE, }, - { 0x1823, "H616", - H6_UART0_BASE, }, - { 0x1851, "R329", - R329_UART0_BASE, }, - { 0x1859, "R528", - R329_UART0_BASE, }, - { 0x1886, "V853", - R329_UART0_BASE, }, + { 0x1719, "A63", H6_CCM_BASE, + H6_UART0_BASE, FLAG_NEW_CLOCK }, + { 0x1721, "V5", H6_CCM_BASE, + H6_UART0_BASE, FLAG_NEW_CLOCK }, + { 0x1728, "H6", H6_CCM_BASE, + H6_UART0_BASE, FLAG_NEW_CLOCK }, + { 0x1817, "V831", H6_CCM_BASE, + H6_UART0_BASE, FLAG_NEW_CLOCK }, + { 0x1823, "H616", H6_CCM_BASE, + H6_UART0_BASE, FLAG_NEW_CLOCK }, + { 0x1851, "R329", R329_CCM_BASE, + R329_UART0_BASE, FLAG_NCAT2 }, + { 0x1859, "R528", R329_CCM_BASE, + R329_UART0_BASE, FLAG_NCAT2 }, + { 0x1886, "V853", R329_CCM_BASE, + R329_UART0_BASE, FLAG_NCAT2 }, }; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) @@ -476,67 +481,27 @@ int soc_is_h3(void) *****************************************************************************/ #define CONFIG_CONS_INDEX 1 -#define APB2_CFG (AW_CCM_BASE + 0x058) -#define APB1_GATE (AW_CCM_BASE + 0x068) -#define APB2_GATE (AW_CCM_BASE + 0x06C) -#define APB1_RESET (AW_CCM_BASE + 0x2D0) -#define APB2_RESET (AW_CCM_BASE + 0x2D8) -#define APB2_GATE_UART_SHIFT (16) -#define APB1_GATE_UART_SHIFT 20 -#define APB2_RESET_UART_SHIFT (16) -#define APB1_RESET_UART_SHIFT 20 -#define H6_UART_GATE_RESET (H6_CCM_BASE + 0x90C) -#define R329_UART_GATE_RESET (R329_CCM_BASE + 0x90C) -#define H6_UART_GATE_SHIFT (0) -#define H6_UART_RESET_SHIFT (16) - -void clock_init_uart_legacy(void) +static void clock_init_uart(const struct soc_info *soc) { - /* Open the clock gate for UART0 */ - set_wbit(APB2_GATE, 1 << (APB2_GATE_UART_SHIFT + CONFIG_CONS_INDEX - 1)); - /* Deassert UART0 reset (only needed on A31/A64/H3) */ - set_wbit(APB2_RESET, 1 << (APB2_RESET_UART_SHIFT + CONFIG_CONS_INDEX - 1)); -} + if (soc->flags & FLAG_NEW_CLOCK) { + set_wbit(soc->ccu_base + 0x90c, + 0x10001 << (CONFIG_CONS_INDEX - 1)); + } else { + int bit = 16 + CONFIG_CONS_INDEX - 1; + int gate_ofs = 0x06c; + int reset_ofs = 0x2d8; -void clock_init_uart_suniv(void) -{ - /* open the clock for uart */ - set_wbit(APB1_GATE, - 1U << (APB1_GATE_UART_SHIFT + CONFIG_CONS_INDEX - 1)); - - /* deassert uart reset */ - set_wbit(APB1_RESET, - 1U << (APB1_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_r329(void) -{ - /* Open the clock gate for UART0 */ - set_wbit(R329_UART_GATE_RESET, 1 << (H6_UART_GATE_SHIFT + CONFIG_CONS_INDEX - 1)); - /* Deassert UART0 reset */ - set_wbit(R329_UART_GATE_RESET, 1 << (H6_UART_RESET_SHIFT + CONFIG_CONS_INDEX - 1)); -} - -void clock_init_uart(void) -{ - if (soc_is_h6() || soc_is_v831() || soc_is_h616() || soc_is_v5() || - soc_is_a63() || soc_is_t7()) - clock_init_uart_h6(); - else if (soc_is_r329() || soc_is_v853() || soc_is_r528()) - clock_init_uart_r329(); - else if (soc_is_suniv()) - clock_init_uart_suniv(); - else - clock_init_uart_legacy(); + if (soc->flags & FLAG_UART_ON_APB1) { + bit = 20 + CONFIG_CONS_INDEX - 1; + gate_ofs = 0x068; + reset_ofs = 0x2d0; + } + /* Open the clock gate for UART0 */ + set_wbit(soc->ccu_base + gate_ofs, 1U << bit); + /* Deassert UART0 reset (not really needed on old SoCs) */ + set_wbit(soc->ccu_base + reset_ofs, 1U << bit); + } } /***************************************************************************** @@ -665,7 +630,7 @@ static u32 uart0_base; static void uart0_init(const struct soc_info *soc) { - clock_init_uart(); + clock_init_uart(soc); uart0_base = soc->uart0_base;