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 1994848654SScott Wood #include <linux/fsl/guts.h> 2030be4c96STimur Tabi #include <linux/pci.h> 2130be4c96STimur Tabi #include <linux/of_platform.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> 296bd825f0STimur Tabi #include <asm/fsl_lbc.h> 30582d3e09SKyle Moffett #include "smp.h" 312c184cd3STimur Tabi 32543a07b1SDmitry Eremin-Solenikov #include "mpc85xx.h" 33543a07b1SDmitry Eremin-Solenikov 342c184cd3STimur Tabi #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 352c184cd3STimur Tabi 366597c713STimur Tabi #define PMUXCR_ELBCDIU_MASK 0xc0000000 376597c713STimur Tabi #define PMUXCR_ELBCDIU_NOR16 0x80000000 386597c713STimur Tabi #define PMUXCR_ELBCDIU_DIU 0x40000000 396597c713STimur Tabi 402c184cd3STimur Tabi /* 412c184cd3STimur Tabi * Board-specific initialization of the DIU. This code should probably be 422c184cd3STimur Tabi * executed when the DIU is opened, rather than in arch code, but the DIU 432c184cd3STimur Tabi * driver does not have a mechanism for this (yet). 442c184cd3STimur Tabi * 452c184cd3STimur Tabi * This is especially problematic on the P1022DS because the local bus (eLBC) 462c184cd3STimur Tabi * and the DIU video signals share the same pins, which means that enabling the 472c184cd3STimur Tabi * DIU will disable access to NOR flash. 482c184cd3STimur Tabi */ 492c184cd3STimur Tabi 502c184cd3STimur Tabi /* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */ 512c184cd3STimur Tabi #define CLKDVDR_PXCKEN 0x80000000 522c184cd3STimur Tabi #define CLKDVDR_PXCKINV 0x10000000 532c184cd3STimur Tabi #define CLKDVDR_PXCKDLY 0x06000000 542c184cd3STimur Tabi #define CLKDVDR_PXCLK_MASK 0x00FF0000 552c184cd3STimur Tabi 562c184cd3STimur Tabi /* Some ngPIXIS register definitions */ 576597c713STimur Tabi #define PX_CTL 3 586597c713STimur Tabi #define PX_BRDCFG0 8 596597c713STimur Tabi #define PX_BRDCFG1 9 606597c713STimur Tabi 616597c713STimur Tabi #define PX_BRDCFG0_ELBC_SPI_MASK 0xc0 626597c713STimur Tabi #define PX_BRDCFG0_ELBC_SPI_ELBC 0x00 636597c713STimur Tabi #define PX_BRDCFG0_ELBC_SPI_NULL 0xc0 646597c713STimur Tabi #define PX_BRDCFG0_ELBC_DIU 0x02 656597c713STimur Tabi 662c184cd3STimur Tabi #define PX_BRDCFG1_DVIEN 0x80 672c184cd3STimur Tabi #define PX_BRDCFG1_DFPEN 0x40 682c184cd3STimur Tabi #define PX_BRDCFG1_BACKLIGHT 0x20 692c184cd3STimur Tabi #define PX_BRDCFG1_DDCEN 0x10 702c184cd3STimur Tabi 716597c713STimur Tabi #define PX_CTL_ALTACC 0x80 726597c713STimur Tabi 732c184cd3STimur Tabi /* 742c184cd3STimur Tabi * DIU Area Descriptor 752c184cd3STimur Tabi * 762c184cd3STimur Tabi * Note that we need to byte-swap the value before it's written to the AD 772c184cd3STimur Tabi * register. So even though the registers don't look like they're in the same 782c184cd3STimur Tabi * bit positions as they are on the MPC8610, the same value is written to the 792c184cd3STimur Tabi * AD register on the MPC8610 and on the P1022. 802c184cd3STimur Tabi */ 812c184cd3STimur Tabi #define AD_BYTE_F 0x10000000 822c184cd3STimur Tabi #define AD_ALPHA_C_MASK 0x0E000000 832c184cd3STimur Tabi #define AD_ALPHA_C_SHIFT 25 842c184cd3STimur Tabi #define AD_BLUE_C_MASK 0x01800000 852c184cd3STimur Tabi #define AD_BLUE_C_SHIFT 23 862c184cd3STimur Tabi #define AD_GREEN_C_MASK 0x00600000 872c184cd3STimur Tabi #define AD_GREEN_C_SHIFT 21 882c184cd3STimur Tabi #define AD_RED_C_MASK 0x00180000 892c184cd3STimur Tabi #define AD_RED_C_SHIFT 19 902c184cd3STimur Tabi #define AD_PALETTE 0x00040000 912c184cd3STimur Tabi #define AD_PIXEL_S_MASK 0x00030000 922c184cd3STimur Tabi #define AD_PIXEL_S_SHIFT 16 932c184cd3STimur Tabi #define AD_COMP_3_MASK 0x0000F000 942c184cd3STimur Tabi #define AD_COMP_3_SHIFT 12 952c184cd3STimur Tabi #define AD_COMP_2_MASK 0x00000F00 962c184cd3STimur Tabi #define AD_COMP_2_SHIFT 8 972c184cd3STimur Tabi #define AD_COMP_1_MASK 0x000000F0 982c184cd3STimur Tabi #define AD_COMP_1_SHIFT 4 992c184cd3STimur Tabi #define AD_COMP_0_MASK 0x0000000F 1002c184cd3STimur Tabi #define AD_COMP_0_SHIFT 0 1012c184cd3STimur Tabi 1022c184cd3STimur Tabi #define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \ 1032c184cd3STimur Tabi cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \ 1042c184cd3STimur Tabi (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \ 1052c184cd3STimur Tabi (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \ 1062c184cd3STimur Tabi (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \ 1072c184cd3STimur Tabi (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT)) 1082c184cd3STimur Tabi 1096bd825f0STimur Tabi struct fsl_law { 1106bd825f0STimur Tabi u32 lawbar; 1116bd825f0STimur Tabi u32 reserved1; 1126bd825f0STimur Tabi u32 lawar; 1136bd825f0STimur Tabi u32 reserved[5]; 1146bd825f0STimur Tabi }; 1156bd825f0STimur Tabi 1166bd825f0STimur Tabi #define LAWBAR_MASK 0x00F00000 1176bd825f0STimur Tabi #define LAWBAR_SHIFT 12 1186bd825f0STimur Tabi 1196bd825f0STimur Tabi #define LAWAR_EN 0x80000000 1206bd825f0STimur Tabi #define LAWAR_TGT_MASK 0x01F00000 1216bd825f0STimur Tabi #define LAW_TRGT_IF_LBC (0x04 << 20) 1226bd825f0STimur Tabi 1236bd825f0STimur Tabi #define LAWAR_MASK (LAWAR_EN | LAWAR_TGT_MASK) 1246bd825f0STimur Tabi #define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC) 1256bd825f0STimur Tabi 1266bd825f0STimur Tabi #define BR_BA 0xFFFF8000 1276bd825f0STimur Tabi 1286bd825f0STimur Tabi /* 1296bd825f0STimur Tabi * Map a BRx value to a physical address 1306bd825f0STimur Tabi * 1316bd825f0STimur Tabi * The localbus BRx registers only store the lower 32 bits of the address. To 1326bd825f0STimur Tabi * obtain the upper four bits, we need to scan the LAW table. The entry which 1336bd825f0STimur Tabi * maps to the localbus will contain the upper four bits. 1346bd825f0STimur Tabi */ 1356bd825f0STimur Tabi static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br) 1366bd825f0STimur Tabi { 1376bd825f0STimur Tabi #ifndef CONFIG_PHYS_64BIT 1386bd825f0STimur Tabi /* 1396bd825f0STimur Tabi * If we only have 32-bit addressing, then the BRx address *is* the 1406bd825f0STimur Tabi * physical address. 1416bd825f0STimur Tabi */ 1426bd825f0STimur Tabi return br & BR_BA; 1436bd825f0STimur Tabi #else 1446bd825f0STimur Tabi const struct fsl_law *law = ecm + 0xc08; 1456bd825f0STimur Tabi unsigned int i; 1466bd825f0STimur Tabi 1476bd825f0STimur Tabi for (i = 0; i < count; i++) { 1486bd825f0STimur Tabi u64 lawbar = in_be32(&law[i].lawbar); 1496bd825f0STimur Tabi u32 lawar = in_be32(&law[i].lawar); 1506bd825f0STimur Tabi 1516bd825f0STimur Tabi if ((lawar & LAWAR_MASK) == LAWAR_MATCH) 1526bd825f0STimur Tabi /* Extract the upper four bits */ 1536bd825f0STimur Tabi return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12); 1546bd825f0STimur Tabi } 1556bd825f0STimur Tabi 1566bd825f0STimur Tabi return 0; 1576bd825f0STimur Tabi #endif 1586bd825f0STimur Tabi } 1596bd825f0STimur Tabi 1602c184cd3STimur Tabi /** 1612c184cd3STimur Tabi * p1022ds_set_monitor_port: switch the output to a different monitor port 1622c184cd3STimur Tabi */ 1637653aaabSTimur Tabi static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) 1642c184cd3STimur Tabi { 1656597c713STimur Tabi struct device_node *guts_node; 1666bd825f0STimur Tabi struct device_node *lbc_node = NULL; 1676bd825f0STimur Tabi struct device_node *law_node = NULL; 1689cb6abcbSTimur Tabi struct ccsr_guts __iomem *guts; 1696bd825f0STimur Tabi struct fsl_lbc_regs *lbc = NULL; 1706bd825f0STimur Tabi void *ecm = NULL; 1716597c713STimur Tabi u8 __iomem *lbc_lcs0_ba = NULL; 1726597c713STimur Tabi u8 __iomem *lbc_lcs1_ba = NULL; 1736bd825f0STimur Tabi phys_addr_t cs0_addr, cs1_addr; 174896c01cbSTimur Tabi u32 br0, or0, br1, or1; 1756bd825f0STimur Tabi const __be32 *iprop; 1766bd825f0STimur Tabi unsigned int num_laws; 1776597c713STimur Tabi u8 b; 1786597c713STimur Tabi 1796597c713STimur Tabi /* Map the global utilities registers. */ 1806597c713STimur Tabi guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); 1816597c713STimur Tabi if (!guts_node) { 182b6741bc7STim Blechmann pr_err("p1022ds: missing global utilities device node\n"); 1836597c713STimur Tabi return; 1846597c713STimur Tabi } 1856597c713STimur Tabi 1866597c713STimur Tabi guts = of_iomap(guts_node, 0); 1876597c713STimur Tabi if (!guts) { 188b6741bc7STim Blechmann pr_err("p1022ds: could not map global utilities device\n"); 1896597c713STimur Tabi goto exit; 1906597c713STimur Tabi } 1916597c713STimur Tabi 1926bd825f0STimur Tabi lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); 1936bd825f0STimur Tabi if (!lbc_node) { 1946bd825f0STimur Tabi pr_err("p1022ds: missing localbus node\n"); 1956597c713STimur Tabi goto exit; 1966597c713STimur Tabi } 1976597c713STimur Tabi 1986bd825f0STimur Tabi lbc = of_iomap(lbc_node, 0); 1996bd825f0STimur Tabi if (!lbc) { 2006bd825f0STimur Tabi pr_err("p1022ds: could not map localbus node\n"); 2016597c713STimur Tabi goto exit; 2026597c713STimur Tabi } 2036597c713STimur Tabi 2046bd825f0STimur Tabi law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law"); 2056bd825f0STimur Tabi if (!law_node) { 2066bd825f0STimur Tabi pr_err("p1022ds: missing local access window node\n"); 2076597c713STimur Tabi goto exit; 2086597c713STimur Tabi } 2096597c713STimur Tabi 2106bd825f0STimur Tabi ecm = of_iomap(law_node, 0); 2116bd825f0STimur Tabi if (!ecm) { 2126bd825f0STimur Tabi pr_err("p1022ds: could not map local access window node\n"); 2136bd825f0STimur Tabi goto exit; 2146bd825f0STimur Tabi } 2156bd825f0STimur Tabi 216e9c36b0bSTushar Behera iprop = of_get_property(law_node, "fsl,num-laws", NULL); 2176bd825f0STimur Tabi if (!iprop) { 2186bd825f0STimur Tabi pr_err("p1022ds: LAW node is missing fsl,num-laws property\n"); 2196bd825f0STimur Tabi goto exit; 2206bd825f0STimur Tabi } 2216bd825f0STimur Tabi num_laws = be32_to_cpup(iprop); 2226bd825f0STimur Tabi 223896c01cbSTimur Tabi /* 224896c01cbSTimur Tabi * Indirect mode requires both BR0 and BR1 to be set to "GPCM", 225896c01cbSTimur Tabi * otherwise writes to these addresses won't actually appear on the 226896c01cbSTimur Tabi * local bus, and so the PIXIS won't see them. 227896c01cbSTimur Tabi * 228896c01cbSTimur Tabi * In FCM mode, writes go to the NAND controller, which does not pass 229896c01cbSTimur Tabi * them to the localbus directly. So we force BR0 and BR1 into GPCM 230896c01cbSTimur Tabi * mode, since we don't care about what's behind the localbus any 231896c01cbSTimur Tabi * more. 232896c01cbSTimur Tabi */ 233896c01cbSTimur Tabi br0 = in_be32(&lbc->bank[0].br); 234896c01cbSTimur Tabi br1 = in_be32(&lbc->bank[1].br); 235896c01cbSTimur Tabi or0 = in_be32(&lbc->bank[0].or); 236896c01cbSTimur Tabi or1 = in_be32(&lbc->bank[1].or); 237896c01cbSTimur Tabi 238896c01cbSTimur Tabi /* Make sure CS0 and CS1 are programmed */ 239896c01cbSTimur Tabi if (!(br0 & BR_V) || !(br1 & BR_V)) { 240896c01cbSTimur Tabi pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); 241896c01cbSTimur Tabi goto exit; 242896c01cbSTimur Tabi } 243896c01cbSTimur Tabi 244896c01cbSTimur Tabi /* 245896c01cbSTimur Tabi * Use the existing BRx/ORx values if it's already GPCM. Otherwise, 246896c01cbSTimur Tabi * force the values to simple 32KB GPCM windows with the most 247896c01cbSTimur Tabi * conservative timing. 248896c01cbSTimur Tabi */ 249896c01cbSTimur Tabi if ((br0 & BR_MSEL) != BR_MS_GPCM) { 250896c01cbSTimur Tabi br0 = (br0 & BR_BA) | BR_V; 251896c01cbSTimur Tabi or0 = 0xFFFF8000 | 0xFF7; 252896c01cbSTimur Tabi out_be32(&lbc->bank[0].br, br0); 253896c01cbSTimur Tabi out_be32(&lbc->bank[0].or, or0); 254896c01cbSTimur Tabi } 255896c01cbSTimur Tabi if ((br1 & BR_MSEL) != BR_MS_GPCM) { 256896c01cbSTimur Tabi br1 = (br1 & BR_BA) | BR_V; 257896c01cbSTimur Tabi or1 = 0xFFFF8000 | 0xFF7; 258896c01cbSTimur Tabi out_be32(&lbc->bank[1].br, br1); 259896c01cbSTimur Tabi out_be32(&lbc->bank[1].or, or1); 260896c01cbSTimur Tabi } 261896c01cbSTimur Tabi 262896c01cbSTimur Tabi cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); 263896c01cbSTimur Tabi if (!cs0_addr) { 264896c01cbSTimur Tabi pr_err("p1022ds: could not determine physical address for CS0" 265896c01cbSTimur Tabi " (BR0=%08x)\n", br0); 266896c01cbSTimur Tabi goto exit; 267896c01cbSTimur Tabi } 268896c01cbSTimur Tabi cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); 2694700ebd1SJulia Lawall if (!cs1_addr) { 270896c01cbSTimur Tabi pr_err("p1022ds: could not determine physical address for CS1" 271896c01cbSTimur Tabi " (BR1=%08x)\n", br1); 272896c01cbSTimur Tabi goto exit; 273896c01cbSTimur Tabi } 2746bd825f0STimur Tabi 2756bd825f0STimur Tabi lbc_lcs0_ba = ioremap(cs0_addr, 1); 276896c01cbSTimur Tabi if (!lbc_lcs0_ba) { 277896c01cbSTimur Tabi pr_err("p1022ds: could not ioremap CS0 address %llx\n", 278896c01cbSTimur Tabi (unsigned long long)cs0_addr); 279896c01cbSTimur Tabi goto exit; 280896c01cbSTimur Tabi } 2816bd825f0STimur Tabi lbc_lcs1_ba = ioremap(cs1_addr, 1); 282896c01cbSTimur Tabi if (!lbc_lcs1_ba) { 283896c01cbSTimur Tabi pr_err("p1022ds: could not ioremap CS1 address %llx\n", 284896c01cbSTimur Tabi (unsigned long long)cs1_addr); 285896c01cbSTimur Tabi goto exit; 286896c01cbSTimur Tabi } 2876bd825f0STimur Tabi 2886597c713STimur Tabi /* Make sure we're in indirect mode first. */ 2896597c713STimur Tabi if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != 2906597c713STimur Tabi PMUXCR_ELBCDIU_DIU) { 2916597c713STimur Tabi struct device_node *pixis_node; 29231655958STimur Tabi void __iomem *pixis; 2932c184cd3STimur Tabi 2946597c713STimur Tabi pixis_node = 2956597c713STimur Tabi of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga"); 2966597c713STimur Tabi if (!pixis_node) { 2976597c713STimur Tabi pr_err("p1022ds: missing pixis node\n"); 2986597c713STimur Tabi goto exit; 2992c184cd3STimur Tabi } 3002c184cd3STimur Tabi 3016597c713STimur Tabi pixis = of_iomap(pixis_node, 0); 3026597c713STimur Tabi of_node_put(pixis_node); 30331655958STimur Tabi if (!pixis) { 3046597c713STimur Tabi pr_err("p1022ds: could not map pixis registers\n"); 3056597c713STimur Tabi goto exit; 3062c184cd3STimur Tabi } 3076597c713STimur Tabi 3086597c713STimur Tabi /* Enable indirect PIXIS mode. */ 3096597c713STimur Tabi setbits8(pixis + PX_CTL, PX_CTL_ALTACC); 3106597c713STimur Tabi iounmap(pixis); 3116597c713STimur Tabi 3126597c713STimur Tabi /* Switch the board mux to the DIU */ 3136597c713STimur Tabi out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */ 3146597c713STimur Tabi b = in_8(lbc_lcs1_ba); 3156597c713STimur Tabi b |= PX_BRDCFG0_ELBC_DIU; 3166597c713STimur Tabi out_8(lbc_lcs1_ba, b); 3176597c713STimur Tabi 3186597c713STimur Tabi /* Set the chip mux to DIU mode. */ 3196597c713STimur Tabi clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK, 3206597c713STimur Tabi PMUXCR_ELBCDIU_DIU); 3216597c713STimur Tabi in_be32(&guts->pmuxcr); 3226597c713STimur Tabi } 3236597c713STimur Tabi 3242c184cd3STimur Tabi 3257653aaabSTimur Tabi switch (port) { 3267653aaabSTimur Tabi case FSL_DIU_PORT_DVI: 3272c184cd3STimur Tabi /* Enable the DVI port, disable the DFP and the backlight */ 3286597c713STimur Tabi out_8(lbc_lcs0_ba, PX_BRDCFG1); 3296597c713STimur Tabi b = in_8(lbc_lcs1_ba); 3306597c713STimur Tabi b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT); 3316597c713STimur Tabi b |= PX_BRDCFG1_DVIEN; 3326597c713STimur Tabi out_8(lbc_lcs1_ba, b); 3332c184cd3STimur Tabi break; 3347653aaabSTimur Tabi case FSL_DIU_PORT_LVDS: 3356597c713STimur Tabi /* 3366597c713STimur Tabi * LVDS also needs backlight enabled, otherwise the display 3376597c713STimur Tabi * will be blank. 3386597c713STimur Tabi */ 3392c184cd3STimur Tabi /* Enable the DFP port, disable the DVI and the backlight */ 3406597c713STimur Tabi out_8(lbc_lcs0_ba, PX_BRDCFG1); 3416597c713STimur Tabi b = in_8(lbc_lcs1_ba); 3426597c713STimur Tabi b &= ~PX_BRDCFG1_DVIEN; 3436597c713STimur Tabi b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT; 3446597c713STimur Tabi out_8(lbc_lcs1_ba, b); 3452c184cd3STimur Tabi break; 3462c184cd3STimur Tabi default: 3477653aaabSTimur Tabi pr_err("p1022ds: unsupported monitor port %i\n", port); 3482c184cd3STimur Tabi } 34931655958STimur Tabi 3506597c713STimur Tabi exit: 3516597c713STimur Tabi if (lbc_lcs1_ba) 3526597c713STimur Tabi iounmap(lbc_lcs1_ba); 3536597c713STimur Tabi if (lbc_lcs0_ba) 3546597c713STimur Tabi iounmap(lbc_lcs0_ba); 3556bd825f0STimur Tabi if (lbc) 3566bd825f0STimur Tabi iounmap(lbc); 3576bd825f0STimur Tabi if (ecm) 3586bd825f0STimur Tabi iounmap(ecm); 3596597c713STimur Tabi if (guts) 3606597c713STimur Tabi iounmap(guts); 3616597c713STimur Tabi 3626bd825f0STimur Tabi of_node_put(law_node); 3636bd825f0STimur Tabi of_node_put(lbc_node); 3646597c713STimur Tabi of_node_put(guts_node); 3652c184cd3STimur Tabi } 3662c184cd3STimur Tabi 3672c184cd3STimur Tabi /** 3682c184cd3STimur Tabi * p1022ds_set_pixel_clock: program the DIU's clock 3692c184cd3STimur Tabi * 3702c184cd3STimur Tabi * @pixclock: the wavelength, in picoseconds, of the clock 3712c184cd3STimur Tabi */ 3722c184cd3STimur Tabi void p1022ds_set_pixel_clock(unsigned int pixclock) 3732c184cd3STimur Tabi { 3742c184cd3STimur Tabi struct device_node *guts_np = NULL; 3759cb6abcbSTimur Tabi struct ccsr_guts __iomem *guts; 3762c184cd3STimur Tabi unsigned long freq; 3772c184cd3STimur Tabi u64 temp; 3782c184cd3STimur Tabi u32 pxclk; 3792c184cd3STimur Tabi 3802c184cd3STimur Tabi /* Map the global utilities registers. */ 3812c184cd3STimur Tabi guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts"); 3822c184cd3STimur Tabi if (!guts_np) { 383b6741bc7STim Blechmann pr_err("p1022ds: missing global utilities device node\n"); 3842c184cd3STimur Tabi return; 3852c184cd3STimur Tabi } 3862c184cd3STimur Tabi 3872c184cd3STimur Tabi guts = of_iomap(guts_np, 0); 3882c184cd3STimur Tabi of_node_put(guts_np); 3892c184cd3STimur Tabi if (!guts) { 390b6741bc7STim Blechmann pr_err("p1022ds: could not map global utilities device\n"); 3912c184cd3STimur Tabi return; 3922c184cd3STimur Tabi } 3932c184cd3STimur Tabi 3942c184cd3STimur Tabi /* Convert pixclock from a wavelength to a frequency */ 3952c184cd3STimur Tabi temp = 1000000000000ULL; 3962c184cd3STimur Tabi do_div(temp, pixclock); 3972c184cd3STimur Tabi freq = temp; 3982c184cd3STimur Tabi 3997b93eccfSTimur Tabi /* 4007b93eccfSTimur Tabi * 'pxclk' is the ratio of the platform clock to the pixel clock. 4017b93eccfSTimur Tabi * This number is programmed into the CLKDVDR register, and the valid 4027b93eccfSTimur Tabi * range of values is 2-255. 4037b93eccfSTimur Tabi */ 4042c184cd3STimur Tabi pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq); 4057b93eccfSTimur Tabi pxclk = clamp_t(u32, pxclk, 2, 255); 4062c184cd3STimur Tabi 4072c184cd3STimur Tabi /* Disable the pixel clock, and set it to non-inverted and no delay */ 4082c184cd3STimur Tabi clrbits32(&guts->clkdvdr, 4092c184cd3STimur Tabi CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK); 4102c184cd3STimur Tabi 4112c184cd3STimur Tabi /* Enable the clock and set the pxclk */ 4122c184cd3STimur Tabi setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16)); 41331655958STimur Tabi 41431655958STimur Tabi iounmap(guts); 4152c184cd3STimur Tabi } 4162c184cd3STimur Tabi 4172c184cd3STimur Tabi /** 4187653aaabSTimur Tabi * p1022ds_valid_monitor_port: set the monitor port for sysfs 4192c184cd3STimur Tabi */ 4207653aaabSTimur Tabi enum fsl_diu_monitor_port 4217653aaabSTimur Tabi p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port) 4222c184cd3STimur Tabi { 4237653aaabSTimur Tabi switch (port) { 4247653aaabSTimur Tabi case FSL_DIU_PORT_DVI: 4257653aaabSTimur Tabi case FSL_DIU_PORT_LVDS: 4267653aaabSTimur Tabi return port; 4277653aaabSTimur Tabi default: 4287653aaabSTimur Tabi return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */ 4292c184cd3STimur Tabi } 4302c184cd3STimur Tabi } 4312c184cd3STimur Tabi 4322c184cd3STimur Tabi #endif 43330be4c96STimur Tabi 43430be4c96STimur Tabi void __init p1022_ds_pic_init(void) 43530be4c96STimur Tabi { 436e55d7f73SKyle Moffett struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN | 43730be4c96STimur Tabi MPIC_SINGLE_DEST_CPU, 43830be4c96STimur Tabi 0, 256, " OpenPIC "); 43930be4c96STimur Tabi BUG_ON(mpic == NULL); 44030be4c96STimur Tabi mpic_init(mpic); 44130be4c96STimur Tabi } 44230be4c96STimur Tabi 4434951896aSTimur Tabi #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 4444951896aSTimur Tabi 4454951896aSTimur Tabi /* TRUE if there is a "video=fslfb" command-line parameter. */ 4464951896aSTimur Tabi static bool fslfb; 4474951896aSTimur Tabi 4484951896aSTimur Tabi /* 4494951896aSTimur Tabi * Search for a "video=fslfb" command-line parameter, and set 'fslfb' to 4504951896aSTimur Tabi * true if we find it. 4514951896aSTimur Tabi * 4524951896aSTimur Tabi * We need to use early_param() instead of __setup() because the normal 4534951896aSTimur Tabi * __setup() gets called to late. However, early_param() gets called very 4544951896aSTimur Tabi * early, before the device tree is unflattened, so all we can do now is set a 4554951896aSTimur Tabi * global variable. Later on, p1022_ds_setup_arch() will use that variable 4564951896aSTimur Tabi * to determine if we need to update the device tree. 4574951896aSTimur Tabi */ 4584951896aSTimur Tabi static int __init early_video_setup(char *options) 4594951896aSTimur Tabi { 4604951896aSTimur Tabi fslfb = (strncmp(options, "fslfb:", 6) == 0); 4614951896aSTimur Tabi 4624951896aSTimur Tabi return 0; 4634951896aSTimur Tabi } 4644951896aSTimur Tabi early_param("video", early_video_setup); 4654951896aSTimur Tabi 4664951896aSTimur Tabi #endif 4674951896aSTimur Tabi 46830be4c96STimur Tabi /* 46930be4c96STimur Tabi * Setup the architecture 47030be4c96STimur Tabi */ 47130be4c96STimur Tabi static void __init p1022_ds_setup_arch(void) 47230be4c96STimur Tabi { 47330be4c96STimur Tabi if (ppc_md.progress) 47430be4c96STimur Tabi ppc_md.progress("p1022_ds_setup_arch()", 0); 47530be4c96STimur Tabi 4762c184cd3STimur Tabi #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) 4772c184cd3STimur Tabi diu_ops.set_monitor_port = p1022ds_set_monitor_port; 4782c184cd3STimur Tabi diu_ops.set_pixel_clock = p1022ds_set_pixel_clock; 4797653aaabSTimur Tabi diu_ops.valid_monitor_port = p1022ds_valid_monitor_port; 4804951896aSTimur Tabi 4814951896aSTimur Tabi /* 4826269f258STimur Tabi * Disable the NOR and NAND flash nodes if there is video=fslfb... 4836269f258STimur Tabi * command-line parameter. When the DIU is active, the localbus is 4846269f258STimur Tabi * unavailable, so we have to disable these nodes before the MTD 4856269f258STimur Tabi * driver loads. 4864951896aSTimur Tabi */ 4874951896aSTimur Tabi if (fslfb) { 4884951896aSTimur Tabi struct device_node *np = 4894951896aSTimur Tabi of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); 4904951896aSTimur Tabi 4914951896aSTimur Tabi if (np) { 4926269f258STimur Tabi struct device_node *np2; 4936269f258STimur Tabi 4946269f258STimur Tabi of_node_get(np); 4956269f258STimur Tabi np2 = of_find_compatible_node(np, NULL, "cfi-flash"); 4966269f258STimur Tabi if (np2) { 4974951896aSTimur Tabi static struct property nor_status = { 4984951896aSTimur Tabi .name = "status", 4994951896aSTimur Tabi .value = "disabled", 5004951896aSTimur Tabi .length = sizeof("disabled"), 5014951896aSTimur Tabi }; 5024951896aSTimur Tabi 5036269f258STimur Tabi /* 50479d1c712SNathan Fontenot * of_update_property() is called before 5056269f258STimur Tabi * kmalloc() is available, so the 'new' object 5066269f258STimur Tabi * should be allocated in the global area. 5076269f258STimur Tabi * The easiest way is to do that is to 5086269f258STimur Tabi * allocate one static local variable for each 5096269f258STimur Tabi * call to this function. 5106269f258STimur Tabi */ 511b7c670d6SRob Herring pr_info("p1022ds: disabling %pOF node", 512b7c670d6SRob Herring np2); 51379d1c712SNathan Fontenot of_update_property(np2, &nor_status); 5146269f258STimur Tabi of_node_put(np2); 5154951896aSTimur Tabi } 5166269f258STimur Tabi 5176269f258STimur Tabi of_node_get(np); 5186269f258STimur Tabi np2 = of_find_compatible_node(np, NULL, 5196269f258STimur Tabi "fsl,elbc-fcm-nand"); 5206269f258STimur Tabi if (np2) { 5216269f258STimur Tabi static struct property nand_status = { 5226269f258STimur Tabi .name = "status", 5236269f258STimur Tabi .value = "disabled", 5246269f258STimur Tabi .length = sizeof("disabled"), 5256269f258STimur Tabi }; 5266269f258STimur Tabi 527b7c670d6SRob Herring pr_info("p1022ds: disabling %pOF node", 528b7c670d6SRob Herring np2); 52979d1c712SNathan Fontenot of_update_property(np2, &nand_status); 5306269f258STimur Tabi of_node_put(np2); 5316269f258STimur Tabi } 5326269f258STimur Tabi 5336269f258STimur Tabi of_node_put(np); 5344951896aSTimur Tabi } 5354951896aSTimur Tabi 5364951896aSTimur Tabi } 5374951896aSTimur Tabi 5382c184cd3STimur Tabi #endif 5392c184cd3STimur Tabi 54030be4c96STimur Tabi mpc85xx_smp_init(); 54130be4c96STimur Tabi 542905e75c4SJia Hongtao fsl_pci_assign_primary(); 543905e75c4SJia Hongtao 544905e75c4SJia Hongtao swiotlb_detect_4g(); 54530be4c96STimur Tabi 54630be4c96STimur Tabi pr_info("Freescale P1022 DS reference board\n"); 54730be4c96STimur Tabi } 54830be4c96STimur Tabi 549905e75c4SJia Hongtao machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices); 55030be4c96STimur Tabi 55130be4c96STimur Tabi machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier); 55230be4c96STimur Tabi 55330be4c96STimur Tabi /* 55430be4c96STimur Tabi * Called very early, device-tree isn't unflattened 55530be4c96STimur Tabi */ 55630be4c96STimur Tabi static int __init p1022_ds_probe(void) 55730be4c96STimur Tabi { 55856571384SBenjamin Herrenschmidt return of_machine_is_compatible("fsl,p1022ds"); 55930be4c96STimur Tabi } 56030be4c96STimur Tabi 56130be4c96STimur Tabi define_machine(p1022_ds) { 56230be4c96STimur Tabi .name = "P1022 DS", 56330be4c96STimur Tabi .probe = p1022_ds_probe, 56430be4c96STimur Tabi .setup_arch = p1022_ds_setup_arch, 56530be4c96STimur Tabi .init_IRQ = p1022_ds_pic_init, 56630be4c96STimur Tabi #ifdef CONFIG_PCI 56730be4c96STimur Tabi .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 56848b16180SWang Dongsheng .pcibios_fixup_phb = fsl_pcibios_fixup_phb, 56930be4c96STimur Tabi #endif 57030be4c96STimur Tabi .get_irq = mpic_get_irq, 57130be4c96STimur Tabi .calibrate_decr = generic_calibrate_decr, 57230be4c96STimur Tabi .progress = udbg_progress, 57330be4c96STimur Tabi }; 574