summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv7/sunxi/clock_sun4i.c27
-rw-r--r--arch/arm/cpu/armv7/sunxi/clock_sun6i.c29
-rw-r--r--arch/arm/cpu/armv7/sunxi/dram_sun4i.c4
-rw-r--r--arch/arm/cpu/armv7/sunxi/dram_sun6i.c3
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock.h2
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun4i.h47
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun6i.h67
-rw-r--r--arch/arm/include/asm/arch-sunxi/cpu.h4
-rw-r--r--arch/arm/include/asm/arch-sunxi/display.h187
-rw-r--r--arch/arm/include/asm/arch-sunxi/gpio.h1
-rw-r--r--board/sunxi/Kconfig15
-rw-r--r--board/sunxi/ahci.c2
-rw-r--r--board/sunxi/board.c10
-rw-r--r--board/sunxi/gmac.c45
-rw-r--r--common/fdt_support.c62
-rw-r--r--common/lcd.c47
-rw-r--r--configs/A13-OLinuXinoM_defconfig2
-rw-r--r--configs/A13-OLinuXino_defconfig2
-rw-r--r--configs/Colombus_defconfig1
-rw-r--r--configs/Ippo_q8h_v5_defconfig2
-rw-r--r--configs/Mele_M9_defconfig8
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/sunxi_display.c451
-rw-r--r--include/configs/sun7i.h1
-rw-r--r--include/configs/sunxi-common.h62
-rw-r--r--include/fdt_support.h3
26 files changed, 1032 insertions, 53 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
index a0e49d1..49f4032 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
@@ -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);
+}
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
index 16ab6f3..8e949c6 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
@@ -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);
+}
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
index dc9fdb9..ec8aaa7 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun4i.c
@@ -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
}
diff --git a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
index 10a6241..699173c 100644
--- a/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
+++ b/arch/arm/cpu/armv7/sunxi/dram_sun6i.c
@@ -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);
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index b40c16b..64acff3 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -25,9 +25,11 @@
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
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
index 9dca800..eb88969 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index e16a764..3599054 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index bdee89e..2c92b5c 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -99,9 +99,13 @@
#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
index 0000000..ddb71c1
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/display.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index c734cf0..366c0dc 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -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
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index 7555896..246cd9a 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -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
diff --git a/board/sunxi/ahci.c b/board/sunxi/ahci.c
index 5e12328..b7f0dda 100644
--- a/board/sunxi/ahci.c
+++ b/board/sunxi/ahci.c
@@ -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)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index e6ec5b8..4c1c69a 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -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 */
diff --git a/board/sunxi/gmac.c b/board/sunxi/gmac.c
index 051aca0..571bc9e 100644
--- a/board/sunxi/gmac.c
+++ b/board/sunxi/gmac.c
@@ -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
diff --git a/common/fdt_support.c b/common/fdt_support.c
index ce32fe7..ea42c63 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -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;
+}
diff --git a/common/lcd.c b/common/lcd.c
index d8e1371..28b3fe7 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -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)
diff --git a/configs/A13-OLinuXinoM_defconfig b/configs/A13-OLinuXinoM_defconfig
index 8517203..be8652b 100644
--- a/configs/A13-OLinuXinoM_defconfig
+++ b/configs/A13-OLinuXinoM_defconfig
@@ -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
diff --git a/configs/A13-OLinuXino_defconfig b/configs/A13-OLinuXino_defconfig
index 61f5466..654e12a 100644
--- a/configs/A13-OLinuXino_defconfig
+++ b/configs/A13-OLinuXino_defconfig
@@ -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
diff --git a/configs/Colombus_defconfig b/configs/Colombus_defconfig
index bef568d..de78a01 100644
--- a/configs/Colombus_defconfig
+++ b/configs/Colombus_defconfig
@@ -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
diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig
index fc67bd9..50c2f93 100644
--- a/configs/Ippo_q8h_v5_defconfig
+++ b/configs/Ippo_q8h_v5_defconfig
@@ -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
diff --git a/configs/Mele_M9_defconfig b/configs/Mele_M9_defconfig
index f46439f..ac3cd36 100644
--- a/configs/Mele_M9_defconfig
+++ b/configs/Mele_M9_defconfig
@@ -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=""
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 14a6781..7301be3 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -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
index 0000000..d241397
--- /dev/null
+++ b/drivers/video/sunxi_display.c
@@ -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 */
diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h
index 3629587..f6b1b3e 100644
--- a/include/configs/sun7i.h
+++ b/include/configs/sun7i.h
@@ -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
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index ce038ed..3f890b2 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -197,6 +197,36 @@
#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 */
@@ -217,6 +247,13 @@
#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 && \
@@ -225,6 +262,7 @@
#endif
#define CONFIG_MISC_INIT_R
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV
#ifndef CONFIG_SPL_BUILD
#include <config_distro_defaults.h>
@@ -266,7 +304,31 @@
#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" \
diff --git a/include/fdt_support.h b/include/fdt_support.h
index 0fbc9bd..1f19fe4 100644
--- a/include/fdt_support.h
+++ b/include/fdt_support.h
@@ -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