blob: 72ec711fcba242775feea3064bdcb69de6c1812e [file] [log] [blame]
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -07001/*******************************************************************************
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
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070016 The full GNU General Public License is included in this distribution in
17 the file called "COPYING".
18
19 Author: Carl Shaw <carl.shaw@st.com>
20 Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
21*******************************************************************************/
22
LABBE Corentinbbf89282017-02-08 09:31:10 +010023#include <linux/io.h>
LABBE Corentina5f48ad2017-02-08 09:31:12 +010024#include <linux/iopoll.h>
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070025#include <linux/mii.h>
Srinivas Kandagatla0e076472013-07-04 10:35:48 +010026#include <linux/of.h>
27#include <linux/of_gpio.h>
Phil Reide34d6562015-12-14 11:31:59 +080028#include <linux/of_mdio.h>
LABBE Corentinbbf89282017-02-08 09:31:10 +010029#include <linux/phy.h>
30#include <linux/slab.h>
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070031
32#include "stmmac.h"
33
34#define MII_BUSY 0x00000001
35#define MII_WRITE 0x00000002
36
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +020037/* GMAC4 defines */
38#define MII_GMAC4_GOC_SHIFT 2
39#define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)
40#define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT)
41
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070042/**
43 * stmmac_mdio_read
44 * @bus: points to the mii_bus structure
LABBE Corentinb91dce42016-12-01 16:19:41 +010045 * @phyaddr: MII addr
46 * @phyreg: MII reg
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070047 * Description: it reads data from the MII register from within the phy device.
48 * For the 7111 GMAC, we must set the bit 0 in the MII address register while
49 * accessing the PHY registers.
50 * Fortunately, it seems this has no drawback for the 7109 MAC.
51 */
52static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
53{
54 struct net_device *ndev = bus->priv;
55 struct stmmac_priv *priv = netdev_priv(ndev);
Giuseppe CAVALLAROdb98a0b2010-01-06 23:07:17 +000056 unsigned int mii_address = priv->hw->mii.addr;
57 unsigned int mii_data = priv->hw->mii.data;
LABBE Corentina5f48ad2017-02-08 09:31:12 +010058 u32 v;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070059 int data;
LABBE Corentinb91dce42016-12-01 16:19:41 +010060 u32 value = MII_BUSY;
61
62 value |= (phyaddr << priv->hw->mii.addr_shift)
63 & priv->hw->mii.addr_mask;
64 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
jpinto567be782016-12-23 10:15:59 +000065 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
66 & priv->hw->mii.clk_csr_mask;
LABBE Corentinb91dce42016-12-01 16:19:41 +010067 if (priv->plat->has_gmac4)
68 value |= MII_GMAC4_READ;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070069
LABBE Corentina5f48ad2017-02-08 09:31:12 +010070 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
71 100, 10000))
Deepak SIKRI39b401d2012-04-04 04:33:24 +000072 return -EBUSY;
73
LABBE Corentin01f1f612016-12-01 16:19:40 +010074 writel(value, priv->ioaddr + mii_address);
Deepak SIKRI39b401d2012-04-04 04:33:24 +000075
LABBE Corentina5f48ad2017-02-08 09:31:12 +010076 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
77 100, 10000))
Deepak SIKRI39b401d2012-04-04 04:33:24 +000078 return -EBUSY;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070079
80 /* Read the data from the MII data register */
Giuseppe CAVALLAROad01b7d2010-08-23 20:40:42 +000081 data = (int)readl(priv->ioaddr + mii_data);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070082
83 return data;
84}
85
86/**
87 * stmmac_mdio_write
88 * @bus: points to the mii_bus structure
LABBE Corentinb91dce42016-12-01 16:19:41 +010089 * @phyaddr: MII addr
90 * @phyreg: MII reg
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -070091 * @phydata: phy data
92 * Description: it writes the data into the MII register from within the device.
93 */
94static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
95 u16 phydata)
96{
97 struct net_device *ndev = bus->priv;
98 struct stmmac_priv *priv = netdev_priv(ndev);
Giuseppe CAVALLAROdb98a0b2010-01-06 23:07:17 +000099 unsigned int mii_address = priv->hw->mii.addr;
100 unsigned int mii_data = priv->hw->mii.data;
LABBE Corentina5f48ad2017-02-08 09:31:12 +0100101 u32 v;
Kweh, Hock Leong5799fc92016-12-28 04:07:41 +0800102 u32 value = MII_BUSY;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700103
LABBE Corentinb91dce42016-12-01 16:19:41 +0100104 value |= (phyaddr << priv->hw->mii.addr_shift)
105 & priv->hw->mii.addr_mask;
106 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
Giuseppe CAVALLAROdfb8fb92010-09-17 03:23:39 +0000107
jpinto567be782016-12-23 10:15:59 +0000108 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
109 & priv->hw->mii.clk_csr_mask;
LABBE Corentinb91dce42016-12-01 16:19:41 +0100110 if (priv->plat->has_gmac4)
111 value |= MII_GMAC4_WRITE;
Kweh, Hock Leong5799fc92016-12-28 04:07:41 +0800112 else
113 value |= MII_WRITE;
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +0200114
115 /* Wait until any existing MII operation is complete */
LABBE Corentina5f48ad2017-02-08 09:31:12 +0100116 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
117 100, 10000))
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +0200118 return -EBUSY;
119
120 /* Set the MII address register to write */
121 writel(phydata, priv->ioaddr + mii_data);
122 writel(value, priv->ioaddr + mii_address);
123
124 /* Wait until any existing MII operation is complete */
LABBE Corentina5f48ad2017-02-08 09:31:12 +0100125 return readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
126 100, 10000);
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +0200127}
128
129/**
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700130 * stmmac_mdio_reset
131 * @bus: points to the mii_bus structure
132 * Description: reset the MII bus
133 */
Srinivas Kandagatla073752a2014-01-16 10:52:27 +0000134int stmmac_mdio_reset(struct mii_bus *bus)
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700135{
Giuseppe CAVALLARObfab27a2011-12-21 03:58:19 +0000136#if defined(CONFIG_STMMAC_PLATFORM)
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700137 struct net_device *ndev = bus->priv;
138 struct stmmac_priv *priv = netdev_priv(ndev);
Giuseppe CAVALLAROdb98a0b2010-01-06 23:07:17 +0000139 unsigned int mii_address = priv->hw->mii.addr;
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100140 struct stmmac_mdio_bus_data *data = priv->plat->mdio_bus_data;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700141
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100142#ifdef CONFIG_OF
143 if (priv->device->of_node) {
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100144 if (data->reset_gpio < 0) {
145 struct device_node *np = priv->device->of_node;
LABBE Corentinefd89b62017-02-08 09:31:11 +0100146
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100147 if (!np)
148 return 0;
149
150 data->reset_gpio = of_get_named_gpio(np,
151 "snps,reset-gpio", 0);
152 if (data->reset_gpio < 0)
153 return 0;
154
155 data->active_low = of_property_read_bool(np,
156 "snps,reset-active-low");
157 of_property_read_u32_array(np,
158 "snps,reset-delays-us", data->delays, 3);
Giuseppe CAVALLAROae26c1c2015-11-26 08:35:44 +0100159
160 if (gpio_request(data->reset_gpio, "mdio-reset"))
161 return 0;
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100162 }
163
Giuseppe CAVALLAROae26c1c2015-11-26 08:35:44 +0100164 gpio_direction_output(data->reset_gpio,
165 data->active_low ? 1 : 0);
166 if (data->delays[0])
167 msleep(DIV_ROUND_UP(data->delays[0], 1000));
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100168
Giuseppe CAVALLAROae26c1c2015-11-26 08:35:44 +0100169 gpio_set_value(data->reset_gpio, data->active_low ? 0 : 1);
170 if (data->delays[1])
171 msleep(DIV_ROUND_UP(data->delays[1], 1000));
Sjoerd Simons892aa012015-09-11 22:25:48 +0200172
Giuseppe CAVALLAROae26c1c2015-11-26 08:35:44 +0100173 gpio_set_value(data->reset_gpio, data->active_low ? 1 : 0);
174 if (data->delays[2])
175 msleep(DIV_ROUND_UP(data->delays[2], 1000));
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100176 }
177#endif
178
179 if (data->phy_reset) {
LABBE Corentin38ddc592016-11-16 20:09:39 +0100180 netdev_dbg(ndev, "stmmac_mdio_reset: calling phy_reset\n");
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100181 data->phy_reset(priv->plat->bsp_priv);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700182 }
183
184 /* This is a workaround for problems with the STE101P PHY.
185 * It doesn't complete its reset until at least one clock cycle
LABBE Corentin8d45e422017-02-08 09:31:08 +0100186 * on MDC, so perform a dummy mdio read. To be updated for GMAC4
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +0200187 * if needed.
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700188 */
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +0200189 if (!priv->plat->has_gmac4)
190 writel(0, priv->ioaddr + mii_address);
Giuseppe CAVALLARObfab27a2011-12-21 03:58:19 +0000191#endif
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700192 return 0;
193}
194
195/**
196 * stmmac_mdio_register
197 * @ndev: net device structure
198 * Description: it registers the MII bus
199 */
200int stmmac_mdio_register(struct net_device *ndev)
201{
202 int err = 0;
203 struct mii_bus *new_bus;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700204 struct stmmac_priv *priv = netdev_priv(ndev);
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000205 struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
Giuseppe CAVALLAROa7657f12016-04-01 09:07:16 +0200206 struct device_node *mdio_node = priv->plat->mdio_node;
Romain Perierfbca1642017-08-10 16:56:05 +0200207 struct device *dev = ndev->dev.parent;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700208 int addr, found;
209
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000210 if (!mdio_bus_data)
211 return 0;
212
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700213 new_bus = mdiobus_alloc();
LABBE Corentinefd89b62017-02-08 09:31:11 +0100214 if (!new_bus)
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700215 return -ENOMEM;
216
Andrew Lunne7f4dc32016-01-06 20:11:15 +0100217 if (mdio_bus_data->irqs)
Marek Vasut643d60b2016-05-26 00:40:23 +0200218 memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700219
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100220#ifdef CONFIG_OF
221 if (priv->device->of_node)
222 mdio_bus_data->reset_gpio = -1;
223#endif
224
Alessandro Rubini90b9a5452012-01-23 23:26:48 +0000225 new_bus->name = "stmmac";
LABBE Corentinb91dce42016-12-01 16:19:41 +0100226 new_bus->read = &stmmac_mdio_read;
227 new_bus->write = &stmmac_mdio_write;
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +0200228
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700229 new_bus->reset = &stmmac_mdio_reset;
Florian Fainellidb8857b2012-01-09 23:59:20 +0000230 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000231 new_bus->name, priv->plat->bus_id);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700232 new_bus->priv = ndev;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000233 new_bus->phy_mask = mdio_bus_data->phy_mask;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700234 new_bus->parent = priv->device;
Phil Reide34d6562015-12-14 11:31:59 +0800235
Romain Perier6c672c92016-01-07 21:13:28 +0100236 if (mdio_node)
237 err = of_mdiobus_register(new_bus, mdio_node);
238 else
239 err = mdiobus_register(new_bus);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700240 if (err != 0) {
Romain Perierfbca1642017-08-10 16:56:05 +0200241 dev_err(dev, "Cannot register the MDIO bus\n");
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700242 goto bus_register_fail;
243 }
244
Phil Reidcc2fa612016-03-15 15:34:33 +0800245 if (priv->plat->phy_node || mdio_node)
246 goto bus_register_done;
247
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700248 found = 0;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000249 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
Andrew Lunn7f854422016-01-06 20:11:18 +0100250 struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
LABBE Corentincc26dc62017-02-15 10:46:44 +0100251 int act = 0;
252 char irq_num[4];
253 char *irq_str;
LABBE Corentinefd89b62017-02-08 09:31:11 +0100254
LABBE Corentincc26dc62017-02-15 10:46:44 +0100255 if (!phydev)
256 continue;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000257
LABBE Corentincc26dc62017-02-15 10:46:44 +0100258 /*
259 * If an IRQ was provided to be assigned after
260 * the bus probe, do it here.
261 */
262 if (!mdio_bus_data->irqs &&
263 (mdio_bus_data->probed_phy_irq > 0)) {
264 new_bus->irq[addr] = mdio_bus_data->probed_phy_irq;
265 phydev->irq = mdio_bus_data->probed_phy_irq;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700266 }
LABBE Corentincc26dc62017-02-15 10:46:44 +0100267
268 /*
269 * If we're going to bind the MAC to this PHY bus,
270 * and no PHY number was provided to the MAC,
271 * use the one probed here.
272 */
273 if (priv->plat->phy_addr == -1)
274 priv->plat->phy_addr = addr;
275
276 act = (priv->plat->phy_addr == addr);
277 switch (phydev->irq) {
278 case PHY_POLL:
279 irq_str = "POLL";
280 break;
281 case PHY_IGNORE_INTERRUPT:
282 irq_str = "IGNORE";
283 break;
284 default:
285 sprintf(irq_num, "%d", phydev->irq);
286 irq_str = irq_num;
287 break;
288 }
Romain Perierfbca1642017-08-10 16:56:05 +0200289 phy_attached_info(phydev);
LABBE Corentincc26dc62017-02-15 10:46:44 +0100290 found = 1;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700291 }
292
Phil Reide34d6562015-12-14 11:31:59 +0800293 if (!found && !mdio_node) {
Romain Perierfbca1642017-08-10 16:56:05 +0200294 dev_warn(dev, "No PHY found\n");
Giuseppe CAVALLARO3955b22b2013-02-06 20:47:52 +0000295 mdiobus_unregister(new_bus);
296 mdiobus_free(new_bus);
297 return -ENODEV;
298 }
299
Phil Reidcc2fa612016-03-15 15:34:33 +0800300bus_register_done:
Giuseppe CAVALLARO3955b22b2013-02-06 20:47:52 +0000301 priv->mii = new_bus;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700302
303 return 0;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000304
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700305bus_register_fail:
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000306 mdiobus_free(new_bus);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700307 return err;
308}
309
310/**
311 * stmmac_mdio_unregister
312 * @ndev: net device structure
313 * Description: it unregisters the MII bus
314 */
315int stmmac_mdio_unregister(struct net_device *ndev)
316{
317 struct stmmac_priv *priv = netdev_priv(ndev);
318
Srinivas Kandagatlaa5cf5ce2012-08-30 05:49:58 +0000319 if (!priv->mii)
320 return 0;
321
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700322 mdiobus_unregister(priv->mii);
323 priv->mii->priv = NULL;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000324 mdiobus_free(priv->mii);
325 priv->mii = NULL;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700326
327 return 0;
328}