Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * P1022DS board specific routines
0003  *
0004  * Authors: Travis Wheatley <travis.wheatley@freescale.com>
0005  *          Dave Liu <daveliu@freescale.com>
0006  *          Timur Tabi <timur@freescale.com>
0007  *
0008  * Copyright 2010 Freescale Semiconductor, Inc.
0009  *
0010  * This file is taken from the Freescale P1022DS BSP, with modifications:
0011  * 2) No AMP support
0012  * 3) No PCI endpoint support
0013  *
0014  * This file is licensed under the terms of the GNU General Public License
0015  * version 2.  This program is licensed "as is" without any warranty of any
0016  * kind, whether express or implied.
0017  */
0018 
0019 #include <linux/fsl/guts.h>
0020 #include <linux/pci.h>
0021 #include <linux/of_address.h>
0022 #include <linux/of_platform.h>
0023 #include <asm/div64.h>
0024 #include <asm/mpic.h>
0025 #include <asm/swiotlb.h>
0026 
0027 #include <sysdev/fsl_soc.h>
0028 #include <sysdev/fsl_pci.h>
0029 #include <asm/udbg.h>
0030 #include <asm/fsl_lbc.h>
0031 #include "smp.h"
0032 
0033 #include "mpc85xx.h"
0034 
0035 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
0036 
0037 #define PMUXCR_ELBCDIU_MASK 0xc0000000
0038 #define PMUXCR_ELBCDIU_NOR16    0x80000000
0039 #define PMUXCR_ELBCDIU_DIU  0x40000000
0040 
0041 /*
0042  * Board-specific initialization of the DIU.  This code should probably be
0043  * executed when the DIU is opened, rather than in arch code, but the DIU
0044  * driver does not have a mechanism for this (yet).
0045  *
0046  * This is especially problematic on the P1022DS because the local bus (eLBC)
0047  * and the DIU video signals share the same pins, which means that enabling the
0048  * DIU will disable access to NOR flash.
0049  */
0050 
0051 /* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
0052 #define CLKDVDR_PXCKEN      0x80000000
0053 #define CLKDVDR_PXCKINV     0x10000000
0054 #define CLKDVDR_PXCKDLY     0x06000000
0055 #define CLKDVDR_PXCLK_MASK  0x00FF0000
0056 
0057 /* Some ngPIXIS register definitions */
0058 #define PX_CTL      3
0059 #define PX_BRDCFG0  8
0060 #define PX_BRDCFG1  9
0061 
0062 #define PX_BRDCFG0_ELBC_SPI_MASK    0xc0
0063 #define PX_BRDCFG0_ELBC_SPI_ELBC    0x00
0064 #define PX_BRDCFG0_ELBC_SPI_NULL    0xc0
0065 #define PX_BRDCFG0_ELBC_DIU     0x02
0066 
0067 #define PX_BRDCFG1_DVIEN    0x80
0068 #define PX_BRDCFG1_DFPEN    0x40
0069 #define PX_BRDCFG1_BACKLIGHT    0x20
0070 #define PX_BRDCFG1_DDCEN    0x10
0071 
0072 #define PX_CTL_ALTACC       0x80
0073 
0074 /*
0075  * DIU Area Descriptor
0076  *
0077  * Note that we need to byte-swap the value before it's written to the AD
0078  * register.  So even though the registers don't look like they're in the same
0079  * bit positions as they are on the MPC8610, the same value is written to the
0080  * AD register on the MPC8610 and on the P1022.
0081  */
0082 #define AD_BYTE_F       0x10000000
0083 #define AD_ALPHA_C_MASK     0x0E000000
0084 #define AD_ALPHA_C_SHIFT    25
0085 #define AD_BLUE_C_MASK      0x01800000
0086 #define AD_BLUE_C_SHIFT     23
0087 #define AD_GREEN_C_MASK     0x00600000
0088 #define AD_GREEN_C_SHIFT    21
0089 #define AD_RED_C_MASK       0x00180000
0090 #define AD_RED_C_SHIFT      19
0091 #define AD_PALETTE      0x00040000
0092 #define AD_PIXEL_S_MASK     0x00030000
0093 #define AD_PIXEL_S_SHIFT    16
0094 #define AD_COMP_3_MASK      0x0000F000
0095 #define AD_COMP_3_SHIFT     12
0096 #define AD_COMP_2_MASK      0x00000F00
0097 #define AD_COMP_2_SHIFT     8
0098 #define AD_COMP_1_MASK      0x000000F0
0099 #define AD_COMP_1_SHIFT     4
0100 #define AD_COMP_0_MASK      0x0000000F
0101 #define AD_COMP_0_SHIFT     0
0102 
0103 #define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \
0104     cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \
0105     (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \
0106     (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \
0107     (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
0108     (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
0109 
0110 struct fsl_law {
0111     u32 lawbar;
0112     u32 reserved1;
0113     u32 lawar;
0114     u32 reserved[5];
0115 };
0116 
0117 #define LAWBAR_MASK 0x00F00000
0118 #define LAWBAR_SHIFT    12
0119 
0120 #define LAWAR_EN    0x80000000
0121 #define LAWAR_TGT_MASK  0x01F00000
0122 #define LAW_TRGT_IF_LBC (0x04 << 20)
0123 
0124 #define LAWAR_MASK  (LAWAR_EN | LAWAR_TGT_MASK)
0125 #define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC)
0126 
0127 #define BR_BA       0xFFFF8000
0128 
0129 /*
0130  * Map a BRx value to a physical address
0131  *
0132  * The localbus BRx registers only store the lower 32 bits of the address.  To
0133  * obtain the upper four bits, we need to scan the LAW table.  The entry which
0134  * maps to the localbus will contain the upper four bits.
0135  */
0136 static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br)
0137 {
0138 #ifndef CONFIG_PHYS_64BIT
0139     /*
0140      * If we only have 32-bit addressing, then the BRx address *is* the
0141      * physical address.
0142      */
0143     return br & BR_BA;
0144 #else
0145     const struct fsl_law *law = ecm + 0xc08;
0146     unsigned int i;
0147 
0148     for (i = 0; i < count; i++) {
0149         u64 lawbar = in_be32(&law[i].lawbar);
0150         u32 lawar = in_be32(&law[i].lawar);
0151 
0152         if ((lawar & LAWAR_MASK) == LAWAR_MATCH)
0153             /* Extract the upper four bits */
0154             return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12);
0155     }
0156 
0157     return 0;
0158 #endif
0159 }
0160 
0161 /**
0162  * p1022ds_set_monitor_port: switch the output to a different monitor port
0163  */
0164 static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
0165 {
0166     struct device_node *guts_node;
0167     struct device_node *lbc_node = NULL;
0168     struct device_node *law_node = NULL;
0169     struct ccsr_guts __iomem *guts;
0170     struct fsl_lbc_regs *lbc = NULL;
0171     void *ecm = NULL;
0172     u8 __iomem *lbc_lcs0_ba = NULL;
0173     u8 __iomem *lbc_lcs1_ba = NULL;
0174     phys_addr_t cs0_addr, cs1_addr;
0175     u32 br0, or0, br1, or1;
0176     const __be32 *iprop;
0177     unsigned int num_laws;
0178     u8 b;
0179 
0180     /* Map the global utilities registers. */
0181     guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
0182     if (!guts_node) {
0183         pr_err("p1022ds: missing global utilities device node\n");
0184         return;
0185     }
0186 
0187     guts = of_iomap(guts_node, 0);
0188     if (!guts) {
0189         pr_err("p1022ds: could not map global utilities device\n");
0190         goto exit;
0191     }
0192 
0193     lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
0194     if (!lbc_node) {
0195         pr_err("p1022ds: missing localbus node\n");
0196         goto exit;
0197     }
0198 
0199     lbc = of_iomap(lbc_node, 0);
0200     if (!lbc) {
0201         pr_err("p1022ds: could not map localbus node\n");
0202         goto exit;
0203     }
0204 
0205     law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
0206     if (!law_node) {
0207         pr_err("p1022ds: missing local access window node\n");
0208         goto exit;
0209     }
0210 
0211     ecm = of_iomap(law_node, 0);
0212     if (!ecm) {
0213         pr_err("p1022ds: could not map local access window node\n");
0214         goto exit;
0215     }
0216 
0217     iprop = of_get_property(law_node, "fsl,num-laws", NULL);
0218     if (!iprop) {
0219         pr_err("p1022ds: LAW node is missing fsl,num-laws property\n");
0220         goto exit;
0221     }
0222     num_laws = be32_to_cpup(iprop);
0223 
0224     /*
0225      * Indirect mode requires both BR0 and BR1 to be set to "GPCM",
0226      * otherwise writes to these addresses won't actually appear on the
0227      * local bus, and so the PIXIS won't see them.
0228      *
0229      * In FCM mode, writes go to the NAND controller, which does not pass
0230      * them to the localbus directly.  So we force BR0 and BR1 into GPCM
0231      * mode, since we don't care about what's behind the localbus any
0232      * more.
0233      */
0234     br0 = in_be32(&lbc->bank[0].br);
0235     br1 = in_be32(&lbc->bank[1].br);
0236     or0 = in_be32(&lbc->bank[0].or);
0237     or1 = in_be32(&lbc->bank[1].or);
0238 
0239     /* Make sure CS0 and CS1 are programmed */
0240     if (!(br0 & BR_V) || !(br1 & BR_V)) {
0241         pr_err("p1022ds: CS0 and/or CS1 is not programmed\n");
0242         goto exit;
0243     }
0244 
0245     /*
0246      * Use the existing BRx/ORx values if it's already GPCM. Otherwise,
0247      * force the values to simple 32KB GPCM windows with the most
0248      * conservative timing.
0249      */
0250     if ((br0 & BR_MSEL) != BR_MS_GPCM) {
0251         br0 = (br0 & BR_BA) | BR_V;
0252         or0 = 0xFFFF8000 | 0xFF7;
0253         out_be32(&lbc->bank[0].br, br0);
0254         out_be32(&lbc->bank[0].or, or0);
0255     }
0256     if ((br1 & BR_MSEL) != BR_MS_GPCM) {
0257         br1 = (br1 & BR_BA) | BR_V;
0258         or1 = 0xFFFF8000 | 0xFF7;
0259         out_be32(&lbc->bank[1].br, br1);
0260         out_be32(&lbc->bank[1].or, or1);
0261     }
0262 
0263     cs0_addr = lbc_br_to_phys(ecm, num_laws, br0);
0264     if (!cs0_addr) {
0265         pr_err("p1022ds: could not determine physical address for CS0"
0266                " (BR0=%08x)\n", br0);
0267         goto exit;
0268     }
0269     cs1_addr = lbc_br_to_phys(ecm, num_laws, br1);
0270     if (!cs1_addr) {
0271         pr_err("p1022ds: could not determine physical address for CS1"
0272                " (BR1=%08x)\n", br1);
0273         goto exit;
0274     }
0275 
0276     lbc_lcs0_ba = ioremap(cs0_addr, 1);
0277     if (!lbc_lcs0_ba) {
0278         pr_err("p1022ds: could not ioremap CS0 address %llx\n",
0279                (unsigned long long)cs0_addr);
0280         goto exit;
0281     }
0282     lbc_lcs1_ba = ioremap(cs1_addr, 1);
0283     if (!lbc_lcs1_ba) {
0284         pr_err("p1022ds: could not ioremap CS1 address %llx\n",
0285                (unsigned long long)cs1_addr);
0286         goto exit;
0287     }
0288 
0289     /* Make sure we're in indirect mode first. */
0290     if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
0291         PMUXCR_ELBCDIU_DIU) {
0292         struct device_node *pixis_node;
0293         void __iomem *pixis;
0294 
0295         pixis_node =
0296             of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
0297         if (!pixis_node) {
0298             pr_err("p1022ds: missing pixis node\n");
0299             goto exit;
0300         }
0301 
0302         pixis = of_iomap(pixis_node, 0);
0303         of_node_put(pixis_node);
0304         if (!pixis) {
0305             pr_err("p1022ds: could not map pixis registers\n");
0306             goto exit;
0307         }
0308 
0309         /* Enable indirect PIXIS mode.  */
0310         setbits8(pixis + PX_CTL, PX_CTL_ALTACC);
0311         iounmap(pixis);
0312 
0313         /* Switch the board mux to the DIU */
0314         out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */
0315         b = in_8(lbc_lcs1_ba);
0316         b |= PX_BRDCFG0_ELBC_DIU;
0317         out_8(lbc_lcs1_ba, b);
0318 
0319         /* Set the chip mux to DIU mode. */
0320         clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK,
0321                 PMUXCR_ELBCDIU_DIU);
0322         in_be32(&guts->pmuxcr);
0323     }
0324 
0325 
0326     switch (port) {
0327     case FSL_DIU_PORT_DVI:
0328         /* Enable the DVI port, disable the DFP and the backlight */
0329         out_8(lbc_lcs0_ba, PX_BRDCFG1);
0330         b = in_8(lbc_lcs1_ba);
0331         b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
0332         b |= PX_BRDCFG1_DVIEN;
0333         out_8(lbc_lcs1_ba, b);
0334         break;
0335     case FSL_DIU_PORT_LVDS:
0336         /*
0337          * LVDS also needs backlight enabled, otherwise the display
0338          * will be blank.
0339          */
0340         /* Enable the DFP port, disable the DVI and the backlight */
0341         out_8(lbc_lcs0_ba, PX_BRDCFG1);
0342         b = in_8(lbc_lcs1_ba);
0343         b &= ~PX_BRDCFG1_DVIEN;
0344         b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT;
0345         out_8(lbc_lcs1_ba, b);
0346         break;
0347     default:
0348         pr_err("p1022ds: unsupported monitor port %i\n", port);
0349     }
0350 
0351 exit:
0352     if (lbc_lcs1_ba)
0353         iounmap(lbc_lcs1_ba);
0354     if (lbc_lcs0_ba)
0355         iounmap(lbc_lcs0_ba);
0356     if (lbc)
0357         iounmap(lbc);
0358     if (ecm)
0359         iounmap(ecm);
0360     if (guts)
0361         iounmap(guts);
0362 
0363     of_node_put(law_node);
0364     of_node_put(lbc_node);
0365     of_node_put(guts_node);
0366 }
0367 
0368 /**
0369  * p1022ds_set_pixel_clock: program the DIU's clock
0370  *
0371  * @pixclock: the wavelength, in picoseconds, of the clock
0372  */
0373 void p1022ds_set_pixel_clock(unsigned int pixclock)
0374 {
0375     struct device_node *guts_np = NULL;
0376     struct ccsr_guts __iomem *guts;
0377     unsigned long freq;
0378     u64 temp;
0379     u32 pxclk;
0380 
0381     /* Map the global utilities registers. */
0382     guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
0383     if (!guts_np) {
0384         pr_err("p1022ds: missing global utilities device node\n");
0385         return;
0386     }
0387 
0388     guts = of_iomap(guts_np, 0);
0389     of_node_put(guts_np);
0390     if (!guts) {
0391         pr_err("p1022ds: could not map global utilities device\n");
0392         return;
0393     }
0394 
0395     /* Convert pixclock from a wavelength to a frequency */
0396     temp = 1000000000000ULL;
0397     do_div(temp, pixclock);
0398     freq = temp;
0399 
0400     /*
0401      * 'pxclk' is the ratio of the platform clock to the pixel clock.
0402      * This number is programmed into the CLKDVDR register, and the valid
0403      * range of values is 2-255.
0404      */
0405     pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
0406     pxclk = clamp_t(u32, pxclk, 2, 255);
0407 
0408     /* Disable the pixel clock, and set it to non-inverted and no delay */
0409     clrbits32(&guts->clkdvdr,
0410           CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
0411 
0412     /* Enable the clock and set the pxclk */
0413     setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
0414 
0415     iounmap(guts);
0416 }
0417 
0418 /**
0419  * p1022ds_valid_monitor_port: set the monitor port for sysfs
0420  */
0421 enum fsl_diu_monitor_port
0422 p1022ds_valid_monitor_port(enum fsl_diu_monitor_port port)
0423 {
0424     switch (port) {
0425     case FSL_DIU_PORT_DVI:
0426     case FSL_DIU_PORT_LVDS:
0427         return port;
0428     default:
0429         return FSL_DIU_PORT_DVI; /* Dual-link LVDS is not supported */
0430     }
0431 }
0432 
0433 #endif
0434 
0435 void __init p1022_ds_pic_init(void)
0436 {
0437     struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
0438         MPIC_SINGLE_DEST_CPU,
0439         0, 256, " OpenPIC  ");
0440     BUG_ON(mpic == NULL);
0441     mpic_init(mpic);
0442 }
0443 
0444 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
0445 
0446 /* TRUE if there is a "video=fslfb" command-line parameter. */
0447 static bool fslfb;
0448 
0449 /*
0450  * Search for a "video=fslfb" command-line parameter, and set 'fslfb' to
0451  * true if we find it.
0452  *
0453  * We need to use early_param() instead of __setup() because the normal
0454  * __setup() gets called to late.  However, early_param() gets called very
0455  * early, before the device tree is unflattened, so all we can do now is set a
0456  * global variable.  Later on, p1022_ds_setup_arch() will use that variable
0457  * to determine if we need to update the device tree.
0458  */
0459 static int __init early_video_setup(char *options)
0460 {
0461     fslfb = (strncmp(options, "fslfb:", 6) == 0);
0462 
0463     return 0;
0464 }
0465 early_param("video", early_video_setup);
0466 
0467 #endif
0468 
0469 /*
0470  * Setup the architecture
0471  */
0472 static void __init p1022_ds_setup_arch(void)
0473 {
0474     if (ppc_md.progress)
0475         ppc_md.progress("p1022_ds_setup_arch()", 0);
0476 
0477 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
0478     diu_ops.set_monitor_port    = p1022ds_set_monitor_port;
0479     diu_ops.set_pixel_clock     = p1022ds_set_pixel_clock;
0480     diu_ops.valid_monitor_port  = p1022ds_valid_monitor_port;
0481 
0482     /*
0483      * Disable the NOR and NAND flash nodes if there is video=fslfb...
0484      * command-line parameter.  When the DIU is active, the localbus is
0485      * unavailable, so we have to disable these nodes before the MTD
0486      * driver loads.
0487      */
0488     if (fslfb) {
0489         struct device_node *np =
0490             of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
0491 
0492         if (np) {
0493             struct device_node *np2;
0494 
0495             of_node_get(np);
0496             np2 = of_find_compatible_node(np, NULL, "cfi-flash");
0497             if (np2) {
0498                 static struct property nor_status = {
0499                     .name = "status",
0500                     .value = "disabled",
0501                     .length = sizeof("disabled"),
0502                 };
0503 
0504                 /*
0505                  * of_update_property() is called before
0506                  * kmalloc() is available, so the 'new' object
0507                  * should be allocated in the global area.
0508                  * The easiest way is to do that is to
0509                  * allocate one static local variable for each
0510                  * call to this function.
0511                  */
0512                 pr_info("p1022ds: disabling %pOF node",
0513                     np2);
0514                 of_update_property(np2, &nor_status);
0515                 of_node_put(np2);
0516             }
0517 
0518             of_node_get(np);
0519             np2 = of_find_compatible_node(np, NULL,
0520                               "fsl,elbc-fcm-nand");
0521             if (np2) {
0522                 static struct property nand_status = {
0523                     .name = "status",
0524                     .value = "disabled",
0525                     .length = sizeof("disabled"),
0526                 };
0527 
0528                 pr_info("p1022ds: disabling %pOF node",
0529                     np2);
0530                 of_update_property(np2, &nand_status);
0531                 of_node_put(np2);
0532             }
0533 
0534             of_node_put(np);
0535         }
0536 
0537     }
0538 
0539 #endif
0540 
0541     mpc85xx_smp_init();
0542 
0543     fsl_pci_assign_primary();
0544 
0545     swiotlb_detect_4g();
0546 
0547     pr_info("Freescale P1022 DS reference board\n");
0548 }
0549 
0550 machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices);
0551 
0552 /*
0553  * Called very early, device-tree isn't unflattened
0554  */
0555 static int __init p1022_ds_probe(void)
0556 {
0557     return of_machine_is_compatible("fsl,p1022ds");
0558 }
0559 
0560 define_machine(p1022_ds) {
0561     .name           = "P1022 DS",
0562     .probe          = p1022_ds_probe,
0563     .setup_arch     = p1022_ds_setup_arch,
0564     .init_IRQ       = p1022_ds_pic_init,
0565 #ifdef CONFIG_PCI
0566     .pcibios_fixup_bus  = fsl_pcibios_fixup_bus,
0567     .pcibios_fixup_phb  = fsl_pcibios_fixup_phb,
0568 #endif
0569     .get_irq        = mpic_get_irq,
0570     .calibrate_decr     = generic_calibrate_decr,
0571     .progress       = udbg_progress,
0572 };