From: Icenowy Zheng <icen...@aosc.io>

Add support for the suniv architecture, which is newer ARM9 SoCs by
Allwinner. The design of it seems to be a mixture of sun3i, sun4i and
sun6i.

Signed-off-by: Icenowy Zheng <icen...@aosc.io>
Signed-off-by: Jesse Taube <mr.bossman...@gmail.com>
---
V1->V2:
* Remove change in s_init (sunxi: remove lowlevel_init)
V2->V3:
* Covert to if(IS_ENABLED) from ifdef
* Remove busy loop
* Remove depends on for SPL_SPI_SUNXI
---
 arch/arm/mach-sunxi/Kconfig       | 14 ++++-
 arch/arm/mach-sunxi/board.c       | 28 +++++++++-
 arch/arm/mach-sunxi/clock.c       |  3 +-
 arch/arm/mach-sunxi/clock_sun6i.c | 89 +++++++++++++++++++++----------
 arch/arm/mach-sunxi/cpu_info.c    |  2 +
 5 files changed, 104 insertions(+), 32 deletions(-)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 4e49ad4f0c..11f295033f 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -1,7 +1,8 @@
 if ARCH_SUNXI
 
 config SPL_LDSCRIPT
-       default "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds" if !ARM64
+       default "arch/arm/cpu/arm926ejs/sunxi/u-boot-spl.lds" if MACH_SUNIV
+       default "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds" if !ARM64 && 
!MACH_SUNIV
 
 config IDENT_STRING
        default " Allwinner Technology"
@@ -183,6 +184,12 @@ choice
        prompt "Sunxi SoC Variant"
        optional
 
+config MACH_SUNIV
+       bool "suniv (Allwinner F1C100s/F1C200s/F1C600/R6)"
+       select CPU_ARM926EJS
+       select SUNXI_GEN_SUN6I
+       select SUPPORT_SPL
+
 config MACH_SUN4I
        bool "sun4i (Allwinner A10)"
        select CPU_V7A
@@ -585,6 +592,7 @@ config DRAM_ODT_CORRECTION
 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
@@ -596,6 +604,7 @@ config SYS_CLK_FREQ
        default 1008000000 if MACH_SUN50I_H616
 
 config SYS_CONFIG_NAME
+       default "suniv" if MACH_SUNIV
        default "sun4i" if MACH_SUN4I
        default "sun5i" if MACH_SUN5I
        default "sun6i" if MACH_SUN6I
@@ -803,7 +812,7 @@ config VIDEO_SUNXI
 
 config VIDEO_HDMI
        bool "HDMI output support"
-       depends on VIDEO_SUNXI && !MACH_SUN8I
+       depends on VIDEO_SUNXI && !MACH_SUN8I && !MACH_SUNIV
        default y
        ---help---
        Say Y here to add support for outputting video over HDMI.
@@ -1003,6 +1012,7 @@ config GMAC_TX_DELAY
        Set the GMAC Transmit Clock Delay Chain value.
 
 config SPL_STACK_R_ADDR
+       default 0x81e00000 if MACH_SUNIV
        default 0x4fe00000 if MACH_SUN4I
        default 0x4fe00000 if MACH_SUN5I
        default 0x4fe00000 if MACH_SUN6I
diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c
index a60dc6b299..2aa30c62c5 100644
--- a/arch/arm/mach-sunxi/board.c
+++ b/arch/arm/mach-sunxi/board.c
@@ -87,7 +87,8 @@ static int gpio_init(void)
        sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUNXI_GPIO_INPUT);
        sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUNXI_GPIO_INPUT);
 #endif
-#if defined(CONFIG_MACH_SUN8I) && !defined(CONFIG_MACH_SUN8I_R40)
+#if (defined(CONFIG_MACH_SUN8I) && !defined(CONFIG_MACH_SUN8I_R40)) || \
+    defined(CONFIG_MACH_SUNIV)
        sunxi_gpio_set_cfgpin(SUNXI_GPF(2), SUN8I_GPF_UART0);
        sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUN8I_GPF_UART0);
 #else
@@ -95,6 +96,10 @@ static int gpio_init(void)
        sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUNXI_GPF_UART0);
 #endif
        sunxi_gpio_set_pull(SUNXI_GPF(4), 1);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUNIV)
