17ac6653aSJeff Kirsher /*******************************************************************************
27ac6653aSJeff Kirsher   STMMAC Ethernet Driver -- MDIO bus implementation
37ac6653aSJeff Kirsher   Provides Bus interface for MII registers
47ac6653aSJeff Kirsher 
57ac6653aSJeff Kirsher   Copyright (C) 2007-2009  STMicroelectronics Ltd
67ac6653aSJeff Kirsher 
77ac6653aSJeff Kirsher   This program is free software; you can redistribute it and/or modify it
87ac6653aSJeff Kirsher   under the terms and conditions of the GNU General Public License,
97ac6653aSJeff Kirsher   version 2, as published by the Free Software Foundation.
107ac6653aSJeff Kirsher 
117ac6653aSJeff Kirsher   This program is distributed in the hope it will be useful, but WITHOUT
127ac6653aSJeff Kirsher   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
137ac6653aSJeff Kirsher   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
147ac6653aSJeff Kirsher   more details.
157ac6653aSJeff Kirsher 
167ac6653aSJeff Kirsher   You should have received a copy of the GNU General Public License along with
177ac6653aSJeff Kirsher   this program; if not, write to the Free Software Foundation, Inc.,
187ac6653aSJeff Kirsher   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
197ac6653aSJeff Kirsher 
207ac6653aSJeff Kirsher   The full GNU General Public License is included in this distribution in
217ac6653aSJeff Kirsher   the file called "COPYING".
227ac6653aSJeff Kirsher 
237ac6653aSJeff Kirsher   Author: Carl Shaw <carl.shaw@st.com>
247ac6653aSJeff Kirsher   Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
257ac6653aSJeff Kirsher *******************************************************************************/
267ac6653aSJeff Kirsher 
277ac6653aSJeff Kirsher #include <linux/mii.h>
287ac6653aSJeff Kirsher #include <linux/phy.h>
297ac6653aSJeff Kirsher #include <linux/slab.h>
300e076471SSrinivas Kandagatla #include <linux/of.h>
310e076471SSrinivas Kandagatla #include <linux/of_gpio.h>
32e34d6569SPhil Reid #include <linux/of_mdio.h>
337ac6653aSJeff Kirsher #include <asm/io.h>
347ac6653aSJeff Kirsher 
357ac6653aSJeff Kirsher #include "stmmac.h"
367ac6653aSJeff Kirsher 
377ac6653aSJeff Kirsher #define MII_BUSY 0x00000001
387ac6653aSJeff Kirsher #define MII_WRITE 0x00000002
397ac6653aSJeff Kirsher 
40ac1f74a7SAlexandre TORGUE /* GMAC4 defines */
41ac1f74a7SAlexandre TORGUE #define MII_GMAC4_GOC_SHIFT		2
42ac1f74a7SAlexandre TORGUE #define MII_GMAC4_WRITE			(1 << MII_GMAC4_GOC_SHIFT)
43ac1f74a7SAlexandre TORGUE #define MII_GMAC4_READ			(3 << MII_GMAC4_GOC_SHIFT)
44ac1f74a7SAlexandre TORGUE 
4539b401dbSDeepak SIKRI static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
4639b401dbSDeepak SIKRI {
4739b401dbSDeepak SIKRI 	unsigned long curr;
4839b401dbSDeepak SIKRI 	unsigned long finish = jiffies + 3 * HZ;
4939b401dbSDeepak SIKRI 
5039b401dbSDeepak SIKRI 	do {
5139b401dbSDeepak SIKRI 		curr = jiffies;
5239b401dbSDeepak SIKRI 		if (readl(ioaddr + mii_addr) & MII_BUSY)
5339b401dbSDeepak SIKRI 			cpu_relax();
5439b401dbSDeepak SIKRI 		else
5539b401dbSDeepak SIKRI 			return 0;
5639b401dbSDeepak SIKRI 	} while (!time_after_eq(curr, finish));
5739b401dbSDeepak SIKRI 
5839b401dbSDeepak SIKRI 	return -EBUSY;
5939b401dbSDeepak SIKRI }
6039b401dbSDeepak SIKRI 
617ac6653aSJeff Kirsher /**
627ac6653aSJeff Kirsher  * stmmac_mdio_read
637ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
64b91dce4cSLABBE Corentin  * @phyaddr: MII addr
65b91dce4cSLABBE Corentin  * @phyreg: MII reg
667ac6653aSJeff Kirsher  * Description: it reads data from the MII register from within the phy device.
677ac6653aSJeff Kirsher  * For the 7111 GMAC, we must set the bit 0 in the MII address register while
687ac6653aSJeff Kirsher  * accessing the PHY registers.
697ac6653aSJeff Kirsher  * Fortunately, it seems this has no drawback for the 7109 MAC.
707ac6653aSJeff Kirsher  */
717ac6653aSJeff Kirsher static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
727ac6653aSJeff Kirsher {
737ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
747ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
757ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
767ac6653aSJeff Kirsher 	unsigned int mii_data = priv->hw->mii.data;
777ac6653aSJeff Kirsher 
787ac6653aSJeff Kirsher 	int data;
79b91dce4cSLABBE Corentin 	u32 value = MII_BUSY;
80b91dce4cSLABBE Corentin 
81b91dce4cSLABBE Corentin 	value |= (phyaddr << priv->hw->mii.addr_shift)
82b91dce4cSLABBE Corentin 		& priv->hw->mii.addr_mask;
83b91dce4cSLABBE Corentin 	value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
84567be786Sjpinto 	value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
85567be786Sjpinto 		& priv->hw->mii.clk_csr_mask;
86b91dce4cSLABBE Corentin 	if (priv->plat->has_gmac4)
87b91dce4cSLABBE Corentin 		value |= MII_GMAC4_READ;
887ac6653aSJeff Kirsher 
8939b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
9039b401dbSDeepak SIKRI 		return -EBUSY;
9139b401dbSDeepak SIKRI 
9201f1f615SLABBE Corentin 	writel(value, priv->ioaddr + mii_address);
9339b401dbSDeepak SIKRI 
9439b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
9539b401dbSDeepak SIKRI 		return -EBUSY;
967ac6653aSJeff Kirsher 
977ac6653aSJeff Kirsher 	/* Read the data from the MII data register */
987ac6653aSJeff Kirsher 	data = (int)readl(priv->ioaddr + mii_data);
997ac6653aSJeff Kirsher 
1007ac6653aSJeff Kirsher 	return data;
1017ac6653aSJeff Kirsher }
1027ac6653aSJeff Kirsher 
1037ac6653aSJeff Kirsher /**
1047ac6653aSJeff Kirsher  * stmmac_mdio_write
1057ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
106b91dce4cSLABBE Corentin  * @phyaddr: MII addr
107b91dce4cSLABBE Corentin  * @phyreg: MII reg
1087ac6653aSJeff Kirsher  * @phydata: phy data
1097ac6653aSJeff Kirsher  * Description: it writes the data into the MII register from within the device.
1107ac6653aSJeff Kirsher  */
1117ac6653aSJeff Kirsher static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
1127ac6653aSJeff Kirsher 			     u16 phydata)
1137ac6653aSJeff Kirsher {
1147ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
1157ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
1167ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
1177ac6653aSJeff Kirsher 	unsigned int mii_data = priv->hw->mii.data;
1187ac6653aSJeff Kirsher 
1195799fc90SKweh, Hock Leong 	u32 value = MII_BUSY;
1207ac6653aSJeff Kirsher 
121b91dce4cSLABBE Corentin 	value |= (phyaddr << priv->hw->mii.addr_shift)
122b91dce4cSLABBE Corentin 		& priv->hw->mii.addr_mask;
123b91dce4cSLABBE Corentin 	value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
1247ac6653aSJeff Kirsher 
125567be786Sjpinto 	value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
126567be786Sjpinto 		& priv->hw->mii.clk_csr_mask;
127b91dce4cSLABBE Corentin 	if (priv->plat->has_gmac4)
128b91dce4cSLABBE Corentin 		value |= MII_GMAC4_WRITE;
1295799fc90SKweh, Hock Leong 	else
1305799fc90SKweh, Hock Leong 		value |= MII_WRITE;
131ac1f74a7SAlexandre TORGUE 
132ac1f74a7SAlexandre TORGUE 	/* Wait until any existing MII operation is complete */
133ac1f74a7SAlexandre TORGUE 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
134ac1f74a7SAlexandre TORGUE 		return -EBUSY;
135ac1f74a7SAlexandre TORGUE 
136ac1f74a7SAlexandre TORGUE 	/* Set the MII address register to write */
137ac1f74a7SAlexandre TORGUE 	writel(phydata, priv->ioaddr + mii_data);
138ac1f74a7SAlexandre TORGUE 	writel(value, priv->ioaddr + mii_address);
139ac1f74a7SAlexandre TORGUE 
140ac1f74a7SAlexandre TORGUE 	/* Wait until any existing MII operation is complete */
141ac1f74a7SAlexandre TORGUE 	return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
142ac1f74a7SAlexandre TORGUE }
143ac1f74a7SAlexandre TORGUE 
144ac1f74a7SAlexandre TORGUE /**
1457ac6653aSJeff Kirsher  * stmmac_mdio_reset
1467ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
1477ac6653aSJeff Kirsher  * Description: reset the MII bus
1487ac6653aSJeff Kirsher  */
149073752aaSSrinivas Kandagatla int stmmac_mdio_reset(struct mii_bus *bus)
1507ac6653aSJeff Kirsher {
151bfab27a1SGiuseppe CAVALLARO #if defined(CONFIG_STMMAC_PLATFORM)
1527ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
1537ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
1547ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
1550e076471SSrinivas Kandagatla 	struct stmmac_mdio_bus_data *data = priv->plat->mdio_bus_data;
1567ac6653aSJeff Kirsher 
1570e076471SSrinivas Kandagatla #ifdef CONFIG_OF
1580e076471SSrinivas Kandagatla 	if (priv->device->of_node) {
1590e076471SSrinivas Kandagatla 
1600e076471SSrinivas Kandagatla 		if (data->reset_gpio < 0) {
1610e076471SSrinivas Kandagatla 			struct device_node *np = priv->device->of_node;
1620e076471SSrinivas Kandagatla 			if (!np)
1630e076471SSrinivas Kandagatla 				return 0;
1640e076471SSrinivas Kandagatla 
1650e076471SSrinivas Kandagatla 			data->reset_gpio = of_get_named_gpio(np,
1660e076471SSrinivas Kandagatla 						"snps,reset-gpio", 0);
1670e076471SSrinivas Kandagatla 			if (data->reset_gpio < 0)
1680e076471SSrinivas Kandagatla 				return 0;
1690e076471SSrinivas Kandagatla 
1700e076471SSrinivas Kandagatla 			data->active_low = of_property_read_bool(np,
1710e076471SSrinivas Kandagatla 						"snps,reset-active-low");
1720e076471SSrinivas Kandagatla 			of_property_read_u32_array(np,
1730e076471SSrinivas Kandagatla 				"snps,reset-delays-us", data->delays, 3);
174ae26c1c6SGiuseppe CAVALLARO 
175ae26c1c6SGiuseppe CAVALLARO 			if (gpio_request(data->reset_gpio, "mdio-reset"))
176ae26c1c6SGiuseppe CAVALLARO 				return 0;
1770e076471SSrinivas Kandagatla 		}
1780e076471SSrinivas Kandagatla 
179ae26c1c6SGiuseppe CAVALLARO 		gpio_direction_output(data->reset_gpio,
180ae26c1c6SGiuseppe CAVALLARO 				      data->active_low ? 1 : 0);
181892aa01dSSjoerd Simons 		if (data->delays[0])
182892aa01dSSjoerd Simons 			msleep(DIV_ROUND_UP(data->delays[0], 1000));
183892aa01dSSjoerd Simons 
184ae26c1c6SGiuseppe CAVALLARO 		gpio_set_value(data->reset_gpio, data->active_low ? 0 : 1);
185892aa01dSSjoerd Simons 		if (data->delays[1])
186892aa01dSSjoerd Simons 			msleep(DIV_ROUND_UP(data->delays[1], 1000));
187892aa01dSSjoerd Simons 
188ae26c1c6SGiuseppe CAVALLARO 		gpio_set_value(data->reset_gpio, data->active_low ? 1 : 0);
189892aa01dSSjoerd Simons 		if (data->delays[2])
190892aa01dSSjoerd Simons 			msleep(DIV_ROUND_UP(data->delays[2], 1000));
1910e076471SSrinivas Kandagatla 	}
1920e076471SSrinivas Kandagatla #endif
1930e076471SSrinivas Kandagatla 
1940e076471SSrinivas Kandagatla 	if (data->phy_reset) {
19538ddc59dSLABBE Corentin 		netdev_dbg(ndev, "stmmac_mdio_reset: calling phy_reset\n");
1960e076471SSrinivas Kandagatla 		data->phy_reset(priv->plat->bsp_priv);
1977ac6653aSJeff Kirsher 	}
1987ac6653aSJeff Kirsher 
1997ac6653aSJeff Kirsher 	/* This is a workaround for problems with the STE101P PHY.
2007ac6653aSJeff Kirsher 	 * It doesn't complete its reset until at least one clock cycle
2018d45e42bSLABBE Corentin 	 * on MDC, so perform a dummy mdio read. To be updated for GMAC4
202ac1f74a7SAlexandre TORGUE 	 * if needed.
2037ac6653aSJeff Kirsher 	 */
204ac1f74a7SAlexandre TORGUE 	if (!priv->plat->has_gmac4)
2057ac6653aSJeff Kirsher 		writel(0, priv->ioaddr + mii_address);
206bfab27a1SGiuseppe CAVALLARO #endif
2077ac6653aSJeff Kirsher 	return 0;
2087ac6653aSJeff Kirsher }
2097ac6653aSJeff Kirsher 
2107ac6653aSJeff Kirsher /**
2117ac6653aSJeff Kirsher  * stmmac_mdio_register
2127ac6653aSJeff Kirsher  * @ndev: net device structure
2137ac6653aSJeff Kirsher  * Description: it registers the MII bus
2147ac6653aSJeff Kirsher  */
2157ac6653aSJeff Kirsher int stmmac_mdio_register(struct net_device *ndev)
2167ac6653aSJeff Kirsher {
2177ac6653aSJeff Kirsher 	int err = 0;
2187ac6653aSJeff Kirsher 	struct mii_bus *new_bus;
2197ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2207ac6653aSJeff Kirsher 	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
221a7657f12SGiuseppe CAVALLARO 	struct device_node *mdio_node = priv->plat->mdio_node;
2227ac6653aSJeff Kirsher 	int addr, found;
2237ac6653aSJeff Kirsher 
2247ac6653aSJeff Kirsher 	if (!mdio_bus_data)
2257ac6653aSJeff Kirsher 		return 0;
2267ac6653aSJeff Kirsher 
2277ac6653aSJeff Kirsher 	new_bus = mdiobus_alloc();
2287ac6653aSJeff Kirsher 	if (new_bus == NULL)
2297ac6653aSJeff Kirsher 		return -ENOMEM;
2307ac6653aSJeff Kirsher 
231e7f4dc35SAndrew Lunn 	if (mdio_bus_data->irqs)
232643d60bfSMarek Vasut 		memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));
2337ac6653aSJeff Kirsher 
2340e076471SSrinivas Kandagatla #ifdef CONFIG_OF
2350e076471SSrinivas Kandagatla 	if (priv->device->of_node)
2360e076471SSrinivas Kandagatla 		mdio_bus_data->reset_gpio = -1;
2370e076471SSrinivas Kandagatla #endif
2380e076471SSrinivas Kandagatla 
23990b9a545SAlessandro Rubini 	new_bus->name = "stmmac";
2407ac6653aSJeff Kirsher 	new_bus->read = &stmmac_mdio_read;
2417ac6653aSJeff Kirsher 	new_bus->write = &stmmac_mdio_write;
242ac1f74a7SAlexandre TORGUE 
2437ac6653aSJeff Kirsher 	new_bus->reset = &stmmac_mdio_reset;
244db8857bfSFlorian Fainelli 	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
245d56631a6SSrinivas Kandagatla 		 new_bus->name, priv->plat->bus_id);
2467ac6653aSJeff Kirsher 	new_bus->priv = ndev;
2477ac6653aSJeff Kirsher 	new_bus->phy_mask = mdio_bus_data->phy_mask;
2487ac6653aSJeff Kirsher 	new_bus->parent = priv->device;
249e34d6569SPhil Reid 
2506c672c9bSRomain Perier 	if (mdio_node)
251e34d6569SPhil Reid 		err = of_mdiobus_register(new_bus, mdio_node);
2526c672c9bSRomain Perier 	else
2536c672c9bSRomain Perier 		err = mdiobus_register(new_bus);
2547ac6653aSJeff Kirsher 	if (err != 0) {
25538ddc59dSLABBE Corentin 		netdev_err(ndev, "Cannot register the MDIO bus\n");
2567ac6653aSJeff Kirsher 		goto bus_register_fail;
2577ac6653aSJeff Kirsher 	}
2587ac6653aSJeff Kirsher 
259cc2fa619SPhil Reid 	if (priv->plat->phy_node || mdio_node)
260cc2fa619SPhil Reid 		goto bus_register_done;
261cc2fa619SPhil Reid 
2627ac6653aSJeff Kirsher 	found = 0;
2637ac6653aSJeff Kirsher 	for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
2647f854420SAndrew Lunn 		struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
2657ac6653aSJeff Kirsher 		if (phydev) {
2667ac6653aSJeff Kirsher 			int act = 0;
2677ac6653aSJeff Kirsher 			char irq_num[4];
2687ac6653aSJeff Kirsher 			char *irq_str;
2697ac6653aSJeff Kirsher 
2707ac6653aSJeff Kirsher 			/*
2717ac6653aSJeff Kirsher 			 * If an IRQ was provided to be assigned after
2727ac6653aSJeff Kirsher 			 * the bus probe, do it here.
2737ac6653aSJeff Kirsher 			 */
2747ac6653aSJeff Kirsher 			if ((mdio_bus_data->irqs == NULL) &&
2757ac6653aSJeff Kirsher 			    (mdio_bus_data->probed_phy_irq > 0)) {
276e7f4dc35SAndrew Lunn 				new_bus->irq[addr] =
277e7f4dc35SAndrew Lunn 					mdio_bus_data->probed_phy_irq;
2787ac6653aSJeff Kirsher 				phydev->irq = mdio_bus_data->probed_phy_irq;
2797ac6653aSJeff Kirsher 			}
2807ac6653aSJeff Kirsher 
2817ac6653aSJeff Kirsher 			/*
2827ac6653aSJeff Kirsher 			 * If we're going to bind the MAC to this PHY bus,
2837ac6653aSJeff Kirsher 			 * and no PHY number was provided to the MAC,
2847ac6653aSJeff Kirsher 			 * use the one probed here.
2857ac6653aSJeff Kirsher 			 */
286d56631a6SSrinivas Kandagatla 			if (priv->plat->phy_addr == -1)
2877ac6653aSJeff Kirsher 				priv->plat->phy_addr = addr;
2887ac6653aSJeff Kirsher 
289d56631a6SSrinivas Kandagatla 			act = (priv->plat->phy_addr == addr);
2907ac6653aSJeff Kirsher 			switch (phydev->irq) {
2917ac6653aSJeff Kirsher 			case PHY_POLL:
2927ac6653aSJeff Kirsher 				irq_str = "POLL";
2937ac6653aSJeff Kirsher 				break;
2947ac6653aSJeff Kirsher 			case PHY_IGNORE_INTERRUPT:
2957ac6653aSJeff Kirsher 				irq_str = "IGNORE";
2967ac6653aSJeff Kirsher 				break;
2977ac6653aSJeff Kirsher 			default:
2987ac6653aSJeff Kirsher 				sprintf(irq_num, "%d", phydev->irq);
2997ac6653aSJeff Kirsher 				irq_str = irq_num;
3007ac6653aSJeff Kirsher 				break;
3017ac6653aSJeff Kirsher 			}
30238ddc59dSLABBE Corentin 			netdev_info(ndev, "PHY ID %08x at %d IRQ %s (%s)%s\n",
30338ddc59dSLABBE Corentin 				    phydev->phy_id, addr,
30484eff6d1SAndrew Lunn 				    irq_str, phydev_name(phydev),
3057ac6653aSJeff Kirsher 				    act ? " active" : "");
3067ac6653aSJeff Kirsher 			found = 1;
3077ac6653aSJeff Kirsher 		}
3087ac6653aSJeff Kirsher 	}
3097ac6653aSJeff Kirsher 
310e34d6569SPhil Reid 	if (!found && !mdio_node) {
31138ddc59dSLABBE Corentin 		netdev_warn(ndev, "No PHY found\n");
3123955b22bSGiuseppe CAVALLARO 		mdiobus_unregister(new_bus);
3133955b22bSGiuseppe CAVALLARO 		mdiobus_free(new_bus);
3143955b22bSGiuseppe CAVALLARO 		return -ENODEV;
3153955b22bSGiuseppe CAVALLARO 	}
3163955b22bSGiuseppe CAVALLARO 
317cc2fa619SPhil Reid bus_register_done:
3183955b22bSGiuseppe CAVALLARO 	priv->mii = new_bus;
3197ac6653aSJeff Kirsher 
3207ac6653aSJeff Kirsher 	return 0;
3217ac6653aSJeff Kirsher 
3227ac6653aSJeff Kirsher bus_register_fail:
3237ac6653aSJeff Kirsher 	mdiobus_free(new_bus);
3247ac6653aSJeff Kirsher 	return err;
3257ac6653aSJeff Kirsher }
3267ac6653aSJeff Kirsher 
3277ac6653aSJeff Kirsher /**
3287ac6653aSJeff Kirsher  * stmmac_mdio_unregister
3297ac6653aSJeff Kirsher  * @ndev: net device structure
3307ac6653aSJeff Kirsher  * Description: it unregisters the MII bus
3317ac6653aSJeff Kirsher  */
3327ac6653aSJeff Kirsher int stmmac_mdio_unregister(struct net_device *ndev)
3337ac6653aSJeff Kirsher {
3347ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
3357ac6653aSJeff Kirsher 
336a5cf5ce9SSrinivas Kandagatla 	if (!priv->mii)
337a5cf5ce9SSrinivas Kandagatla 		return 0;
338a5cf5ce9SSrinivas Kandagatla 
3397ac6653aSJeff Kirsher 	mdiobus_unregister(priv->mii);
3407ac6653aSJeff Kirsher 	priv->mii->priv = NULL;
3417ac6653aSJeff Kirsher 	mdiobus_free(priv->mii);
3427ac6653aSJeff Kirsher 	priv->mii = NULL;
3437ac6653aSJeff Kirsher 
3447ac6653aSJeff Kirsher 	return 0;
3457ac6653aSJeff Kirsher }
346