]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
Merge branch 'master' of http://git.denx.de/u-boot-sunxi
authorTom Rini <trini@ti.com>
Tue, 25 Nov 2014 16:09:48 +0000 (11:09 -0500)
committerTom Rini <trini@ti.com>
Wed, 26 Nov 2014 16:21:16 +0000 (11:21 -0500)
26 files changed:
arch/arm/cpu/armv7/sunxi/clock_sun4i.c
arch/arm/cpu/armv7/sunxi/clock_sun6i.c
arch/arm/cpu/armv7/sunxi/dram_sun4i.c
arch/arm/cpu/armv7/sunxi/dram_sun6i.c
arch/arm/include/asm/arch-sunxi/clock.h
arch/arm/include/asm/arch-sunxi/clock_sun4i.h
arch/arm/include/asm/arch-sunxi/clock_sun6i.h
arch/arm/include/asm/arch-sunxi/cpu.h
arch/arm/include/asm/arch-sunxi/display.h [new file with mode: 0644]
arch/arm/include/asm/arch-sunxi/gpio.h
board/sunxi/Kconfig
board/sunxi/ahci.c
board/sunxi/board.c
board/sunxi/gmac.c
common/fdt_support.c
common/lcd.c
configs/A13-OLinuXinoM_defconfig
configs/A13-OLinuXino_defconfig
configs/Colombus_defconfig
configs/Ippo_q8h_v5_defconfig
configs/Mele_M9_defconfig
drivers/video/Makefile
drivers/video/sunxi_display.c [new file with mode: 0644]
include/configs/sun7i.h
include/configs/sunxi-common.h
include/fdt_support.h

index a0e49d179feff469f212f479925bc6ab881b3585..49f4032e9cfda56acab108adf57278c63e5e63a0 100644 (file)
@@ -180,6 +180,21 @@ void clock_set_pll1(unsigned int hz)
 }
 #endif
 
+void clock_set_pll3(unsigned int clk)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+       if (clk == 0) {
+               clrbits_le32(&ccm->pll3_cfg, CCM_PLL3_CTRL_EN);
+               return;
+       }
+
+       /* PLL3 rate = 3000000 * m */
+       writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE |
+              CCM_PLL3_CTRL_M(clk / 3000000), &ccm->pll3_cfg);
+}
+
 unsigned int clock_get_pll5p(void)
 {
        struct sunxi_ccm_reg *const ccm =
@@ -200,3 +215,15 @@ unsigned int clock_get_pll6(void)
        int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1;
        return 24000000 * n * k / 2;
 }
+
+void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz)
+{
+       int pll = clock_get_pll5p();
+       int div = 1;
+
+       while ((pll / div) > hz)
+               div++;
+
+       writel(CCM_DE_CTRL_GATE | CCM_DE_CTRL_RST | CCM_DE_CTRL_PLL5P |
+              CCM_DE_CTRL_M(div), clk_cfg);
+}
index 16ab6f372976923f8903266a566bde7c907e2a1c..8e949c6901d2e1e6299825b1c6b4f9c17e2fc01e 100644 (file)
@@ -127,6 +127,23 @@ void clock_set_pll1(unsigned int clk)
 }
 #endif
 
+void clock_set_pll3(unsigned int clk)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       const int m = 8; /* 3 MHz steps just like sun4i, sun5i and sun7i */
+
+       if (clk == 0) {
+               clrbits_le32(&ccm->pll3_cfg, CCM_PLL3_CTRL_EN);
+               return;
+       }
+
+       /* PLL3 rate = 24000000 * n / m */
+       writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE |
+              CCM_PLL3_CTRL_N(clk / (24000000 / m)) | CCM_PLL3_CTRL_M(m),
+              &ccm->pll3_cfg);
+}
+
 void clock_set_pll5(unsigned int clk)
 {
        struct sunxi_ccm_reg * const ccm =
@@ -151,3 +168,15 @@ unsigned int clock_get_pll6(void)
        int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1;
        return 24000000 * n * k / 2;
 }
+
+void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz)
+{
+       int pll = clock_get_pll6() * 2;
+       int div = 1;
+
+       while ((pll / div) > hz)
+               div++;
+
+       writel(CCM_DE_CTRL_GATE | CCM_DE_CTRL_PLL6_2X | CCM_DE_CTRL_M(div),
+              clk_cfg);
+}
index dc9fdb930b6e5c51c2d7252f7b4511439c3f33a2..ec8aaa7d48e6a92ca3c94825b034d495dd00a87c 100644 (file)
@@ -428,9 +428,9 @@ static void dramc_clock_output_en(u32 on)
 #ifdef CONFIG_MACH_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);
+               setbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT);
        else
-               clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT);
+               clrbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT);
 #endif
 }
 
index 10a62416d2686194642542e7aab2ee3548ff7044..699173cf699b252e68793190513daa65ee6f755c 100644 (file)
@@ -142,9 +142,6 @@ static void mctl_channel_init(int ch_index, struct dram_sun6i_para *para)
 
        writel((MCTL_TITMSRST << 18) | (MCTL_TDLLLOCK << 6) | MCTL_TDLLSRST,
               &mctl_phy->ptr0);
-       /* Unknown magic performed by boot0 */
-       if ((readl(SUNXI_RTC_BASE + 0x20c) & 3) == 2)
-               setbits_le32(&mctl_phy->ptr0, 1 << 18);
 
        writel((MCTL_TDINIT1 << 19) | MCTL_TDINIT0, &mctl_phy->ptr1);
        writel((MCTL_TDINIT3 << 17) | MCTL_TDINIT2, &mctl_phy->ptr2);
index b40c16b6e7bc262fee8b2faebf9b1921a9e62ab6..64acff3504154a75253a430819e25fe2c3ba1e13 100644 (file)
 int clock_init(void);
 int clock_twi_onoff(int port, int state);
 void clock_set_pll1(unsigned int hz);
+void clock_set_pll3(unsigned int hz);
 void clock_set_pll5(unsigned int hz);
 unsigned int clock_get_pll5p(void);
 unsigned int clock_get_pll6(void);
+void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz);
 void clock_init_safe(void);
 void clock_init_uart(void);
 #endif
