linux/arch/powerpc/platforms/85xx/mpc85xx_mds.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2006-2010, 2012-2013 Freescale Semiconductor, Inc.
   4 * All rights reserved.
   5 *
   6 * Author: Andy Fleming <afleming@freescale.com>
   7 *
   8 * Based on 83xx/mpc8360e_pb.c by:
   9 *         Li Yang <LeoLi@freescale.com>
  10 *         Yin Olivia <Hong-hua.Yin@freescale.com>
  11 *
  12 * Description:
  13 * MPC85xx MDS board specific routines.
  14 */
  15
  16#include <linux/stddef.h>
  17#include <linux/kernel.h>
  18#include <linux/init.h>
  19#include <linux/errno.h>
  20#include <linux/reboot.h>
  21#include <linux/pci.h>
  22#include <linux/kdev_t.h>
  23#include <linux/major.h>
  24#include <linux/console.h>
  25#include <linux/delay.h>
  26#include <linux/seq_file.h>
  27#include <linux/initrd.h>
  28#include <linux/fsl_devices.h>
  29#include <linux/of_platform.h>
  30#include <linux/of_device.h>
  31#include <linux/phy.h>
  32#include <linux/memblock.h>
  33#include <linux/fsl/guts.h>
  34
  35#include <linux/atomic.h>
  36#include <asm/time.h>
  37#include <asm/io.h>
  38#include <asm/machdep.h>
  39#include <asm/pci-bridge.h>
  40#include <asm/irq.h>
  41#include <mm/mmu_decl.h>
  42#include <asm/prom.h>
  43#include <asm/udbg.h>
  44#include <sysdev/fsl_soc.h>
  45#include <sysdev/fsl_pci.h>
  46#include <soc/fsl/qe/qe.h>
  47#include <asm/mpic.h>
  48#include <asm/swiotlb.h>
  49#include "smp.h"
  50
  51#include "mpc85xx.h"
  52
  53#undef DEBUG
  54#ifdef DEBUG
  55#define DBG(fmt...) udbg_printf(fmt)
  56#else
  57#define DBG(fmt...)
  58#endif
  59
  60#if IS_BUILTIN(CONFIG_PHYLIB)
  61
  62#define MV88E1111_SCR   0x10
  63#define MV88E1111_SCR_125CLK    0x0010
  64static int mpc8568_fixup_125_clock(struct phy_device *phydev)
  65{
  66        int scr;
  67        int err;
  68
  69        /* Workaround for the 125 CLK Toggle */
  70        scr = phy_read(phydev, MV88E1111_SCR);
  71
  72        if (scr < 0)
  73                return scr;
  74
  75        err = phy_write(phydev, MV88E1111_SCR, scr & ~(MV88E1111_SCR_125CLK));
  76
  77        if (err)
  78                return err;
  79
  80        err = phy_write(phydev, MII_BMCR, BMCR_RESET);
  81
  82        if (err)
  83                return err;
  84
  85        scr = phy_read(phydev, MV88E1111_SCR);
  86
  87        if (scr < 0)
  88                return scr;
  89
  90        err = phy_write(phydev, MV88E1111_SCR, scr | 0x0008);
  91
  92        return err;
  93}
  94
  95static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
  96{
  97        int temp;
  98        int err;
  99
 100        /* Errata */
 101        err = phy_write(phydev,29, 0x0006);
 102
 103        if (err)
 104                return err;
 105
 106        temp = phy_read(phydev, 30);
 107
 108        if (temp < 0)
 109                return temp;
 110
 111        temp = (temp & (~0x8000)) | 0x4000;
 112        err = phy_write(phydev,30, temp);
 113
 114        if (err)
 115                return err;
 116
 117        err = phy_write(phydev,29, 0x000a);
 118
 119        if (err)
 120                return err;
 121
 122        temp = phy_read(phydev, 30);
 123
 124        if (temp < 0)
 125                return temp;
 126
 127        temp = phy_read(phydev, 30);
 128
 129        if (temp < 0)
 130                return temp;
 131
 132        temp &= ~0x0020;
 133
 134        err = phy_write(phydev,30,temp);
 135
 136        if (err)
 137                return err;
 138
 139        /* Disable automatic MDI/MDIX selection */
 140        temp = phy_read(phydev, 16);
 141
 142        if (temp < 0)
 143                return temp;
 144
 145        temp &= ~0x0060;
 146        err = phy_write(phydev,16,temp);
 147
 148        return err;
 149}
 150
 151#endif
 152
 153/* ************************************************************************
 154 *
 155 * Setup the architecture
 156 *
 157 */
 158#ifdef CONFIG_QUICC_ENGINE
 159static void __init mpc85xx_mds_reset_ucc_phys(void)
 160{
 161        struct device_node *np;
 162        static u8 __iomem *bcsr_regs;
 163
 164        /* Map BCSR area */
 165        np = of_find_node_by_name(NULL, "bcsr");
 166        if (!np)
 167                return;
 168
 169        bcsr_regs = of_iomap(np, 0);
 170        of_node_put(np);
 171        if (!bcsr_regs)
 172                return;
 173
 174        if (machine_is(mpc8568_mds)) {
 175#define BCSR_UCC1_GETH_EN       (0x1 << 7)
 176#define BCSR_UCC2_GETH_EN       (0x1 << 7)
 177#define BCSR_UCC1_MODE_MSK      (0x3 << 4)
 178#define BCSR_UCC2_MODE_MSK      (0x3 << 0)
 179
 180                /* Turn off UCC1 & UCC2 */
 181                clrbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
 182                clrbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
 183
 184                /* Mode is RGMII, all bits clear */
 185                clrbits8(&bcsr_regs[11], BCSR_UCC1_MODE_MSK |
 186                                         BCSR_UCC2_MODE_MSK);
 187
 188                /* Turn UCC1 & UCC2 on */
 189                setbits8(&bcsr_regs[8], BCSR_UCC1_GETH_EN);
 190                setbits8(&bcsr_regs[9], BCSR_UCC2_GETH_EN);
 191        } else if (machine_is(mpc8569_mds)) {
 192#define BCSR7_UCC12_GETHnRST    (0x1 << 2)
 193#define BCSR8_UEM_MARVELL_RST   (0x1 << 1)
 194#define BCSR_UCC_RGMII          (0x1 << 6)
 195#define BCSR_UCC_RTBI           (0x1 << 5)
 196                /*
 197                 * U-Boot mangles interrupt polarity for Marvell PHYs,
 198                 * so reset built-in and UEM Marvell PHYs, this puts
 199                 * the PHYs into their normal state.
 200                 */
 201                clrbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
 202                setbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
 203
 204                setbits8(&bcsr_regs[7], BCSR7_UCC12_GETHnRST);
 205                clrbits8(&bcsr_regs[8], BCSR8_UEM_MARVELL_RST);
 206
 207                for_each_compatible_node(np, "network", "ucc_geth") {
 208                        const unsigned int *prop;
 209                        int ucc_num;
 210
 211                        prop = of_get_property(np, "cell-index", NULL);
 212                        if (prop == NULL)
 213                                continue;
 214
 215                        ucc_num = *prop - 1;
 216
 217                        prop = of_get_property(np, "phy-connection-type", NULL);
 218                        if (prop == NULL)
 219                                continue;
 220
 221                        if (strcmp("rtbi", (const char *)prop) == 0)
 222                                clrsetbits_8(&bcsr_regs[7 + ucc_num],
 223                                        BCSR_UCC_RGMII, BCSR_UCC_RTBI);
 224                }
 225        } else if (machine_is(p1021_mds)) {
 226#define BCSR11_ENET_MICRST     (0x1 << 5)
 227                /* Reset Micrel PHY */
 228                clrbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
 229                setbits8(&bcsr_regs[11], BCSR11_ENET_MICRST);
 230        }
 231
 232        iounmap(bcsr_regs);
 233}
 234
 235static void __init mpc85xx_mds_qe_init(void)
 236{
 237        struct device_node *np;
 238
 239        mpc85xx_qe_par_io_init();
 240        mpc85xx_mds_reset_ucc_phys();
 241
 242        if (machine_is(p1021_mds)) {
 243
 244                struct ccsr_guts __iomem *guts;
 245
 246                np = of_find_node_by_name(NULL, "global-utilities");
 247                if (np) {
 248                        guts = of_iomap(np, 0);
 249                        if (!guts)
 250                                pr_err("mpc85xx-rdb: could not map global utilities register\n");
 251                        else{
 252                        /* P1021 has pins muxed for QE and other functions. To
 253                         * enable QE UEC mode, we need to set bit QE0 for UCC1
 254                         * in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
 255                         * and QE12 for QE MII management signals in PMUXCR
 256                         * register.
 257                         */
 258                                setbits32(&guts->pmuxcr, MPC85xx_PMUXCR_QE(0) |
 259                                                  MPC85xx_PMUXCR_QE(3) |
 260                                                  MPC85xx_PMUXCR_QE(9) |
 261                                                  MPC85xx_PMUXCR_QE(12));
 262                                iounmap(guts);
 263                        }
 264                        of_node_put(np);
 265                }
 266
 267        }
 268}
 269
 270#else
 271static void __init mpc85xx_mds_qe_init(void) { }
 272#endif  /* CONFIG_QUICC_ENGINE */
 273
 274static void __init mpc85xx_mds_setup_arch(void)
 275{
 276        if (ppc_md.progress)
 277                ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
 278
 279        mpc85xx_smp_init();
 280
 281        mpc85xx_mds_qe_init();
 282
 283        fsl_pci_assign_primary();
 284
 285        swiotlb_detect_4g();
 286}
 287
 288#if IS_BUILTIN(CONFIG_PHYLIB)
 289
 290static int __init board_fixups(void)
 291{
 292        char phy_id[20];
 293        char *compstrs[2] = {"fsl,gianfar-mdio", "fsl,ucc-mdio"};
 294        struct device_node *mdio;
 295        struct resource res;
 296        int i;
 297
 298        for (i = 0; i < ARRAY_SIZE(compstrs); i++) {
 299                mdio = of_find_compatible_node(NULL, NULL, compstrs[i]);
 300
 301                of_address_to_resource(mdio, 0, &res);
 302                snprintf(phy_id, sizeof(phy_id), "%llx:%02x",
 303                        (unsigned long long)res.start, 1);
 304
 305                phy_register_fixup_for_id(phy_id, mpc8568_fixup_125_clock);
 306                phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);
 307
 308                /* Register a workaround for errata */
 309                snprintf(phy_id, sizeof(phy_id), "%llx:%02x",
 310                        (unsigned long long)res.start, 7);
 311                phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);
 312
 313                of_node_put(mdio);
 314        }
 315
 316        return 0;
 317}
 318
 319machine_arch_initcall(mpc8568_mds, board_fixups);
 320machine_arch_initcall(mpc8569_mds, board_fixups);
 321
 322#endif
 323
 324static int __init mpc85xx_publish_devices(void)
 325{
 326        return mpc85xx_common_publish_devices();
 327}
 328
 329machine_arch_initcall(mpc8568_mds, mpc85xx_publish_devices);
 330machine_arch_initcall(mpc8569_mds, mpc85xx_publish_devices);
 331machine_arch_initcall(p1021_mds, mpc85xx_common_publish_devices);
 332
 333static void __init mpc85xx_mds_pic_init(void)
 334{
 335        struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
 336                        MPIC_SINGLE_DEST_CPU,
 337                        0, 256, " OpenPIC  ");
 338        BUG_ON(mpic == NULL);
 339
 340        mpic_init(mpic);
 341}
 342
 343static int __init mpc85xx_mds_probe(void)
 344{
 345        return of_machine_is_compatible("MPC85xxMDS");
 346}
 347
 348define_machine(mpc8568_mds) {
 349        .name           = "MPC8568 MDS",
 350        .probe          = mpc85xx_mds_probe,
 351        .setup_arch     = mpc85xx_mds_setup_arch,
 352        .init_IRQ       = mpc85xx_mds_pic_init,
 353        .get_irq        = mpic_get_irq,
 354        .calibrate_decr = generic_calibrate_decr,
 355        .progress       = udbg_progress,
 356#ifdef CONFIG_PCI
 357        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 358        .pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
 359#endif
 360};
 361
 362static int __init mpc8569_mds_probe(void)
 363{
 364        return of_machine_is_compatible("fsl,MPC8569EMDS");
 365}
 366
 367define_machine(mpc8569_mds) {
 368        .name           = "MPC8569 MDS",
 369        .probe          = mpc8569_mds_probe,
 370        .setup_arch     = mpc85xx_mds_setup_arch,
 371        .init_IRQ       = mpc85xx_mds_pic_init,
 372        .get_irq        = mpic_get_irq,
 373        .calibrate_decr = generic_calibrate_decr,
 374        .progress       = udbg_progress,
 375#ifdef CONFIG_PCI
 376        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 377        .pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
 378#endif
 379};
 380
 381static int __init p1021_mds_probe(void)
 382{
 383        return of_machine_is_compatible("fsl,P1021MDS");
 384
 385}
 386
 387define_machine(p1021_mds) {
 388        .name           = "P1021 MDS",
 389        .probe          = p1021_mds_probe,
 390        .setup_arch     = mpc85xx_mds_setup_arch,
 391        .init_IRQ       = mpc85xx_mds_pic_init,
 392        .get_irq        = mpic_get_irq,
 393        .calibrate_decr = generic_calibrate_decr,
 394        .progress       = udbg_progress,
 395#ifdef CONFIG_PCI
 396        .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
 397        .pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
 398#endif
 399};
 400