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