Commit f2ffe7da7fcc266f8c9cb557031066cfd5eb2a03
Exists in
v2017.01-smarct4x
and in
37 other branches
Merge branch 'master' of http://git.denx.de/u-boot-sunxi
Showing 26 changed files Side-by-side Diff
- 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
- 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
- include/configs/sun7i.h
- include/configs/sunxi-common.h
- include/fdt_support.h
arch/arm/cpu/armv7/sunxi/clock_sun4i.c
... | ... | @@ -180,6 +180,21 @@ |
180 | 180 | } |
181 | 181 | #endif |
182 | 182 | |
183 | +void clock_set_pll3(unsigned int clk) | |
184 | +{ | |
185 | + struct sunxi_ccm_reg * const ccm = | |
186 | + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | |
187 | + | |
188 | + if (clk == 0) { | |
189 | + clrbits_le32(&ccm->pll3_cfg, CCM_PLL3_CTRL_EN); | |
190 | + return; | |
191 | + } | |
192 | + | |
193 | + /* PLL3 rate = 3000000 * m */ | |
194 | + writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE | | |
195 | + CCM_PLL3_CTRL_M(clk / 3000000), &ccm->pll3_cfg); | |
196 | +} | |
197 | + | |
183 | 198 | unsigned int clock_get_pll5p(void) |
184 | 199 | { |
185 | 200 | struct sunxi_ccm_reg *const ccm = |
... | ... | @@ -199,5 +214,17 @@ |
199 | 214 | int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT); |
200 | 215 | int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1; |
201 | 216 | return 24000000 * n * k / 2; |
217 | +} | |
218 | + | |
219 | +void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz) | |
220 | +{ | |
221 | + int pll = clock_get_pll5p(); | |
222 | + int div = 1; | |
223 | + | |
224 | + while ((pll / div) > hz) | |
225 | + div++; | |
226 | + | |
227 | + writel(CCM_DE_CTRL_GATE | CCM_DE_CTRL_RST | CCM_DE_CTRL_PLL5P | | |
228 | + CCM_DE_CTRL_M(div), clk_cfg); | |
202 | 229 | } |
arch/arm/cpu/armv7/sunxi/clock_sun6i.c
... | ... | @@ -127,6 +127,23 @@ |
127 | 127 | } |
128 | 128 | #endif |
129 | 129 | |
130 | +void clock_set_pll3(unsigned int clk) | |
131 | +{ | |
132 | + struct sunxi_ccm_reg * const ccm = | |
133 | + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | |
134 | + const int m = 8; /* 3 MHz steps just like sun4i, sun5i and sun7i */ | |
135 | + | |
136 | + if (clk == 0) { | |
137 | + clrbits_le32(&ccm->pll3_cfg, CCM_PLL3_CTRL_EN); | |
138 | + return; | |
139 | + } | |
140 | + | |
141 | + /* PLL3 rate = 24000000 * n / m */ | |
142 | + writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE | | |
143 | + CCM_PLL3_CTRL_N(clk / (24000000 / m)) | CCM_PLL3_CTRL_M(m), | |
144 | + &ccm->pll3_cfg); | |
145 | +} | |
146 | + | |
130 | 147 | void clock_set_pll5(unsigned int clk) |
131 | 148 | { |
132 | 149 | struct sunxi_ccm_reg * const ccm = |
... | ... | @@ -150,5 +167,17 @@ |
150 | 167 | int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1; |
151 | 168 | int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1; |
152 | 169 | return 24000000 * n * k / 2; |
170 | +} | |
171 | + | |
172 | +void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz) | |
173 | +{ | |
174 | + int pll = clock_get_pll6() * 2; | |
175 | + int div = 1; | |
176 | + | |
177 | + while ((pll / div) > hz) | |
178 | + div++; | |
179 | + | |
180 | + writel(CCM_DE_CTRL_GATE | CCM_DE_CTRL_PLL6_2X | CCM_DE_CTRL_M(div), | |
181 | + clk_cfg); | |
153 | 182 | } |
arch/arm/cpu/armv7/sunxi/dram_sun4i.c
... | ... | @@ -428,9 +428,9 @@ |
428 | 428 | #ifdef CONFIG_MACH_SUN4I |
429 | 429 | struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; |
430 | 430 | if (on) |
431 | - setbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT); | |
431 | + setbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT); | |
432 | 432 | else |
433 | - clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT); | |
433 | + clrbits_le32(&ccm->dram_clk_gate, CCM_DRAM_CTRL_DCLK_OUT); | |
434 | 434 | #endif |
435 | 435 | } |
436 | 436 |
arch/arm/cpu/armv7/sunxi/dram_sun6i.c
... | ... | @@ -142,9 +142,6 @@ |
142 | 142 | |
143 | 143 | writel((MCTL_TITMSRST << 18) | (MCTL_TDLLLOCK << 6) | MCTL_TDLLSRST, |
144 | 144 | &mctl_phy->ptr0); |
145 | - /* Unknown magic performed by boot0 */ | |
146 | - if ((readl(SUNXI_RTC_BASE + 0x20c) & 3) == 2) | |
147 | - setbits_le32(&mctl_phy->ptr0, 1 << 18); | |
148 | 145 | |
149 | 146 | writel((MCTL_TDINIT1 << 19) | MCTL_TDINIT0, &mctl_phy->ptr1); |
150 | 147 | writel((MCTL_TDINIT3 << 17) | MCTL_TDINIT2, &mctl_phy->ptr2); |
arch/arm/include/asm/arch-sunxi/clock.h
... | ... | @@ -25,9 +25,11 @@ |
25 | 25 | int clock_init(void); |
26 | 26 | int clock_twi_onoff(int port, int state); |
27 | 27 | void clock_set_pll1(unsigned int hz); |
28 | +void clock_set_pll3(unsigned int hz); | |
28 | 29 | void clock_set_pll5(unsigned int hz); |
29 | 30 | unsigned int clock_get_pll5p(void); |
30 | 31 | unsigned int clock_get_pll6(void); |
32 | +void clock_set_de_mod_clock(u32 *clk_cfg, unsigned int hz); | |
31 | 33 | void clock_init_safe(void); |
32 | 34 | void clock_init_uart(void); |
33 | 35 | #endif |
arch/arm/include/asm/arch-sunxi/clock_sun4i.h
... | ... | @@ -62,7 +62,7 @@ |
62 | 62 | u32 gps_clk_cfg; /* 0xd0 */ |
63 | 63 | u32 spi3_clk_cfg; /* 0xd4 */ |
64 | 64 | u8 res5[0x28]; |
65 | - u32 dram_clk_cfg; /* 0x100 */ | |
65 | + u32 dram_clk_gate; /* 0x100 */ | |
66 | 66 | u32 be0_clk_cfg; /* 0x104 */ |
67 | 67 | u32 be1_clk_cfg; /* 0x108 */ |
68 | 68 | u32 fe0_clk_cfg; /* 0x10c */ |
69 | 69 | |
... | ... | @@ -186,12 +186,20 @@ |
186 | 186 | |
187 | 187 | /* ahb clock gate bit offset (second register) */ |
188 | 188 | #define AHB_GATE_OFFSET_GMAC 17 |
189 | +#define AHB_GATE_OFFSET_DE_BE0 12 | |
190 | +#define AHB_GATE_OFFSET_HDMI 11 | |
191 | +#define AHB_GATE_OFFSET_LCD1 5 | |
192 | +#define AHB_GATE_OFFSET_LCD0 4 | |
189 | 193 | |
190 | 194 | #define CCM_AHB_GATE_GPS (0x1 << 26) |
191 | 195 | #define CCM_AHB_GATE_SDRAM (0x1 << 14) |
192 | 196 | #define CCM_AHB_GATE_DLL (0x1 << 15) |
193 | 197 | #define CCM_AHB_GATE_ACE (0x1 << 16) |
194 | 198 | |
199 | +#define CCM_PLL3_CTRL_M(n) (((n) & 0x7f) << 0) | |
200 | +#define CCM_PLL3_CTRL_INTEGER_MODE (0x1 << 15) | |
201 | +#define CCM_PLL3_CTRL_EN (0x1 << 31) | |
202 | + | |
195 | 203 | #define CCM_PLL5_CTRL_M(n) (((n) & 0x3) << 0) |
196 | 204 | #define CCM_PLL5_CTRL_M_MASK CCM_PLL5_CTRL_M(0x3) |
197 | 205 | #define CCM_PLL5_CTRL_M_X(n) ((n) - 1) |
... | ... | @@ -253,6 +261,34 @@ |
253 | 261 | |
254 | 262 | #define CCM_MMC_CTRL_ENABLE (0x1 << 31) |
255 | 263 | |
264 | +#define CCM_DRAM_GATE_OFFSET_DE_BE0 26 | |
265 | + | |
266 | +#define CCM_LCD_CH0_CTRL_PLL3 (0 << 24) | |
267 | +#define CCM_LCD_CH0_CTRL_PLL7 (1 << 24) | |
268 | +#define CCM_LCD_CH0_CTRL_PLL3_2X (2 << 24) | |
269 | +#define CCM_LCD_CH0_CTRL_PLL7_2X (3 << 24) | |
270 | +#define CCM_LCD_CH0_CTRL_RST (0x1 << 30) | |
271 | +#define CCM_LCD_CH0_CTRL_GATE (0x1 << 31) | |
272 | + | |
273 | +#define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0) | |
274 | +/* We leave bit 11 set to 0, so sclk1 == sclk2 */ | |
275 | +#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24) | |
276 | +#define CCM_LCD_CH1_CTRL_PLL7 (1 << 24) | |
277 | +#define CCM_LCD_CH1_CTRL_PLL3_2X (2 << 24) | |
278 | +#define CCM_LCD_CH1_CTRL_PLL7_2X (3 << 24) | |
279 | +/* Enable / disable both ch1 sclk1 and sclk2 at the same time */ | |
280 | +#define CCM_LCD_CH1_CTRL_GATE (0x1 << 31 | 0x1 << 15) | |
281 | + | |
282 | +#define CCM_HDMI_CTRL_M(n) ((((n) - 1) & 0xf) << 0) | |
283 | +#define CCM_HDMI_CTRL_PLL_MASK (3 << 24) | |
284 | +#define CCM_HDMI_CTRL_PLL3 (0 << 24) | |
285 | +#define CCM_HDMI_CTRL_PLL7 (1 << 24) | |
286 | +#define CCM_HDMI_CTRL_PLL3_2X (2 << 24) | |
287 | +#define CCM_HDMI_CTRL_PLL7_2X (3 << 24) | |
288 | +/* No separate ddc gate on sun4i, sun5i and sun7i */ | |
289 | +#define CCM_HDMI_CTRL_DDC_GATE 0 | |
290 | +#define CCM_HDMI_CTRL_GATE (0x1 << 31) | |
291 | + | |
256 | 292 | #define CCM_GMAC_CTRL_TX_CLK_SRC_MII 0x0 |
257 | 293 | #define CCM_GMAC_CTRL_TX_CLK_SRC_EXT_RGMII 0x1 |
258 | 294 | #define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2 |
... | ... | @@ -265,6 +301,15 @@ |
265 | 301 | /* These 2 are sun6i only, define them as 0 on sun4i */ |
266 | 302 | #define CCM_USB_CTRL_PHY1_CLK 0 |
267 | 303 | #define CCM_USB_CTRL_PHY2_CLK 0 |
304 | + | |
305 | +/* CCM bits common to all Display Engine (and IEP) clock ctrl regs */ | |
306 | +#define CCM_DE_CTRL_M(n) ((((n) - 1) & 0xf) << 0) | |
307 | +#define CCM_DE_CTRL_PLL_MASK (3 << 24) | |
308 | +#define CCM_DE_CTRL_PLL3 (0 << 24) | |
309 | +#define CCM_DE_CTRL_PLL7 (1 << 24) | |
310 | +#define CCM_DE_CTRL_PLL5P (2 << 24) | |
311 | +#define CCM_DE_CTRL_RST (1 << 30) | |
312 | +#define CCM_DE_CTRL_GATE (1 << 31) | |
268 | 313 | |
269 | 314 | #endif /* _SUNXI_CLOCK_SUN4I_H */ |
arch/arm/include/asm/arch-sunxi/clock_sun6i.h
... | ... | @@ -176,13 +176,18 @@ |
176 | 176 | #define CCM_PLL1_CTRL_MAGIC (0x1 << 16) |
177 | 177 | #define CCM_PLL1_CTRL_EN (0x1 << 31) |
178 | 178 | |
179 | +#define CCM_PLL3_CTRL_M(n) ((((n) - 1) & 0xf) << 0) | |
180 | +#define CCM_PLL3_CTRL_N(n) ((((n) - 1) & 0x7f) << 8) | |
181 | +#define CCM_PLL3_CTRL_INTEGER_MODE (0x1 << 24) | |
182 | +#define CCM_PLL3_CTRL_EN (0x1 << 31) | |
183 | + | |
179 | 184 | #define CCM_PLL5_CTRL_M(n) ((((n) - 1) & 0x3) << 0) |
180 | 185 | #define CCM_PLL5_CTRL_K(n) ((((n) - 1) & 0x3) << 4) |
181 | 186 | #define CCM_PLL5_CTRL_N(n) ((((n) - 1) & 0x1f) << 8) |
182 | 187 | #define CCM_PLL5_CTRL_UPD (0x1 << 20) |
183 | 188 | #define CCM_PLL5_CTRL_EN (0x1 << 31) |
184 | 189 | |
185 | -#define PLL6_CFG_DEFAULT 0x90041811 | |
190 | +#define PLL6_CFG_DEFAULT 0x90041811 /* 600 MHz */ | |
186 | 191 | |
187 | 192 | #define CCM_PLL6_CTRL_N_SHIFT 8 |
188 | 193 | #define CCM_PLL6_CTRL_N_MASK (0x1f << CCM_PLL6_CTRL_N_SHIFT) |
189 | 194 | |
190 | 195 | |
... | ... | @@ -193,17 +198,26 @@ |
193 | 198 | |
194 | 199 | #define AXI_GATE_OFFSET_DRAM 0 |
195 | 200 | |
201 | +/* ahb_gate0 offsets */ | |
196 | 202 | #define AHB_GATE_OFFSET_USB_OHCI1 30 |
197 | 203 | #define AHB_GATE_OFFSET_USB_OHCI0 29 |
198 | 204 | #define AHB_GATE_OFFSET_USB_EHCI1 27 |
199 | 205 | #define AHB_GATE_OFFSET_USB_EHCI0 26 |
200 | 206 | #define AHB_GATE_OFFSET_MCTL 14 |
207 | +#define AHB_GATE_OFFSET_GMAC 17 | |
201 | 208 | #define AHB_GATE_OFFSET_MMC3 11 |
202 | 209 | #define AHB_GATE_OFFSET_MMC2 10 |
203 | 210 | #define AHB_GATE_OFFSET_MMC1 9 |
204 | 211 | #define AHB_GATE_OFFSET_MMC0 8 |
205 | 212 | #define AHB_GATE_OFFSET_MMC(n) (AHB_GATE_OFFSET_MMC0 + (n)) |
206 | 213 | |
214 | +/* ahb_gate1 offsets */ | |
215 | +#define AHB_GATE_OFFSET_DRC0 25 | |
216 | +#define AHB_GATE_OFFSET_DE_BE0 12 | |
217 | +#define AHB_GATE_OFFSET_HDMI 11 | |
218 | +#define AHB_GATE_OFFSET_LCD1 5 | |
219 | +#define AHB_GATE_OFFSET_LCD0 4 | |
220 | + | |
207 | 221 | #define CCM_MMC_CTRL_OSCM24 (0x0 << 24) |
208 | 222 | #define CCM_MMC_CTRL_PLL6 (0x1 << 24) |
209 | 223 | |
... | ... | @@ -216,6 +230,12 @@ |
216 | 230 | #define CCM_USB_CTRL_PHY1_CLK (0x1 << 9) |
217 | 231 | #define CCM_USB_CTRL_PHY2_CLK (0x1 << 10) |
218 | 232 | |
233 | +#define CCM_GMAC_CTRL_TX_CLK_SRC_MII 0x0 | |
234 | +#define CCM_GMAC_CTRL_TX_CLK_SRC_EXT_RGMII 0x1 | |
235 | +#define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2 | |
236 | +#define CCM_GMAC_CTRL_GPIT_MII (0x0 << 2) | |
237 | +#define CCM_GMAC_CTRL_GPIT_RGMII (0x1 << 2) | |
238 | + | |
219 | 239 | #define MDFS_CLK_DEFAULT 0x81000002 /* PLL6 / 3 */ |
220 | 240 | |
221 | 241 | #define CCM_DRAMCLK_CFG_DIV0(x) ((x - 1) << 8) |
222 | 242 | |
... | ... | @@ -223,8 +243,35 @@ |
223 | 243 | #define CCM_DRAMCLK_CFG_UPD (0x1 << 16) |
224 | 244 | #define CCM_DRAMCLK_CFG_RST (0x1 << 31) |
225 | 245 | |
246 | +#define CCM_DRAM_GATE_OFFSET_DE_BE0 26 | |
247 | + | |
248 | +#define CCM_LCD_CH0_CTRL_PLL3 (0 << 24) | |
249 | +#define CCM_LCD_CH0_CTRL_PLL7 (1 << 24) | |
250 | +#define CCM_LCD_CH0_CTRL_PLL3_2X (2 << 24) | |
251 | +#define CCM_LCD_CH0_CTRL_PLL7_2X (3 << 24) | |
252 | +#define CCM_LCD_CH0_CTRL_MIPI_PLL (4 << 24) | |
253 | +#define CCM_LCD_CH0_CTRL_GATE (0x1 << 31) | |
254 | + | |
255 | +#define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0) | |
256 | +#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24) | |
257 | +#define CCM_LCD_CH1_CTRL_PLL7 (1 << 24) | |
258 | +#define CCM_LCD_CH1_CTRL_PLL3_2X (2 << 24) | |
259 | +#define CCM_LCD_CH1_CTRL_PLL7_2X (3 << 24) | |
260 | +#define CCM_LCD_CH1_CTRL_GATE (0x1 << 31) | |
261 | + | |
262 | +#define CCM_HDMI_CTRL_M(n) ((((n) - 1) & 0xf) << 0) | |
263 | +#define CCM_HDMI_CTRL_PLL_MASK (3 << 24) | |
264 | +#define CCM_HDMI_CTRL_PLL3 (0 << 24) | |
265 | +#define CCM_HDMI_CTRL_PLL7 (1 << 24) | |
266 | +#define CCM_HDMI_CTRL_PLL3_2X (2 << 24) | |
267 | +#define CCM_HDMI_CTRL_PLL7_2X (3 << 24) | |
268 | +#define CCM_HDMI_CTRL_DDC_GATE (0x1 << 30) | |
269 | +#define CCM_HDMI_CTRL_GATE (0x1 << 31) | |
270 | + | |
226 | 271 | #define MBUS_CLK_DEFAULT 0x81000001 /* PLL6 / 2 */ |
227 | 272 | |
273 | +/* ahb_reset0 offsets */ | |
274 | +#define AHB_RESET_OFFSET_GMAC 17 | |
228 | 275 | #define AHB_RESET_OFFSET_MCTL 14 |
229 | 276 | #define AHB_RESET_OFFSET_MMC3 11 |
230 | 277 | #define AHB_RESET_OFFSET_MMC2 10 |
231 | 278 | |
... | ... | @@ -232,11 +279,29 @@ |
232 | 279 | #define AHB_RESET_OFFSET_MMC0 8 |
233 | 280 | #define AHB_RESET_OFFSET_MMC(n) (AHB_RESET_OFFSET_MMC0 + (n)) |
234 | 281 | |
282 | +/* ahb_reset0 offsets */ | |
283 | +#define AHB_RESET_OFFSET_DRC0 25 | |
284 | +#define AHB_RESET_OFFSET_DE_BE0 12 | |
285 | +#define AHB_RESET_OFFSET_HDMI 11 | |
286 | +#define AHB_RESET_OFFSET_LCD1 5 | |
287 | +#define AHB_RESET_OFFSET_LCD0 4 | |
288 | + | |
235 | 289 | /* apb2 reset */ |
236 | 290 | #define APB2_RESET_UART_SHIFT (16) |
237 | 291 | #define APB2_RESET_UART_MASK (0xff << APB2_RESET_UART_SHIFT) |
238 | 292 | #define APB2_RESET_TWI_SHIFT (0) |
239 | 293 | #define APB2_RESET_TWI_MASK (0xf << APB2_RESET_TWI_SHIFT) |
294 | + | |
295 | +/* CCM bits common to all Display Engine (and IEP) clock ctrl regs */ | |
296 | +#define CCM_DE_CTRL_M(n) ((((n) - 1) & 0xf) << 0) | |
297 | +#define CCM_DE_CTRL_PLL_MASK (0xf << 24) | |
298 | +#define CCM_DE_CTRL_PLL3 (0 << 24) | |
299 | +#define CCM_DE_CTRL_PLL7 (1 << 24) | |
300 | +#define CCM_DE_CTRL_PLL6_2X (2 << 24) | |
301 | +#define CCM_DE_CTRL_PLL8 (3 << 24) | |
302 | +#define CCM_DE_CTRL_PLL9 (4 << 24) | |
303 | +#define CCM_DE_CTRL_PLL10 (5 << 24) | |
304 | +#define CCM_DE_CTRL_GATE (1 << 31) | |
240 | 305 | |
241 | 306 | #endif /* _SUNXI_CLOCK_SUN6I_H */ |
arch/arm/include/asm/arch-sunxi/cpu.h
... | ... | @@ -99,9 +99,13 @@ |
99 | 99 | |
100 | 100 | #define SUNXI_SCR_BASE 0x01c2c400 |
101 | 101 | |
102 | +#ifndef CONFIG_MACH_SUN6I | |
102 | 103 | #define SUNXI_GPS_BASE 0x01c30000 |
103 | 104 | #define SUNXI_MALI400_BASE 0x01c40000 |
104 | 105 | #define SUNXI_GMAC_BASE 0x01c50000 |
106 | +#else | |
107 | +#define SUNXI_GMAC_BASE 0x01c30000 | |
108 | +#endif | |
105 | 109 | |
106 | 110 | #define SUNXI_DRAM_COM_BASE 0x01c62000 |
107 | 111 | #define SUNXI_DRAM_CTL0_BASE 0x01c63000 |
arch/arm/include/asm/arch-sunxi/display.h
1 | +/* | |
2 | + * Sunxi platform display controller register and constant defines | |
3 | + * | |
4 | + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> | |
5 | + * | |
6 | + * SPDX-License-Identifier: GPL-2.0+ | |
7 | + */ | |
8 | + | |
9 | +#ifndef _SUNXI_DISPLAY_H | |
10 | +#define _SUNXI_DISPLAY_H | |
11 | + | |
12 | +struct sunxi_de_be_reg { | |
13 | + u8 res0[0x800]; /* 0x000 */ | |
14 | + u32 mode; /* 0x800 */ | |
15 | + u32 backcolor; /* 0x804 */ | |
16 | + u32 disp_size; /* 0x808 */ | |
17 | + u8 res1[0x4]; /* 0x80c */ | |
18 | + u32 layer0_size; /* 0x810 */ | |
19 | + u32 layer1_size; /* 0x814 */ | |
20 | + u32 layer2_size; /* 0x818 */ | |
21 | + u32 layer3_size; /* 0x81c */ | |
22 | + u32 layer0_pos; /* 0x820 */ | |
23 | + u32 layer1_pos; /* 0x824 */ | |
24 | + u32 layer2_pos; /* 0x828 */ | |
25 | + u32 layer3_pos; /* 0x82c */ | |
26 | + u8 res2[0x10]; /* 0x830 */ | |
27 | + u32 layer0_stride; /* 0x840 */ | |
28 | + u32 layer1_stride; /* 0x844 */ | |
29 | + u32 layer2_stride; /* 0x848 */ | |
30 | + u32 layer3_stride; /* 0x84c */ | |
31 | + u32 layer0_addr_low32b; /* 0x850 */ | |
32 | + u32 layer1_addr_low32b; /* 0x854 */ | |
33 | + u32 layer2_addr_low32b; /* 0x858 */ | |
34 | + u32 layer3_addr_low32b; /* 0x85c */ | |
35 | + u32 layer0_addr_high4b; /* 0x860 */ | |
36 | + u32 layer1_addr_high4b; /* 0x864 */ | |
37 | + u32 layer2_addr_high4b; /* 0x868 */ | |
38 | + u32 layer3_addr_high4b; /* 0x86c */ | |
39 | + u32 reg_ctrl; /* 0x870 */ | |
40 | + u8 res3[0xc]; /* 0x874 */ | |
41 | + u32 color_key_max; /* 0x880 */ | |
42 | + u32 color_key_min; /* 0x884 */ | |
43 | + u32 color_key_config; /* 0x888 */ | |
44 | + u8 res4[0x4]; /* 0x88c */ | |
45 | + u32 layer0_attr0_ctrl; /* 0x890 */ | |
46 | + u32 layer1_attr0_ctrl; /* 0x894 */ | |
47 | + u32 layer2_attr0_ctrl; /* 0x898 */ | |
48 | + u32 layer3_attr0_ctrl; /* 0x89c */ | |
49 | + u32 layer0_attr1_ctrl; /* 0x8a0 */ | |
50 | + u32 layer1_attr1_ctrl; /* 0x8a4 */ | |
51 | + u32 layer2_attr1_ctrl; /* 0x8a8 */ | |
52 | + u32 layer3_attr1_ctrl; /* 0x8ac */ | |
53 | +}; | |
54 | + | |
55 | +struct sunxi_lcdc_reg { | |
56 | + u32 ctrl; /* 0x00 */ | |
57 | + u32 int0; /* 0x04 */ | |
58 | + u32 int1; /* 0x08 */ | |
59 | + u8 res0[0x04]; /* 0x0c */ | |
60 | + u32 frame_ctrl; /* 0x10 */ | |
61 | + u8 res1[0x2c]; /* 0x14 */ | |
62 | + u32 tcon0_ctrl; /* 0x40 */ | |
63 | + u32 tcon0_dclk; /* 0x44 */ | |
64 | + u32 tcon0_basic_timing0; /* 0x48 */ | |
65 | + u32 tcon0_basic_timing1; /* 0x4c */ | |
66 | + u32 tcon0_basic_timing2; /* 0x50 */ | |
67 | + u32 tcon0_basic_timing3; /* 0x54 */ | |
68 | + u32 tcon0_hv_intf; /* 0x58 */ | |
69 | + u8 res2[0x04]; /* 0x5c */ | |
70 | + u32 tcon0_cpu_intf; /* 0x60 */ | |
71 | + u32 tcon0_cpu_wr_dat; /* 0x64 */ | |
72 | + u32 tcon0_cpu_rd_dat0; /* 0x68 */ | |
73 | + u32 tcon0_cpu_rd_dat1; /* 0x6c */ | |
74 | + u32 tcon0_ttl_timing0; /* 0x70 */ | |
75 | + u32 tcon0_ttl_timing1; /* 0x74 */ | |
76 | + u32 tcon0_ttl_timing2; /* 0x78 */ | |
77 | + u32 tcon0_ttl_timing3; /* 0x7c */ | |
78 | + u32 tcon0_ttl_timing4; /* 0x80 */ | |
79 | + u32 tcon0_lvds_intf; /* 0x84 */ | |
80 | + u32 tcon0_io_polarity; /* 0x88 */ | |
81 | + u32 tcon0_io_tristate; /* 0x8c */ | |
82 | + u32 tcon1_ctrl; /* 0x90 */ | |
83 | + u32 tcon1_timing_source; /* 0x94 */ | |
84 | + u32 tcon1_timing_scale; /* 0x98 */ | |
85 | + u32 tcon1_timing_out; /* 0x9c */ | |
86 | + u32 tcon1_timing_h; /* 0xa0 */ | |
87 | + u32 tcon1_timing_v; /* 0xa4 */ | |
88 | + u32 tcon1_timing_sync; /* 0xa8 */ | |
89 | + u8 res3[0x44]; /* 0xac */ | |
90 | + u32 tcon1_io_polarity; /* 0xf0 */ | |
91 | + u32 tcon1_io_tristate; /* 0xf4 */ | |
92 | +}; | |
93 | + | |
94 | +struct sunxi_hdmi_reg { | |
95 | + u32 version_id; /* 0x000 */ | |
96 | + u32 ctrl; /* 0x004 */ | |
97 | + u32 irq; /* 0x008 */ | |
98 | + u32 hpd; /* 0x00c */ | |
99 | + u32 video_ctrl; /* 0x010 */ | |
100 | + u32 video_size; /* 0x014 */ | |
101 | + u32 video_bp; /* 0x018 */ | |
102 | + u32 video_fp; /* 0x01c */ | |
103 | + u32 video_spw; /* 0x020 */ | |
104 | + u32 video_polarity; /* 0x024 */ | |
105 | + u8 res0[0x1d8]; /* 0x028 */ | |
106 | + u32 pad_ctrl0; /* 0x200 */ | |
107 | + u32 pad_ctrl1; /* 0x204 */ | |
108 | + u32 pll_ctrl; /* 0x208 */ | |
109 | + u32 pll_dbg0; /* 0x20c */ | |
110 | +}; | |
111 | + | |
112 | +/* | |
113 | + * DE-BE register constants. | |
114 | + */ | |
115 | +#define SUNXI_DE_BE_WIDTH(x) (((x) - 1) << 0) | |
116 | +#define SUNXI_DE_BE_HEIGHT(y) (((y) - 1) << 16) | |
117 | +#define SUNXI_DE_BE_MODE_ENABLE (1 << 0) | |
118 | +#define SUNXI_DE_BE_MODE_START (1 << 1) | |
119 | +#define SUNXI_DE_BE_MODE_LAYER0_ENABLE (1 << 8) | |
120 | +#define SUNXI_DE_BE_LAYER_STRIDE(x) ((x) << 5) | |
121 | +#define SUNXI_DE_BE_REG_CTRL_LOAD_REGS (1 << 0) | |
122 | +#define SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888 (0x09 << 8) | |
123 | + | |
124 | +/* | |
125 | + * LCDC register constants. | |
126 | + */ | |
127 | +#define SUNXI_LCDC_X(x) (((x) - 1) << 16) | |
128 | +#define SUNXI_LCDC_Y(y) (((y) - 1) << 0) | |
129 | +#define SUNXI_LCDC_CTRL_IO_MAP_MASK (1 << 0) | |
130 | +#define SUNXI_LCDC_CTRL_IO_MAP_TCON0 (0 << 0) | |
131 | +#define SUNXI_LCDC_CTRL_IO_MAP_TCON1 (1 << 0) | |
132 | +#define SUNXI_LCDC_CTRL_TCON_ENABLE (1 << 31) | |
133 | +#define SUNXI_LCDC_TCON0_DCLK_ENABLE (0xf << 28) | |
134 | +#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n) (((n) & 0x1f) << 4) | |
135 | +#define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31) | |
136 | +#define SUNXI_LCDC_TCON1_TIMING_H_BP(n) (((n) - 1) << 0) | |
137 | +#define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n) (((n) - 1) << 16) | |
138 | +#define SUNXI_LCDC_TCON1_TIMING_V_BP(n) (((n) - 1) << 0) | |
139 | +#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n) (((n) * 2) << 16) | |
140 | + | |
141 | +/* | |
142 | + * HDMI register constants. | |
143 | + */ | |
144 | +#define SUNXI_HDMI_X(x) (((x) - 1) << 0) | |
145 | +#define SUNXI_HDMI_Y(y) (((y) - 1) << 16) | |
146 | +#define SUNXI_HDMI_CTRL_ENABLE (1 << 31) | |
147 | +#define SUNXI_HDMI_IRQ_STATUS_FIFO_UF (1 << 0) | |
148 | +#define SUNXI_HDMI_IRQ_STATUS_FIFO_OF (1 << 1) | |
149 | +#define SUNXI_HDMI_IRQ_STATUS_BITS 0x73 | |
150 | +#define SUNXI_HDMI_HPD_DETECT (1 << 0) | |
151 | +#define SUNXI_HDMI_VIDEO_CTRL_ENABLE (1 << 31) | |
152 | +#define SUNXI_HDMI_VIDEO_POL_HOR (1 << 0) | |
153 | +#define SUNXI_HDMI_VIDEO_POL_VER (1 << 1) | |
154 | +#define SUNXI_HDMI_VIDEO_POL_TX_CLK (0x3e0 << 16) | |
155 | + | |
156 | +#ifdef CONFIG_MACH_SUN6I | |
157 | +#define SUNXI_HDMI_PAD_CTRL0_HDP 0x7e80000f | |
158 | +#define SUNXI_HDMI_PAD_CTRL0_RUN 0x7e8000ff | |
159 | +#else | |
160 | +#define SUNXI_HDMI_PAD_CTRL0_HDP 0xfe800000 | |
161 | +#define SUNXI_HDMI_PAD_CTRL0_RUN 0xfe800000 | |
162 | +#endif | |
163 | + | |
164 | +#ifdef CONFIG_MACH_SUN4I | |
165 | +#define SUNXI_HDMI_PAD_CTRL1 0x00d8c820 | |
166 | +#elif defined CONFIG_MACH_SUN6I | |
167 | +#define SUNXI_HDMI_PAD_CTRL1 0x01ded030 | |
168 | +#else | |
169 | +#define SUNXI_HDMI_PAD_CTRL1 0x00d8c830 | |
170 | +#endif | |
171 | +#define SUNXI_HDMI_PAD_CTRL1_HALVE (1 << 6) | |
172 | + | |
173 | +#ifdef CONFIG_MACH_SUN6I | |
174 | +#define SUNXI_HDMI_PLL_CTRL 0xba48a308 | |
175 | +#define SUNXI_HDMI_PLL_CTRL_DIV(n) (((n) - 1) << 4) | |
176 | +#else | |
177 | +#define SUNXI_HDMI_PLL_CTRL 0xfa4ef708 | |
178 | +#define SUNXI_HDMI_PLL_CTRL_DIV(n) ((n) << 4) | |
179 | +#endif | |
180 | +#define SUNXI_HDMI_PLL_CTRL_DIV_MASK (0xf << 4) | |
181 | + | |
182 | +#define SUNXI_HDMI_PLL_DBG0_PLL3 (0 << 21) | |
183 | +#define SUNXI_HDMI_PLL_DBG0_PLL7 (1 << 21) | |
184 | + | |
185 | +int sunxi_simplefb_setup(void *blob); | |
186 | + | |
187 | +#endif /* _SUNXI_DISPLAY_H */ |
arch/arm/include/asm/arch-sunxi/gpio.h
board/sunxi/Kconfig
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | select CPU_V7_HAS_NONSEC |
25 | 25 | select CPU_V7_HAS_VIRT |
26 | 26 | select SUPPORT_SPL |
27 | + select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT | |
27 | 28 | |
28 | 29 | config MACH_SUN8I |
29 | 30 | bool "sun8i (Allwinner A23)" |
... | ... | @@ -214,6 +215,20 @@ |
214 | 215 | default "PH24" if MACH_SUN6I |
215 | 216 | ---help--- |
216 | 217 | See USB1_VBUS_PIN help text. |
218 | + | |
219 | +config VIDEO | |
220 | + boolean "Enable graphical uboot console on HDMI" | |
221 | + default y | |
222 | + ---help--- | |
223 | + Say Y here to add support for using a cfb console on the HDMI output | |
224 | + found on most sunxi devices. | |
225 | + | |
226 | +config USB_KEYBOARD | |
227 | + boolean "Enable USB keyboard support" | |
228 | + default y | |
229 | + ---help--- | |
230 | + Say Y here to add support for using a USB keyboard (typically used | |
231 | + in combination with a graphical console on HDMI). | |
217 | 232 | |
218 | 233 | endif |
board/sunxi/ahci.c
... | ... | @@ -76,6 +76,8 @@ |
76 | 76 | #ifdef CONFIG_SATAPWR |
77 | 77 | gpio_request(CONFIG_SATAPWR, "satapwr"); |
78 | 78 | gpio_direction_output(CONFIG_SATAPWR, 1); |
79 | + /* Give attached sata device time to power-up to avoid link timeouts */ | |
80 | + mdelay(500); | |
79 | 81 | #endif |
80 | 82 | |
81 | 83 | if (sunxi_ahci_phy_init(SUNXI_SATA_BASE) < 0) |
board/sunxi/board.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #endif |
25 | 25 | #include <asm/arch/clock.h> |
26 | 26 | #include <asm/arch/cpu.h> |
27 | +#include <asm/arch/display.h> | |
27 | 28 | #include <asm/arch/dram.h> |
28 | 29 | #include <asm/arch/gpio.h> |
29 | 30 | #include <asm/arch/mmc.h> |
... | ... | @@ -237,4 +238,13 @@ |
237 | 238 | return 0; |
238 | 239 | } |
239 | 240 | #endif |
241 | + | |
242 | +#ifdef CONFIG_OF_BOARD_SETUP | |
243 | +int ft_board_setup(void *blob, bd_t *bd) | |
244 | +{ | |
245 | +#ifdef CONFIG_VIDEO_DT_SIMPLEFB | |
246 | + return sunxi_simplefb_setup(blob); | |
247 | +#endif | |
248 | +} | |
249 | +#endif /* CONFIG_OF_BOARD_SETUP */ |
board/sunxi/gmac.c
... | ... | @@ -13,7 +13,12 @@ |
13 | 13 | (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; |
14 | 14 | |
15 | 15 | /* Set up clock gating */ |
16 | +#ifndef CONFIG_MACH_SUN6I | |
16 | 17 | setbits_le32(&ccm->ahb_gate1, 0x1 << AHB_GATE_OFFSET_GMAC); |
18 | +#else | |
19 | + setbits_le32(&ccm->ahb_reset0_cfg, 0x1 << AHB_RESET_OFFSET_GMAC); | |
20 | + setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_GMAC); | |
21 | +#endif | |
17 | 22 | |
18 | 23 | /* Set MII clock */ |
19 | 24 | #ifdef CONFIG_RGMII |
... | ... | @@ -33,6 +38,7 @@ |
33 | 38 | setbits_le32(&ccm->gmac_clk_cfg, 0x3 << 10); |
34 | 39 | #endif |
35 | 40 | |
41 | +#ifndef CONFIG_MACH_SUN6I | |
36 | 42 | /* Configure pin mux settings for GMAC */ |
37 | 43 | for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(16); pin++) { |
38 | 44 | #ifdef CONFIG_RGMII |
39 | 45 | |
... | ... | @@ -43,9 +49,48 @@ |
43 | 49 | sunxi_gpio_set_cfgpin(pin, SUN7I_GPA0_GMAC); |
44 | 50 | sunxi_gpio_set_drv(pin, 3); |
45 | 51 | } |
52 | +#elif defined CONFIG_RGMII | |
53 | + /* Configure sun6i RGMII mode pin mux settings */ | |
54 | + for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(3); pin++) { | |
55 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
56 | + sunxi_gpio_set_drv(pin, 3); | |
57 | + } | |
58 | + for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) { | |
59 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
60 | + sunxi_gpio_set_drv(pin, 3); | |
61 | + } | |
62 | + for (pin = SUNXI_GPA(19); pin <= SUNXI_GPA(20); pin++) { | |
63 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
64 | + sunxi_gpio_set_drv(pin, 3); | |
65 | + } | |
66 | + for (pin = SUNXI_GPA(25); pin <= SUNXI_GPA(27); pin++) { | |
67 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
68 | + sunxi_gpio_set_drv(pin, 3); | |
69 | + } | |
70 | +#elif defined CONFIG_GMII | |
71 | + /* Configure sun6i GMII mode pin mux settings */ | |
72 | + for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(27); pin++) { | |
73 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
74 | + sunxi_gpio_set_drv(pin, 2); | |
75 | + } | |
76 | +#else | |
77 | + /* Configure sun6i MII mode pin mux settings */ | |
78 | + for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(3); pin++) | |
79 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
80 | + for (pin = SUNXI_GPA(8); pin <= SUNXI_GPA(9); pin++) | |
81 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
82 | + for (pin = SUNXI_GPA(11); pin <= SUNXI_GPA(14); pin++) | |
83 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
84 | + for (pin = SUNXI_GPA(19); pin <= SUNXI_GPA(24); pin++) | |
85 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
86 | + for (pin = SUNXI_GPA(26); pin <= SUNXI_GPA(27); pin++) | |
87 | + sunxi_gpio_set_cfgpin(pin, SUN6I_GPA0_GMAC); | |
88 | +#endif | |
46 | 89 | |
47 | 90 | #ifdef CONFIG_RGMII |
48 | 91 | return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_RGMII); |
92 | +#elif defined CONFIG_GMII | |
93 | + return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_GMII); | |
49 | 94 | #else |
50 | 95 | return designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_MII); |
51 | 96 | #endif |
common/fdt_support.c
... | ... | @@ -1499,4 +1499,66 @@ |
1499 | 1499 | |
1500 | 1500 | return 0; |
1501 | 1501 | } |
1502 | + | |
1503 | +/** | |
1504 | + * fdt_setup_simplefb_node - Fill and enable a simplefb node | |
1505 | + * | |
1506 | + * @fdt: ptr to device tree | |
1507 | + * @node: offset of the simplefb node | |
1508 | + * @base_address: framebuffer base address | |
1509 | + * @width: width in pixels | |
1510 | + * @height: height in pixels | |
1511 | + * @stride: bytes per line | |
1512 | + * @format: pixel format string | |
1513 | + * | |
1514 | + * Convenience function to fill and enable a simplefb node. | |
1515 | + */ | |
1516 | +int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width, | |
1517 | + u32 height, u32 stride, const char *format) | |
1518 | +{ | |
1519 | + char name[32]; | |
1520 | + fdt32_t cells[4]; | |
1521 | + int i, addrc, sizec, ret; | |
1522 | + | |
1523 | + of_bus_default_count_cells(fdt, fdt_parent_offset(fdt, node), | |
1524 | + &addrc, &sizec); | |
1525 | + i = 0; | |
1526 | + if (addrc == 2) | |
1527 | + cells[i++] = cpu_to_fdt32(base_address >> 32); | |
1528 | + cells[i++] = cpu_to_fdt32(base_address); | |
1529 | + if (sizec == 2) | |
1530 | + cells[i++] = 0; | |
1531 | + cells[i++] = cpu_to_fdt32(height * stride); | |
1532 | + | |
1533 | + ret = fdt_setprop(fdt, node, "reg", cells, sizeof(cells[0]) * i); | |
1534 | + if (ret < 0) | |
1535 | + return ret; | |
1536 | + | |
1537 | + snprintf(name, sizeof(name), "framebuffer@%llx", base_address); | |
1538 | + ret = fdt_set_name(fdt, node, name); | |
1539 | + if (ret < 0) | |
1540 | + return ret; | |
1541 | + | |
1542 | + ret = fdt_setprop_u32(fdt, node, "width", width); | |
1543 | + if (ret < 0) | |
1544 | + return ret; | |
1545 | + | |
1546 | + ret = fdt_setprop_u32(fdt, node, "height", height); | |
1547 | + if (ret < 0) | |
1548 | + return ret; | |
1549 | + | |
1550 | + ret = fdt_setprop_u32(fdt, node, "stride", stride); | |
1551 | + if (ret < 0) | |
1552 | + return ret; | |
1553 | + | |
1554 | + ret = fdt_setprop_string(fdt, node, "format", format); | |
1555 | + if (ret < 0) | |
1556 | + return ret; | |
1557 | + | |
1558 | + ret = fdt_setprop_string(fdt, node, "status", "okay"); | |
1559 | + if (ret < 0) | |
1560 | + return ret; | |
1561 | + | |
1562 | + return 0; | |
1563 | +} |
common/lcd.c
... | ... | @@ -30,6 +30,7 @@ |
30 | 30 | #include <splash.h> |
31 | 31 | #include <asm/io.h> |
32 | 32 | #include <asm/unaligned.h> |
33 | +#include <fdt_support.h> | |
33 | 34 | |
34 | 35 | #if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \ |
35 | 36 | defined(CONFIG_CPU_MONAHANS) |
36 | 37 | |
37 | 38 | |
38 | 39 | |
... | ... | @@ -1172,51 +1173,13 @@ |
1172 | 1173 | #if defined(CONFIG_LCD_DT_SIMPLEFB) |
1173 | 1174 | static int lcd_dt_simplefb_configure_node(void *blob, int off) |
1174 | 1175 | { |
1175 | - u32 stride; | |
1176 | - fdt32_t cells[2]; | |
1177 | - int ret; | |
1178 | - static const char format[] = | |
1179 | 1176 | #if LCD_BPP == LCD_COLOR16 |
1180 | - "r5g6b5"; | |
1177 | + return fdt_setup_simplefb_node(blob, off, gd->fb_base, | |
1178 | + panel_info.vl_col, panel_info.vl_row, | |
1179 | + panel_info.vl_col * 2, "r5g6b5"); | |
1181 | 1180 | #else |
1182 | - ""; | |
1181 | + return -1; | |
1183 | 1182 | #endif |
1184 | - | |
1185 | - if (!format[0]) | |
1186 | - return -1; | |
1187 | - | |
1188 | - stride = panel_info.vl_col * 2; | |
1189 | - | |
1190 | - cells[0] = cpu_to_fdt32(gd->fb_base); | |
1191 | - cells[1] = cpu_to_fdt32(stride * panel_info.vl_row); | |
1192 | - ret = fdt_setprop(blob, off, "reg", cells, sizeof(cells[0]) * 2); | |
1193 | - if (ret < 0) | |
1194 | - return -1; | |
1195 | - | |
1196 | - cells[0] = cpu_to_fdt32(panel_info.vl_col); | |
1197 | - ret = fdt_setprop(blob, off, "width", cells, sizeof(cells[0])); | |
1198 | - if (ret < 0) | |
1199 | - return -1; | |
1200 | - | |
1201 | - cells[0] = cpu_to_fdt32(panel_info.vl_row); | |
1202 | - ret = fdt_setprop(blob, off, "height", cells, sizeof(cells[0])); | |
1203 | - if (ret < 0) | |
1204 | - return -1; | |
1205 | - | |
1206 | - cells[0] = cpu_to_fdt32(stride); | |
1207 | - ret = fdt_setprop(blob, off, "stride", cells, sizeof(cells[0])); | |
1208 | - if (ret < 0) | |
1209 | - return -1; | |
1210 | - | |
1211 | - ret = fdt_setprop(blob, off, "format", format, strlen(format) + 1); | |
1212 | - if (ret < 0) | |
1213 | - return -1; | |
1214 | - | |
1215 | - ret = fdt_delprop(blob, off, "status"); | |
1216 | - if (ret < 0) | |
1217 | - return -1; | |
1218 | - | |
1219 | - return 0; | |
1220 | 1183 | } |
1221 | 1184 | |
1222 | 1185 | int lcd_dt_simplefb_add_node(void *blob) |
configs/A13-OLinuXinoM_defconfig
configs/A13-OLinuXino_defconfig
configs/Colombus_defconfig
configs/Ippo_q8h_v5_defconfig
configs/Mele_M9_defconfig
1 | 1 | CONFIG_SPL=y |
2 | -CONFIG_SYS_EXTRA_OPTIONS="USB_EHCI" | |
2 | +CONFIG_SYS_EXTRA_OPTIONS="USB_EHCI,SUNXI_GMAC" | |
3 | 3 | CONFIG_FDTFILE="sun6i-a31-m9.dtb" |
4 | 4 | +S:CONFIG_ARM=y |
5 | 5 | +S:CONFIG_ARCH_SUNXI=y |
... | ... | @@ -14,6 +14,8 @@ |
14 | 14 | # HDMI power ? |
15 | 15 | +S:CONFIG_AXP221_ALDO2_VOLT=1800 |
16 | 16 | +S:CONFIG_AXP221_ALDO3_VOLT=3000 |
17 | -# No Vbus gpio for usb1 | |
18 | -+S:CONFIG_USB1_VBUS_PIN="" | |
17 | +# Vbus gpio for usb1 | |
18 | ++S:CONFIG_USB1_VBUS_PIN="PC27" | |
19 | +# No Vbus gpio for usb2 | |
20 | ++S:CONFIG_USB2_VBUS_PIN="" |
drivers/video/Makefile
... | ... | @@ -39,6 +39,7 @@ |
39 | 39 | obj-$(CONFIG_VIDEO_SED13806) += sed13806.o |
40 | 40 | obj-$(CONFIG_VIDEO_SM501) += sm501.o |
41 | 41 | obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o |
42 | +obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o | |
42 | 43 | obj-$(CONFIG_VIDEO_TEGRA) += tegra.o |
43 | 44 | obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o |
44 | 45 | obj-$(CONFIG_FORMIKE) += formike.o |
drivers/video/sunxi_display.c
1 | +/* | |
2 | + * Display driver for Allwinner SoCs. | |
3 | + * | |
4 | + * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be> | |
5 | + * (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com> | |
6 | + * | |
7 | + * SPDX-License-Identifier: GPL-2.0+ | |
8 | + */ | |
9 | + | |
10 | +#include <common.h> | |
11 | + | |
12 | +#include <asm/arch/clock.h> | |
13 | +#include <asm/arch/display.h> | |
14 | +#include <asm/global_data.h> | |
15 | +#include <asm/io.h> | |
16 | +#include <fdtdec.h> | |
17 | +#include <fdt_support.h> | |
18 | +#include <linux/fb.h> | |
19 | +#include <video_fb.h> | |
20 | + | |
21 | +DECLARE_GLOBAL_DATA_PTR; | |
22 | + | |
23 | +struct sunxi_display { | |
24 | + GraphicDevice graphic_device; | |
25 | + bool enabled; | |
26 | +} sunxi_display; | |
27 | + | |
28 | +static int sunxi_hdmi_hpd_detect(void) | |
29 | +{ | |
30 | + struct sunxi_ccm_reg * const ccm = | |
31 | + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | |
32 | + struct sunxi_hdmi_reg * const hdmi = | |
33 | + (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; | |
34 | + | |
35 | + /* Set pll3 to 300MHz */ | |
36 | + clock_set_pll3(300000000); | |
37 | + | |
38 | + /* Set hdmi parent to pll3 */ | |
39 | + clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_PLL_MASK, | |
40 | + CCM_HDMI_CTRL_PLL3); | |
41 | + | |
42 | + /* Set ahb gating to pass */ | |
43 | +#ifdef CONFIG_MACH_SUN6I | |
44 | + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI); | |
45 | +#endif | |
46 | + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI); | |
47 | + | |
48 | + /* Clock on */ | |
49 | + setbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE); | |
50 | + | |
51 | + writel(SUNXI_HDMI_CTRL_ENABLE, &hdmi->ctrl); | |
52 | + writel(SUNXI_HDMI_PAD_CTRL0_HDP, &hdmi->pad_ctrl0); | |
53 | + | |
54 | + udelay(1000); | |
55 | + | |
56 | + if (readl(&hdmi->hpd) & SUNXI_HDMI_HPD_DETECT) | |
57 | + return 1; | |
58 | + | |
59 | + /* No need to keep these running */ | |
60 | + clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE); | |
61 | + clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE); | |
62 | + clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI); | |
63 | +#ifdef CONFIG_MACH_SUN6I | |
64 | + clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI); | |
65 | +#endif | |
66 | + clock_set_pll3(0); | |
67 | + | |
68 | + return 0; | |
69 | +} | |
70 | + | |
71 | +/* | |
72 | + * This is the entity that mixes and matches the different layers and inputs. | |
73 | + * Allwinner calls it the back-end, but i like composer better. | |
74 | + */ | |
75 | +static void sunxi_composer_init(void) | |
76 | +{ | |
77 | + struct sunxi_ccm_reg * const ccm = | |
78 | + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | |
79 | + struct sunxi_de_be_reg * const de_be = | |
80 | + (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; | |
81 | + int i; | |
82 | + | |
83 | +#ifdef CONFIG_MACH_SUN6I | |
84 | + /* Reset off */ | |
85 | + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0); | |
86 | +#endif | |
87 | + | |
88 | + /* Clocks on */ | |
89 | + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_DE_BE0); | |
90 | + setbits_le32(&ccm->dram_clk_gate, 1 << CCM_DRAM_GATE_OFFSET_DE_BE0); | |
91 | + clock_set_de_mod_clock(&ccm->be0_clk_cfg, 300000000); | |
92 | + | |
93 | + /* Engine bug, clear registers after reset */ | |
94 | + for (i = 0x0800; i < 0x1000; i += 4) | |
95 | + writel(0, SUNXI_DE_BE0_BASE + i); | |
96 | + | |
97 | + setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE); | |
98 | +} | |
99 | + | |
100 | +static void sunxi_composer_mode_set(struct fb_videomode *mode, | |
101 | + unsigned int address) | |
102 | +{ | |
103 | + struct sunxi_de_be_reg * const de_be = | |
104 | + (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; | |
105 | + | |
106 | + writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres), | |
107 | + &de_be->disp_size); | |
108 | + writel(SUNXI_DE_BE_HEIGHT(mode->yres) | SUNXI_DE_BE_WIDTH(mode->xres), | |
109 | + &de_be->layer0_size); | |
110 | + writel(SUNXI_DE_BE_LAYER_STRIDE(mode->xres), &de_be->layer0_stride); | |
111 | + writel(address << 3, &de_be->layer0_addr_low32b); | |
112 | + writel(address >> 29, &de_be->layer0_addr_high4b); | |
113 | + writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl); | |
114 | + | |
115 | + setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE); | |
116 | +} | |
117 | + | |
118 | +/* | |
119 | + * LCDC, what allwinner calls a CRTC, so timing controller and serializer. | |
120 | + */ | |
121 | +static void sunxi_lcdc_pll_set(int dotclock, int *clk_div, int *clk_double) | |
122 | +{ | |
123 | + struct sunxi_ccm_reg * const ccm = | |
124 | + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | |
125 | + int value, n, m, diff; | |
126 | + int best_n = 0, best_m = 0, best_diff = 0x0FFFFFFF; | |
127 | + int best_double = 0; | |
128 | + | |
129 | + /* | |
130 | + * Find the lowest divider resulting in a matching clock, if there | |
131 | + * is no match, pick the closest lower clock, as monitors tend to | |
132 | + * not sync to higher frequencies. | |
133 | + */ | |
134 | + for (m = 15; m > 0; m--) { | |
135 | + n = (m * dotclock) / 3000; | |
136 | + | |
137 | + if ((n >= 9) && (n <= 127)) { | |
138 | + value = (3000 * n) / m; | |
139 | + diff = dotclock - value; | |
140 | + if (diff < best_diff) { | |
141 | + best_diff = diff; | |
142 | + best_m = m; | |
143 | + best_n = n; | |
144 | + best_double = 0; | |
145 | + } | |
146 | + } | |
147 | + | |
148 | + /* These are just duplicates */ | |
149 | + if (!(m & 1)) | |
150 | + continue; | |
151 | + | |
152 | + n = (m * dotclock) / 6000; | |
153 | + if ((n >= 9) && (n <= 127)) { | |
154 | + value = (6000 * n) / m; | |
155 | + diff = dotclock - value; | |
156 | + if (diff < best_diff) { | |
157 | + best_diff = diff; | |
158 | + best_m = m; | |
159 | + best_n = n; | |
160 | + best_double = 1; | |
161 | + } | |
162 | + } | |
163 | + } | |
164 | + | |
165 | + debug("dotclock: %dkHz = %dkHz: (%d * 3MHz * %d) / %d\n", | |
166 | + dotclock, (best_double + 1) * 3000 * best_n / best_m, | |
167 | + best_double + 1, best_n, best_m); | |
168 | + | |
169 | + clock_set_pll3(best_n * 3000000); | |
170 | + | |
171 | + writel(CCM_LCD_CH1_CTRL_GATE | | |
172 | + (best_double ? CCM_LCD_CH1_CTRL_PLL3_2X : CCM_LCD_CH1_CTRL_PLL3) | | |
173 | + CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg); | |
174 | + | |
175 | + *clk_div = best_m; | |
176 | + *clk_double = best_double; | |
177 | +} | |
178 | + | |
179 | +static void sunxi_lcdc_init(void) | |
180 | +{ | |
181 | + struct sunxi_ccm_reg * const ccm = | |
182 | + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | |
183 | + struct sunxi_lcdc_reg * const lcdc = | |
184 | + (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; | |
185 | + | |
186 | + /* Reset off */ | |
187 | +#ifdef CONFIG_MACH_SUN6I | |
188 | + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0); | |
189 | +#else | |
190 | + setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST); | |
191 | +#endif | |
192 | + | |
193 | + /* Clock on */ | |
194 | + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD0); | |
195 | + | |
196 | + /* Init lcdc */ | |
197 | + writel(0, &lcdc->ctrl); /* Disable tcon */ | |
198 | + writel(0, &lcdc->int0); /* Disable all interrupts */ | |
199 | + | |
200 | + /* Disable tcon0 dot clock */ | |
201 | + clrbits_le32(&lcdc->tcon0_dclk, SUNXI_LCDC_TCON0_DCLK_ENABLE); | |
202 | + | |
203 | + /* Set all io lines to tristate */ | |
204 | + writel(0xffffffff, &lcdc->tcon0_io_tristate); | |
205 | + writel(0xffffffff, &lcdc->tcon1_io_tristate); | |
206 | +} | |
207 | + | |
208 | +static void sunxi_lcdc_mode_set(struct fb_videomode *mode, | |
209 | + int *clk_div, int *clk_double) | |
210 | +{ | |
211 | + struct sunxi_lcdc_reg * const lcdc = | |
212 | + (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; | |
213 | + int bp, total; | |
214 | + | |
215 | + /* Use tcon1 */ | |
216 | + clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK, | |
217 | + SUNXI_LCDC_CTRL_IO_MAP_TCON1); | |
218 | + | |
219 | + /* Enabled, 0x1e start delay */ | |
220 | + writel(SUNXI_LCDC_TCON1_CTRL_ENABLE | | |
221 | + SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(0x1e), &lcdc->tcon1_ctrl); | |
222 | + | |
223 | + writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres), | |
224 | + &lcdc->tcon1_timing_source); | |
225 | + writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres), | |
226 | + &lcdc->tcon1_timing_scale); | |
227 | + writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres), | |
228 | + &lcdc->tcon1_timing_out); | |
229 | + | |
230 | + bp = mode->hsync_len + mode->left_margin; | |
231 | + total = mode->xres + mode->right_margin + bp; | |
232 | + writel(SUNXI_LCDC_TCON1_TIMING_H_TOTAL(total) | | |
233 | + SUNXI_LCDC_TCON1_TIMING_H_BP(bp), &lcdc->tcon1_timing_h); | |
234 | + | |
235 | + bp = mode->vsync_len + mode->upper_margin; | |
236 | + total = mode->yres + mode->lower_margin + bp; | |
237 | + writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) | | |
238 | + SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v); | |
239 | + | |
240 | + writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len), | |
241 | + &lcdc->tcon1_timing_sync); | |
242 | + | |
243 | + sunxi_lcdc_pll_set(mode->pixclock, clk_div, clk_double); | |
244 | +} | |
245 | + | |
246 | +#ifdef CONFIG_MACH_SUN6I | |
247 | +static void sunxi_drc_init(void) | |
248 | +{ | |
249 | + struct sunxi_ccm_reg * const ccm = | |
250 | + (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; | |
251 | + | |
252 | + /* On sun6i the drc must be clocked even when in pass-through mode */ | |
253 | + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0); | |
254 | + clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000); | |
255 | +} | |
256 | +#endif | |
257 | + | |
258 | +static void sunxi_hdmi_mode_set(struct fb_videomode *mode, | |
259 | + int clk_div, int clk_double) | |
260 | +{ | |
261 | + struct sunxi_hdmi_reg * const hdmi = | |
262 | + (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; | |
263 | + int x, y; | |
264 | + | |
265 | + /* Write clear interrupt status bits */ | |
266 | + writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq); | |
267 | + | |
268 | + /* Init various registers, select pll3 as clock source */ | |
269 | + writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity); | |
270 | + writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0); | |
271 | + writel(SUNXI_HDMI_PAD_CTRL1, &hdmi->pad_ctrl1); | |
272 | + writel(SUNXI_HDMI_PLL_CTRL, &hdmi->pll_ctrl); | |
273 | + writel(SUNXI_HDMI_PLL_DBG0_PLL3, &hdmi->pll_dbg0); | |
274 | + | |
275 | + /* Setup clk div and doubler */ | |
276 | + clrsetbits_le32(&hdmi->pll_ctrl, SUNXI_HDMI_PLL_CTRL_DIV_MASK, | |
277 | + SUNXI_HDMI_PLL_CTRL_DIV(clk_div)); | |
278 | + if (!clk_double) | |
279 | + setbits_le32(&hdmi->pad_ctrl1, SUNXI_HDMI_PAD_CTRL1_HALVE); | |
280 | + | |
281 | + /* Setup timing registers */ | |
282 | + writel(SUNXI_HDMI_Y(mode->yres) | SUNXI_HDMI_X(mode->xres), | |
283 | + &hdmi->video_size); | |
284 | + | |
285 | + x = mode->hsync_len + mode->left_margin; | |
286 | + y = mode->vsync_len + mode->upper_margin; | |
287 | + writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_bp); | |
288 | + | |
289 | + x = mode->right_margin; | |
290 | + y = mode->lower_margin; | |
291 | + writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_fp); | |
292 | + | |
293 | + x = mode->hsync_len; | |
294 | + y = mode->vsync_len; | |
295 | + writel(SUNXI_HDMI_Y(y) | SUNXI_HDMI_X(x), &hdmi->video_spw); | |
296 | + | |
297 | + if (mode->sync & FB_SYNC_HOR_HIGH_ACT) | |
298 | + setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_HOR); | |
299 | + | |
300 | + if (mode->sync & FB_SYNC_VERT_HIGH_ACT) | |
301 | + setbits_le32(&hdmi->video_polarity, SUNXI_HDMI_VIDEO_POL_VER); | |
302 | +} | |
303 | + | |
304 | +static void sunxi_engines_init(void) | |
305 | +{ | |
306 | + sunxi_composer_init(); | |
307 | + sunxi_lcdc_init(); | |
308 | +#ifdef CONFIG_MACH_SUN6I | |
309 | + sunxi_drc_init(); | |
310 | +#endif | |
311 | +} | |
312 | + | |
313 | +static void sunxi_mode_set(struct fb_videomode *mode, unsigned int address) | |
314 | +{ | |
315 | + struct sunxi_de_be_reg * const de_be = | |
316 | + (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; | |
317 | + struct sunxi_lcdc_reg * const lcdc = | |
318 | + (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; | |
319 | + struct sunxi_hdmi_reg * const hdmi = | |
320 | + (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; | |
321 | + int clk_div, clk_double; | |
322 | + int retries = 3; | |
323 | + | |
324 | +retry: | |
325 | + clrbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE); | |
326 | + clrbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE); | |
327 | + clrbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START); | |
328 | + | |
329 | + sunxi_composer_mode_set(mode, address); | |
330 | + sunxi_lcdc_mode_set(mode, &clk_div, &clk_double); | |
331 | + sunxi_hdmi_mode_set(mode, clk_div, clk_double); | |
332 | + | |
333 | + setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS); | |
334 | + setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START); | |
335 | + | |
336 | + udelay(1000000 / mode->refresh + 500); | |
337 | + | |
338 | + setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE); | |
339 | + | |
340 | + udelay(1000000 / mode->refresh + 500); | |
341 | + | |
342 | + setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE); | |
343 | + | |
344 | + udelay(1000000 / mode->refresh + 500); | |
345 | + | |
346 | + /* | |
347 | + * Sometimes the display pipeline does not sync up properly, if | |
348 | + * this happens the hdmi fifo underrun or overrun bits are set. | |
349 | + */ | |
350 | + if (readl(&hdmi->irq) & | |
351 | + (SUNXI_HDMI_IRQ_STATUS_FIFO_UF | SUNXI_HDMI_IRQ_STATUS_FIFO_OF)) { | |
352 | + if (retries--) | |
353 | + goto retry; | |
354 | + printf("HDMI fifo under or overrun\n"); | |
355 | + } | |
356 | +} | |
357 | + | |
358 | +void *video_hw_init(void) | |
359 | +{ | |
360 | + static GraphicDevice *graphic_device = &sunxi_display.graphic_device; | |
361 | + /* | |
362 | + * Vesa standard 1024x768@60 | |
363 | + * 65.0 1024 1048 1184 1344 768 771 777 806 -hsync -vsync | |
364 | + */ | |
365 | + struct fb_videomode mode = { | |
366 | + .name = "1024x768", | |
367 | + .refresh = 60, | |
368 | + .xres = 1024, | |
369 | + .yres = 768, | |
370 | + .pixclock = 65000, | |
371 | + .left_margin = 160, | |
372 | + .right_margin = 24, | |
373 | + .upper_margin = 29, | |
374 | + .lower_margin = 3, | |
375 | + .hsync_len = 136, | |
376 | + .vsync_len = 6, | |
377 | + .sync = 0, | |
378 | + .vmode = 0, | |
379 | + .flag = 0, | |
380 | + }; | |
381 | + int ret; | |
382 | + | |
383 | + memset(&sunxi_display, 0, sizeof(struct sunxi_display)); | |
384 | + | |
385 | + printf("Reserved %dkB of RAM for Framebuffer.\n", | |
386 | + CONFIG_SUNXI_FB_SIZE >> 10); | |
387 | + gd->fb_base = gd->ram_top; | |
388 | + | |
389 | + ret = sunxi_hdmi_hpd_detect(); | |
390 | + if (!ret) | |
391 | + return NULL; | |
392 | + | |
393 | + printf("HDMI connected.\n"); | |
394 | + sunxi_display.enabled = true; | |
395 | + | |
396 | + printf("Setting up a %s console.\n", mode.name); | |
397 | + sunxi_engines_init(); | |
398 | + sunxi_mode_set(&mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE); | |
399 | + | |
400 | + /* | |
401 | + * These are the only members of this structure that are used. All the | |
402 | + * others are driver specific. There is nothing to decribe pitch or | |
403 | + * stride, but we are lucky with our hw. | |
404 | + */ | |
405 | + graphic_device->frameAdrs = gd->fb_base; | |
406 | + graphic_device->gdfIndex = GDF_32BIT_X888RGB; | |
407 | + graphic_device->gdfBytesPP = 4; | |
408 | + graphic_device->winSizeX = mode.xres; | |
409 | + graphic_device->winSizeY = mode.yres; | |
410 | + | |
411 | + return graphic_device; | |
412 | +} | |
413 | + | |
414 | +/* | |
415 | + * Simplefb support. | |
416 | + */ | |
417 | +#if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB) | |
418 | +int sunxi_simplefb_setup(void *blob) | |
419 | +{ | |
420 | + static GraphicDevice *graphic_device = &sunxi_display.graphic_device; | |
421 | + int offset, ret; | |
422 | + | |
423 | + if (!sunxi_display.enabled) | |
424 | + return 0; | |
425 | + | |
426 | + /* Find a framebuffer node, with pipeline == "de_be0-lcd0-hdmi" */ | |
427 | + offset = fdt_node_offset_by_compatible(blob, -1, | |
428 | + "allwinner,simple-framebuffer"); | |
429 | + while (offset >= 0) { | |
430 | + ret = fdt_find_string(blob, offset, "allwinner,pipeline", | |
431 | + "de_be0-lcd0-hdmi"); | |
432 | + if (ret == 0) | |
433 | + break; | |
434 | + offset = fdt_node_offset_by_compatible(blob, offset, | |
435 | + "allwinner,simple-framebuffer"); | |
436 | + } | |
437 | + if (offset < 0) { | |
438 | + eprintf("Cannot setup simplefb: node not found\n"); | |
439 | + return 0; /* Keep older kernels working */ | |
440 | + } | |
441 | + | |
442 | + ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base, | |
443 | + graphic_device->winSizeX, graphic_device->winSizeY, | |
444 | + graphic_device->winSizeX * graphic_device->gdfBytesPP, | |
445 | + "x8r8g8b8"); | |
446 | + if (ret) | |
447 | + eprintf("Cannot setup simplefb: Error setting properties\n"); | |
448 | + | |
449 | + return ret; | |
450 | +} | |
451 | +#endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */ |
include/configs/sun7i.h
include/configs/sunxi-common.h
... | ... | @@ -197,6 +197,36 @@ |
197 | 197 | #define CONFIG_SPL_GPIO_SUPPORT |
198 | 198 | #define CONFIG_CMD_GPIO |
199 | 199 | |
200 | +#ifdef CONFIG_VIDEO | |
201 | +/* | |
202 | + * The amount of RAM that is reserved for the FB. This will not show up as | |
203 | + * RAM to the kernel, but will be reclaimed by a KMS driver in future. | |
204 | + */ | |
205 | +#define CONFIG_SUNXI_FB_SIZE (8 << 20) | |
206 | + | |
207 | +/* Do we want to initialize a simple FB? */ | |
208 | +#define CONFIG_VIDEO_DT_SIMPLEFB | |
209 | + | |
210 | +#define CONFIG_VIDEO_SUNXI | |
211 | + | |
212 | +#define CONFIG_CFB_CONSOLE | |
213 | +#define CONFIG_VIDEO_SW_CURSOR | |
214 | +#define CONFIG_VIDEO_LOGO | |
215 | + | |
216 | +/* allow both serial and cfb console. */ | |
217 | +#define CONFIG_CONSOLE_MUX | |
218 | +/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */ | |
219 | +#define CONFIG_VGA_AS_SINGLE_DEVICE | |
220 | + | |
221 | +#define CONFIG_SYS_MEM_TOP_HIDE ((CONFIG_SUNXI_FB_SIZE + 0xFFF) & ~0xFFF) | |
222 | + | |
223 | +/* To be able to hook simplefb into dt */ | |
224 | +#ifdef CONFIG_VIDEO_DT_SIMPLEFB | |
225 | +#define CONFIG_OF_BOARD_SETUP | |
226 | +#endif | |
227 | + | |
228 | +#endif /* CONFIG_VIDEO */ | |
229 | + | |
200 | 230 | /* Ethernet support */ |
201 | 231 | #ifdef CONFIG_SUNXI_EMAC |
202 | 232 | #define CONFIG_MII /* MII PHY management */ |
... | ... | @@ -217,6 +247,13 @@ |
217 | 247 | #define CONFIG_USB_STORAGE |
218 | 248 | #endif |
219 | 249 | |
250 | +#ifdef CONFIG_USB_KEYBOARD | |
251 | +#define CONFIG_CONSOLE_MUX | |
252 | +#define CONFIG_PREBOOT | |
253 | +#define CONFIG_SYS_STDIO_DEREGISTER | |
254 | +#define CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE | |
255 | +#endif | |
256 | + | |
220 | 257 | #if !defined CONFIG_ENV_IS_IN_MMC && \ |
221 | 258 | !defined CONFIG_ENV_IS_IN_NAND && \ |
222 | 259 | !defined CONFIG_ENV_IS_IN_FAT && \ |
... | ... | @@ -225,6 +262,7 @@ |
225 | 262 | #endif |
226 | 263 | |
227 | 264 | #define CONFIG_MISC_INIT_R |
265 | +#define CONFIG_SYS_CONSOLE_IS_IN_ENV | |
228 | 266 | |
229 | 267 | #ifndef CONFIG_SPL_BUILD |
230 | 268 | #include <config_distro_defaults.h> |
231 | 269 | |
... | ... | @@ -266,7 +304,31 @@ |
266 | 304 | |
267 | 305 | #include <config_distro_bootcmd.h> |
268 | 306 | |
307 | +#ifdef CONFIG_USB_KEYBOARD | |
308 | +#define CONSOLE_STDIN_SETTINGS \ | |
309 | + "preboot=usb start\0" \ | |
310 | + "stdin=serial,usbkbd\0" | |
311 | +#else | |
312 | +#define CONSOLE_STDIN_SETTINGS \ | |
313 | + "stdin=serial\0" | |
314 | +#endif | |
315 | + | |
316 | +#ifdef CONFIG_VIDEO | |
317 | +#define CONSOLE_STDOUT_SETTINGS \ | |
318 | + "stdout=serial,vga\0" \ | |
319 | + "stderr=serial,vga\0" | |
320 | +#else | |
321 | +#define CONSOLE_STDOUT_SETTINGS \ | |
322 | + "stdout=serial\0" \ | |
323 | + "stderr=serial\0" | |
324 | +#endif | |
325 | + | |
326 | +#define CONSOLE_ENV_SETTINGS \ | |
327 | + CONSOLE_STDIN_SETTINGS \ | |
328 | + CONSOLE_STDOUT_SETTINGS | |
329 | + | |
269 | 330 | #define CONFIG_EXTRA_ENV_SETTINGS \ |
331 | + CONSOLE_ENV_SETTINGS \ | |
270 | 332 | MEM_LAYOUT_ENV_SETTINGS \ |
271 | 333 | "fdtfile=" CONFIG_FDTFILE "\0" \ |
272 | 334 | "console=ttyS0,115200\0" \ |
include/fdt_support.h
... | ... | @@ -172,6 +172,9 @@ |
172 | 172 | int ft_verify_fdt(void *fdt); |
173 | 173 | int arch_fixup_memory_node(void *blob); |
174 | 174 | |
175 | +int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width, | |
176 | + u32 height, u32 stride, const char *format); | |
177 | + | |
175 | 178 | #endif /* ifdef CONFIG_OF_LIBFDT */ |
176 | 179 | |
177 | 180 | #ifdef USE_HOSTCC |