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
  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                int reset_gpio, active_low;
 142
 143                if (data->reset_gpio < 0) {
 144                        struct device_node *np = priv->device->of_node;
 145                        if (!np)
 146                                return 0;
 147
 148                        data->reset_gpio = of_get_named_gpio(np,
 149                                                "snps,reset-gpio", 0);
 150                        if (data->reset_gpio < 0)
 151                                return 0;
 152
 153                        data->active_low = of_property_read_bool(np,
 154                                                "snps,reset-active-low");
 155                        of_property_read_u32_array(np,
 156                                "snps,reset-delays-us", data->delays, 3);
 157                }
 158
 159                reset_gpio = data->reset_gpio;
 160                active_low = data->active_low;
 161
 162                if (!gpio_request(reset_gpio, "mdio-reset")) {
 163                        gpio_direction_output(reset_gpio, active_low ? 1 : 0);
 164                        udelay(data->delays[0]);
 165                        gpio_set_value(reset_gpio, active_low ? 0 : 1);
 166                        udelay(data->delays[1]);
 167                        gpio_set_value(reset_gpio, active_low ? 1 : 0);
 168                        udelay(data->delays[2]);
 169                }
 170        }
 171#endif
 172
 173        if (data->phy_reset) {
 174                pr_debug("stmmac_mdio_reset: calling phy_reset\n");
 175                data->phy_reset(priv->plat->bsp_priv);
 176        }
 177
 178        /* This is a workaround for problems with the STE101P PHY.
 179         * It doesn't complete its reset until at least one clock cycle
 180         * on MDC, so perform a dummy mdio read.
 181         */
 182        writel(0, priv->ioaddr + mii_address);
 183#endif
 184        return 0;
 185}
 186
 187/**
 188 * stmmac_mdio_register
 189 * @ndev: net device structure
 190 * Description: it registers the MII bus
 191 */
 192int stmmac_mdio_register(struct net_device *ndev)
 193{
 194        int err = 0;
 195        struct mii_bus *new_bus;
 196        int *irqlist;
 197        struct stmmac_priv *priv = netdev_priv(ndev);
 198        struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
 199        int addr, found;
 200
 201        if (!mdio_bus_data)
 202                return 0;
 203
 204        new_bus = mdiobus_alloc();
 205        if (new_bus == NULL)
 206                return -ENOMEM;
 207
 208        if (mdio_bus_data->irqs) {
 209                irqlist = mdio_bus_data->irqs;
 210        } else {
 211                for (addr = 0; addr < PHY_MAX_ADDR; addr++)
 212                        priv->mii_irq[addr] = PHY_POLL;
 213                irqlist = priv->mii_irq;
 214        }
 215
 216#ifdef CONFIG_OF
 217        if (priv->device->of_node)
 218                mdio_bus_data->reset_gpio = -1;
 219#endif
 220
 221        new_bus->name = "stmmac";
 222        new_bus->read = &stmmac_mdio_read;
 223        new_bus->write = &stmmac_mdio_write;
 224        new_bus->reset = &stmmac_mdio_reset;
 225        snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
 226                 new_bus->name, priv->plat->bus_id);
 227        new_bus->priv = ndev;
 228        new_bus->irq = irqlist;
 229        new_bus->phy_mask = mdio_bus_data->phy_mask;
 230        new_bus->parent = priv->device;
 231        err = mdiobus_register(new_bus);
 232        if (err != 0) {
 233                pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
 234                goto bus_register_fail;
 235        }
 236
 237        found = 0;
 238        for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
 239                struct phy_device *phydev = new_bus->phy_map[addr];
 240                if (phydev) {
 241                        int act = 0;
 242                        char irq_num[4];
 243                        char *irq_str;
 244
 245                        /*
 246                         * If an IRQ was provided to be assigned after
 247                         * the bus probe, do it here.
 248                         */
 249                        if ((mdio_bus_data->irqs == NULL) &&
 250                            (mdio_bus_data->probed_phy_irq > 0)) {
 251                                irqlist[addr] = mdio_bus_data->probed_phy_irq;
 252                                phydev->irq = mdio_bus_data->probed_phy_irq;
 253                        }
 254
 255                        /*
 256                         * If we're going to bind the MAC to this PHY bus,
 257                         * and no PHY number was provided to the MAC,
 258                         * use the one probed here.
 259                         */
 260                        if (priv->plat->phy_addr == -1)
 261                                priv->plat->phy_addr = addr;
 262
 263                        act = (priv->plat->phy_addr == addr);
 264                        switch (phydev->irq) {
 265                        case PHY_POLL:
 266                                irq_str = "POLL";
 267                                break;
 268                        case PHY_IGNORE_INTERRUPT:
 269                                irq_str = "IGNORE";
 270                                break;
 271                        default:
 272                                sprintf(irq_num, "%d", phydev->irq);
 273                                irq_str = irq_num;
 274                                break;
 275                        }
 276                        pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
 277                                ndev->name, phydev->phy_id, addr,
 278                                irq_str, dev_name(&phydev->dev),
 279                                act ? " active" : "");
 280                        found = 1;
 281                }
 282        }
 283
 284        if (!found) {
 285                pr_warn("%s: No PHY found\n", ndev->name);
 286                mdiobus_unregister(new_bus);
 287                mdiobus_free(new_bus);
 288                return -ENODEV;
 289        }
 290
 291        priv->mii = new_bus;
 292
 293        return 0;
 294
 295bus_register_fail:
 296        mdiobus_free(new_bus);
 297        return err;
 298}
 299
 300/**
 301 * stmmac_mdio_unregister
 302 * @ndev: net device structure
 303 * Description: it unregisters the MII bus
 304 */
 305int stmmac_mdio_unregister(struct net_device *ndev)
 306{
 307        struct stmmac_priv *priv = netdev_priv(ndev);
 308
 309        if (!priv->mii)
 310                return 0;
 311
 312        mdiobus_unregister(priv->mii);
 313        priv->mii->priv = NULL;
 314        mdiobus_free(priv->mii);
 315        priv->mii = NULL;
 316
 317        return 0;
 318}
 319