Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
stmmac_mdio.c
Go to the documentation of this file.
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 <[email protected]>
24  Maintainer: Giuseppe Cavallaro <[email protected]>
25 *******************************************************************************/
26 
27 #include <linux/mii.h>
28 #include <linux/phy.h>
29 #include <linux/slab.h>
30 #include <asm/io.h>
31 
32 #include "stmmac.h"
33 
34 #define MII_BUSY 0x00000001
35 #define MII_WRITE 0x00000002
36 
37 static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
38 {
39  unsigned long curr;
40  unsigned long finish = jiffies + 3 * HZ;
41 
42  do {
43  curr = jiffies;
44  if (readl(ioaddr + mii_addr) & MII_BUSY)
45  cpu_relax();
46  else
47  return 0;
48  } while (!time_after_eq(curr, finish));
49 
50  return -EBUSY;
51 }
52 
63 static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
64 {
65  struct net_device *ndev = bus->priv;
66  struct stmmac_priv *priv = netdev_priv(ndev);
67  unsigned int mii_address = priv->hw->mii.addr;
68  unsigned int mii_data = priv->hw->mii.data;
69 
70  int data;
71  u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
72  ((phyreg << 6) & (0x000007C0)));
73  regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
74 
75  if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
76  return -EBUSY;
77 
78  writel(regValue, priv->ioaddr + mii_address);
79 
80  if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
81  return -EBUSY;
82 
83  /* Read the data from the MII data register */
84  data = (int)readl(priv->ioaddr + mii_data);
85 
86  return data;
87 }
88 
97 static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
98  u16 phydata)
99 {
100  struct net_device *ndev = bus->priv;
101  struct stmmac_priv *priv = netdev_priv(ndev);
102  unsigned int mii_address = priv->hw->mii.addr;
103  unsigned int mii_data = priv->hw->mii.data;
104 
105  u16 value =
106  (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
107  | MII_WRITE;
108 
109  value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
110 
111  /* Wait until any existing MII operation is complete */
112  if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
113  return -EBUSY;
114 
115  /* Set the MII address register to write */
116  writel(phydata, priv->ioaddr + mii_data);
117  writel(value, priv->ioaddr + mii_address);
118 
119  /* Wait until any existing MII operation is complete */
120  return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
121 }
122 
128 static int stmmac_mdio_reset(struct mii_bus *bus)
129 {
130 #if defined(CONFIG_STMMAC_PLATFORM)
131  struct net_device *ndev = bus->priv;
132  struct stmmac_priv *priv = netdev_priv(ndev);
133  unsigned int mii_address = priv->hw->mii.addr;
134 
135  if (priv->plat->mdio_bus_data->phy_reset) {
136  pr_debug("stmmac_mdio_reset: calling phy_reset\n");
137  priv->plat->mdio_bus_data->phy_reset(priv->plat->bsp_priv);
138  }
139 
140  /* This is a workaround for problems with the STE101P PHY.
141  * It doesn't complete its reset until at least one clock cycle
142  * on MDC, so perform a dummy mdio read.
143  */
144  writel(0, priv->ioaddr + mii_address);
145 #endif
146  return 0;
147 }
148 
155 {
156  int err = 0;
157  struct mii_bus *new_bus;
158  int *irqlist;
159  struct stmmac_priv *priv = netdev_priv(ndev);
160  struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
161  int addr, found;
162 
163  if (!mdio_bus_data)
164  return 0;
165 
166  new_bus = mdiobus_alloc();
167  if (new_bus == NULL)
168  return -ENOMEM;
169 
170  if (mdio_bus_data->irqs)
171  irqlist = mdio_bus_data->irqs;
172  else
173  irqlist = priv->mii_irq;
174 
175  new_bus->name = "stmmac";
176  new_bus->read = &stmmac_mdio_read;
177  new_bus->write = &stmmac_mdio_write;
178  new_bus->reset = &stmmac_mdio_reset;
179  snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
180  new_bus->name, priv->plat->bus_id);
181  new_bus->priv = ndev;
182  new_bus->irq = irqlist;
183  new_bus->phy_mask = mdio_bus_data->phy_mask;
184  new_bus->parent = priv->device;
185  err = mdiobus_register(new_bus);
186  if (err != 0) {
187  pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
188  goto bus_register_fail;
189  }
190 
191  priv->mii = new_bus;
192 
193  found = 0;
194  for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
195  struct phy_device *phydev = new_bus->phy_map[addr];
196  if (phydev) {
197  int act = 0;
198  char irq_num[4];
199  char *irq_str;
200 
201  /*
202  * If an IRQ was provided to be assigned after
203  * the bus probe, do it here.
204  */
205  if ((mdio_bus_data->irqs == NULL) &&
206  (mdio_bus_data->probed_phy_irq > 0)) {
207  irqlist[addr] = mdio_bus_data->probed_phy_irq;
208  phydev->irq = mdio_bus_data->probed_phy_irq;
209  }
210 
211  /*
212  * If we're going to bind the MAC to this PHY bus,
213  * and no PHY number was provided to the MAC,
214  * use the one probed here.
215  */
216  if (priv->plat->phy_addr == -1)
217  priv->plat->phy_addr = addr;
218 
219  act = (priv->plat->phy_addr == addr);
220  switch (phydev->irq) {
221  case PHY_POLL:
222  irq_str = "POLL";
223  break;
225  irq_str = "IGNORE";
226  break;
227  default:
228  sprintf(irq_num, "%d", phydev->irq);
229  irq_str = irq_num;
230  break;
231  }
232  pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
233  ndev->name, phydev->phy_id, addr,
234  irq_str, dev_name(&phydev->dev),
235  act ? " active" : "");
236  found = 1;
237  }
238  }
239 
240  if (!found)
241  pr_warning("%s: No PHY found\n", ndev->name);
242 
243  return 0;
244 
245 bus_register_fail:
246  mdiobus_free(new_bus);
247  return err;
248 }
249 
256 {
257  struct stmmac_priv *priv = netdev_priv(ndev);
258 
259  if (!priv->mii)
260  return 0;
261 
262  mdiobus_unregister(priv->mii);
263  priv->mii->priv = NULL;
264  mdiobus_free(priv->mii);
265  priv->mii = NULL;
266 
267  return 0;
268 }