index 9dca800d7851a762de594e46ac92bc6354560de4..eb889695d9143e5cc9756a2c2a0661068336fc57 100644 (file)
@@ -62,7 +62,7 @@ struct sunxi_ccm_reg {
        u32 gps_clk_cfg;        /* 0xd0 */
        u32 spi3_clk_cfg;       /* 0xd4 */
        u8 res5[0x28];
-       u32 dram_clk_cfg;       /* 0x100 */
+       u32 dram_clk_gate;      /* 0x100 */
        u32 be0_clk_cfg;        /* 0x104 */
        u32 be1_clk_cfg;        /* 0x108 */
        u32 fe0_clk_cfg;        /* 0x10c */
@@ -186,12 +186,20 @@ struct sunxi_ccm_reg {
 
 /* ahb clock gate bit offset (second register) */
 #define AHB_GATE_OFFSET_GMAC           17
+#define AHB_GATE_OFFSET_DE_BE0         12
+#define AHB_GATE_OFFSET_HDMI           11
+#define AHB_GATE_OFFSET_LCD1           5
+#define AHB_GATE_OFFSET_LCD0           4
 
 #define CCM_AHB_GATE_GPS (0x1 << 26)
 #define CCM_AHB_GATE_SDRAM (0x1 << 14)
 #define CCM_AHB_GATE_DLL (0x1 << 15)
 #define CCM_AHB_GATE_ACE (0x1 << 16)
 
+#define CCM_PLL3_CTRL_M(n)             (((n) & 0x7f) << 0)
+#define CCM_PLL3_CTRL_INTEGER_MODE     (0x1 << 15)
+#define CCM_PLL3_CTRL_EN               (0x1 << 31)
+
 #define CCM_PLL5_CTRL_M(n) (((n) & 0x3) << 0)
 #define CCM_PLL5_CTRL_M_MASK CCM_PLL5_CTRL_M(0x3)
 #define CCM_PLL5_CTRL_M_X(n) ((n) - 1)
@@ -253,6 +261,34 @@ struct sunxi_ccm_reg {
 
 #define CCM_MMC_CTRL_ENABLE (0x1 << 31)
 
+#define CCM_DRAM_GATE_OFFSET_DE_BE0    26
+
+#define CCM_LCD_CH0_CTRL_PLL3          (0 << 24)
+#define CCM_LCD_CH0_CTRL_PLL7          (1 << 24)
+#define CCM_LCD_CH0_CTRL_PLL3_2X       (2 << 24)
+#define CCM_LCD_CH0_CTRL_PLL7_2X       (3 << 24)
+#define CCM_LCD_CH0_CTRL_RST           (0x1 << 30)
+#define CCM_LCD_CH0_CTRL_GATE          (0x1 << 31)
+
+#define CCM_LCD_CH1_CTRL_M(n)          ((((n) - 1) & 0xf) << 0)
+/* We leave bit 11 set to 0, so sclk1 == sclk2 */
+#define CCM_LCD_CH1_CTRL_PLL3          (0 << 24)
+#define CCM_LCD_CH1_CTRL_PLL7          (1 << 24)
+#define CCM_LCD_CH1_CTRL_PLL3_2X       (2 << 24)
+#define CCM_LCD_CH1_CTRL_PLL7_2X       (3 << 24)
+/* Enable / disable both ch1 sclk1 and sclk2 at the same time */
+#define CCM_LCD_CH1_CTRL_GATE          (0x1 << 31 | 0x1 << 15)
+
+#define CCM_HDMI_CTRL_M(n)             ((((n) - 1) & 0xf) << 0)
+#define CCM_HDMI_CTRL_PLL_MASK         (3 << 24)
+#define CCM_HDMI_CTRL_PLL3             (0 << 24)
+#define CCM_HDMI_CTRL_PLL7             (1 << 24)
+#define CCM_HDMI_CTRL_PLL3_2X          (2 << 24)
+#define CCM_HDMI_CTRL_PLL7_2X          (3 << 24)
+/* No separate ddc gate on sun4i, sun5i and sun7i */
+#define CCM_HDMI_CTRL_DDC_GATE         0
+#define CCM_HDMI_CTRL_GATE             (0x1 << 31)
+
 #define CCM_GMAC_CTRL_TX_CLK_SRC_MII 0x0
 #define CCM_GMAC_CTRL_TX_CLK_SRC_EXT_RGMII 0x1
 #define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2
@@ -266,4 +302,13 @@ struct sunxi_ccm_reg {
 #define CCM_USB_CTRL_PHY1_CLK 0
 #define CCM_USB_CTRL_PHY2_CLK 0
 
+/* CCM bits common to all Display Engine (and IEP) clock ctrl regs */
+#define CCM_DE_CTRL_M(n)               ((((n) - 1) & 0xf) << 0)
+#define CCM_DE_CTRL_PLL_MASK           (3 << 24)
+#define CCM_DE_CTRL_PLL3               (0 << 24)
+#define CCM_DE_CTRL_PLL7               (1 << 24)
+#define CCM_DE_CTRL_PLL5P              (2 << 24)
+#define CCM_DE_CTRL_RST                        (1 << 30)
+#define CCM_DE_CTRL_GATE               (1 << 31)
+
 #endif /* _SUNXI_CLOCK_SUN4I_H */
index e16a7647ed9f711800e17ae06b98e54b838da429..359905452c3e27979ee1a2325351a2444cb7160a 100644 (file)
@@ -176,13 +176,18 @@ struct sunxi_ccm_reg {
 #define CCM_PLL1_CTRL_MAGIC            (0x1 << 16)
 #define CCM_PLL1_CTRL_EN               (0x1 << 31)
 
+#define CCM_PLL3_CTRL_M(n)             ((((n) - 1) & 0xf) << 0)
+#define CCM_PLL3_CTRL_N(n)             ((((n) - 1) & 0x7f) << 8)
+#define CCM_PLL3_CTRL_INTEGER_MODE     (0x1 << 24)
+#define CCM_PLL3_CTRL_EN               (0x1 << 31)
+
 #define CCM_PLL5_CTRL_M(n)             ((((n) - 1) & 0x3) << 0)
 #define CCM_PLL5_CTRL_K(n)             ((((n) - 1) & 0x3) << 4)
 #define CCM_PLL5_CTRL_N(n)             ((((n) - 1) & 0x1f) << 8)
 #define CCM_PLL5_CTRL_UPD              (0x1 << 20)
 #define CCM_PLL5_CTRL_EN               (0x1 << 31)
 
-#define PLL6_CFG_DEFAULT               0x90041811
+#define PLL6_CFG_DEFAULT               0x90041811 /* 600 MHz */
 
 #define CCM_PLL6_CTRL_N_SHIFT          8
 #define CCM_PLL6_CTRL_N_MASK           (0x1f << CCM_PLL6_CTRL_N_SHIFT)
@@ -193,17 +198,26 @@ struct sunxi_ccm_reg {
 
 #define AXI_GATE_OFFSET_DRAM           0
 
+/* ahb_gate0 offsets */
 #define AHB_GATE_OFFSET_USB_OHCI1      30
 #define AHB_GATE_OFFSET_USB_OHCI0      29
 #define AHB_GATE_OFFSET_USB_EHCI1      27
 #define AHB_GATE_OFFSET_USB_EHCI0      26
 #define AHB_GATE_OFFSET_MCTL           14
+#define AHB_GATE_OFFSET_GMAC           17
 #define AHB_GATE_OFFSET_MMC3           11
 #define AHB_GATE_OFFSET_MMC2           10
 #define AHB_GATE_OFFSET_MMC1           9
 #define AHB_GATE_OFFSET_MMC0           8
 #define AHB_GATE_OFFSET_MMC(n)         (AHB_GATE_OFFSET_MMC0 + (n))
 
+/* ahb_gate1 offsets */
+#define AHB_GATE_OFFSET_DRC0           25
+#define AHB_GATE_OFFSET_DE_BE0         12
+#define AHB_GATE_OFFSET_HDMI           11
+#define AHB_GATE_OFFSET_LCD1           5
+#define AHB_GATE_OFFSET_LCD0           4
+
 #define CCM_MMC_CTRL_OSCM24 (0x0 << 24)
 #define CCM_MMC_CTRL_PLL6   (0x1 << 24)
 
@@ -216,6 +230,12 @@ struct sunxi_ccm_reg {
 #define CCM_USB_CTRL_PHY1_CLK (0x1 << 9)
 #define CCM_USB_CTRL_PHY2_CLK (0x1 << 10)
 
+#define CCM_GMAC_CTRL_TX_CLK_SRC_MII   0x0
+#define CCM_GMAC_CTRL_TX_CLK_SRC_EXT_RGMII 0x1
+#define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2
+#define CCM_GMAC_CTRL_GPIT_MII         (0x0 << 2)
+#define CCM_GMAC_CTRL_GPIT_RGMII       (0x1 << 2)
+
 #define MDFS_CLK_DEFAULT               0x81000002 /* PLL6 / 3 */
 
 #define CCM_DRAMCLK_CFG_DIV0(x)                ((x - 1) << 8)
@@ -223,8 +243,35 @@ struct sunxi_ccm_reg {
 #define CCM_DRAMCLK_CFG_UPD            (0x1 << 16)
 #define CCM_DRAMCLK_CFG_RST            (0x1 << 31)
 
+#define CCM_DRAM_GATE_OFFSET_DE_BE0    26
+
+#define CCM_LCD_CH0_CTRL_PLL3          (0 << 24)
+#define CCM_LCD_CH0_CTRL_PLL7          (1 << 24)
+#define CCM_LCD_CH0_CTRL_PLL3_2X       (2 << 24)
+#define CCM_LCD_CH0_CTRL_PLL7_2X       (3 << 24)
+#define CCM_LCD_CH0_CTRL_MIPI_PLL      (4 << 24)
+#define CCM_LCD_CH0_CTRL_GATE          (0x1 << 31)
+
+#define CCM_LCD_CH1_CTRL_M(n)          ((((n) - 1) & 0xf) << 0)
+#define CCM_LCD_CH1_CTRL_PLL3          (0 << 24)
+#define CCM_LCD_CH1_CTRL_PLL7          (1 << 24)
+#define CCM_LCD_CH1_CTRL_PLL3_2X       (2 << 24)
+#define CCM_LCD_CH1_CTRL_PLL7_2X       (3 << 24)
+#define CCM_LCD_CH1_CTRL_GATE          (0x1 << 31)
+
+#define CCM_HDMI_CTRL_M(n)             ((((n) - 1) & 0xf) << 0)
+#define CCM_HDMI_CTRL_PLL_MASK         (3 << 24)
+#define CCM_HDMI_CTRL_PLL3             (0 << 24)
+#define CCM_HDMI_CTRL_PLL7             (1 << 24)
+#define CCM_HDMI_CTRL_PLL3_2X          (2 << 24)
+#define CCM_HDMI_CTRL_PLL7_2X          (3 << 24)
+#define CCM_HDMI_CTRL_DDC_GATE         (0x1 << 30)
+#define CCM_HDMI_CTRL_GATE             (0x1 << 31)
+
 #define MBUS_CLK_DEFAULT               0x81000001 /* PLL6 / 2 */
 
+/* ahb_reset0 offsets */
+#define AHB_RESET_OFFSET_GMAC          17
 #define AHB_RESET_OFFSET_MCTL          14
 #define AHB_RESET_OFFSET_MMC3          11
 #define AHB_RESET_OFFSET_MMC2          10
@@ -232,10 +279,28 @@ struct sunxi_ccm_reg {
 #define AHB_RESET_OFFSET_MMC0          8
 #define AHB_RESET_OFFSET_MMC(n)                (AHB_RESET_OFFSET_MMC0 + (n))
 
+/* ahb_reset0 offsets */
+#define AHB_RESET_OFFSET_DRC0          25
+#define AHB_RESET_OFFSET_DE_BE0                12
+#define AHB_RESET_OFFSET_HDMI          11
+#define AHB_RESET_OFFSET_LCD1          5
+#define AHB_RESET_OFFSET_LCD0          4
+
 /* apb2 reset */
 #define APB2_RESET_UART_SHIFT          (16)
 #define APB2_RESET_UART_MASK           (0xff << APB2_RESET_UART_SHIFT)
 #define APB2_RESET_TWI_SHIFT           (0)
 #define APB2_RESET_TWI_MASK            (0xf << APB2_RESET_TWI_SHIFT)
 
+/* CCM bits common to all Display Engine (and IEP) clock ctrl regs */
+#define CCM_DE_CTRL_M(n)               ((((n) - 1) & 0xf) << 0)
+#define CCM_DE_CTRL_PLL_MASK           (0xf << 24)
+#define CCM_DE_CTRL_PLL3               (0 << 24)
+#define CCM_DE_CTRL_PLL7               (1 << 24)
+#define CCM_DE_CTRL_PLL6_2X            (2 << 24)
+#define CCM_DE_CTRL_PLL8               (3 << 24)
+#define CCM_DE_CTRL_PLL9               (4 << 24)
+#define CCM_DE_CTRL_PLL10              (5 << 24)
+#define CCM_DE_CTRL_GATE               (1 << 31)
+
 #endif /* _SUNXI_CLOCK_SUN6I_H */
index bdee89e87da7c95c01e00b6a67c5d18f0a09d0cd..2c92b5ca568363b26125c166caa6f2fe1b3f15d4 100644 (file)
 
 #define SUNXI_SCR_BASE                 0x01c2c400
 
+#ifndef CONFIG_MACH_SUN6I
 #define SUNXI_GPS_BASE                 0x01c30000
 #define SUNXI_MALI400_BASE             0x01c40000
 #define SUNXI_GMAC_BASE                        0x01c50000
+#else
+#define SUNXI_GMAC_BASE                        0x01c30000
+#endif
 
 #define SUNXI_DRAM_COM_BASE            0x01c62000
 #define SUNXI_DRAM_CTL0_BASE           0x01c63000
diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h
new file mode 100644 (file)
index 0000000..ddb71c1
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Sunxi platform display controller register and constant defines
+ *
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _SUNXI_DISPLAY_H
+#define _SUNXI_DISPLAY_H
+
+struct sunxi_de_be_reg {
+       u8 res0[0x800];                 /* 0x000 */
+       u32 mode;                       /* 0x800 */
+       u32 backcolor;                  /* 0x804 */
+       u32 disp_size;                  /* 0x808 */
+       u8 res1[0x4];                   /* 0x80c */
+       u32 layer0_size;                /* 0x810 */
+       u32 layer1_size;                /* 0x814 */
+       u32 layer2_size;                /* 0x818 */
+       u32 layer3_size;                /* 0x81c */
+       u32 layer0_pos;                 /* 0x820 */
+       u32 layer1_pos;                 /* 0x824 */
+       u32 layer2_pos;                 /* 0x828 */
+       u32 layer3_pos;                 /* 0x82c */
+       u8 res2[0x10];                  /* 0x830 */
+       u32 layer0_stride;              /* 0x840 */
+       u32 layer1_stride;              /* 0x844 */
+       u32 layer2_stride;              /* 0x848 */
+       u32 layer3_stride;              /* 0x84c */
+       u32 layer0_addr_low32b;         /* 0x850 */
+       u32 layer1_addr_low32b;         /* 0x854 */
+       u32 layer2_addr_low32b;         /* 0x858 */
+       u32 layer3_addr_low32b;         /* 0x85c */
+       u32 layer0_addr_high4b;         /* 0x860 */
+       u32 layer1_addr_high4b;         /* 0x864 */
+       u32 layer2_addr_high4b;         /* 0x868 */
+       u32 layer3_addr_high4b;         /* 0x86c */
+       u32 reg_ctrl;                   /* 0x870 */
+       u8 res3[0xc];                   /* 0x874 */
+       u32 color_key_max;              /* 0x880 */
+       u32 color_key_min;              /* 0x884 */
+       u32 color_key_config;           /* 0x888 */
+       u8 res4[0x4];                   /* 0x88c */
+       u32 layer0_attr0_ctrl;          /* 0x890 */
+       u32 layer1_attr0_ctrl;          /* 0x894 */
+       u32 layer2_attr0_ctrl;          /* 0x898 */
+       u32 layer3_attr0_ctrl;          /* 0x89c */
+       u32 layer0_attr1_ctrl;          /* 0x8a0 */
+       u32 layer1_attr1_ctrl;          /* 0x8a4 */
+       u32 layer2_attr1_ctrl;          /* 0x8a8 */
+       u32 layer3_attr1_ctrl;          /* 0x8ac */
+};
+
+struct sunxi_lcdc_reg {
+       u32 ctrl;                       /* 0x00 */
+       u32 int0;                       /* 0x04 */
+       u32 int1;                       /* 0x08 */
+       u8 res0[0x04];                  /* 0x0c */
+       u32 frame_ctrl;                 /* 0x10 */
+       u8 res1[0x2c];                  /* 0x14 */
+       u32 tcon0_ctrl;                 /* 0x40 */
+       u32 tcon0_dclk;                 /* 0x44 */
+       u32 tcon0_basic_timing0;        /* 0x48 */
+       u32 tcon0_basic_timing1;        /* 0x4c */
+       u32 tcon0_basic_timing2;        /* 0x50 */
+       u32 tcon0_basic_timing3;        /* 0x54 */
+       u32 tcon0_hv_intf;              /* 0x58 */
+       u8 res2[0x04];                  /* 0x5c */
+       u32 tcon0_cpu_intf;             /* 0x60 */
+       u32 tcon0_cpu_wr_dat;           /* 0x64 */
+       u32 tcon0_cpu_rd_dat0;          /* 0x68 */
+       u32 tcon0_cpu_rd_dat1;          /* 0x6c */
+       u32 tcon0_ttl_timing0;          /* 0x70 */
+       u32 tcon0_ttl_timing1;          /* 0x74 */
+       u32 tcon0_ttl_timing2;          /* 0x78 */
+       u32 tcon0_ttl_timing3;          /* 0x7c */
+       u32 tcon0_ttl_timing4;          /* 0x80 */
+       u32 tcon0_lvds_intf;            /* 0x84 */
+       u32 tcon0_io_polarity;          /* 0x88 */
+       u32 tcon0_io_tristate;          /* 0x8c */
+       u32 tcon1_ctrl;                 /* 0x90 */
+       u32 tcon1_timing_source;        /* 0x94 */
+       u32 tcon1_timing_scale;         /* 0x98 */
+       u32 tcon1_timing_out;           /* 0x9c */
+       u32 tcon1_timing_h;             /* 0xa0 */
+       u32 tcon1_timing_v;             /* 0xa4 */
+       u32 tcon1_timing_sync;          /* 0xa8 */
+       u8 res3[0x44];                  /* 0xac */
+       u32 tcon1_io_polarity;          /* 0xf0 */
+       u32 tcon1_io_tristate;          /* 0xf4 */
+};
+
+struct sunxi_hdmi_reg {
+       u32 version_id;                 /* 0x000 */
+       u32 ctrl;                       /* 0x004 */
+       u32 irq;                        /* 0x008 */
+       u32 hpd;                        /* 0x00c */
+       u32 video_ctrl;                 /* 0x010 */
+       u32 video_size;                 /* 0x014 */
+       u32 video_bp;                   /* 0x018 */
+       u32 video_fp;                   /* 0x01c */
+       u32 video_spw;                  /* 0x020 */
+       u32 video_polarity;             /* 0x024 */
+       u8 res0[0x1d8];                 /* 0x028 */
+       u32 pad_ctrl0;                  /* 0x200 */
+       u32 pad_ctrl1;                  /* 0x204 */
+       u32 pll_ctrl;                   /* 0x208 */
+       u32 pll_dbg0;                   /* 0x20c */
+};
+
+/*
+ * DE-BE register constants.
+ */
+#define SUNXI_DE_BE_WIDTH(x)                   (((x) - 1) << 0)
+#define SUNXI_DE_BE_HEIGHT(y)                  (((y) - 1) << 16)
+#define SUNXI_DE_BE_MODE_ENABLE                        (1 << 0)
+#define SUNXI_DE_BE_MODE_START                 (1 << 1)
+#define SUNXI_DE_BE_MODE_LAYER0_ENABLE         (1 << 8)
+#define SUNXI_DE_BE_LAYER_STRIDE(x)            ((x) << 5)
+#define SUNXI_DE_BE_REG_CTRL_LOAD_REGS         (1 << 0)
+#define SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888   (0x09 << 8)
+
+/*
+ * LCDC register constants.
+ */
+#define SUNXI_LCDC_X(x)                                (((x) - 1) << 16)
+#define SUNXI_LCDC_Y(y)                                (((y) - 1) << 0)
+#define SUNXI_LCDC_CTRL_IO_MAP_MASK            (1 << 0)
+#define SUNXI_LCDC_CTRL_IO_MAP_TCON0           (0 << 0)
+#define SUNXI_LCDC_CTRL_IO_MAP_TCON1           (1 << 0)
+#define SUNXI_LCDC_CTRL_TCON_ENABLE            (1 << 31)
+#define SUNXI_LCDC_TCON0_DCLK_ENABLE           (0xf << 28)
+#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n)     (((n) & 0x1f) << 4)
+#define SUNXI_LCDC_TCON1_CTRL_ENABLE           (1 << 31)
+#define SUNXI_LCDC_TCON1_TIMING_H_BP(n)                (((n) - 1) << 0)
+#define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n)     (((n) - 1) << 16)
+#define SUNXI_LCDC_TCON1_TIMING_V_BP(n)                (((n) - 1) << 0)
+#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n)     (((n) * 2) << 16)
+
+/*
+ * HDMI register constants.
+ */
+#define SUNXI_HDMI_X(x)                                (((x) - 1) << 0)
+#define SUNXI_HDMI_Y(y)                                (((y) - 1) << 16)
+#define SUNXI_HDMI_CTRL_ENABLE                 (1 << 31)
+#define SUNXI_HDMI_IRQ_STATUS_FIFO_UF          (1 << 0)
+#define SUNXI_HDMI_IRQ_STATUS_FIFO_OF          (1 << 1)
+#define SUNXI_HDMI_IRQ_STATUS_BITS             0x73
+#define SUNXI_HDMI_HPD_DETECT                  (1 << 0)
+#define SUNXI_HDMI_VIDEO_CTRL_ENABLE           (1 << 31)
+#define SUNXI_HDMI_VIDEO_POL_HOR               (1 << 0)
+#define SUNXI_HDMI_VIDEO_POL_VER               (1 << 1)
+#define SUNXI_HDMI_VIDEO_POL_TX_CLK            (0x3e0 << 16)
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HDMI_PAD_CTRL0_HDP               0x7e80000f
+#define SUNXI_HDMI_PAD_CTRL0_RUN               0x7e8000ff
+#else
+#define SUNXI_HDMI_PAD_CTRL0_HDP               0xfe800000
+#define SUNXI_HDMI_PAD_CTRL0_RUN               0xfe800000
+#endif
+
+#ifdef CONFIG_MACH_SUN4I
+#define SUNXI_HDMI_PAD_CTRL1                   0x00d8c820
+#elif defined CONFIG_MACH_SUN6I
+#define SUNXI_HDMI_PAD_CTRL1                   0x01ded030
+#else
+#define SUNXI_HDMI_PAD_CTRL1                   0x00d8c830
+#endif
+#define SUNXI_HDMI_PAD_CTRL1_HALVE             (1 << 6)
+
+#ifdef CONFIG_MACH_SUN6I
+#define SUNXI_HDMI_PLL_CTRL                    0xba48a308
+#define SUNXI_HDMI_PLL_CTRL_DIV(n)             (((n) - 1) << 4)
+#else
+#define SUNXI_HDMI_PLL_CTRL                    0xfa4ef708
+#define SUNXI_HDMI_PLL_CTRL_DIV(n)             ((n) << 4)
+#endif
+#define SUNXI_HDMI_PLL_CTRL_DIV_MASK           (0xf << 4)
+
+#define SUNXI_HDMI_PLL_DBG0_PLL3               (0 << 21)
+#define SUNXI_HDMI_PLL_DBG0_PLL7               (1 << 21)
+
+int sunxi_simplefb_setup(void *blob);
+
+#endif /* _SUNXI_DISPLAY_H */
index c734cf015e631f8304ba489f7e91324c3a6ae08c..366c0dc45ac119ea428a795b89edacf90b5a47b6 100644 (file)
@@ -134,6 +134,7 @@ enum sunxi_gpio_number {
 #define SUNXI_GPIO_OUTPUT      1
 
 #define SUNXI_GPA0_EMAC                2
+#define SUN6I_GPA0_GMAC                2
 #define SUN7I_GPA0_GMAC                5
 
 #define SUNXI_GPB0_TWI0                2
index 7555896f740885343dd9f1f49f314635d3b34198..246cd9a1a708df0d42892586d4db6188c3c75b36 100644 (file)
@@ -24,6 +24,7 @@ config MACH_SUN7I
        select CPU_V7_HAS_NONSEC
        select CPU_V7_HAS_VIRT
        select SUPPORT_SPL
+       select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
 
 config MACH_SUN8I
        bool "sun8i (Allwinner A23)"
@@ -215,4 +216,18 @@ config USB2_VBUS_PIN
        ---help---
        See USB1_VBUS_PIN help text.
 
+config VIDEO
+       boolean "Enable graphical uboot console on HDMI"
+       default y
+       ---help---
+       Say Y here to add support for using a cfb console on the HDMI output
+       found on most sunxi devices.
+
+config USB_KEYBOARD
+       boolean "Enable USB keyboard support"
+       default y
+       ---help---
+       Say Y here to add support for using a USB keyboard (typically used
+       in combination with a graphical console on HDMI).
+
 endif
index 5e123285b03d2d8a8fb29b6c2712d11bf4fa1df5..b7f0dda2058eecf97547270a2feac54565b5d7b1 100644 (file)
@@ -76,6 +76,8 @@ void scsi_init(void)
 #ifdef CONFIG_SATAPWR
        gpio_request(CONFIG_SATAPWR, "satapwr");
        gpio_direction_output(CONFIG_SATAPWR, 1);
+       /* Give attached sata device time to power-up to avoid link timeouts */
+       mdelay(500);
 #endif
 
        if (sunxi_ahci_phy_init(SUNXI_SATA_BASE) < 0)
index e6ec5b8fc10b89447f6088ec1320eb0701a10108..4c1c69a6ae1381fafc9b0c2b6f1117377ee5c3aa 100644 (file)
@@ -24,6 +24,7 @@
 #endif
 #include <asm/arch/clock.h>
 #include <asm/arch/cpu.h>
+#include <asm/arch/display.h>
 #include <asm/arch/dram.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
@@ -237,3 +238,12 @@ int misc_init_r(void)
        return 0;
 }
 #endif
+
+#ifdef CONFIG_OF_BOARD_SETUP
+int ft_board_setup(void *blob, bd_t *bd)
+{
+#ifdef CONFIG_VIDEO_DT_SIMPLEFB
+       return sunxi_simplefb_setup(blob);
+#endif
+}
+#endif /* CONFIG_OF_BOARD_SETUP */
index 051aca01a83202fdb026458bdaf40711601d207f..571bc9e0ab0d49ba3ab6c1ef621adff2f038441e 100644 (file)
@@ -13,7 +13,12 @@ int sunxi_gmac_initialize(bd_t *bis)
                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 
        /* Set up clock gating */
+#ifndef CONFIG_MACH_SUN6I
        setbits_le32(&ccm->ahb_gate1, 0x1 << AHB_GATE_OFFSET_GMAC);
+#else
+       setbits_le32(&ccm->ahb_reset0_cfg, 0x1 << AHB_RESET_OFFSET_GMAC);
+       setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_GMAC);
+#endif
 
        /* Set MII clock */
 #ifdef CONFIG_RGMII
@@ -33,6 +38,7 @@ int sunxi_gmac_initialize(bd_t *bis)
        setbits_le32(&ccm->gmac_clk_cfg, 0x3 << 10);
 #endif
 
+#ifndef CONFIG_MACH_SUN6I
        /* Configure pin mux settings for GMAC */
        for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(16); pin++) {
 #ifdef CONFIG_RGMII
@@ -43,9 +49,48 @@ int sunxi_gmac_initialize(bd_t *bis)
                sunxi_gpio_set_cfgpin(pin, SUN7I_GPA0_GMAC);
                sunxi_gpio_set_drv(pin, 3);
        }
+#elif defined CONFIG_RGMII
+       /* Configure sun6i RGMII mode pin mux settings */
+       for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(3); pin++) {
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+               sunxi_gpio_set_drv(pin, 3);
+       }
+       for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) {
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+               sunxi_gpio_set_drv(pin, 3);
+       }
+       for (pin = SUNXI_GPA(19); pin <= SUNXI_GPA(20); pin++) {
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+               sunxi_gpio_set_drv(pin, 3);
+       }
+       for (pin = SUNXI_GPA(25); pin <= SUNXI_GPA(27); pin++) {
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+               sunxi_gpio_set_drv(pin, 3);
+       }
+#elif defined CONFIG_GMII
+       /* Configure sun6i GMII mode pin mux settings */
+       for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(27); pin++) {
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+               sunxi_gpio_set_drv(pin, 2);
+       }
+#else
+       /* Configure sun6i MII mode pin mux settings */
+       for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(3); pin++)
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+       for (pin = SUNXI_GPA(8); pin <= SUNXI_GPA(9); pin++)
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+       for (pin = SUNXI_GPA(11); pin <= SUNXI_GPA(14); pin++)
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+       for (pin = SUNXI_GPA(19); pin <= SUNXI_GPA(24); pin++)
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+       for (pin = SUNXI_GPA(26); pin <= SUNXI_GPA(27); pin++)
+               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC);
+#endif
 
 #ifdef CONFIG_RGMII
        return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_RGMII);
+#elif defined CONFIG_GMII
+       return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_GMII);
 #else
        return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_MII);
 #endif
