130be4c96STimur Tabi /* 230be4c96STimur Tabi * P1022DS board specific routines 330be4c96STimur Tabi * 430be4c96STimur Tabi * Authors: Travis Wheatley <travis.wheatley@freescale.com> 530be4c96STimur Tabi * Dave Liu <daveliu@freescale.com> 630be4c96STimur Tabi * Timur Tabi <timur@freescale.com> 730be4c96STimur Tabi * 830be4c96STimur Tabi * Copyright 2010 Freescale Semiconductor, Inc. 930be4c96STimur Tabi * 1030be4c96STimur Tabi * This file is taken from the Freescale P1022DS BSP, with modifications: 1130be4c96STimur Tabi * 2) No AMP support 1230be4c96STimur Tabi * 3) No PCI endpoint support 1330be4c96STimur Tabi * 1430be4c96STimur Tabi * This file is licensed under the terms of the GNU General Public License 1530be4c96STimur Tabi * version 2. This program is licensed "as is" without any warranty of any 1630be4c96STimur Tabi * kind, whether express or implied. 1730be4c96STimur Tabi */ 1830be4c96STimur Tabi 1930be4c96STimur Tabi #include <linux/pci.h> 2030be4c96STimur Tabi #include <linux/of_platform.h> 21dc1c41f4SKumar Gala #include <linux/memblock.h> 222c184cd3STimur Tabi #include <asm/div64.h> 2330be4c96STimur Tabi #include <asm/mpic.h> 2430be4c96STimur Tabi #include <asm/swiotlb.h> 2530be4c96STimur Tabi 2630be4c96STimur Tabi #include <sysdev/fsl_soc.h> 2730be4c96STimur Tabi #include <sysdev/fsl_pci.h> 28ba8438fbSMichael Neuling #include <asm/udbg.h> 292c184cd3STimur Tabi #include <asm/fsl_guts.h> 306bd825f0STimur Tabi #include <asm/fsl_lbc.h> 31582d3e09SKyle Moffett #include "smp.h" 322c184cd3STimur Tabi 33543a07b1SDmitry Eremin-Solenikov #include "mpc85xx.h" 34543a07b1SDmitry Eremin-Solenikov 352c184cd3STimur Tabi #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 362c184cd3STimur Tabi 376597c713STimur Tabi #define PMUXCR_ELBCDIU_MASK 0xc0000000 386597c713STimur Tabi #define PMUXCR_ELBCDIU_NOR16 0x80000000 396597c713STimur Tabi #define PMUXCR_ELBCDIU_DIU 0x40000000 406597c713STimur Tabi 412c184cd3STimur Tabi /* 422c184cd3STimur Tabi * Board-specific initialization of the DIU. This code should probably be 432c184cd3STimur Tabi * executed when the DIU is opened, rather than in arch code, but the DIU 442c184cd3STimur Tabi * driver does not have a mechanism for this (yet). 452c184cd3STimur Tabi * 462c184cd3STimur Tabi * This is especially problematic on the P1022DS because the local bus (eLBC) 472c184cd3STimur Tabi * and the DIU video signals share the same pins, which means that enabling the 482c184cd3STimur Tabi * DIU will disable access to NOR flash. 492c184cd3STimur Tabi */ 502c184cd3STimur Tabi 512c184cd3STimur Tabi /* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */ 522c184cd3STimur Tabi #define CLKDVDR_PXCKEN 0x80000000 532c184cd3STimur Tabi #define CLKDVDR_PXCKINV 0x10000000 542c184cd3STimur Tabi #define CLKDVDR_PXCKDLY 0x06000000 552c184cd3STimur Tabi #define CLKDVDR_PXCLK_MASK 0x00FF0000 562c184cd3STimur Tabi 572c184cd3STimur Tabi /* Some ngPIXIS register definitions */ 586597c713STimur Tabi #define PX_CTL 3 596597c713STimur Tabi #define PX_BRDCFG0 8 606597c713STimur Tabi #define PX_BRDCFG1 9 616597c713STimur Tabi 626597c713STimur Tabi #define PX_BRDCFG0_ELBC_SPI_MASK 0xc0 636597c713STimur Tabi #define PX_BRDCFG0_ELBC_SPI_ELBC 0x00 646597c713STimur Tabi #define PX_BRDCFG0_ELBC_SPI_NULL 0xc0 656597c713STimur Tabi #define PX_BRDCFG0_ELBC_DIU 0x02 666597c713STimur Tabi 672c184cd3STimur Tabi #define PX_BRDCFG1_DVIEN 0x80 682c184cd3STimur Tabi #define PX_BRDCFG1_DFPEN 0x40 692c184cd3STimur Tabi #define PX_BRDCFG1_BACKLIGHT 0x20 702c184cd3STimur Tabi #define PX_BRDCFG1_DDCEN 0x10 712c184cd3STimur Tabi 726597c713STimur Tabi #define PX_CTL_ALTACC 0x80 736597c713STimur Tabi 742c184cd3STimur Tabi /* 752c184cd3STimur Tabi * DIU Area Descriptor 762c184cd3STimur Tabi * 772c184cd3STimur Tabi * Note that we need to byte-swap the value before it's written to the AD 782c184cd3STimur Tabi * register. So even though the registers don't look like they're in the same 792c184cd3STimur Tabi * bit positions as they are on the MPC8610, the same value is written to the 802c184cd3STimur Tabi * AD register on the MPC8610 and on the P1022. 812c184cd3STimur Tabi */ 822c184cd3STimur Tabi #define AD_BYTE_F 0x10000000 832c184cd3STimur Tabi #define AD_ALPHA_C_MASK 0x0E000000 842c184cd3STimur Tabi #define AD_ALPHA_C_SHIFT 25 852c184cd3STimur Tabi #define AD_BLUE_C_MASK 0x01800000 862c184cd3STimur Tabi #define AD_BLUE_C_SHIFT 23 872c184cd3STimur Tabi #define AD_GREEN_C_MASK 0x00600000 882c184cd3STimur Tabi #define AD_GREEN_C_SHIFT 21 892c184cd3STimur Tabi #define AD_RED_C_MASK 0x00180000 902c184cd3STimur Tabi #define AD_RED_C_SHIFT 19 912c184cd3STimur Tabi #define AD_PALETTE 0x00040000 922c184cd3STimur Tabi #define AD_PIXEL_S_MASK 0x00030000 932c184cd3STimur Tabi #define AD_PIXEL_S_SHIFT 16 942c184cd3STimur Tabi #define AD_COMP_3_MASK 0x0000F000 952c184cd3STimur Tabi #define AD_COMP_3_SHIFT 12 962c184cd3STimur Tabi #define AD_COMP_2_MASK 0x00000F00 972c184cd3STimur Tabi #define AD_COMP_2_SHIFT 8 982c184cd3STimur Tabi #define AD_COMP_1_MASK 0x000000F0 992c184cd3STimur Tabi #define AD_COMP_1_SHIFT 4 1002c184cd3STimur Tabi #define AD_COMP_0_MASK 0x0000000F 1012c184cd3STimur Tabi #define AD_COMP_0_SHIFT 0 1022c184cd3STimur Tabi 1032c184cd3STimur Tabi #define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \ 1042c184cd3STimur Tabi cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \ 1052c184cd3STimur Tabi (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \ 1062c184cd3STimur Tabi (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \ 1072c184cd3STimur Tabi (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \ 1082c184cd3STimur Tabi (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT)) 1092c184cd3STimur Tabi 1102c184cd3STimur Tabi /** 1112c184cd3STimur Tabi * p1022ds_get_pixel_format: return the Area Descriptor for a given pixel depth 1122c184cd3STimur Tabi * 1132c184cd3STimur Tabi * The Area Descriptor is a 32-bit value that determine which bits in each 1142c184cd3STimur Tabi * pixel are to be used for each color. 1152c184cd3STimur Tabi */ 1167653aaabSTimur Tabi static u32 p1022ds_get_pixel_format(enum fsl_diu_monitor_port port, 1177653aaabSTimur Tabi unsigned int bits_per_pixel) 1182c184cd3STimur Tabi { 1192c184cd3STimur Tabi switch (bits_per_pixel) { 1202c184cd3STimur Tabi case 32: 1212c184cd3STimur Tabi /* 0x88883316 */ 1222c184cd3STimur Tabi return MAKE_AD(3, 2, 0, 1, 3, 8, 8, 8, 8); 1232c184cd3STimur Tabi case 24: 1242c184cd3STimur Tabi /* 0x88082219 */ 1252c184cd3STimur Tabi return MAKE_AD(4, 0, 1, 2, 2, 0, 8, 8, 8); 1262c184cd3STimur Tabi case 16: 1272c184cd3STimur Tabi /* 0x65053118 */ 1282c184cd3STimur Tabi return MAKE_AD(4, 2, 1, 0, 1, 5, 6, 5, 0); 1292c184cd3STimur Tabi default: 1302c184cd3STimur Tabi pr_err("fsl-diu: unsupported pixel depth %u\n", bits_per_pixel); 1312c184cd3STimur Tabi return 0; 1322c184cd3STimur Tabi } 1332c184cd3STimur Tabi } 1342c184cd3STimur Tabi 1352c184cd3STimur Tabi /** 1362c184cd3STimur Tabi * p1022ds_set_gamma_table: update the gamma table, if necessary 1372c184cd3STimur Tabi * 1382c184cd3STimur Tabi * On some boards, the gamma table for some ports may need to be modified. 1392c184cd3STimur Tabi * This is not the case on the P1022DS, so we do nothing. 1402c184cd3STimur Tabi */ 1417653aaabSTimur Tabi static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port, 1427653aaabSTimur Tabi char *gamma_table_base) 1432c184cd3STimur Tabi { 1442c184cd3STimur Tabi } 1452c184cd3STimur Tabi 1466bd825f0STimur Tabi struct fsl_law { 1476bd825f0STimur Tabi u32 lawbar; 1486bd825f0STimur Tabi u32 reserved1; 1496bd825f0STimur Tabi u32 lawar; 1506bd825f0STimur Tabi u32 reserved[5]; 1516bd825f0STimur Tabi }; 1526bd825f0STimur Tabi 1536bd825f0STimur Tabi #define LAWBAR_MASK 0x00F00000 1546bd825f0STimur Tabi #define LAWBAR_SHIFT 12 1556bd825f0STimur Tabi 1566bd825f0STimur Tabi #define LAWAR_EN 0x80000000 1576bd825f0STimur Tabi #define LAWAR_TGT_MASK 0x01F00000 1586bd825f0STimur Tabi #define LAW_TRGT_IF_LBC (0x04 << 20) 1596bd825f0STimur Tabi 1606bd825f0STimur Tabi #define LAWAR_MASK (LAWAR_EN | LAWAR_TGT_MASK) 1616bd825f0STimur Tabi #define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC) 1626bd825f0STimur Tabi 1636bd825f0STimur Tabi #define BR_BA 0xFFFF8000 1646bd825f0STimur Tabi 1656bd825f0STimur Tabi /* 1666bd825f0STimur Tabi * Map a BRx value to a physical address 1676bd825f0STimur Tabi * 1686bd825f0STimur Tabi * The localbus BRx registers only store the lower 32 bits of the address. To 1696bd825f0STimur Tabi * obtain the upper four bits, we need to scan the LAW table. The entry which 1706bd825f0STimur Tabi * maps to the localbus will contain the upper four bits. 1716bd825f0STimur Tabi */ 1726bd825f0STimur Tabi static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br) 1736bd825f0STimur Tabi { 1746bd825f0STimur Tabi #ifndef CONFIG_PHYS_64BIT 1756bd825f0STimur Tabi /* 1766bd825f0STimur Tabi * If we only have 32-bit addressing, then the BRx address *is* the 1776bd825f0STimur Tabi * physical address. 1786bd825f0STimur Tabi */ 1796bd825f0STimur Tabi return br & BR_BA; 1806bd825f0STimur Tabi #else 1816bd825f0STimur Tabi const struct fsl_law *law = ecm + 0xc08; 1826bd825f0STimur Tabi unsigned int i; 1836bd825f0STimur Tabi 1846bd825f0STimur Tabi for (i = 0; i < count; i++) { 1856bd825f0STimur Tabi u64 lawbar = in_be32(&law[i].lawbar); 1866bd825f0STimur Tabi u32 lawar = in_be32(&law[i].lawar); 1876bd825f0STimur Tabi 1886bd825f0STimur Tabi if ((lawar & LAWAR_MASK) == LAWAR_MATCH) 1896bd825f0STimur Tabi /* Extract the upper four bits */ 1906bd825f0STimur Tabi return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12); 1916bd825f0STimur Tabi } 1926bd825f0STimur Tabi 1936bd825f0STimur Tabi return 0; 1946bd825f0STimur Tabi #endif 1956bd825f0STimur Tabi } 1966bd825f0STimur Tabi 1972c184cd3STimur Tabi /** 1982c184cd3STimur Tabi * p1022ds_set_monitor_port: switch the output to a different monitor port 1992c184cd3STimur Tabi */ 2007653aaabSTimur Tabi static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) 2012c184cd3STimur Tabi { 2026597c713STimur Tabi struct device_node *guts_node; 2036bd825f0STimur Tabi struct device_node *lbc_node = NULL; 2046bd825f0STimur Tabi struct device_node *law_node = NULL; 2059cb6abcbSTimur Tabi struct ccsr_guts __iomem *guts; 2066bd825f0STimur Tabi struct fsl_lbc_regs *lbc = NULL; 2076bd825f0STimur Tabi void *ecm = NULL; 2086597c713STimur Tabi u8 __iomem *lbc_lcs0_ba = NULL; 2096597c713STimur Tabi u8 __iomem *lbc_lcs1_ba = NULL; 2106bd825f0STimur Tabi phys_addr_t cs0_addr, cs1_addr; 211896c01cbSTimur Tabi u32 br0, or0, br1, or1; 2126bd825f0STimur Tabi const __be32 *iprop; 2136bd825f0STimur Tabi unsigned int num_laws; 2146597c713STimur Tabi u8 b; 2156597c713STimur Tabi 2166597c713STimur Tabi /* Map the global utilities registers. */ 2176597c713STimur Tabi guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); 2186597c713STimur Tabi if (!guts_node) { 2196597c713STimur Tabi pr_err("p1022ds: missing global utilties device node\n"); 2206597c713STimur Tabi return; 2216597c713STimur Tabi } 2226597c713STimur Tabi 2236597c713STimur Tabi guts = of_iomap(guts_node, 0); 2246597c713STimur Tabi if (!guts) { 2256597c713STimur Tabi pr_err("p1022ds: could not map global utilties device\n"); 2266597c713STimur Tabi goto exit; 2276597c713STimur Tabi } 2286597c713STimur Tabi 2296bd825f0STimur Tabi lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); 2306bd825f0STimur Tabi if (!lbc_node) { 2316bd825f0STimur Tabi pr_err("p1022ds: missing localbus node\n"); 2326597c713STimur Tabi goto exit; 2336597c713STimur Tabi } 2346597c713STimur Tabi 2356bd825f0STimur Tabi lbc = of_iomap(lbc_node, 0); 2366bd825f0STimur Tabi if (!lbc) { 2376bd825f0STimur Tabi pr_err("p1022ds: could not map localbus node\n"); 2386597c713STimur Tabi goto exit; 2396597c713STimur Tabi } 2406597c713STimur Tabi 2416bd825f0STimur Tabi law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law"); 2426bd825f0STimur Tabi if (!law_node) { 2436bd825f0STimur Tabi pr_err("p1022ds: missing local access window node\n"); 2446597c713STimur Tabi goto exit; 2456597c713STimur Tabi } 2466597c713STimur Tabi 2476bd825f0STimur Tabi ecm = of_iomap(law_node, 0); 2486bd825f0STimur Tabi if (!ecm) { 2496bd825f0STimur Tabi pr_err("p1022ds: could not map local access window node\n"); 2506bd825f0STimur Tabi goto exit; 2516bd825f0STimur Tabi } 2526bd825f0STimur Tabi 2536bd825f0STimur Tabi iprop = of_get_property(law_node, "fsl,num-laws", 0); 2546bd825f0STimur Tabi if (!iprop) { 2556bd825f0STimur Tabi pr_err("p1022ds: LAW node is missing fsl,num-laws property\n"); 2566bd825f0STimur Tabi goto exit; 2576bd825f0STimur Tabi } 2586bd825f0STimur Tabi num_laws = be32_to_cpup(iprop); 2596bd825f0STimur Tabi 260896c01cbSTimur Tabi /* 261896c01cbSTimur Tabi * Indirect mode requires both BR0 and BR1 to be set to "GPCM", 262896c01cbSTimur Tabi * otherwise writes to these addresses won't actually appear on the 263896c01cbSTimur Tabi * local bus, and so the PIXIS won't see them. 264896c01cbSTimur Tabi * 265896c01cbSTimur Tabi * In FCM mode, writes go to the NAND controller, which does not pass 266896c01cbSTimur Tabi * them to the localbus directly. So we force BR0 and BR1 into GPCM 267896c01cbSTimur Tabi * mode, since we don't care about what's behind the localbus any 268896c01cbSTimur Tabi * more. 269896c01cbSTimur Tabi */ 270896c01cbSTimur Tabi br0 = in_be32(&lbc->bank[0].br); 271896c01cbSTimur Tabi br1 = in_be32(&lbc->bank[1].br); 272896c01cbSTimur Tabi or0 = in_be32(&lbc->bank[0].or); 273896c01cbSTimur Tabi or1 = in_be32(&lbc->bank[1].or); 274896c01cbSTimur Tabi 275896c01cbSTimur Tabi /* Make sure CS0 and CS1 are programmed */ 276896c01cbSTimur Tabi if (!(br0 & BR_V) || !(br1 & BR_V)) { 277896c01cbSTimur Tabi pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); 278896c01cbSTimur Tabi goto exit; 279896c01cbSTimur Tabi } 280896c01cbSTimur Tabi 281896c01cbSTimur Tabi /* 282896c01cbSTimur Tabi * Use the existing BRx/ORx values if it's already GPCM. Otherwise, 283896c01cbSTimur Tabi * force the values to simple 32KB GPCM windows with the most 284896c01cbSTimur Tabi * conservative timing. 285896c01cbSTimur Tabi */ 286896c01cbSTimur Tabi if ((br0 & BR_MSEL) != BR_MS_GPCM) { 287896c01cbSTimur Tabi br0 = (br0 & BR_BA) | BR_V; 288896c01cbSTimur Tabi or0 = 0xFFFF8000 | 0xFF7; 289896c01cbSTimur Tabi out_be32(&lbc->bank[0].br, br0); 290896c01cbSTimur Tabi out_be32(&lbc->bank[0].or, or0); 291896c01cbSTimur Tabi } 292896c01cbSTimur Tabi if ((br1 & BR_MSEL) != BR_MS_GPCM) { 293896c01cbSTimur Tabi br1 = (br1 & BR_BA) | BR_V; 294896c01cbSTimur Tabi or1 = 0xFFFF8000 | 0xFF7; 295896c01cbSTimur Tabi out_be32(&lbc->bank[1].br, br1); 296896c01cbSTimur Tabi out_be32(&lbc->bank[1].or, or1); 297896c01cbSTimur Tabi } 298896c01cbSTimur Tabi 299896c01cbSTimur Tabi cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); 300896c01cbSTimur Tabi if (!cs0_addr) { 301896c01cbSTimur Tabi pr_err("p1022ds: could not determine physical address for CS0" 302896c01cbSTimur Tabi " (BR0=%08x)\n", br0); 303896c01cbSTimur Tabi goto exit; 304896c01cbSTimur Tabi } 305896c01cbSTimur Tabi cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); 306896c01cbSTimur Tabi if (!cs0_addr) { 307896c01cbSTimur Tabi pr_err("p1022ds: could not determine physical address for CS1" 308896c01cbSTimur Tabi " (BR1=%08x)\n", br1); 309896c01cbSTimur Tabi goto exit; 310896c01cbSTimur Tabi } 3116bd825f0STimur Tabi 3126bd825f0STimur Tabi lbc_lcs0_ba = ioremap(cs0_addr, 1); 313896c01cbSTimur Tabi if (!lbc_lcs0_ba) { 314896c01cbSTimur Tabi pr_err("p1022ds: could not ioremap CS0 address %llx\n", 315896c01cbSTimur Tabi (unsigned long long)cs0_addr); 316896c01cbSTimur Tabi goto exit; 317896c01cbSTimur Tabi } 3186bd825f0STimur Tabi lbc_lcs1_ba = ioremap(cs1_addr, 1); 319896c01cbSTimur Tabi if (!lbc_lcs1_ba) { 320896c01cbSTimur Tabi pr_err("p1022ds: could not ioremap CS1 address %llx\n", 321896c01cbSTimur Tabi (unsigned long long)cs1_addr); 322896c01cbSTimur Tabi goto exit; 323896c01cbSTimur Tabi } 3246bd825f0STimur Tabi 3256597c713STimur Tabi /* Make sure we're in indirect mode first. */ 3266597c713STimur Tabi if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != 3276597c713STimur Tabi PMUXCR_ELBCDIU_DIU) { 3286597c713STimur Tabi struct device_node *pixis_node; 32931655958STimur Tabi void __iomem *pixis; 3302c184cd3STimur Tabi 3316597c713STimur Tabi pixis_node = 3326597c713STimur Tabi of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); 3336597c713STimur Tabi if (!pixis_node) { 3346597c713STimur Tabi pr_err("p1022ds: missing pixis node\n"); 3356597c713STimur Tabi goto exit; 3362c184cd3STimur Tabi } 3372c184cd3STimur Tabi 3386597c713STimur Tabi pixis = of_iomap(pixis_node, 0); 3396597c713STimur Tabi of_node_put(pixis_node); 34031655958STimur Tabi if (!pixis) { 3416597c713STimur Tabi pr_err("p1022ds: could not map pixis registers\n"); 3426597c713STimur Tabi goto exit; 3432c184cd3STimur Tabi } 3446597c713STimur Tabi 3456597c713STimur Tabi /* Enable indirect PIXIS mode. */ 3466597c713STimur Tabi setbits8(pixis + PX_CTL, PX_CTL_ALTACC); 3476597c713STimur Tabi iounmap(pixis); 3486597c713STimur Tabi 3496597c713STimur Tabi /* Switch the board mux to the DIU */ 3506597c713STimur Tabi out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */ 3516597c713STimur Tabi b = in_8(lbc_lcs1_ba); 3526597c713STimur Tabi b |= PX_BRDCFG0_ELBC_DIU; 3536597c713STimur Tabi out_8(lbc_lcs1_ba, b); 3546597c713STimur Tabi 3556597c713STimur Tabi /* Set the chip mux to DIU mode. */ 3566597c713STimur Tabi clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK, 3576597c713STimur Tabi PMUXCR_ELBCDIU_DIU); 3586597c713STimur Tabi in_be32(&guts->pmuxcr); 3596597c713STimur Tabi } 3606597c713STimur Tabi 3612c184cd3STimur Tabi 3627653aaabSTimur Tabi switch (port) { 3637653aaabSTimur Tabi case FSL_DIU_PORT_DVI: 3642c184cd3STimur Tabi /* Enable the DVI port, disable the DFP and the backlight */ 3656597c713STimur Tabi out_8(lbc_lcs0_ba, PX_BRDCFG1); 3666597c713STimur Tabi b = in_8(lbc_lcs1_ba); 3676597c713STimur Tabi b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); 3686597c713STimur Tabi b |= PX_BRDCFG1_DVIEN; 3696597c713STimur Tabi out_8(lbc_lcs1_ba, b); 3702c184cd3STimur Tabi break; 3717653aaabSTimur Tabi case FSL_DIU_PORT_LVDS: 3726597c713STimur Tabi /* 3736597c713STimur Tabi * LVDS also needs backlight enabled, otherwise the display 3746597c713STimur Tabi * will be blank. 3756597c713STimur Tabi */ 3762c184cd3STimur Tabi /* Enable the DFP port, disable the DVI and the backlight */ 3776597c713STimur Tabi out_8(lbc_lcs0_ba, PX_BRDCFG1); 3786597c713STimur Tabi b = in_8(lbc_lcs1_ba); 3796597c713STimur Tabi b &= ~PX_BRDCFG1_DVIEN; 3806597c713STimur Tabi b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT; 3816597c713STimur Tabi out_8(lbc_lcs1_ba, b); 3822c184cd3STimur Tabi break; 3832c184cd3STimur Tabi default: 3847653aaabSTimur Tabi pr_err("p1022ds: unsupported monitor port %i\n", port); 3852c184cd3STimur Tabi } 38631655958STimur Tabi 3876597c713STimur Tabi exit: 3886597c713STimur Tabi if (lbc_lcs1_ba) 3896597c713STimur Tabi iounmap(lbc_lcs1_ba); 3906597c713STimur Tabi if (lbc_lcs0_ba) 3916597c713STimur Tabi iounmap(lbc_lcs0_ba); 3926bd825f0STimur Tabi if (lbc) 3936bd825f0STimur Tabi iounmap(lbc); 3946bd825f0STimur Tabi if (ecm) 3956bd825f0STimur Tabi iounmap(ecm); 3966597c713STimur Tabi if (guts) 3976597c713STimur Tabi iounmap(guts); 3986597c713STimur Tabi 3996bd825f0STimur Tabi of_node_put(law_node); 4006bd825f0STimur Tabi of_node_put(lbc_node); 4016597c713STimur Tabi of_node_put(guts_node); 4022c184cd3STimur Tabi } 4032c184cd3STimur Tabi 4042c184cd3STimur Tabi /** 4052c184cd3STimur Tabi * p1022ds_set_pixel_clock: program the DIU's clock 4062c184cd3STimur Tabi * 4072c184cd3STimur Tabi * @pixclock: the wavelength, in picoseconds, of the clock 4082c184cd3STimur Tabi */ 4092c184cd3STimur Tabi void p1022ds_set_pixel_clock(unsigned int pixclock) 4102c184cd3STimur Tabi { 4112c184cd3STimur Tabi struct device_node *guts_np = NULL; 4129cb6abcbSTimur Tabi struct ccsr_guts __iomem *guts; 4132c184cd3STimur Tabi unsigned long freq; 4142c184cd3STimur Tabi u64 temp; 4152c184cd3STimur Tabi u32 pxclk; 4162c184cd3STimur Tabi 4172c184cd3STimur Tabi /* Map the global utilities registers. */ 4182c184cd3STimur Tabi guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); 4192c184cd3STimur Tabi if (!guts_np) { 4202c184cd3STimur Tabi pr_err("p1022ds: missing global utilties device node\n"); 4212c184cd3STimur Tabi return; 4222c184cd3STimur Tabi } 4232c184cd3STimur Tabi 4242c184cd3STimur Tabi guts = of_iomap(guts_np, 0); 4252c184cd3STimur Tabi of_node_put(guts_np); 4262c184cd3STimur Tabi if (!guts) { 4272c184cd3STimur Tabi pr_err("p1022ds: could not map global utilties device\n"); 4282c184cd3STimur Tabi return; 4292c184cd3STimur Tabi } 4302c184cd3STimur Tabi 4312c184cd3STimur Tabi /* Convert pixclock from a wavelength to a frequency */ 4322c184cd3STimur Tabi temp = 1000000000000ULL; 4332c184cd3STimur Tabi do_div(temp, pixclock); 4342c184cd3STimur Tabi freq = temp; 4352c184cd3STimur Tabi 4367b93eccfSTimur Tabi /* 4377b93eccfSTimur Tabi * 'pxclk' is the ratio of the platform clock to the pixel clock. 4387b93eccfSTimur Tabi * This number is programmed into the CLKDVDR register, and the valid 4397b93eccfSTimur Tabi * range of values is 2-255. 4407b93eccfSTimur Tabi */ 4412c184cd3STimur Tabi pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq); 4427b93eccfSTimur Tabi pxclk = clamp_t(u32, pxclk, 2, 255); 4432c184cd3STimur Tabi 4442c184cd3STimur Tabi /* Disable the pixel clock, and set it to non-inverted and no delay */ 4452c184cd3STimur Tabi clrbits32(&guts->clkdvdr, 4462c184cd3STimur Tabi CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK); 4472c184cd3STimur Tabi 4482c184cd3STimur Tabi /* Enable the clock and set the pxclk */ 4492c184cd3STimur Tabi setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16)); 45031655958STimur Tabi 45131655958STimur Tabi iounmap(guts); 4522c184cd3STimur Tabi } 4532c184cd3STimur Tabi 4542c184cd3STimur Tabi /** 4557653aaabSTimur Tabi * p1022ds_valid_monitor_port: set the monitor port for sysfs 4562c184cd3STimur Tabi */ 4577653aaabSTimur Tabi enum fsl_diu_monitor_port 4587653aaabSTimur Tabi p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port) 4592c184cd3STimur Tabi { 4607653aaabSTimur Tabi switch (port) { 4617653aaabSTimur Tabi case FSL_DIU_PORT_DVI: 4627653aaabSTimur Tabi case FSL_DIU_PORT_LVDS: 4637653aaabSTimur Tabi return port; 4647653aaabSTimur Tabi default: 4657653aaabSTimur Tabi return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */ 4662c184cd3STimur Tabi } 4672c184cd3STimur Tabi } 4682c184cd3STimur Tabi 4692c184cd3STimur Tabi #endif 47030be4c96STimur Tabi 47130be4c96STimur Tabi void __init p1022_ds_pic_init(void) 47230be4c96STimur Tabi { 473e55d7f73SKyle Moffett struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN | 47430be4c96STimur Tabi MPIC_SINGLE_DEST_CPU, 47530be4c96STimur Tabi 0, 256, " OpenPIC "); 47630be4c96STimur Tabi BUG_ON(mpic == NULL); 47730be4c96STimur Tabi mpic_init(mpic); 47830be4c96STimur Tabi } 47930be4c96STimur Tabi 4804951896aSTimur Tabi #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 4814951896aSTimur Tabi 4824951896aSTimur Tabi /* TRUE if there is a "video=fslfb" command-line parameter. */ 4834951896aSTimur Tabi static bool fslfb; 4844951896aSTimur Tabi 4854951896aSTimur Tabi /* 4864951896aSTimur Tabi * Search for a "video=fslfb" command-line parameter, and set 'fslfb' to 4874951896aSTimur Tabi * true if we find it. 4884951896aSTimur Tabi * 4894951896aSTimur Tabi * We need to use early_param() instead of __setup() because the normal 4904951896aSTimur Tabi * __setup() gets called to late. However, early_param() gets called very 4914951896aSTimur Tabi * early, before the device tree is unflattened, so all we can do now is set a 4924951896aSTimur Tabi * global variable. Later on, p1022_ds_setup_arch() will use that variable 4934951896aSTimur Tabi * to determine if we need to update the device tree. 4944951896aSTimur Tabi */ 4954951896aSTimur Tabi static int __init early_video_setup(char *options) 4964951896aSTimur Tabi { 4974951896aSTimur Tabi fslfb = (strncmp(options, "fslfb:", 6) == 0); 4984951896aSTimur Tabi 4994951896aSTimur Tabi return 0; 5004951896aSTimur Tabi } 5014951896aSTimur Tabi early_param("video", early_video_setup); 5024951896aSTimur Tabi 5034951896aSTimur Tabi #endif 5044951896aSTimur Tabi 50530be4c96STimur Tabi /* 50630be4c96STimur Tabi * Setup the architecture 50730be4c96STimur Tabi */ 50830be4c96STimur Tabi static void __init p1022_ds_setup_arch(void) 50930be4c96STimur Tabi { 51030be4c96STimur Tabi #ifdef CONFIG_PCI 51130be4c96STimur Tabi struct device_node *np; 51230be4c96STimur Tabi #endif 51330be4c96STimur Tabi dma_addr_t max = 0xffffffff; 51430be4c96STimur Tabi 51530be4c96STimur Tabi if (ppc_md.progress) 51630be4c96STimur Tabi ppc_md.progress("p1022_ds_setup_arch()", 0); 51730be4c96STimur Tabi 51830be4c96STimur Tabi #ifdef CONFIG_PCI 51930be4c96STimur Tabi for_each_compatible_node(np, "pci", "fsl,p1022-pcie") { 52030be4c96STimur Tabi struct resource rsrc; 52130be4c96STimur Tabi struct pci_controller *hose; 52230be4c96STimur Tabi 52330be4c96STimur Tabi of_address_to_resource(np, 0, &rsrc); 52430be4c96STimur Tabi 52530be4c96STimur Tabi if ((rsrc.start & 0xfffff) == 0x8000) 52630be4c96STimur Tabi fsl_add_bridge(np, 1); 52730be4c96STimur Tabi else 52830be4c96STimur Tabi fsl_add_bridge(np, 0); 52930be4c96STimur Tabi 53030be4c96STimur Tabi hose = pci_find_hose_for_OF_device(np); 53130be4c96STimur Tabi max = min(max, hose->dma_window_base_cur + 53230be4c96STimur Tabi hose->dma_window_size); 53330be4c96STimur Tabi } 53430be4c96STimur Tabi #endif 53530be4c96STimur Tabi 5362c184cd3STimur Tabi #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 5372c184cd3STimur Tabi diu_ops.get_pixel_format = p1022ds_get_pixel_format; 5382c184cd3STimur Tabi diu_ops.set_gamma_table = p1022ds_set_gamma_table; 5392c184cd3STimur Tabi diu_ops.set_monitor_port = p1022ds_set_monitor_port; 5402c184cd3STimur Tabi diu_ops.set_pixel_clock = p1022ds_set_pixel_clock; 5417653aaabSTimur Tabi diu_ops.valid_monitor_port = p1022ds_valid_monitor_port; 5424951896aSTimur Tabi 5434951896aSTimur Tabi /* 5446269f258STimur Tabi * Disable the NOR and NAND flash nodes if there is video=fslfb... 5456269f258STimur Tabi * command-line parameter. When the DIU is active, the localbus is 5466269f258STimur Tabi * unavailable, so we have to disable these nodes before the MTD 5476269f258STimur Tabi * driver loads. 5484951896aSTimur Tabi */ 5494951896aSTimur Tabi if (fslfb) { 5504951896aSTimur Tabi struct device_node *np = 5514951896aSTimur Tabi of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); 5524951896aSTimur Tabi 5534951896aSTimur Tabi if (np) { 5546269f258STimur Tabi struct device_node *np2; 5556269f258STimur Tabi 5566269f258STimur Tabi of_node_get(np); 5576269f258STimur Tabi np2 = of_find_compatible_node(np, NULL, "cfi-flash"); 5586269f258STimur Tabi if (np2) { 5594951896aSTimur Tabi static struct property nor_status = { 5604951896aSTimur Tabi .name = "status", 5614951896aSTimur Tabi .value = "disabled", 5624951896aSTimur Tabi .length = sizeof("disabled"), 5634951896aSTimur Tabi }; 5644951896aSTimur Tabi 5656269f258STimur Tabi /* 5666269f258STimur Tabi * prom_update_property() is called before 5676269f258STimur Tabi * kmalloc() is available, so the 'new' object 5686269f258STimur Tabi * should be allocated in the global area. 5696269f258STimur Tabi * The easiest way is to do that is to 5706269f258STimur Tabi * allocate one static local variable for each 5716269f258STimur Tabi * call to this function. 5726269f258STimur Tabi */ 5734951896aSTimur Tabi pr_info("p1022ds: disabling %s node", 5746269f258STimur Tabi np2->full_name); 5756269f258STimur Tabi prom_update_property(np2, &nor_status); 5766269f258STimur Tabi of_node_put(np2); 5774951896aSTimur Tabi } 5786269f258STimur Tabi 5796269f258STimur Tabi of_node_get(np); 5806269f258STimur Tabi np2 = of_find_compatible_node(np, NULL, 5816269f258STimur Tabi "fsl,elbc-fcm-nand"); 5826269f258STimur Tabi if (np2) { 5836269f258STimur Tabi static struct property nand_status = { 5846269f258STimur Tabi .name = "status", 5856269f258STimur Tabi .value = "disabled", 5866269f258STimur Tabi .length = sizeof("disabled"), 5876269f258STimur Tabi }; 5886269f258STimur Tabi 5896269f258STimur Tabi pr_info("p1022ds: disabling %s node", 5906269f258STimur Tabi np2->full_name); 5916269f258STimur Tabi prom_update_property(np2, &nand_status); 5926269f258STimur Tabi of_node_put(np2); 5936269f258STimur Tabi } 5946269f258STimur Tabi 5956269f258STimur Tabi of_node_put(np); 5964951896aSTimur Tabi } 5974951896aSTimur Tabi 5984951896aSTimur Tabi } 5994951896aSTimur Tabi 6002c184cd3STimur Tabi #endif 6012c184cd3STimur Tabi 60230be4c96STimur Tabi mpc85xx_smp_init(); 60330be4c96STimur Tabi 60430be4c96STimur Tabi #ifdef CONFIG_SWIOTLB 605a5cb82daSBharat Bhushan if ((memblock_end_of_DRAM() - 1) > max) { 60630be4c96STimur Tabi ppc_swiotlb_enable = 1; 60730be4c96STimur Tabi set_pci_dma_ops(&swiotlb_dma_ops); 60830be4c96STimur Tabi ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; 60930be4c96STimur Tabi } 61030be4c96STimur Tabi #endif 61130be4c96STimur Tabi 61230be4c96STimur Tabi pr_info("Freescale P1022 DS reference board\n"); 61330be4c96STimur Tabi } 61430be4c96STimur Tabi 6158a95bc8dSTimur Tabi machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices); 61630be4c96STimur Tabi 61730be4c96STimur Tabi machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier); 61830be4c96STimur Tabi 61930be4c96STimur Tabi /* 62030be4c96STimur Tabi * Called very early, device-tree isn't unflattened 62130be4c96STimur Tabi */ 62230be4c96STimur Tabi static int __init p1022_ds_probe(void) 62330be4c96STimur Tabi { 62430be4c96STimur Tabi unsigned long root = of_get_flat_dt_root(); 62530be4c96STimur Tabi 62630be4c96STimur Tabi return of_flat_dt_is_compatible(root, "fsl,p1022ds"); 62730be4c96STimur Tabi } 62830be4c96STimur Tabi 62930be4c96STimur Tabi define_machine(p1022_ds) { 63030be4c96STimur Tabi .name = "P1022 DS", 63130be4c96STimur Tabi .probe = p1022_ds_probe, 63230be4c96STimur Tabi .setup_arch = p1022_ds_setup_arch, 63330be4c96STimur Tabi .init_IRQ = p1022_ds_pic_init, 63430be4c96STimur Tabi #ifdef CONFIG_PCI 63530be4c96STimur Tabi .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 63630be4c96STimur Tabi #endif 63730be4c96STimur Tabi .get_irq = mpic_get_irq, 63830be4c96STimur Tabi .restart = fsl_rstcr_restart, 63930be4c96STimur Tabi .calibrate_decr = generic_calibrate_decr, 64030be4c96STimur Tabi .progress = udbg_progress, 64130be4c96STimur Tabi }; 642