linux/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
<<
>>
Prefs
   1/*******************************************************************************
   2  STMMAC Ethernet Driver -- MDIO bus implementation
   3  Provides Bus interface for MII registers
   4
   5  Copyright (C) 2007-2009  STMicroelectronics Ltd
   6
   7  This program is free software; you can redistribute it and/or modify it
   8  under the terms and conditions of the GNU General Public License,
   9  version 2, as published by the Free Software Foundation.
  10
  11  This program is distributed in the hope it will be useful, but WITHOUT
  12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14  more details.
  15
  16  You should have received a copy of the GNU General Public License along with
  17  this program; if not, write to the Free Software Foundation, Inc.,
  18  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  19
  20  The full GNU General Public License is included in this distribution in
  21  the file called "COPYING".
  22
  23  Author: Carl Shaw <carl.shaw@st.com>
  24  Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
  25*******************************************************************************/
  26
  27#include <linux/mii.h>
  28#include <linux/phy.h>
  29#include <linux/slab.h>
  30#include <linux/of.h>
  31#include <linux/of_gpio.h>
  32#include <linux/of_mdio.h>
  33#include <asm/io.h>
  34
  35#include "stmmac.h"
  36
  37#define MII_BUSY 0x00000001
  38#define MII_WRITE 0x00000002
  39
  40static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
  41{
  42        unsigned long curr;
  43        unsigned long finish = jiffies + 3 * HZ;
  44
  45        do {
  46                curr = jiffies;
  47                if (readl(ioaddr + mii_addr) & MII_BUSY)
  48                        cpu_relax();
  49                else
  50                        return 0;
  51        } while (!time_after_eq(curr, finish));
  52
  53        return -EBUSY;
  54}
  55
  56/**
  57 * stmmac_mdio_read
  58 * @bus: points to the mii_bus structure
  59 * @phyaddr: MII addr reg bits 15-11
  60 * @phyreg: MII addr reg bits 10-6
  61 * Description: it reads data from the MII register from within the phy device.
  62 * For the 7111 GMAC, we must set the bit 0 in the MII address register while
  63 * accessing the PHY registers.
  64 * Fortunately, it seems this has no drawback for the 7109 MAC.
  65 */
  66static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
  67{
  68        struct net_device *ndev = bus->priv;
  69        struct stmmac_priv *priv = netdev_priv(ndev);
  70        unsigned int mii_address = priv->hw->mii.addr;
  71        unsigned int mii_data = priv->hw->mii.data;
  72
  73        int data;
  74        u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
  75                        ((phyreg << 6) & (0x000007C0)));
  76        regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
  77
  78        if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
  79                return -EBUSY;
  80
  81        writel(regValue, priv->ioaddr + mii_address);
  82
  83        if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
  84                return -EBUSY;
  85
  86        /* Read the data from the MII data register */
  87        data = (int)readl(priv->ioaddr + mii_data);
  88
  89        return data;
  90}
  91
  92/**
  93 * stmmac_mdio_write
  94 * @bus: points to the mii_bus structure
  95 * @phyaddr: MII addr reg bits 15-11
  96 * @phyreg: MII addr reg bits 10-6
  97 * @phydata: phy data
  98 * Description: it writes the data into the MII register from within the device.
  99 */
 100static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
 101                             u16 phydata)
 102{
 103        struct net_device *ndev = bus->priv;
 104        struct stmmac_priv *priv = netdev_priv(ndev);
 105        unsigned int mii_address = priv->hw->mii.addr;
 106        unsigned int mii_data = priv->hw->mii.data;
 107
 108        u16 value =
 109            (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
 110            | MII_WRITE;
 111
 112        value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
 113
 114        /* Wait until any existing MII operation is complete */
 115        if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
 116                return -EBUSY;
 117
 118        /* Set the MII address register to write */
 119        writel(phydata, priv->ioaddr + mii_data);
 120        writel(value, priv->ioaddr + mii_address);
 121
 122        /* Wait until any existing MII operation is complete */
 123        return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
 124}
 125
 126/**
 127 * stmmac_mdio_reset
 128 * @bus: points to the mii_bus structure
 129 * Description: reset the MII bus
 130 */
 131int stmmac_mdio_reset(struct mii_bus *bus)
 132{
 133#if defined(CONFIG_STMMAC_PLATFORM)
 134        struct net_device *ndev = bus->priv;
 135        struct stmmac_priv *priv = netdev_priv(ndev);
 136        unsigned int mii_address = priv->hw->mii.addr;
 137        struct stmmac_mdio_bus_data *data = priv->plat->mdio_bus_data;
 138
 139#ifdef CONFIG_OF
 140        if (priv->device->of_node) {
 141
 142                if (data->reset_gpio < 0) {
 143                        struct device_node *np = priv->device->of_node;
 144                        if (!np)
 145                                return 0;
 146
 147                        data->reset_gpio = of_get_named_gpio(np,
 148                                                "snps,reset-gpio", 0);
 149                        if (data->reset_gpio < 0)
 150                                return 0;
 151
 152                        data->active_low = of_property_read_bool(np,
 153                                                "snps,reset-active-low");
 154                        of_property_read_u32_array(np,
 155                                "snps,reset-delays-us", data->delays, 3);
 156
 157                        if (gpio_request(data->reset_gpio, "mdio-reset"))
 158                                return 0;
 159                }
 160
 161                gpio_direction_output(data->reset_gpio,
 162                                      data->active_low ? 1 : 0);
 163                if (data->delays[0])
 164                        msleep(DIV_ROUND_UP(data->delays[0], 1000));
 165
 166                gpio_set_value(data->reset_gpio, data->active_low ? 0 : 1);
 167                if (data->delays[1])
 168                        msleep(DIV_ROUND_UP(data->delays[1], 1000));
 169
 170                gpio_set_value(data->reset_gpio, data->active_low ? 1 : 0);
 171                if (data->delays[2])
 172                        msleep(DIV_ROUND_UP(data->delays[2], 1000));
 173        }
 174#endif
 175
 176        if (data->phy_reset) {
 177                pr_debug("stmmac_mdio_reset: calling phy_reset\n");
 178                data->phy_reset(priv->plat->bsp_priv);
 179        }
 180
 181        /* This is a workaround for problems with the STE101P PHY.
 182         * It doesn't complete its reset until at least one clock cycle
 183         * on MDC, so perform a dummy mdio read.
 184         */
 185        writel(0, priv->ioaddr + mii_address);
 186#endif
 187        return 0;
 188}
 189
 190/**
 191 * stmmac_mdio_register
 192 * @ndev: net device structure
 193 * Description: it registers the MII bus
 194 */
 195int stmmac_mdio_register(struct net_device *ndev)
 196{
 197        int err = 0;
 198        struct mii_bus *new_bus;
 199        struct stmmac_priv *priv = netdev_priv(ndev);
 200        struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
 201        struct device_node *mdio_node = priv->plat->mdio_node;
 202        int addr, found;
 203
 204        if (!mdio_bus_data)
 205                return 0;
 206
 207        new_bus = mdiobus_alloc();
 208        if (new_bus == NULL)
 209                return -ENOMEM;
 210
 211        if (mdio_bus_data->irqs)
 212                memcpy(new_bus->irq, mdio_bus_data, sizeof(new_bus->irq));
 213
 214#ifdef CONFIG_OF
 215        if (priv->device->of_node)
 216                mdio_bus_data->reset_gpio = -1;
 217#endif
 218
 219        new_bus->name = "stmmac";
 220        new_bus->read = &stmmac_mdio_read;
 221        new_bus->write = &stmmac_mdio_write;
 222        new_bus->reset = &stmmac_mdio_reset;
 223        snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
 224                 new_bus->name, priv->plat->bus_id);
 225        new_bus->priv = ndev;
 226        new_bus->phy_mask = mdio_bus_data->phy_mask;
 227        new_bus->parent = priv->device;
 228
 229        if (mdio_node)
 230                err = of_mdiobus_register(new_bus, mdio_node);
 231        else
 232                err = mdiobus_register(new_bus);
 233        if (err != 0) {
 234                pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
 235                goto bus_register_fail;
 236        }
 237
 238        if (priv->plat->phy_node || mdio_node)
 239                goto bus_register_done;
 240
 241        found = 0;
 242        for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
 243                struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
 244                if (phydev) {
 245                        int act = 0;
 246                        char irq_num[4];
 247                        char *irq_str;
 248
 249                        /*
 250                         * If an IRQ was provided to be assigned after
 251                         * the bus probe, do it here.
 252                         */
 253                        if ((mdio_bus_data->irqs == NULL) &&
 254                            (mdio_bus_data->probed_phy_irq > 0)) {
 255                                new_bus->irq[addr] =
 256                                        mdio_bus_data->probed_phy_irq;
 257                                phydev->irq = mdio_bus_data->probed_phy_irq;
 258                        }
 259
 260                        /*
 261                         * If we're going to bind the MAC to this PHY bus,
 262                         * and no PHY number was provided to the MAC,
 263                         * use the one probed here.
 264                         */
 265                        if (priv->plat->phy_addr == -1)
 266                                priv->plat->phy_addr = addr;
 267
 268                        act = (priv->plat->phy_addr == addr);
 269                        switch (phydev->irq) {
 270                        case PHY_POLL:
 271                                irq_str = "POLL";
 272                                break;
 273                        case PHY_IGNORE_INTERRUPT:
 274                                irq_str = "IGNORE";
 275                                break;
 276                        default:
 277                                sprintf(irq_num, "%d", phydev->irq);
 278                                irq_str = irq_num;
 279                                break;
 280                        }
 281                        pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
 282                                ndev->name, phydev->phy_id, addr,
 283                                irq_str, phydev_name(phydev),
 284                                act ? " active" : "");
 285                        found = 1;
 286                }
 287        }
 288
 289        if (!found && !mdio_node) {
 290                pr_warn("%s: No PHY found\n", ndev->name);
 291                mdiobus_unregister(new_bus);
 292                mdiobus_free(new_bus);
 293                return -ENODEV;
 294        }
 295
 296bus_register_done:
 297        priv->mii = new_bus;
 298
 299        return 0;
 300
 301bus_register_fail:
 302        mdiobus_free(new_bus);
 303        return err;
 304}
 305
 306/**
 307 * stmmac_mdio_unregister
 308 * @ndev: net device structure
 309 * Description: it unregisters the MII bus
 310 */
 311int stmmac_mdio_unregister(struct net_device *ndev)
 312{
 313        struct stmmac_priv *priv = netdev_priv(ndev);
 314
 315        if (!priv->mii)
 316                return 0;
 317
 318        mdiobus_unregister(priv->mii);
 319        priv->mii->priv = NULL;
 320        mdiobus_free(priv->mii);
 321        priv->mii = NULL;
 322
 323        return 0;
 324}
 325