index ce32fe73aff2c7d42d683ee71bf4f4eedfcf6a81..ea42c63eaafd74300374dd5734726f6a64aaf8e3 100644 (file)
@@ -1499,3 +1499,65 @@ int fdt_read_range(void *fdt, int node, int n, uint64_t *child_addr,
 
        return 0;
 }
+
+/**
+ * fdt_setup_simplefb_node - Fill and enable a simplefb node
+ *
+ * @fdt: ptr to device tree
+ * @node: offset of the simplefb node
+ * @base_address: framebuffer base address
+ * @width: width in pixels
+ * @height: height in pixels
+ * @stride: bytes per line
+ * @format: pixel format string
+ *
+ * Convenience function to fill and enable a simplefb node.
+ */
+int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width,
+                           u32 height, u32 stride, const char *format)
+{
+       char name[32];
+       fdt32_t cells[4];
+       int i, addrc, sizec, ret;
+
+       of_bus_default_count_cells(fdt, fdt_parent_offset(fdt, node),
+                                  &addrc, &sizec);
+       i = 0;
+       if (addrc == 2)
+               cells[i++] = cpu_to_fdt32(base_address >> 32);
+       cells[i++] = cpu_to_fdt32(base_address);
+       if (sizec == 2)
+               cells[i++] = 0;
+       cells[i++] = cpu_to_fdt32(height * stride);
+
+       ret = fdt_setprop(fdt, node, "reg", cells, sizeof(cells[0]) * i);
+       if (ret < 0)
+               return ret;
+
+       snprintf(name, sizeof(name), "framebuffer@%llx", base_address);
+       ret = fdt_set_name(fdt, node, name);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_u32(fdt, node, "width", width);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_u32(fdt, node, "height", height);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_u32(fdt, node, "stride", stride);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_string(fdt, node, "format", format);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_string(fdt, node, "status", "okay");
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
index d8e13715c18f82c269cfd3b670a9567bbf895fd3..28b3fe79184d627eebbe941e46330955d5092fab 100644 (file)
@@ -30,6 +30,7 @@
 #include <splash.h>
 #include <asm/io.h>
 #include <asm/unaligned.h>
+#include <fdt_support.h>
 
 #if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \
        defined(CONFIG_CPU_MONAHANS)
@@ -1172,51 +1173,13 @@ int lcd_get_screen_columns(void)
 #if defined(CONFIG_LCD_DT_SIMPLEFB)
 static int lcd_dt_simplefb_configure_node(void *blob, int off)
 {
-       u32 stride;
-       fdt32_t cells[2];
-       int ret;
-       static const char format[] =
 #if LCD_BPP == LCD_COLOR16
-               "r5g6b5";
+       return fdt_setup_simplefb_node(blob, off, gd->fb_base,
+                                      panel_info.vl_col, panel_info.vl_row,
+                                      panel_info.vl_col * 2, "r5g6b5");
 #else
-               "";
+       return -1;
 #endif
-
-       if (!format[0])
-               return -1;
-
-       stride = panel_info.vl_col * 2;
-
-       cells[0] = cpu_to_fdt32(gd->fb_base);
-       cells[1] = cpu_to_fdt32(stride * panel_info.vl_row);
-       ret = fdt_setprop(blob, off, "reg", cells, sizeof(cells[0]) * 2);
-       if (ret < 0)
-               return -1;
-
-       cells[0] = cpu_to_fdt32(panel_info.vl_col);
-       ret = fdt_setprop(blob, off, "width", cells, sizeof(cells[0]));
-       if (ret < 0)
-               return -1;
-
-       cells[0] = cpu_to_fdt32(panel_info.vl_row);
-       ret = fdt_setprop(blob, off, "height", cells, sizeof(cells[0]));
-       if (ret < 0)
-               return -1;
-
-       cells[0] = cpu_to_fdt32(stride);
-       ret = fdt_setprop(blob, off, "stride", cells, sizeof(cells[0]));
-       if (ret < 0)
-               return -1;
-
-       ret = fdt_setprop(blob, off, "format", format, strlen(format) + 1);
-       if (ret < 0)
-               return -1;
-
-       ret = fdt_delprop(blob, off, "status");
-       if (ret < 0)
-               return -1;
-
-       return 0;
 }
 
 int lcd_dt_simplefb_add_node(void *blob)
index 8517203613327389ecc9b75557dc19def929889e..be8652b459a29c768ac59d00f0ed29f4c92343b7 100644 (file)
@@ -2,6 +2,8 @@ CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,USB_EHCI"
 CONFIG_FDTFILE="sun5i-a13-olinuxino-micro.dtb"
 CONFIG_USB1_VBUS_PIN="PG11"
+CONFIG_VIDEO=n
+CONFIG_USB_KEYBOARD=n
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
index 61f54666c24eb6608172380f329cf23ff9a0850b..654e12aaa3fb0dbb18ebd3472795b7b37fe996a4 100644 (file)
@@ -2,6 +2,8 @@ CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=2,AXP209_POWER,USB_EHCI"
 CONFIG_FDTFILE="sun5i-a13-olinuxino.dtb"
 CONFIG_USB1_VBUS_PIN="PG11"
+CONFIG_VIDEO=n
+CONFIG_USB_KEYBOARD=n
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN5I=y
index bef568df7132bd885e7f1241ea006fab1bb48c8d..de78a01801ed939aebaee7e0ba30f75616d3e947 100644 (file)
@@ -1,5 +1,6 @@
 CONFIG_SPL=y
 CONFIG_FDTFILE="sun6i-a31-colombus.dtb"
+CONFIG_USB_KEYBOARD=n
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
 +S:CONFIG_MACH_SUN6I=y
index fc67bd9d56cec113477818eccb1c2af3943c8436..50c2f9366ed9e87197e2d2099adadc52c01795a4 100644 (file)
@@ -4,3 +4,5 @@ CONFIG_ARCH_SUNXI=y
 CONFIG_MACH_SUN8I=y
 CONFIG_TARGET_IPPO_Q8H_V5=y
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
+CONFIG_VIDEO=n
+CONFIG_USB_KEYBOARD=n
index f46439fa4e8bb91d4d0b90827d82869a6c9b640d..ac3cd36be800e4bee266706d8ea10435b1d482e3 100644 (file)
@@ -1,5 +1,5 @@
 CONFIG_SPL=y
-CONFIG_SYS_EXTRA_OPTIONS="USB_EHCI"
+CONFIG_SYS_EXTRA_OPTIONS="USB_EHCI,SUNXI_GMAC"
 CONFIG_FDTFILE="sun6i-a31-m9.dtb"
 +S:CONFIG_ARM=y
 +S:CONFIG_ARCH_SUNXI=y
@@ -14,5 +14,7 @@ CONFIG_FDTFILE="sun6i-a31-m9.dtb"
 # HDMI power ?
 +S:CONFIG_AXP221_ALDO2_VOLT=1800
 +S:CONFIG_AXP221_ALDO3_VOLT=3000
-# No Vbus gpio for usb1
-+S:CONFIG_USB1_VBUS_PIN=""
+# Vbus gpio for usb1
++S:CONFIG_USB1_VBUS_PIN="PC27"
+# No Vbus gpio for usb2
++S:CONFIG_USB2_VBUS_PIN=""
index 14a6781edca17c9bd830c6b714a081b133030d80..7301be395548083053d30cea6fd8992ab95a55fd 100644 (file)
@@ -39,6 +39,7 @@ obj-$(CONFIG_VIDEO_SANDBOX_SDL) += sandbox_sdl.o
 obj-$(CONFIG_VIDEO_SED13806) += sed13806.o
 obj-$(CONFIG_VIDEO_SM501) += sm501.o
 obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o
+obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o
 obj-$(CONFIG_VIDEO_TEGRA) += tegra.o
 obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
 obj-$(CONFIG_FORMIKE) += formike.o
diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c
new file mode 100644 (file)
index 0000000..d241397
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * Display driver for Allwinner SoCs.
+ *
+ * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
+ * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <asm/arch/clock.h>
+#include <asm/arch/display.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <fdtdec.h>
+#include <fdt_support.h>
+#include <linux/fb.h>
+#include <video_fb.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct sunxi_display {
+       GraphicDevice graphic_device;
+       bool enabled;
+} sunxi_display;
+
+static int sunxi_hdmi_hpd_detect(void)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       struct sunxi_hdmi_reg * const hdmi =
+               (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
+
+       /* Set pll3 to 300MHz */
+       clock_set_pll3(300000000);
+
+       /* Set hdmi parent to pll3 */
+       clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK,
+                       CCM_HDMI_CTRL_PLL3);
+
+       /* Set ahb gating to pass */
+#ifdef CONFIG_MACH_SUN6I
+       setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
+#endif
+       setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
+
+       /* Clock on */
+       setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
+
+       writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl);
+       writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0);
+
+       udelay(1000);
+
+       if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT)
+               return 1;
+
+       /* No need to keep these running */
+       clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE);
+       clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE);
+       clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI);
+#ifdef CONFIG_MACH_SUN6I
+       clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI);
+#endif
+       clock_set_pll3(0);
+
+       return 0;
+}
+
+/*
+ * This is the entity that mixes and matches the different layers and inputs.
+ * Allwinner calls it the back-end, but i like composer better.
+ */
+static void sunxi_composer_init(void)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       struct sunxi_de_be_reg * const de_be =
+               (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
+       int i;
+
+#ifdef CONFIG_MACH_SUN6I
+       /* Reset off */
+       setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0);
+#endif
+
+       /* Clocks on */
+       setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0);
+       setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0);
+       clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000);
+
+       /* Engine bug, clear registers after reset */
+       for (i = 0x0800; i < 0x1000; i += 4)
+               writel(0, SUNXI_DE_BE0_BASE + i);
+
+       setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE);
+}
+
+static void sunxi_composer_mode_set(struct fb_videomode *mode,
+                                   unsigned int address)
+{
+       struct sunxi_de_be_reg * const de_be =
+               (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
+
+       writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
+              &de_be->disp_size);
+       writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres),
+              &de_be->layer0_size);
+       writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride);
+       writel(address << 3, &de_be->layer0_addr_low32b);
+       writel(address >> 29, &de_be->layer0_addr_high4b);
+       writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
+
+       setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
+}
+
+/*
+ * LCDC, what allwinner calls a CRTC, so timing controller and serializer.
+ */
+static void sunxi_lcdc_pll_set(int dotclock, int *clk_div, int *clk_double)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       int value, n, m, diff;
+       int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF;
+       int best_double = 0;
+
+       /*
+        * Find the lowest divider resulting in a matching clock, if there
+        * is no match, pick the closest lower clock, as monitors tend to
+        * not sync to higher frequencies.
+        */
+       for (m = 15; m > 0; m--) {
+               n = (m * dotclock) / 3000;
+
+               if ((n >= 9) && (n <= 127)) {
+                       value = (3000 * n) / m;
+                       diff = dotclock - value;
+                       if (diff < best_diff) {
+                               best_diff = diff;
+                               best_m = m;
+                               best_n = n;
+                               best_double = 0;
+                       }
+               }
+
+               /* These are just duplicates */
+               if (!(m & 1))
+                       continue;
+
+               n = (m * dotclock) / 6000;
+               if ((n >= 9) && (n <= 127)) {
+                       value = (6000 * n) / m;
+                       diff = dotclock - value;
+                       if (diff < best_diff) {
+                               best_diff = diff;
+                               best_m = m;
+                               best_n = n;
+                               best_double = 1;
+                       }
+               }
+       }
+
+       debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n",
+             dotclock, (best_double + 1) * 3000 * best_n / best_m,
+             best_double + 1, best_n, best_m);
+
+       clock_set_pll3(best_n * 3000000);
+
+       writel(CCM_LCD_CH1_CTRL_GATE |
+           (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X : CCM_LCD_CH1_CTRL_PLL3) |
+           CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
+
+       *clk_div = best_m;
+       *clk_double = best_double;
+}
+
+static void sunxi_lcdc_init(void)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+       struct sunxi_lcdc_reg * const lcdc =
+               (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+
+       /* Reset off */
+#ifdef CONFIG_MACH_SUN6I
+       setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0);
+#else
+       setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST);
+#endif
+
+       /* Clock on */
+       setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0);
+
+       /* Init lcdc */
+       writel(0, &lcdc->ctrl); /* Disable tcon */
+       writel(0, &lcdc->int0); /* Disable all interrupts */
+
+       /* Disable tcon0 dot clock */
+       clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE);
+
+       /* Set all io lines to tristate */
+       writel(0xffffffff, &lcdc->tcon0_io_tristate);
+       writel(0xffffffff, &lcdc->tcon1_io_tristate);
+}
+
+static void sunxi_lcdc_mode_set(struct fb_videomode *mode,
+                               int *clk_div, int *clk_double)
+{
+       struct sunxi_lcdc_reg * const lcdc =
+               (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+       int bp, total;
+
+       /* Use tcon1 */
+       clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
+                       SUNXI_LCDC_CTRL_IO_MAP_TCON1);
+
+       /* Enabled, 0x1e start delay */
+       writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
+              SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(0x1e), &lcdc->tcon1_ctrl);
+
+       writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
+              &lcdc->tcon1_timing_source);
+       writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
+              &lcdc->tcon1_timing_scale);
+       writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
+              &lcdc->tcon1_timing_out);
+
+       bp = mode->hsync_len + mode->left_margin;
+       total = mode->xres + mode->right_margin + bp;
+       writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) |
+              SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h);
+
+       bp = mode->vsync_len + mode->upper_margin;
+       total = mode->yres + mode->lower_margin + bp;
+       writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
+              SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
+
+       writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
+              &lcdc->tcon1_timing_sync);
+
+       sunxi_lcdc_pll_set(mode->pixclock, clk_div, clk_double);
+}
+
+#ifdef CONFIG_MACH_SUN6I
+static void sunxi_drc_init(void)
+{
+       struct sunxi_ccm_reg * const ccm =
+               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+       /* On sun6i the drc must be clocked even when in pass-through mode */
+       setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0);
+       clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000);
+}
+#endif
+
+static void sunxi_hdmi_mode_set(struct fb_videomode *mode,
+                               int clk_div, int clk_double)
+{
+       struct sunxi_hdmi_reg * const hdmi =
+               (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
+       int x, y;
+
+       /* Write clear interrupt status bits */
+       writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
+
+       /* Init various registers, select pll3 as clock source */
+       writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
+       writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
+       writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1);
+       writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl);
+       writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0);
+
+       /* Setup clk div and doubler */
+       clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK,
+                       SUNXI_HDMI_PLL_CTRL_DIV(clk_div));
+       if (!clk_double)
+               setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE);
+
+       /* Setup timing registers */
+       writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres),
+              &hdmi->video_size);
+
+       x = mode->hsync_len + mode->left_margin;
+       y = mode->vsync_len + mode->upper_margin;
+       writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp);
+
+       x = mode->right_margin;
+       y = mode->lower_margin;
+       writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp);
+
+       x = mode->hsync_len;
+       y = mode->vsync_len;
+       writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw);
+
+       if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+               setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR);
+
+       if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+               setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER);
+}
+
+static void sunxi_engines_init(void)
+{
+       sunxi_composer_init();
+       sunxi_lcdc_init();
+#ifdef CONFIG_MACH_SUN6I
+       sunxi_drc_init();
+#endif
+}
+
+static void sunxi_mode_set(struct fb_videomode *mode, unsigned int address)
+{
+       struct sunxi_de_be_reg * const de_be =
+               (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
+       struct sunxi_lcdc_reg * const lcdc =
+               (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+       struct sunxi_hdmi_reg * const hdmi =
+               (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
+       int clk_div, clk_double;
+       int retries = 3;
+
+retry:
+       clrbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
+       clrbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
+       clrbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
+
+       sunxi_composer_mode_set(mode, address);
+       sunxi_lcdc_mode_set(mode, &clk_div, &clk_double);
+       sunxi_hdmi_mode_set(mode, clk_div, clk_double);
+
+       setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
+       setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
+
+       udelay(1000000 / mode->refresh + 500);
+
+       setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
+
+       udelay(1000000 / mode->refresh + 500);
+
+       setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
+
+       udelay(1000000 / mode->refresh + 500);
+
+       /*
+        * Sometimes the display pipeline does not sync up properly, if
+        * this happens the hdmi fifo underrun or overrun bits are set.
+        */
+       if (readl(&hdmi->irq) &
+           (SUNXI_HDMI_IRQ_STATUS_FIFO_UF | SUNXI_HDMI_IRQ_STATUS_FIFO_OF)) {
+               if (retries--)
+                       goto retry;
+               printf("HDMI fifo under or overrun\n");
+       }
+}
+
+void *video_hw_init(void)
+{
+       static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+       /*
+        * Vesa standard 1024x768@60
+        * 65.0  1024 1048 1184 1344  768 771 777 806  -hsync -vsync
+        */
+       struct fb_videomode mode = {
+               .name = "1024x768",
+               .refresh = 60,
+               .xres = 1024,
+               .yres = 768,
+               .pixclock = 65000,
+               .left_margin = 160,
+               .right_margin = 24,
+               .upper_margin = 29,
+               .lower_margin = 3,
+               .hsync_len = 136,
+               .vsync_len = 6,
+               .sync = 0,
+               .vmode = 0,
+               .flag = 0,
+       };
+       int ret;
+
+       memset(&sunxi_display, 0, sizeof(struct sunxi_display));
+
+       printf("Reserved %dkB of RAM for Framebuffer.\n",
+              CONFIG_SUNXI_FB_SIZE >> 10);
+       gd->fb_base = gd->ram_top;
+
+       ret = sunxi_hdmi_hpd_detect();
+       if (!ret)
+               return NULL;
+
+       printf("HDMI connected.\n");
+       sunxi_display.enabled = true;
+
+       printf("Setting up a %s console.\n", mode.name);
+       sunxi_engines_init();
+       sunxi_mode_set(&mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
+
+       /*
+        * These are the only members of this structure that are used. All the
+        * others are driver specific. There is nothing to decribe pitch or
+        * stride, but we are lucky with our hw.
+        */
+       graphic_device->frameAdrs = gd->fb_base;
+       graphic_device->gdfIndex = GDF_32BIT_X888RGB;
+       graphic_device->gdfBytesPP = 4;
+       graphic_device->winSizeX = mode.xres;
+       graphic_device->winSizeY = mode.yres;
+
+       return graphic_device;
+}
+
+/*
+ * Simplefb support.
+ */
+#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
+int sunxi_simplefb_setup(void *blob)
+{
+       static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+       int offset, ret;
+
+       if (!sunxi_display.enabled)
+               return 0;
+
+       /* Find a framebuffer node, with pipeline == "de_be0-lcd0-hdmi" */
+       offset = fdt_node_offset_by_compatible(blob, -1,
+                                              "allwinner,simple-framebuffer");
+       while (offset >= 0) {
+               ret = fdt_find_string(blob, offset, "allwinner,pipeline",
+                                     "de_be0-lcd0-hdmi");
+               if (ret == 0)
+                       break;
+               offset = fdt_node_offset_by_compatible(blob, offset,
+                                              "allwinner,simple-framebuffer");
+       }
+       if (offset < 0) {
+               eprintf("Cannot setup simplefb: node not found\n");
+               return 0; /* Keep older kernels working */
+       }
+
+       ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
+                       graphic_device->winSizeX, graphic_device->winSizeY,
+                       graphic_device->winSizeX * graphic_device->gdfBytesPP,
+                       "x8r8g8b8");
+       if (ret)
+               eprintf("Cannot setup simplefb: Error setting properties\n");
+
+       return ret;
+}
+#endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */
index 36295876fd87fe6367afe20b1cb38befdb99da8d..f6b1b3edc12f0cf2c5f2ffb676a3e121517571ef 100644 (file)
@@ -23,7 +23,6 @@
 #endif
 
 #define CONFIG_ARMV7_PSCI              1
-#define CONFIG_ARMV7_PSCI_NR_CPUS      2
 #define CONFIG_ARMV7_SECURE_BASE       SUNXI_SRAM_B_BASE
 #define CONFIG_SYS_CLK_FREQ            24000000
 
index ce038eddf04b1858cc87bf22fc87709301559599..3f890b2fb0338f63fbf46655189f9d27b55699d8 100644 (file)
 #define CONFIG_SPL_GPIO_SUPPORT
 #define CONFIG_CMD_GPIO
 
+#ifdef CONFIG_VIDEO
+/*
+ * The amount of RAM that is reserved for the FB. This will not show up as
+ * RAM to the kernel, but will be reclaimed by a KMS driver in future.
+ */
+#define CONFIG_SUNXI_FB_SIZE (8 << 20)
+
+/* Do we want to initialize a simple FB? */
+#define CONFIG_VIDEO_DT_SIMPLEFB
+
+#define CONFIG_VIDEO_SUNXI
+
+#define CONFIG_CFB_CONSOLE
+#define CONFIG_VIDEO_SW_CURSOR
+#define CONFIG_VIDEO_LOGO
+
+/* allow both serial and cfb console. */
+#define CONFIG_CONSOLE_MUX
+/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
+#define CONFIG_VGA_AS_SINGLE_DEVICE
+
+#define CONFIG_SYS_MEM_TOP_HIDE ((CONFIG_SUNXI_FB_SIZE + 0xFFF) & ~0xFFF)
+
+/* To be able to hook simplefb into dt */
+#ifdef CONFIG_VIDEO_DT_SIMPLEFB
+#define CONFIG_OF_BOARD_SETUP
+#endif
+
+#endif /* CONFIG_VIDEO */
+
 /* Ethernet support */
 #ifdef CONFIG_SUNXI_EMAC
 #define CONFIG_MII                     /* MII PHY management           */
 #define CONFIG_USB_STORAGE
 #endif
 
+#ifdef CONFIG_USB_KEYBOARD
+#define CONFIG_CONSOLE_MUX
+#define CONFIG_PREBOOT
+#define CONFIG_SYS_STDIO_DEREGISTER
+#define CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
+#endif
+
 #if !defined CONFIG_ENV_IS_IN_MMC && \
     !defined CONFIG_ENV_IS_IN_NAND && \
     !defined CONFIG_ENV_IS_IN_FAT && \
 #endif
 
 #define CONFIG_MISC_INIT_R
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
 
 #ifndef CONFIG_SPL_BUILD
 #include <config_distro_defaults.h>
 
 #include <config_distro_bootcmd.h>
 
+#ifdef CONFIG_USB_KEYBOARD
+#define CONSOLE_STDIN_SETTINGS \
+       "preboot=usb start\0" \
+       "stdin=serial,usbkbd\0"
+#else
+#define CONSOLE_STDIN_SETTINGS \
+       "stdin=serial\0"
+#endif
+
+#ifdef CONFIG_VIDEO
+#define CONSOLE_STDOUT_SETTINGS \
+       "stdout=serial,vga\0" \
+       "stderr=serial,vga\0"
+#else
+#define CONSOLE_STDOUT_SETTINGS \
+       "stdout=serial\0" \
+       "stderr=serial\0"
+#endif
+
+#define CONSOLE_ENV_SETTINGS \
+       CONSOLE_STDIN_SETTINGS \
+       CONSOLE_STDOUT_SETTINGS
+
 #define CONFIG_EXTRA_ENV_SETTINGS \
+       CONSOLE_ENV_SETTINGS \
        MEM_LAYOUT_ENV_SETTINGS \
        "fdtfile=" CONFIG_FDTFILE "\0" \
        "console=ttyS0,115200\0" \
index 0fbc9bdd6717d48b7a9d9319c0ab2baab6c93e65..1f19fe4c9622a84c365f500ff80b2b72bb61baf1 100644 (file)
@@ -172,6 +172,9 @@ void of_bus_default_count_cells(void *blob, int parentoffset,
 int ft_verify_fdt(void *fdt);
 int arch_fixup_memory_node(void *blob);
 
+int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width,
+                           u32 height, u32 stride, const char *format);
+
 #endif /* ifdef CONFIG_OF_LIBFDT */
 
 #ifdef USE_HOSTCC