xref: /openbmc/u-boot/board/freescale/p1022ds/diu.c (revision ed09a554)
1 /*
2  * Copyright 2010-2011 Freescale Semiconductor, Inc.
3  * Authors: Timur Tabi <timur@freescale.com>
4  *
5  * FSL DIU Framebuffer driver
6  *
7  * SPDX-License-Identifier:	GPL-2.0+
8  */
9 
10 #include <common.h>
11 #include <command.h>
12 #include <linux/ctype.h>
13 #include <asm/io.h>
14 #include <stdio_dev.h>
15 #include <video_fb.h>
16 #include "../common/ngpixis.h"
17 #include <fsl_diu_fb.h>
18 
19 /* The CTL register is called 'csr' in the ngpixis_t structure */
20 #define PX_CTL_ALTACC		0x80
21 
22 #define PX_BRDCFG0_ELBC_SPI_MASK	0xc0
23 #define PX_BRDCFG0_ELBC_SPI_ELBC	0x00
24 #define PX_BRDCFG0_ELBC_SPI_NULL	0xc0
25 #define PX_BRDCFG0_ELBC_DIU		0x02
26 
27 #define PX_BRDCFG1_DVIEN	0x80
28 #define PX_BRDCFG1_DFPEN	0x40
29 #define PX_BRDCFG1_BACKLIGHT	0x20
30 
31 #define PMUXCR_ELBCDIU_MASK	0xc0000000
32 #define PMUXCR_ELBCDIU_NOR16	0x80000000
33 #define PMUXCR_ELBCDIU_DIU	0x40000000
34 
35 /*
36  * DIU Area Descriptor
37  *
38  * Note that we need to byte-swap the value before it's written to the AD
39  * register.  So even though the registers don't look like they're in the same
40  * bit positions as they are on the MPC8610, the same value is written to the
41  * AD register on the MPC8610 and on the P1022.
42  */
43 #define AD_BYTE_F		0x10000000
44 #define AD_ALPHA_C_SHIFT	25
45 #define AD_BLUE_C_SHIFT		23
46 #define AD_GREEN_C_SHIFT	21
47 #define AD_RED_C_SHIFT		19
48 #define AD_PIXEL_S_SHIFT	16
49 #define AD_COMP_3_SHIFT		12
50 #define AD_COMP_2_SHIFT		8
51 #define AD_COMP_1_SHIFT		4
52 #define AD_COMP_0_SHIFT		0
53 
54 /*
55  * Variables used by the DIU/LBC switching code.  It's safe to makes these
56  * global, because the DIU requires DDR, so we'll only run this code after
57  * relocation.
58  */
59 static u8 px_brdcfg0;
60 static u32 pmuxcr;
61 static void *lbc_lcs0_ba;
62 static void *lbc_lcs1_ba;
63 static u32 old_br0, old_or0, old_br1, old_or1;
64 static u32 new_br0, new_or0, new_br1, new_or1;
65 
66 void diu_set_pixel_clock(unsigned int pixclock)
67 {
68 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
69 	unsigned long speed_ccb, temp;
70 	u32 pixval;
71 
72 	speed_ccb = get_bus_freq(0);
73 	temp = 1000000000 / pixclock;
74 	temp *= 1000;
75 	pixval = speed_ccb / temp;
76 	debug("DIU pixval = %u\n", pixval);
77 
78 	/* Modify PXCLK in GUTS CLKDVDR */
79 	temp = in_be32(&gur->clkdvdr) & 0x2000FFFF;
80 	out_be32(&gur->clkdvdr, temp);			/* turn off clock */
81 	out_be32(&gur->clkdvdr, temp | 0x80000000 | ((pixval & 0x1F) << 16));
82 }
83 
84 int platform_diu_init(unsigned int xres, unsigned int yres, const char *port)
85 {
86 	ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
87 	const char *name;
88 	u32 pixel_format;
89 	u8 temp;
90 	phys_addr_t phys0, phys1; /* BR0/BR1 physical addresses */
91 
92 	/*
93 	 * Indirect mode requires both BR0 and BR1 to be set to "GPCM",
94 	 * otherwise writes to these addresses won't actually appear on the
95 	 * local bus, and so the PIXIS won't see them.
96 	 *
97 	 * In FCM mode, writes go to the NAND controller, which does not pass
98 	 * them to the localbus directly.  So we force BR0 and BR1 into GPCM
99 	 * mode, since we don't care about what's behind the localbus any
100 	 * more.  However, we save those registers first, so that we can
101 	 * restore them when necessary.
102 	 */
103 	new_br0 = old_br0 = get_lbc_br(0);
104 	new_br1 = old_br1 = get_lbc_br(1);
105 	new_or0 = old_or0 = get_lbc_or(0);
106 	new_or1 = old_or1 = get_lbc_or(1);
107 
108 	/*
109 	 * Use the existing BRx/ORx values if it's already GPCM. Otherwise,
110 	 * force the values to simple 32KB GPCM windows with the most
111 	 * conservative timing.
112 	 */
113 	if ((old_br0 & BR_MSEL) != BR_MS_GPCM) {
114 		new_br0 = (get_lbc_br(0) & BR_BA) | BR_V;
115 		new_or0 = OR_AM_32KB | 0xFF7;
116 		set_lbc_br(0, new_br0);
117 		set_lbc_or(0, new_or0);
118 	}
119 	if ((old_br1 & BR_MSEL) != BR_MS_GPCM) {
120 		new_br1 = (get_lbc_br(1) & BR_BA) | BR_V;
121 		new_or1 = OR_AM_32KB | 0xFF7;
122 		set_lbc_br(1, new_br1);
123 		set_lbc_or(1, new_or1);
124 	}
125 
126 	/*
127 	 * Determine the physical addresses for Chip Selects 0 and 1.  The
128 	 * BR0/BR1 registers contain the truncated physical addresses for the
129 	 * chip selects, mapped via the localbus LAW.  Since the BRx registers
130 	 * only contain the lower 32 bits of the address, we have to determine
131 	 * the upper 4 bits some other way.  The proper way is to scan the LAW
132 	 * table looking for a matching localbus address. Instead, we cheat.
133 	 * We know that the upper bits are 0 for 32-bit addressing, or 0xF for
134 	 * 36-bit addressing.
135 	 */
136 #ifdef CONFIG_PHYS_64BIT
137 	phys0 = 0xf00000000ULL | (old_br0 & old_or0 & BR_BA);
138 	phys1 = 0xf00000000ULL | (old_br1 & old_or1 & BR_BA);
139 #else
140 	phys0 = old_br0 & old_or0 & BR_BA;
141 	phys1 = old_br1 & old_or1 & BR_BA;
142 #endif
143 
144 	 /* Save the LBC LCS0 and LCS1 addresses for the DIU mux functions */
145 	lbc_lcs0_ba = map_physmem(phys0, 1, 0);
146 	lbc_lcs1_ba = map_physmem(phys1, 1, 0);
147 
148 	pixel_format = cpu_to_le32(AD_BYTE_F | (3 << AD_ALPHA_C_SHIFT) |
149 		(0 << AD_BLUE_C_SHIFT) | (1 << AD_GREEN_C_SHIFT) |
150 		(2 << AD_RED_C_SHIFT) | (8 << AD_COMP_3_SHIFT) |
151 		(8 << AD_COMP_2_SHIFT) | (8 << AD_COMP_1_SHIFT) |
152 		(8 << AD_COMP_0_SHIFT) | (3 << AD_PIXEL_S_SHIFT));
153 
154 	temp = in_8(&pixis->brdcfg1);
155 
156 	if (strncmp(port, "lvds", 4) == 0) {
157 		/* Single link LVDS */
158 		temp &= ~PX_BRDCFG1_DVIEN;
159 		/*
160 		 * LVDS also needs backlight enabled, otherwise the display
161 		 * will be blank.
162 		 */
163 		temp |= (PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
164 		name = "Single-Link LVDS";
165 	} else {	/* DVI */
166 		/* Enable the DVI port, disable the DFP and the backlight */
167 		temp &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
168 		temp |= PX_BRDCFG1_DVIEN;
169 		name = "DVI";
170 	}
171 
172 	printf("DIU:   Switching to %s monitor @ %ux%u\n", name, xres, yres);
173 	out_8(&pixis->brdcfg1, temp);
174 
175 	/*
176 	 * Enable PIXIS indirect access mode.  This is a hack that allows us to
177 	 * access PIXIS registers even when the LBC pins have been muxed to the
178 	 * DIU.
179 	 */
180 	setbits_8(&pixis->csr, PX_CTL_ALTACC);
181 
182 	/*
183 	 * Route the LAD pins to the DIU.  This will disable access to the eLBC,
184 	 * which means we won't be able to read/write any NOR flash addresses!
185 	 */
186 	out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0));
187 	px_brdcfg0 = in_8(lbc_lcs1_ba);
188 	out_8(lbc_lcs1_ba, px_brdcfg0 | PX_BRDCFG0_ELBC_DIU);
189 	in_8(lbc_lcs1_ba);
190 
191 	/* Set PMUXCR to switch the muxed pins from the LBC to the DIU */
192 	clrsetbits_be32(&gur->pmuxcr, PMUXCR_ELBCDIU_MASK, PMUXCR_ELBCDIU_DIU);
193 	pmuxcr = in_be32(&gur->pmuxcr);
194 
195 	return fsl_diu_init(xres, yres, pixel_format, 0);
196 }
197 
198 /*
199  * set_mux_to_lbc - disable the DIU so that we can read/write to elbc
200  *
201  * On the Freescale P1022, the DIU video signal and the LBC address/data lines
202  * share the same pins, which means that when the DIU is active (e.g. the
203  * console is on the DVI display), NOR flash cannot be accessed.  So we use the
204  * weak accessor feature of the CFI flash code to temporarily switch the pin
205  * mux from DIU to LBC whenever we want to read or write flash.  This has a
206  * significant performance penalty, but it's the only way to make it work.
207  *
208  * There are two muxes: one on the chip, and one on the board. The chip mux
209  * controls whether the pins are used for the DIU or the LBC, and it is
210  * set via PMUXCR.  The board mux controls whether those signals go to
211  * the video connector or the NOR flash chips, and it is set via the ngPIXIS.
212  */
213 static int set_mux_to_lbc(void)
214 {
215 	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
216 
217 	/* Switch the muxes only if they're currently set to DIU mode */
218 	if ((in_be32(&gur->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
219 	    PMUXCR_ELBCDIU_NOR16) {
220 		/*
221 		 * In DIU mode, the PIXIS can only be accessed indirectly
222 		 * since we can't read/write the LBC directly.
223 		 */
224 		/* Set the board mux to LBC.  This will disable the display. */
225 		out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0));
226 		out_8(lbc_lcs1_ba, px_brdcfg0);
227 		in_8(lbc_lcs1_ba);
228 
229 		/* Disable indirect PIXIS mode */
230 		out_8(lbc_lcs0_ba, offsetof(ngpixis_t, csr));
231 		clrbits_8(lbc_lcs1_ba, PX_CTL_ALTACC);
232 
233 		/* Set the chip mux to LBC mode, so that writes go to flash. */
234 		out_be32(&gur->pmuxcr, (pmuxcr & ~PMUXCR_ELBCDIU_MASK) |
235 			 PMUXCR_ELBCDIU_NOR16);
236 		in_be32(&gur->pmuxcr);
237 
238 		/* Restore the BR0 and BR1 settings */
239 		set_lbc_br(0, old_br0);
240 		set_lbc_or(0, old_or0);
241 		set_lbc_br(1, old_br1);
242 		set_lbc_or(1, old_or1);
243 
244 		return 1;
245 	}
246 
247 	return 0;
248 }
249 
250 /*
251  * set_mux_to_diu - re-enable the DIU muxing
252  *
253  * This function restores the chip and board muxing to point to the DIU.
254  */
255 static void set_mux_to_diu(void)
256 {
257 	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
258 
259 	/* Set BR0 and BR1 to GPCM mode */
260 	set_lbc_br(0, new_br0);
261 	set_lbc_or(0, new_or0);
262 	set_lbc_br(1, new_br1);
263 	set_lbc_or(1, new_or1);
264 
265 	/* Enable indirect PIXIS mode */
266 	setbits_8(&pixis->csr, PX_CTL_ALTACC);
267 
268 	/* Set the board mux to DIU.  This will enable the display. */
269 	out_8(lbc_lcs0_ba, offsetof(ngpixis_t, brdcfg0));
270 	out_8(lbc_lcs1_ba, px_brdcfg0 | PX_BRDCFG0_ELBC_DIU);
271 	in_8(lbc_lcs1_ba);
272 
273 	/* Set the chip mux to DIU mode. */
274 	out_be32(&gur->pmuxcr, pmuxcr);
275 	in_be32(&gur->pmuxcr);
276 }
277 
278 /*
279  * pixis_read - board-specific function to read from the PIXIS
280  *
281  * This function overrides the generic pixis_read() function, so that it can
282  * use PIXIS indirect mode if necessary.
283  */
284 u8 pixis_read(unsigned int reg)
285 {
286 	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
287 
288 	/* Use indirect mode if the mux is currently set to DIU mode */
289 	if ((in_be32(&gur->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
290 	    PMUXCR_ELBCDIU_NOR16) {
291 		out_8(lbc_lcs0_ba, reg);
292 		return in_8(lbc_lcs1_ba);
293 	} else {
294 		void *p = (void *)PIXIS_BASE;
295 
296 		return in_8(p + reg);
297 	}
298 }
299 
300 /*
301  * pixis_write - board-specific function to write to the PIXIS
302  *
303  * This function overrides the generic pixis_write() function, so that it can
304  * use PIXIS indirect mode if necessary.
305  */
306 void pixis_write(unsigned int reg, u8 value)
307 {
308 	ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC85xx_GUTS_ADDR;
309 
310 	/* Use indirect mode if the mux is currently set to DIU mode */
311 	if ((in_be32(&gur->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
312 	    PMUXCR_ELBCDIU_NOR16) {
313 		out_8(lbc_lcs0_ba, reg);
314 		out_8(lbc_lcs1_ba, value);
315 		/* Do a read-back to ensure the write completed */
316 		in_8(lbc_lcs1_ba);
317 	} else {
318 		void *p = (void *)PIXIS_BASE;
319 
320 		out_8(p + reg, value);
321 	}
322 }
323 
324 void pixis_bank_reset(void)
325 {
326 	/*
327 	 * For some reason, a PIXIS bank reset does not work if the PIXIS is
328 	 * in indirect mode, so switch to direct mode first.
329 	 */
330 	set_mux_to_lbc();
331 
332 	out_8(&pixis->vctl, 0);
333 	out_8(&pixis->vctl, 1);
334 
335 	while (1);
336 }
337 
338 #ifdef CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS
339 
340 void flash_write8(u8 value, void *addr)
341 {
342 	int sw = set_mux_to_lbc();
343 
344 	__raw_writeb(value, addr);
345 	if (sw) {
346 		/*
347 		 * To ensure the post-write is completed to eLBC, software must
348 		 * perform a dummy read from one valid address from eLBC space
349 		 * before changing the eLBC_DIU from NOR mode to DIU mode.
350 		 * set_mux_to_diu() includes a sync that will ensure the
351 		 * __raw_readb() completes before it switches the mux.
352 		 */
353 		__raw_readb(addr);
354 		set_mux_to_diu();
355 	}
356 }
357 
358 void flash_write16(u16 value, void *addr)
359 {
360 	int sw = set_mux_to_lbc();
361 
362 	__raw_writew(value, addr);
363 	if (sw) {
364 		/*
365 		 * To ensure the post-write is completed to eLBC, software must
366 		 * perform a dummy read from one valid address from eLBC space
367 		 * before changing the eLBC_DIU from NOR mode to DIU mode.
368 		 * set_mux_to_diu() includes a sync that will ensure the
369 		 * __raw_readb() completes before it switches the mux.
370 		 */
371 		__raw_readb(addr);
372 		set_mux_to_diu();
373 	}
374 }
375 
376 void flash_write32(u32 value, void *addr)
377 {
378 	int sw = set_mux_to_lbc();
379 
380 	__raw_writel(value, addr);
381 	if (sw) {
382 		/*
383 		 * To ensure the post-write is completed to eLBC, software must
384 		 * perform a dummy read from one valid address from eLBC space
385 		 * before changing the eLBC_DIU from NOR mode to DIU mode.
386 		 * set_mux_to_diu() includes a sync that will ensure the
387 		 * __raw_readb() completes before it switches the mux.
388 		 */
389 		__raw_readb(addr);
390 		set_mux_to_diu();
391 	}
392 }
393 
394 void flash_write64(u64 value, void *addr)
395 {
396 	int sw = set_mux_to_lbc();
397 	uint32_t *p = addr;
398 
399 	/*
400 	 * There is no __raw_writeq(), so do the write manually.  We don't trust
401 	 * the compiler, so we use inline assembly.
402 	 */
403 	__asm__ __volatile__(
404 		"stw%U0%X0 %2,%0;\n"
405 		"stw%U1%X1 %3,%1;\n"
406 		: "=m" (*p), "=m" (*(p + 1))
407 		: "r" ((uint32_t) (value >> 32)), "r" ((uint32_t) (value)));
408 
409 	if (sw) {
410 		/*
411 		 * To ensure the post-write is completed to eLBC, software must
412 		 * perform a dummy read from one valid address from eLBC space
413 		 * before changing the eLBC_DIU from NOR mode to DIU mode.  We
414 		 * read addr+4 because we just wrote to addr+4, so that's how we
415 		 * maintain execution order.  set_mux_to_diu() includes a sync
416 		 * that will ensure the __raw_readb() completes before it
417 		 * switches the mux.
418 		 */
419 		__raw_readb(addr + 4);
420 		set_mux_to_diu();
421 	}
422 }
423 
424 u8 flash_read8(void *addr)
425 {
426 	u8 ret;
427 
428 	int sw = set_mux_to_lbc();
429 
430 	ret = __raw_readb(addr);
431 	if (sw)
432 		set_mux_to_diu();
433 
434 	return ret;
435 }
436 
437 u16 flash_read16(void *addr)
438 {
439 	u16 ret;
440 
441 	int sw = set_mux_to_lbc();
442 
443 	ret = __raw_readw(addr);
444 	if (sw)
445 		set_mux_to_diu();
446 
447 	return ret;
448 }
449 
450 u32 flash_read32(void *addr)
451 {
452 	u32 ret;
453 
454 	int sw = set_mux_to_lbc();
455 
456 	ret = __raw_readl(addr);
457 	if (sw)
458 		set_mux_to_diu();
459 
460 	return ret;
461 }
462 
463 u64 flash_read64(void *addr)
464 {
465 	u64 ret;
466 
467 	int sw = set_mux_to_lbc();
468 
469 	/* There is no __raw_readq(), so do the read manually */
470 	ret = *(volatile u64 *)addr;
471 	if (sw)
472 		set_mux_to_diu();
473 
474 	return ret;
475 }
476 
477 #endif
478