blob: db157a47000c65fb588d3f1c5dfe21bbd20983fb [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;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700207 int addr, found;
208
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000209 if (!mdio_bus_data)
210 return 0;
211
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700212 new_bus = mdiobus_alloc();
LABBE Corentinefd89b62017-02-08 09:31:11 +0100213 if (!new_bus)
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700214 return -ENOMEM;
215
Andrew Lunne7f4dc32016-01-06 20:11:15 +0100216 if (mdio_bus_data->irqs)
Marek Vasut643d60b2016-05-26 00:40:23 +0200217 memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700218
Srinivas Kandagatla0e076472013-07-04 10:35:48 +0100219#ifdef CONFIG_OF
220 if (priv->device->of_node)
221 mdio_bus_data->reset_gpio = -1;
222#endif
223
Alessandro Rubini90b9a5452012-01-23 23:26:48 +0000224 new_bus->name = "stmmac";
LABBE Corentinb91dce42016-12-01 16:19:41 +0100225 new_bus->read = &stmmac_mdio_read;
226 new_bus->write = &stmmac_mdio_write;
Alexandre TORGUEac1f74a2016-04-28 15:56:45 +0200227
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700228 new_bus->reset = &stmmac_mdio_reset;
Florian Fainellidb8857b2012-01-09 23:59:20 +0000229 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
Giuseppe CAVALLAROceb694992013-04-08 02:10:01 +0000230 new_bus->name, priv->plat->bus_id);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700231 new_bus->priv = ndev;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000232 new_bus->phy_mask = mdio_bus_data->phy_mask;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700233 new_bus->parent = priv->device;
Phil Reide34d6562015-12-14 11:31:59 +0800234
Romain Perier6c672c92016-01-07 21:13:28 +0100235 if (mdio_node)
236 err = of_mdiobus_register(new_bus, mdio_node);
237 else
238 err = mdiobus_register(new_bus);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700239 if (err != 0) {
LABBE Corentin38ddc592016-11-16 20:09:39 +0100240 netdev_err(ndev, "Cannot register the MDIO bus\n");
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700241 goto bus_register_fail;
242 }
243
Phil Reidcc2fa612016-03-15 15:34:33 +0800244 if (priv->plat->phy_node || mdio_node)
245 goto bus_register_done;
246
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700247 found = 0;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000248 for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
Andrew Lunn7f854422016-01-06 20:11:18 +0100249 struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
LABBE Corentincc26dc62017-02-15 10:46:44 +0100250 int act = 0;
251 char irq_num[4];
252 char *irq_str;
LABBE Corentinefd89b62017-02-08 09:31:11 +0100253
LABBE Corentincc26dc62017-02-15 10:46:44 +0100254 if (!phydev)
255 continue;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000256
LABBE Corentincc26dc62017-02-15 10:46:44 +0100257 /*
258 * If an IRQ was provided to be assigned after
259 * the bus probe, do it here.
260 */
261 if (!mdio_bus_data->irqs &&
262 (mdio_bus_data->probed_phy_irq > 0)) {
263 new_bus->irq[addr] = mdio_bus_data->probed_phy_irq;
264 phydev->irq = mdio_bus_data->probed_phy_irq;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700265 }
LABBE Corentincc26dc62017-02-15 10:46:44 +0100266
267 /*
268 * If we're going to bind the MAC to this PHY bus,
269 * and no PHY number was provided to the MAC,
270 * use the one probed here.
271 */
272 if (priv->plat->phy_addr == -1)
273 priv->plat->phy_addr = addr;
274
275 act = (priv->plat->phy_addr == addr);
276 switch (phydev->irq) {
277 case PHY_POLL:
278 irq_str = "POLL";
279 break;
280 case PHY_IGNORE_INTERRUPT:
281 irq_str = "IGNORE";
282 break;
283 default:
284 sprintf(irq_num, "%d", phydev->irq);
285 irq_str = irq_num;
286 break;
287 }
288 netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n",
289 phydev->phy_id, addr, irq_str, phydev_name(phydev),
290 act ? " active" : "");
291 found = 1;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700292 }
293
Phil Reide34d6562015-12-14 11:31:59 +0800294 if (!found && !mdio_node) {
LABBE Corentin38ddc592016-11-16 20:09:39 +0100295 netdev_warn(ndev, "No PHY found\n");
Giuseppe CAVALLARO3955b22b2013-02-06 20:47:52 +0000296 mdiobus_unregister(new_bus);
297 mdiobus_free(new_bus);
298 return -ENODEV;
299 }
300
Phil Reidcc2fa612016-03-15 15:34:33 +0800301bus_register_done:
Giuseppe CAVALLARO3955b22b2013-02-06 20:47:52 +0000302 priv->mii = new_bus;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700303
304 return 0;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000305
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700306bus_register_fail:
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000307 mdiobus_free(new_bus);
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700308 return err;
309}
310
311/**
312 * stmmac_mdio_unregister
313 * @ndev: net device structure
314 * Description: it unregisters the MII bus
315 */
316int stmmac_mdio_unregister(struct net_device *ndev)
317{
318 struct stmmac_priv *priv = netdev_priv(ndev);
319
Srinivas Kandagatlaa5cf5ce2012-08-30 05:49:58 +0000320 if (!priv->mii)
321 return 0;
322
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700323 mdiobus_unregister(priv->mii);
324 priv->mii->priv = NULL;
Giuseppe CAVALLARO36bcfe72011-07-20 00:05:23 +0000325 mdiobus_free(priv->mii);
326 priv->mii = NULL;
Giuseppe Cavallaro47dd7a52009-10-14 15:13:45 -0700327
328 return 0;
329}