sunxi: Add sun4i support
authorHans de Goede <hdegoede@redhat.com>
Mon, 9 Jun 2014 09:36:57 +0000 (11:36 +0200)
committerIan Campbell <ijc@hellion.org.uk>
Sun, 6 Jul 2014 19:12:44 +0000 (20:12 +0100)
Add support for the Allwinner A10 SoC also known as the Allwinner sun4i family,
and add the Cubieboard board which uses the A10 SoC.

Compared to sun7 only the DRAM controller is a bit different:
-Controller reset bits are inverted, but only for Rev. A
-Different hpcr values
-No MBUS on sun4i
-Various other initialization changes

Signed-off-by: Henrik Nordstrom <henrik@henriknordstrom.net>
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Ian Campbell <ijc@hellion.org.uk>
arch/arm/cpu/armv7/sunxi/Makefile
arch/arm/cpu/armv7/sunxi/cpu_info.c
arch/arm/cpu/armv7/sunxi/dram.c
board/sunxi/Makefile
board/sunxi/dram_cubieboard.c [new file with mode: 0644]
boards.cfg
include/configs/sun4i.h [new file with mode: 0644]

index a64bfa1..856d353 100644 (file)
@@ -11,6 +11,7 @@ obj-y += timer.o
 obj-y  += board.o
 obj-y  += clock.o
 obj-y  += pinmux.o
+obj-$(CONFIG_SUN4I)    += clock_sun4i.o
 obj-$(CONFIG_SUN7I)    += clock_sun4i.o
 
 ifndef CONFIG_SPL_BUILD
@@ -18,6 +19,7 @@ obj-y += cpu_info.o
 endif
 
 ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SUN4I)    += dram.o
 obj-$(CONFIG_SUN7I)    += dram.o
 ifdef CONFIG_SPL_FEL
 obj-y  += start.o
index b4c3d5c..b4b5089 100644 (file)
 #ifdef CONFIG_DISPLAY_CPUINFO
 int print_cpuinfo(void)
 {
+#ifdef CONFIG_SUN4I
+       puts("CPU:   Allwinner A10 (SUN4I)\n");
+#elif defined CONFIG_SUN7I
        puts("CPU:   Allwinner A20 (SUN7I)\n");
+#else
+#warning Please update cpu_info.c with correct CPU information
+       puts("CPU:   SUNXI Family\n");
+#endif
        return 0;
 }
 #endif
index b43c4b4..1de7529 100644 (file)
@@ -53,16 +53,37 @@ static void mctl_ddr3_reset(void)
        struct sunxi_dram_reg *dram =
                        (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
 
-       clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
-       udelay(2);
-       setbits_le32(&dram->mcr, DRAM_MCR_RESET);
+#ifdef CONFIG_SUN4I
+       struct sunxi_timer_reg *timer =
+                       (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
+       u32 reg_val;
+
+       writel(0, &timer->cpu_cfg);
+       reg_val = readl(&timer->cpu_cfg);
+
+       if ((reg_val & CPU_CFG_CHIP_VER_MASK) !=
+           CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) {
+               setbits_le32(&dram->mcr, DRAM_MCR_RESET);
+               udelay(2);
+               clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
+       } else
+#endif
+       {
+               clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
+               udelay(2);
+               setbits_le32(&dram->mcr, DRAM_MCR_RESET);
+       }
 }
 
 static void mctl_set_drive(void)
 {
        struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
 
+#ifdef CONFIG_SUN7I
        clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
+#else
+       clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3),
+#endif
                        DRAM_MCR_MODE_EN(0x3) |
                        0xffc);
 }
@@ -134,6 +155,16 @@ static void mctl_enable_dllx(u32 phase)
 }
 
 static u32 hpcr_value[32] = {
+#ifdef CONFIG_SUN4I
+       0x0301, 0x0301, 0x0301, 0x0301,
+       0x0301, 0x0301, 0, 0,
+       0, 0, 0, 0,
+       0, 0, 0, 0,
+       0x1031, 0x1031, 0x0735, 0x5031,
+       0x1035, 0x0731, 0x1031, 0x0735,
+       0x1035, 0x1031, 0x0731, 0x1035,
+       0x1031, 0x0301, 0x0301, 0x0731
+#endif
 #ifdef CONFIG_SUN7I
        0x0301, 0x0301, 0x0301, 0x0301,
        0x0301, 0x0301, 0x0301, 0x0301,
@@ -223,22 +254,32 @@ static void mctl_setup_dram_clock(u32 clk)
        clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
 #endif
 
+#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
        /* setup MBUS clock */
        reg_val = CCM_MBUS_CTRL_GATE |
                  CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
                  CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) |
                  CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
        writel(reg_val, &ccm->mbus_clk_cfg);
+#endif
 
        /*
         * open DRAMC AHB & DLL register clock
         * close it first
         */
+#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
        clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
+#else
+       clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
+#endif
        udelay(22);
 
        /* then open it */
+#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
        setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
+#else
+       setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM);
+#endif
        udelay(22);
 }
 
@@ -385,6 +426,13 @@ static void dramc_clock_output_en(u32 on)
        else
                clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
 #endif