+       sunxi_gpio_set_cfgpin(SUNXI_GPE(0), SUNIV_GPE_UART0);
+       sunxi_gpio_set_cfgpin(SUNXI_GPE(1), SUNIV_GPE_UART0);
+       sunxi_gpio_set_pull(SUNXI_GPE(1), SUNXI_GPIO_PULL_UP);
 #elif CONFIG_CONS_INDEX == 1 && (defined(CONFIG_MACH_SUN4I) || \
                                 defined(CONFIG_MACH_SUN7I) || \
                                 defined(CONFIG_MACH_SUN8I_R40))
@@ -271,10 +276,31 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc 
*mmc,
        return sector;
 }
 
+#ifndef CONFIG_MACH_SUNIV
 u32 spl_boot_device(void)
 {
        return sunxi_get_boot_device();
 }
+#else
+/*
+ * suniv BROM do not pass the boot media type to SPL, so we try with the
+ * boot sequence in BROM: mmc0->spinor->fail.
+ */
+void board_boot_order(u32 *spl_boot_list)
+{
+       /*
+        * See the comments above in sunxi_get_boot_device() for information
+        * about FEL boot.
+        */
+       if (!is_boot0_magic(SPL_ADDR + 4)) {
+               spl_boot_list[0] = BOOT_DEVICE_BOARD;
+               return;
+       }
+
+       spl_boot_list[0] = BOOT_DEVICE_MMC1;
+       spl_boot_list[1] = BOOT_DEVICE_SPI;
+}
+#endif
 
 __weak void sunxi_sram_init(void)
 {
diff --git a/arch/arm/mach-sunxi/clock.c b/arch/arm/mach-sunxi/clock.c
index de7e875298..da3a0eb058 100644
--- a/arch/arm/mach-sunxi/clock.c
+++ b/arch/arm/mach-sunxi/clock.c
@@ -35,7 +35,8 @@ int clock_init(void)
 }
 
 /* These functions are shared between various SoCs so put them here. */
-#if defined CONFIG_SUNXI_GEN_SUN6I && !defined CONFIG_MACH_SUN9I
+#if defined CONFIG_SUNXI_GEN_SUN6I && !defined CONFIG_MACH_SUN9I && \
+       !defined CONFIG_MACH_SUNIV
 int clock_twi_onoff(int port, int state)
 {
        struct sunxi_ccm_reg *const ccm =
diff --git a/arch/arm/mach-sunxi/clock_sun6i.c 
b/arch/arm/mach-sunxi/clock_sun6i.c
index 8e84062bd7..56681fb2b6 100644
--- a/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/arch/arm/mach-sunxi/clock_sun6i.c
@@ -23,7 +23,8 @@ void clock_init_safe(void)
        struct sunxi_ccm_reg * const ccm =
                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
-#if !defined(CONFIG_MACH_SUNXI_H3_H5) && !defined(CONFIG_MACH_SUN50I)
+#if !defined(CONFIG_MACH_SUNXI_H3_H5) && !defined(CONFIG_MACH_SUN50I) && \
+       !defined(CONFIG_MACH_SUNIV)
        struct sunxi_prcm_reg * const prcm =
                (struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
 
@@ -49,9 +50,11 @@ void clock_init_safe(void)
 
        writel(AHB1_ABP1_DIV_DEFAULT, &ccm->ahb1_apb1_div);
 
-       writel(MBUS_CLK_DEFAULT, &ccm->mbus0_clk_cfg);
-       if (IS_ENABLED(CONFIG_MACH_SUN6I))
-               writel(MBUS_CLK_DEFAULT, &ccm->mbus1_clk_cfg);
+       if (!IS_ENABLED(CONFIG_MACH_SUNIV)) {
+               writel(MBUS_CLK_DEFAULT, &ccm->mbus0_clk_cfg);
+               if (IS_ENABLED(CONFIG_MACH_SUN6I))
+                       writel(MBUS_CLK_DEFAULT, &ccm->mbus1_clk_cfg);
+       }
 
 #if defined(CONFIG_MACH_SUN8I_R40) && defined(CONFIG_SUNXI_AHCI)
        setbits_le32(&ccm->sata_pll_cfg, CCM_SATA_PLL_DEFAULT);
@@ -87,21 +90,38 @@ void clock_init_uart(void)
        struct sunxi_ccm_reg *const ccm =
                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
-       /* uart clock source is apb2 */
-       writel(APB2_CLK_SRC_OSC24M|
-              APB2_CLK_RATE_N_1|
-              APB2_CLK_RATE_M(1),
-              &ccm->apb2_div);
-
-       /* open the clock for uart */
-       setbits_le32(&ccm->apb2_gate,
-                    CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT +
-                                      CONFIG_CONS_INDEX - 1));
-
-       /* deassert uart reset */
-       setbits_le32(&ccm->apb2_reset_cfg,
-                    1 << (APB2_RESET_UART_SHIFT +
-                          CONFIG_CONS_INDEX - 1));
+       if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
+               /* suniv doesn't have apb2, so uart clock source is apb1 */
+               writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg);
+               while (!(readl(&ccm->pll6_cfg) & CCM_PLL6_CTRL_LOCK))
+                       ;
+
+               /* open the clock for uart */
+               setbits_le32(&ccm->apb1_gate,
+                            CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT +
+                                              CONFIG_CONS_INDEX - 1));
+
+               /* deassert uart reset */
+               setbits_le32(&ccm->apb1_reset_cfg,
+                            1 << (APB1_RESET_UART_SHIFT +
+                                  CONFIG_CONS_INDEX - 1));
+       } else {
+               /* uart clock source is apb2 */
+               writel(APB2_CLK_SRC_OSC24M|
+                      APB2_CLK_RATE_N_1|
+                      APB2_CLK_RATE_M(1),
+                      &ccm->apb2_div);
+
+               /* open the clock for uart */
+               setbits_le32(&ccm->apb2_gate,
+                            CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT +
+                                              CONFIG_CONS_INDEX - 1));
+
+               /* deassert uart reset */
+               setbits_le32(&ccm->apb2_reset_cfg,
+                            1 << (APB2_RESET_UART_SHIFT +
+                                  CONFIG_CONS_INDEX - 1));
+       }
 #else
        /* enable R_PIO and R_UART clocks, and de-assert resets */
        prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_UART);
