uboot/drivers/net/pfe_eth/pfe_mdio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2015-2016 Freescale Semiconductor, Inc.
   4 * Copyright 2017 NXP
   5 */
   6#include <common.h>
   7#include <dm.h>
   8#include <dm/platform_data/pfe_dm_eth.h>
   9#include <net.h>
  10#include <net/pfe_eth/pfe_eth.h>
  11
  12extern struct gemac_s gem_info[];
  13#if defined(CONFIG_PHYLIB)
  14
  15#define MDIO_TIMEOUT    5000
  16static int pfe_write_addr(struct mii_dev *bus, int phy_addr, int dev_addr,
  17                          int reg_addr)
  18{
  19        void *reg_base = bus->priv;
  20        u32 devadr;
  21        u32 phy;
  22        u32 reg_data;
  23        int timeout = MDIO_TIMEOUT;
  24
  25        devadr = ((dev_addr & EMAC_MII_DATA_RA_MASK) << EMAC_MII_DATA_RA_SHIFT);
  26        phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
  27
  28        reg_data = (EMAC_MII_DATA_TA | phy | devadr | reg_addr);
  29
  30        writel(reg_data, reg_base + EMAC_MII_DATA_REG);
  31
  32        /*
  33         * wait for the MII interrupt
  34         */
  35        while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
  36                if (timeout-- <= 0) {
  37                        printf("Phy MDIO read/write timeout\n");
  38                        return -1;
  39                }
  40        }
  41
  42        /*
  43         * clear MII interrupt
  44         */
  45        writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
  46
  47        return 0;
  48}
  49
  50static int pfe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
  51                        int reg_addr)
  52{
  53        void *reg_base = bus->priv;
  54        u32 reg;
  55        u32 phy;
  56        u32 reg_data;
  57        u16 val;
  58        int timeout = MDIO_TIMEOUT;
  59
  60        if (dev_addr == MDIO_DEVAD_NONE) {
  61                reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
  62                        EMAC_MII_DATA_RA_SHIFT);
  63        } else {
  64                pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
  65                reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
  66                       EMAC_MII_DATA_RA_SHIFT);
  67        }
  68
  69        phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
  70
  71        if (dev_addr == MDIO_DEVAD_NONE)
  72                reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD |
  73                            EMAC_MII_DATA_TA | phy | reg);
  74        else
  75                reg_data = (EMAC_MII_DATA_OP_CL45_RD | EMAC_MII_DATA_TA |
  76                            phy | reg);
  77
  78        writel(reg_data, reg_base + EMAC_MII_DATA_REG);
  79
  80        /*
  81         * wait for the MII interrupt
  82         */
  83        while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
  84                if (timeout-- <= 0) {
  85                        printf("Phy MDIO read/write timeout\n");
  86                        return -1;
  87                }
  88        }
  89
  90        /*
  91         * clear MII interrupt
  92         */
  93        writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
  94
  95        /*
  96         * it's now safe to read the PHY's register
  97         */
  98        val = (u16)readl(reg_base + EMAC_MII_DATA_REG);
  99        debug("%s: %p phy: 0x%x reg:0x%08x val:%#x\n", __func__, reg_base,
 100              phy_addr, reg_addr, val);
 101
 102        return val;
 103}
 104
 105static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
 106                         int reg_addr, u16 data)
 107{
 108        void *reg_base = bus->priv;
 109        u32 reg;
 110        u32 phy;
 111        u32 reg_data;
 112        int timeout = MDIO_TIMEOUT;
 113
 114        if (dev_addr == MDIO_DEVAD_NONE) {
 115                reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
 116                       EMAC_MII_DATA_RA_SHIFT);
 117        } else {
 118                pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
 119                reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
 120                       EMAC_MII_DATA_RA_SHIFT);
 121        }
 122
 123        phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
 124
 125        if (dev_addr == MDIO_DEVAD_NONE)
 126                reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR |
 127                            EMAC_MII_DATA_TA | phy | reg | data);
 128        else
 129                reg_data = (EMAC_MII_DATA_OP_CL45_WR | EMAC_MII_DATA_TA |
 130                            phy | reg | data);
 131
 132        writel(reg_data, reg_base + EMAC_MII_DATA_REG);
 133
 134        /*
 135         * wait for the MII interrupt
 136         */
 137        while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
 138                if (timeout-- <= 0) {
 139                        printf("Phy MDIO read/write timeout\n");
 140                        return -1;
 141                }
 142        }
 143
 144        /*
 145         * clear MII interrupt
 146         */
 147        writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
 148
 149        debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr,
 150              reg_addr, data);
 151
 152        return 0;
 153}
 154
 155static void pfe_configure_serdes(struct pfe_eth_dev *priv)
 156{
 157        struct mii_dev bus;
 158        int value, sgmii_2500 = 0;
 159        struct gemac_s *gem = priv->gem;
 160
 161        if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500)
 162                sgmii_2500 = 1;
 163
 164
 165        /* PCS configuration done with corresponding GEMAC */
 166        bus.priv = gem_info[priv->gemac_port].gemac_base;
 167
 168        pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x0);
 169        pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x1);
 170        pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x2);
 171        pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x3);
 172
 173        /* Reset serdes */
 174        pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x0, 0x8000);
 175
 176        /* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
 177        value = PHY_SGMII_IF_MODE_SGMII;
 178        if (!sgmii_2500)
 179                value |= PHY_SGMII_IF_MODE_AN;
 180        else
 181                value |= PHY_SGMII_IF_MODE_SGMII_GBT;
 182
 183        pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
 184
 185        /* Dev ability according to SGMII specification */
 186        value = PHY_SGMII_DEV_ABILITY_SGMII;
 187        pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
 188
 189        /* These values taken from validation team */
 190        if (!sgmii_2500) {
 191                pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x0);
 192                pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0x400);
 193        } else {
 194                pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x7);
 195                pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xa120);
 196        }
 197
 198        /* Restart AN */
 199        value = PHY_SGMII_CR_DEF_VAL;
 200        if (!sgmii_2500)
 201                value |= PHY_SGMII_CR_RESET_AN;
 202        /* Disable Auto neg for 2.5G SGMII as it doesn't support auto neg*/
 203        if (sgmii_2500)
 204                value &= ~PHY_SGMII_ENABLE_AN;
 205        pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
 206}
 207
 208int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id)
 209{
 210        struct phy_device *phydev = NULL;
 211        struct udevice *dev = priv->dev;
 212        struct gemac_s *gem = priv->gem;
 213        struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
 214
 215        if (!gem->bus)
 216                return -1;
 217
 218        /* Configure SGMII  PCS */
 219        if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII ||
 220            gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500) {
 221                out_be32(&scfg->mdioselcr, 0x00000000);
 222                pfe_configure_serdes(priv);
 223        }
 224
 225        mdelay(100);
 226
 227        /* By this time on-chip SGMII initialization is done
 228         * we can switch mdio interface to external PHYs
 229         */
 230        out_be32(&scfg->mdioselcr, 0x80000000);
 231
 232        phydev = phy_connect(gem->bus, phy_id, dev, gem->phy_mode);
 233        if (!phydev) {
 234                printf("phy_connect failed\n");
 235                return -ENODEV;
 236        }
 237
 238        phy_config(phydev);
 239
 240        priv->phydev = phydev;
 241
 242        return 0;
 243}
 244#endif
 245
 246struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info)
 247{
 248        struct mii_dev *bus;
 249        int ret;
 250        u32 mdio_speed;
 251        u32 pclk = 250000000;
 252
 253        bus = mdio_alloc();
 254        if (!bus) {
 255                printf("mdio_alloc failed\n");
 256                return NULL;
 257        }
 258        bus->read = pfe_phy_read;
 259        bus->write = pfe_phy_write;
 260
 261        /* MAC1 MDIO used to communicate with external PHYS */
 262        bus->priv = mdio_info->reg_base;
 263        sprintf(bus->name, mdio_info->name);
 264
 265        /* configure mdio speed */
 266        mdio_speed = (DIV_ROUND_UP(pclk, 4000000) << EMAC_MII_SPEED_SHIFT);
 267        mdio_speed |= EMAC_HOLDTIME(0x5);
 268        writel(mdio_speed, mdio_info->reg_base + EMAC_MII_CTRL_REG);
 269
 270        ret = mdio_register(bus);
 271        if (ret) {
 272                printf("mdio_register failed\n");
 273                free(bus);
 274                return NULL;
 275        }
 276        return bus;
 277}
 278
 279void pfe_set_mdio(int dev_id, struct mii_dev *bus)
 280{
 281        gem_info[dev_id].bus = bus;
 282}
 283
 284void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode)
 285{
 286        gem_info[dev_id].phy_address = phy_id;
 287        gem_info[dev_id].phy_mode  = phy_mode;
 288}
 289