+#ifdef CONFIG_SUN4I
+       struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       if (on)
+               setbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
+       else
+               clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
+#endif
 }
 
 static const u16 tRFC_table[2][6] = {
@@ -421,11 +469,19 @@ unsigned long dramc_init(struct dram_para *para)
        mctl_setup_dram_clock(para->clock);
 
        /* reset external DRAM */
+#ifndef CONFIG_SUN7I
+       mctl_ddr3_reset();
+#endif
        mctl_set_drive();
 
        /* dram clock off */
        dramc_clock_output_en(0);
 
+#ifdef CONFIG_SUN4I
+       /* select dram controller 1 */
+       writel(DRAM_CSEL_MAGIC, &dram->csel);
+#endif
+
        mctl_itm_disable();
        mctl_enable_dll0(para->tpr3);
 
@@ -482,6 +538,9 @@ unsigned long dramc_init(struct dram_para *para)
                mctl_ddr3_reset();
        else
                setbits_le32(&dram->mcr, DRAM_MCR_RESET);
+#else
+       /* dram clock on */
+       dramc_clock_output_en(1);
 #endif
 
        udelay(1);
@@ -490,6 +549,22 @@ unsigned long dramc_init(struct dram_para *para)
 
        mctl_enable_dllx(para->tpr3);
 
+#ifdef CONFIG_SUN4I
+       /* set odt impedance divide ratio */
+       reg_val = ((para->zq) >> 8) & 0xfffff;
+       reg_val |= ((para->zq) & 0xff) << 20;
+       reg_val |= (para->zq) & 0xf0000000;
+       writel(reg_val, &dram->zqcr0);
+#endif
+
+#ifdef CONFIG_SUN4I
+       /* set I/O configure register */
+       reg_val = 0x00cc0000;
+       reg_val |= (para->odt_en) & 0x3;
+       reg_val |= ((para->odt_en) & 0x3) << 30;
+       writel(reg_val, &dram->iocr);
+#endif
+
        /* set refresh period */
        dramc_set_autorefresh_cycle(para->clock, para->type - 2, density);
 
index cbf8f08..4902d70 100644 (file)
@@ -10,4 +10,5 @@
 #
 obj-y  += board.o
 obj-$(CONFIG_SUNXI_GMAC)       += gmac.o
+obj-$(CONFIG_CUBIEBOARD)       += dram_cubieboard.o
 obj-$(CONFIG_CUBIETRUCK)       += dram_cubietruck.o
diff --git a/board/sunxi/dram_cubieboard.c b/board/sunxi/dram_cubieboard.c
new file mode 100644 (file)
index 0000000..399028c
--- /dev/null
@@ -0,0 +1,31 @@
+/* this file is generated, don't edit it yourself */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+
+static struct dram_para dram_para = {
+       .clock = 480,
+       .type = 3,
+       .rank_num = 1,
+       .density = 4096,
+       .io_width = 16,
+       .bus_width = 32,
+       .cas = 6,
+       .zq = 123,
+       .odt_en = 0,
+       .size = 1024,
+       .tpr0 = 0x30926692,
+       .tpr1 = 0x1090,
+       .tpr2 = 0x1a0c8,
+       .tpr3 = 0,
+       .tpr4 = 0,
+       .tpr5 = 0,
+       .emr1 = 0,
+       .emr2 = 0,
+       .emr3 = 0,
+};
+
+unsigned long sunxi_dram_init(void)
+{
+       return dramc_init(&dram_para);
+}
index 6f8d168..af24128 100644 (file)
@@ -377,6 +377,7 @@ Active  arm         armv7          rmobile     renesas         lager
 Active  arm         armv7          s5pc1xx     samsung         goni                s5p_goni                              -                                                                                                                                 Robert Baldyga <r.baldyga@samsung.com>
 Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100                              -                                                                                                                                 Minkyu Kang <mk7.kang@samsung.com>
 Active  arm         armv7          socfpga     altera          socfpga             socfpga_cyclone5                      -                                                                                                                                 -
+Active  arm         armv7          sunxi       -               sunxi               Cubieboard                            sun4i:CUBIEBOARD,SPL                                                                                                              Hans de Goede <hdegoede@redhat.com>
 Active  arm         armv7          sunxi       -               sunxi               Cubietruck                            sun7i:CUBIETRUCK,SPL,SUNXI_GMAC,RGMII                                                                                             -
 Active  arm         armv7          sunxi       -               sunxi               Cubietruck_FEL                        sun7i:CUBIETRUCK,SPL_FEL,SUNXI_GMAC,RGMII                                                                                         -
 Active  arm         armv7          u8500       st-ericsson     snowball            snowball                              -                                                                                                                                 Mathieu Poirier <mathieu.poirier@linaro.org>
diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h
new file mode 100644 (file)
index 0000000..6560b65
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * Configuration settings for the Allwinner A10 (sun4i) CPU
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * A10 specific configuration
+ */
+#define CONFIG_SUN4I           /* sun4i SoC generation */
+
+#define CONFIG_SYS_PROMPT              "sun4i# "
+
+/*
+ * Include common sunxi configuration where most the settings are
+ */
+#include <configs/sunxi-common.h>
+
+#endif /* __CONFIG_H */