@@ -125,10 +145,15 @@ void clock_set_pll1(unsigned int clk)
        }
 
        /* Switch to 24MHz clock while changing PLL1 */
-       writel(AXI_DIV_3 << AXI_DIV_SHIFT |
-              ATB_DIV_2 << ATB_DIV_SHIFT |
-              CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
-              &ccm->cpu_axi_cfg);
+       if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
+               writel(CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
+                      &ccm->cpu_axi_cfg);
+       } else {
+               writel(AXI_DIV_3 << AXI_DIV_SHIFT |
+                      ATB_DIV_2 << ATB_DIV_SHIFT |
+                      CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
+                      &ccm->cpu_axi_cfg);
+       }
 
        /*
         * sun6i: PLL1 rate = ((24000000 * n * k) >> 0) / m   (p is ignored)
@@ -140,10 +165,15 @@ void clock_set_pll1(unsigned int clk)
        sdelay(200);
 
        /* Switch CPU to PLL1 */
-       writel(AXI_DIV_3 << AXI_DIV_SHIFT |
-              ATB_DIV_2 << ATB_DIV_SHIFT |
-              CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
-              &ccm->cpu_axi_cfg);
+       if (IS_ENABLED(CONFIG_MACH_SUNIV)) {
+               writel(CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
+                      &ccm->cpu_axi_cfg);
+       } else {
+               writel(AXI_DIV_3 << AXI_DIV_SHIFT |
+                      ATB_DIV_2 << ATB_DIV_SHIFT |
+                      CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
+                      &ccm->cpu_axi_cfg);
+       }
 }
 #endif
 
@@ -317,7 +347,10 @@ unsigned int clock_get_pll6(void)
        uint32_t rval = readl(&ccm->pll6_cfg);
        int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
        int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1;
-       return 24000000 * n * k / 2;
+       if (IS_ENABLED(CONFIG_MACH_SUNIV))
+               return 24000000 * n * k;
+       else
+               return 24000000 * n * k / 2;
 }
 
 unsigned int clock_get_mipi_pll(void)
diff --git a/arch/arm/mach-sunxi/cpu_info.c b/arch/arm/mach-sunxi/cpu_info.c
index ba33ef2430..7eef178859 100644
--- a/arch/arm/mach-sunxi/cpu_info.c
+++ b/arch/arm/mach-sunxi/cpu_info.c
@@ -57,6 +57,8 @@ int print_cpuinfo(void)
 {
 #ifdef CONFIG_MACH_SUN4I
        puts("CPU:   Allwinner A10 (SUN4I)\n");
+#elif defined CONFIG_MACH_SUNIV
+       puts("CPU:   Allwinner F Series (SUNIV)\n");
 #elif defined CONFIG_MACH_SUN5I
        u32 val = readl(SUNXI_SID_BASE + 0x08);
        switch ((val >> 12) & 0xf) {
-- 
2.34.1

Reply via email to