linux/arch/powerpc/platforms/85xx/mpc85xx_mds.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Freescale Semicondutor, Inc. 2006-2007. All rights reserved.
   3 *
   4 * Author: Andy Fleming <afleming@freescale.com>
   5 *
   6 * Based on 83xx/mpc8360e_pb.c by:
   7 *         Li Yang <LeoLi@freescale.com>
   8 *         Yin Olivia <Hong-hua.Yin@freescale.com>
   9 *
  10 * Description:
  11 * MPC85xx MDS board specific routines.
  12 *
  13 * This program is free software; you can redistribute  it and/or modify it
  14 * under  the terms of  the GNU General  Public License as published by the
  15 * Free Software Foundation;  either version 2 of the  License, or (at your
  16 * option) any later version.
  17 */
  18
  19#include <linux/stddef.h>
  20#include <linux/kernel.h>
  21#include <linux/init.h>
  22#include <linux/errno.h>
  23#include <linux/reboot.h>
  24#include <linux/pci.h>
  25#include <linux/kdev_t.h>
  26#include <linux/major.h>
  27#include <linux/console.h>
  28#include <linux/delay.h>
  29#include <linux/seq_file.h>
  30#include <linux/initrd.h>
  31#include <linux/module.h>
  32#include <linux/fsl_devices.h>
  33#include <linux/of_platform.h>
  34#include <linux/of_device.h>
  35#include <linux/phy.h>
  36#include <linux/lmb.h>
  37
  38#include <asm/system.h>
  39#include <asm/atomic.h>
  40#include <asm/time.h>
  41#include <asm/io.h>
  42#include <asm/machdep.h>
  43#include <asm/pci-bridge.h>
  44#include <asm/irq.h>
  45#include <mm/mmu_decl.h>
  46#include <asm/prom.h>
  47#include <asm/udbg.h>
  48#include <sysdev/fsl_soc.h>
  49#include <sysdev/fsl_pci.h>
  50#include <sysdev/simple_gpio.h>
  51#include <asm/qe.h>
  52#include <asm/qe_ic.h>
  53#include <asm/mpic.h>
  54#include <asm/swiotlb.h>
  55
  56#undef DEBUG
  57#ifdef DEBUG
  58#define DBG(fmt...) udbg_printf(fmt)
  59#else
  60#define DBG(fmt...)
  61#endif
  62
  63#define MV88E1111_SCR   0x10
  64#define MV88E1111_SCR_125CLK    0x0010
  65static int mpc8568_fixup_125_clock(struct phy_device *phydev)
  66{
  67        int scr;
  68        int err;
  69
  70        /* Workaround for the 125 CLK Toggle */
  71        scr = phy_read(phydev, MV88E1111_SCR);
  72
  73        if (scr < 0)
  74                return scr;
  75
  76        err = phy_write(phydev, MV88E1111_SCR, scr & ~(MV88E1111_SCR_125CLK));
  77
  78        if (err)
  79                return err;
  80
  81        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
  82
  83        if (err)
  84                return err;
  85
  86        scr = phy_read(phydev, MV88E1111_SCR);
  87
  88        if (scr < 0)
  89                return err;
  90
  91        err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008);
  92
  93        return err;
  94}
  95
  96static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
  97{
  98        int temp;
  99        int err;
 100
 101        /* Errata */
 102        err = phy_write(phydev,29, 0x0006);
 103
 104        if (err)
 105                return err;
 106
 107        temp = phy_read(phydev, 30);
 108
 109        if (temp < 0)
 110                return temp;
 111
 112        temp = (temp & (~0x8000)) | 0x4000;
 113        err = phy_write(phydev,30, temp);
 114
 115        if (err)
 116                return err;
 117
 118        err = phy_write(phydev,29, 0x000a);
 119
 120        if (err)
 121                return err;
 122
 123        temp = phy_read(phydev, 30);
 124
 125        if (temp < 0)
 126                return temp;
 127
 128        temp = phy_read(phydev, 30);
 129
 130        if (temp < 0)
 131                return temp;
 132
 133        temp &= ~0x0020;
 134
 135        err = phy_write(phydev,30,temp);
 136
 137        if (err)
 138                return err;
 139
 140        /* Disable automatic MDI/MDIX selection */
 141        temp = phy_read(phydev, 16);
 142
 143        if (temp < 0)
 144                return temp;
 145
 146        temp &= ~0x0060;
 147        err = phy_write(phydev,16,temp);
 148
 149        return err;
 150}
 151
 152/* ************************************************************************
 153 *
 154 * Setup the architecture
 155 *
 156 */
 157static void __init mpc85xx_mds_setup_arch(void)
 158{
 159        struct device_node *np;
 160        static u8 __iomem *bcsr_regs = NULL;
 161#ifdef CONFIG_PCI
 162        struct pci_controller *hose;
 163#endif
 164        dma_addr_t max = 0xffffffff;
 165
 166        if (ppc_md.progress)
 167                ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
 168
 169        /* Map BCSR area */
 170        np = of_find_node_by_name(NULL, "bcsr");
 171        if (np != NULL) {
 172                struct resource res;
 173
 174                of_address_to_resource(np, 0, &res);
 175                bcsr_regs = ioremap(res.start, res.end - res.start +1);
 176                of_node_put(np);
 177        }
 178
 179#ifdef CONFIG_PCI
 180        for_each_node_by_type(np, "pci") {
 181                if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
 182                    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
 183                        struct resource rsrc;
 184                        of_address_to_resource(np, 0, &rsrc);
 185                        if ((rsrc.start & 0xfffff) == 0x8000)
 186                                fsl_add_bridge(np, 1);
 187                        else
 188                                fsl_add_bridge(np, 0);
 189
 190                        hose = pci_find_hose_for_OF_device(np);
 191                        max = min(max, hose->dma_window_base_cur +
 192                                        hose->dma_window_size);
 193                }
 194        }
 195#endif
 196
 197#ifdef CONFIG_QUICC_ENGINE
 198        np = of_find_compatible_node(NULL, NULL, "fsl,qe");
 199        if (!np) {
 200                np = of_find_node_by_name(NULL, "qe");
 201                if (!np)
 202                        return;
 203        }
 204
 205        qe_reset();
 206        of_node_put(np);
 207
 208        np = of_find_node_by_name(NULL, "par_io");
 209        if (np) {
 210                struct device_node *ucc;
 211
 212                par_io_init(np);
 213                of_node_put(np);
 214
 215                for_each_node_by_name(ucc, "ucc")
 216                        par_io_of_config(ucc);
 217        }
 218
 219        if (bcsr_regs) {
 220                if (machine_is(mpc8568_mds)) {
 221#define BCSR_UCC1_GETH_EN       (0x1 << 7)
 222#define BCSR_UCC2_GETH_EN       (0x1 << 7)
 223#define BCSR_UCC1_MODE_MSK      (0x3 << 4)
 224#define BCSR_UCC2_MODE_MSK      (0x3 << 0)
 225
 226                        /* Turn off UCC1 & UCC2 */
 227                        clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
 228                        clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
 229
 230                        /* Mode is RGMII, all bits clear */
 231                        clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
 232                                                 BCSR_UCC2_MODE_MSK);
 233
 234                        /* Turn UCC1 & UCC2 on */
 235                        setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
 236                        setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
 237                } else if (machine_is(mpc8569_mds)) {
 238#define BCSR7_UCC12_GETHnRST    (0x1 << 2)
 239#define BCSR8_UEM_MARVELL_RST   (0x1 << 1)
 240                        /*
 241                         * U-Boot mangles interrupt polarity for Marvell PHYs,
 242                         * so reset built-in and UEM Marvell PHYs, this puts
 243                         * the PHYs into their normal state.
 244                         */
 245                        clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
 246                        setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
 247
 248                        setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
 249                        clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
 250                }
 251                iounmap(bcsr_regs);
 252        }
 253#endif  /* CONFIG_QUICC_ENGINE */
 254
 255#ifdef CONFIG_SWIOTLB
 256        if (lmb_end_of_DRAM() > max) {
 257                ppc_swiotlb_enable = 1;
 258                set_pci_dma_ops(&swiotlb_dma_ops);
 259                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
 260        }
 261#endif
 262}
 263
 264
 265static int __init board_fixups(void)
 266{
 267        char phy_id[20];
 268        char *compstrs[2] = {"fsl,gianfar-mdio", "fsl,ucc-mdio"};
 269        struct device_node *mdio;
 270        struct resource res;
 271        int i;
 272
 273        for (i = 0; i < ARRAY_SIZE(compstrs); i++) {
 274                mdio = of_find_compatible_node(NULL, NULL, compstrs[i]);
 275
 276                of_address_to_resource(mdio, 0, &res);
 277                snprintf(phy_id, sizeof(phy_id), "%llx:%02x",
 278                        (unsigned long long)res.start, 1);
 279
 280                phy_register_fixup_for_id(phy_id, mpc8568_fixup_125_clock);
 281                phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);
 282
 283                /* Register a workaround for errata */
 284                snprintf(phy_id, sizeof(phy_id), "%llx:%02x",
 285                        (unsigned long long)res.start, 7);
 286                phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);
 287
 288                of_node_put(mdio);
 289        }
 290
 291        return 0;
 292}
 293machine_arch_initcall(mpc8568_mds, board_fixups);
 294machine_arch_initcall(mpc8569_mds, board_fixups);
 295
 296static struct of_device_id mpc85xx_ids[] = {
 297        { .type = "soc", },
 298        { .compatible = "soc", },
 299        { .compatible = "simple-bus", },
 300        { .type = "qe", },
 301        { .compatible = "fsl,qe", },
 302        { .compatible = "gianfar", },
 303        { .compatible = "fsl,rapidio-delta", },
 304        {},
 305};
 306
 307static int __init mpc85xx_publish_devices(void)
 308{
 309        if (machine_is(mpc8569_mds))
 310                simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
 311
 312        /* Publish the QE devices */
 313        of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
 314
 315        return 0;
 316}
 317machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
 318machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
 319
 320machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
 321machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
 322
 323static void __init mpc85xx_mds_pic_init(void)
 324{
 325        struct mpic *mpic;
 326        struct resource r;
 327        struct device_node *np = NULL;
 328
 329        np = of_find_node_by_type(NULL, "open-pic");
 330        if (!np)
 331                return;
 332
 333        if (of_address_to_resource(np, 0, &r)) {
 334                printk(KERN_ERR "Failed to map mpic register space\n");
 335                of_node_put(np);
 336                return;
 337        }
 338
 339        mpic = mpic_alloc(np, r.start,
 340                        MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
 341                        0, 256, " OpenPIC  ");
 342        BUG_ON(mpic == NULL);
 343        of_node_put(np);
 344
 345        mpic_init(mpic);
 346
 347#ifdef CONFIG_QUICC_ENGINE
 348        np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
 349        if (!np) {
 350                np = of_find_node_by_type(NULL, "qeic");
 351                if (!np)
 352                        return;
 353        }
 354        qe_ic_init(np, 0, qe_ic_cascade_muxed_mpic, NULL);
 355        of_node_put(np);
 356#endif                          /* CONFIG_QUICC_ENGINE */
 357}
 358
 359static int __init mpc85xx_mds_probe(void)
 360{
 361        unsigned long root = of_get_flat_dt_root();
 362
 363        return of_flat_dt_is_compatible(root, "MPC85xxMDS");
 364}
 365
 366define_machine(mpc8568_mds) {
 367        .name           = "MPC8568 MDS",
 368        .probe          = mpc85xx_mds_probe,
 369        .setup_arch     = mpc85xx_mds_setup_arch,
 370        .init_IRQ       = mpc85xx_mds_pic_init,
 371        .get_irq        = mpic_get_irq,
 372        .restart        = fsl_rstcr_restart,
 373        .calibrate_decr = generic_calibrate_decr,
 374        .progress       = udbg_progress,
 375#ifdef CONFIG_PCI
 376        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 377#endif
 378};
 379
 380static int __init mpc8569_mds_probe(void)
 381{
 382        unsigned long root = of_get_flat_dt_root();
 383
 384        return of_flat_dt_is_compatible(root, "fsl,MPC8569EMDS");
 385}
 386
 387define_machine(mpc8569_mds) {
 388        .name           = "MPC8569 MDS",
 389        .probe          = mpc8569_mds_probe,
 390        .setup_arch     = mpc85xx_mds_setup_arch,
 391        .init_IRQ       = mpc85xx_mds_pic_init,
 392        .get_irq        = mpic_get_irq,
 393        .restart        = fsl_rstcr_restart,
 394        .calibrate_decr = generic_calibrate_decr,
 395        .progress       = udbg_progress,
 396#ifdef CONFIG_PCI
 397        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 398#endif
 399};
 400