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 
45ac1f74a7SAlexandre TORGUE #define MII_PHY_ADDR_GMAC4_SHIFT	21
46ac1f74a7SAlexandre TORGUE #define MII_PHY_ADDR_GMAC4_MASK		GENMASK(25, 21)
47ac1f74a7SAlexandre TORGUE #define MII_PHY_REG_GMAC4_SHIFT		16
48ac1f74a7SAlexandre TORGUE #define MII_PHY_REG_GMAC4_MASK		GENMASK(20, 16)
49ac1f74a7SAlexandre TORGUE #define MII_CSR_CLK_GMAC4_SHIFT		8
50ac1f74a7SAlexandre TORGUE #define MII_CSR_CLK_GMAC4_MASK		GENMASK(11, 8)
51ac1f74a7SAlexandre TORGUE 
5239b401dbSDeepak SIKRI static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
5339b401dbSDeepak SIKRI {
5439b401dbSDeepak SIKRI 	unsigned long curr;
5539b401dbSDeepak SIKRI 	unsigned long finish = jiffies + 3 * HZ;
5639b401dbSDeepak SIKRI 
5739b401dbSDeepak SIKRI 	do {
5839b401dbSDeepak SIKRI 		curr = jiffies;
5939b401dbSDeepak SIKRI 		if (readl(ioaddr + mii_addr) & MII_BUSY)
6039b401dbSDeepak SIKRI 			cpu_relax();
6139b401dbSDeepak SIKRI 		else
6239b401dbSDeepak SIKRI 			return 0;
6339b401dbSDeepak SIKRI 	} while (!time_after_eq(curr, finish));
6439b401dbSDeepak SIKRI 
6539b401dbSDeepak SIKRI 	return -EBUSY;
6639b401dbSDeepak SIKRI }
6739b401dbSDeepak SIKRI 
687ac6653aSJeff Kirsher /**
697ac6653aSJeff Kirsher  * stmmac_mdio_read
707ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
717ac6653aSJeff Kirsher  * @phyaddr: MII addr reg bits 15-11
727ac6653aSJeff Kirsher  * @phyreg: MII addr reg bits 10-6
737ac6653aSJeff Kirsher  * Description: it reads data from the MII register from within the phy device.
747ac6653aSJeff Kirsher  * For the 7111 GMAC, we must set the bit 0 in the MII address register while
757ac6653aSJeff Kirsher  * accessing the PHY registers.
767ac6653aSJeff Kirsher  * Fortunately, it seems this has no drawback for the 7109 MAC.
777ac6653aSJeff Kirsher  */
787ac6653aSJeff Kirsher static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
797ac6653aSJeff Kirsher {
807ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
817ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
827ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
837ac6653aSJeff Kirsher 	unsigned int mii_data = priv->hw->mii.data;
847ac6653aSJeff Kirsher 
857ac6653aSJeff Kirsher 	int data;
867ac6653aSJeff Kirsher 	u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
877ac6653aSJeff Kirsher 			((phyreg << 6) & (0x000007C0)));
88cd7201f4SGiuseppe CAVALLARO 	regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
897ac6653aSJeff Kirsher 
9039b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
9139b401dbSDeepak SIKRI 		return -EBUSY;
9239b401dbSDeepak SIKRI 
937ac6653aSJeff Kirsher 	writel(regValue, priv->ioaddr + mii_address);
9439b401dbSDeepak SIKRI 
9539b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
9639b401dbSDeepak SIKRI 		return -EBUSY;
977ac6653aSJeff Kirsher 
987ac6653aSJeff Kirsher 	/* Read the data from the MII data register */
997ac6653aSJeff Kirsher 	data = (int)readl(priv->ioaddr + mii_data);
1007ac6653aSJeff Kirsher 
1017ac6653aSJeff Kirsher 	return data;
1027ac6653aSJeff Kirsher }
1037ac6653aSJeff Kirsher 
1047ac6653aSJeff Kirsher /**
1057ac6653aSJeff Kirsher  * stmmac_mdio_write
1067ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
1077ac6653aSJeff Kirsher  * @phyaddr: MII addr reg bits 15-11
1087ac6653aSJeff Kirsher  * @phyreg: MII addr reg bits 10-6
1097ac6653aSJeff Kirsher  * @phydata: phy data
1107ac6653aSJeff Kirsher  * Description: it writes the data into the MII register from within the device.
1117ac6653aSJeff Kirsher  */
1127ac6653aSJeff Kirsher static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
1137ac6653aSJeff Kirsher 			     u16 phydata)
1147ac6653aSJeff Kirsher {
1157ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
1167ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
1177ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
1187ac6653aSJeff Kirsher 	unsigned int mii_data = priv->hw->mii.data;
1197ac6653aSJeff Kirsher 
1207ac6653aSJeff Kirsher 	u16 value =
1217ac6653aSJeff Kirsher 	    (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
1227ac6653aSJeff Kirsher 	    | MII_WRITE;
1237ac6653aSJeff Kirsher 
124cd7201f4SGiuseppe CAVALLARO 	value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
1257ac6653aSJeff Kirsher 
1267ac6653aSJeff Kirsher 	/* Wait until any existing MII operation is complete */
12739b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
12839b401dbSDeepak SIKRI 		return -EBUSY;
1297ac6653aSJeff Kirsher 
1307ac6653aSJeff Kirsher 	/* Set the MII address register to write */
1317ac6653aSJeff Kirsher 	writel(phydata, priv->ioaddr + mii_data);
1327ac6653aSJeff Kirsher 	writel(value, priv->ioaddr + mii_address);
1337ac6653aSJeff Kirsher 
1347ac6653aSJeff Kirsher 	/* Wait until any existing MII operation is complete */
13539b401dbSDeepak SIKRI 	return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
1367ac6653aSJeff Kirsher }
1377ac6653aSJeff Kirsher 
1387ac6653aSJeff Kirsher /**
139ac1f74a7SAlexandre TORGUE  * stmmac_mdio_read_gmac4
140ac1f74a7SAlexandre TORGUE  * @bus: points to the mii_bus structure
141ac1f74a7SAlexandre TORGUE  * @phyaddr: MII addr reg bits 25-21
142ac1f74a7SAlexandre TORGUE  * @phyreg: MII addr reg bits 20-16
143ac1f74a7SAlexandre TORGUE  * Description: it reads data from the MII register of GMAC4 from within
144ac1f74a7SAlexandre TORGUE  * the phy device.
145ac1f74a7SAlexandre TORGUE  */
146ac1f74a7SAlexandre TORGUE static int stmmac_mdio_read_gmac4(struct mii_bus *bus, int phyaddr, int phyreg)
147ac1f74a7SAlexandre TORGUE {
148ac1f74a7SAlexandre TORGUE 	struct net_device *ndev = bus->priv;
149ac1f74a7SAlexandre TORGUE 	struct stmmac_priv *priv = netdev_priv(ndev);
150ac1f74a7SAlexandre TORGUE 	unsigned int mii_address = priv->hw->mii.addr;
151ac1f74a7SAlexandre TORGUE 	unsigned int mii_data = priv->hw->mii.data;
152ac1f74a7SAlexandre TORGUE 	int data;
153ac1f74a7SAlexandre TORGUE 	u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) &
154ac1f74a7SAlexandre TORGUE 		     (MII_PHY_ADDR_GMAC4_MASK)) |
155ac1f74a7SAlexandre TORGUE 		     ((phyreg << MII_PHY_REG_GMAC4_SHIFT) &
156ac1f74a7SAlexandre TORGUE 		     (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_READ;
157ac1f74a7SAlexandre TORGUE 
158ac1f74a7SAlexandre TORGUE 	value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK)
159ac1f74a7SAlexandre TORGUE 		 << MII_CSR_CLK_GMAC4_SHIFT);
160ac1f74a7SAlexandre TORGUE 
161ac1f74a7SAlexandre TORGUE 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
162ac1f74a7SAlexandre TORGUE 		return -EBUSY;
163ac1f74a7SAlexandre TORGUE 
164ac1f74a7SAlexandre TORGUE 	writel(value, priv->ioaddr + mii_address);
165ac1f74a7SAlexandre TORGUE 
166ac1f74a7SAlexandre TORGUE 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
167ac1f74a7SAlexandre TORGUE 		return -EBUSY;
168ac1f74a7SAlexandre TORGUE 
169ac1f74a7SAlexandre TORGUE 	/* Read the data from the MII data register */
170ac1f74a7SAlexandre TORGUE 	data = (int)readl(priv->ioaddr + mii_data);
171ac1f74a7SAlexandre TORGUE 
172ac1f74a7SAlexandre TORGUE 	return data;
173ac1f74a7SAlexandre TORGUE }
174ac1f74a7SAlexandre TORGUE 
175ac1f74a7SAlexandre TORGUE /**
176ac1f74a7SAlexandre TORGUE  * stmmac_mdio_write_gmac4
177ac1f74a7SAlexandre TORGUE  * @bus: points to the mii_bus structure
178ac1f74a7SAlexandre TORGUE  * @phyaddr: MII addr reg bits 25-21
179ac1f74a7SAlexandre TORGUE  * @phyreg: MII addr reg bits 20-16
180ac1f74a7SAlexandre TORGUE  * @phydata: phy data
181ac1f74a7SAlexandre TORGUE  * Description: it writes the data into the MII register of GMAC4 from within
182ac1f74a7SAlexandre TORGUE  * the device.
183ac1f74a7SAlexandre TORGUE  */
184ac1f74a7SAlexandre TORGUE static int stmmac_mdio_write_gmac4(struct mii_bus *bus, int phyaddr, int phyreg,
185ac1f74a7SAlexandre TORGUE 				   u16 phydata)
186ac1f74a7SAlexandre TORGUE {
187ac1f74a7SAlexandre TORGUE 	struct net_device *ndev = bus->priv;
188ac1f74a7SAlexandre TORGUE 	struct stmmac_priv *priv = netdev_priv(ndev);
189ac1f74a7SAlexandre TORGUE 	unsigned int mii_address = priv->hw->mii.addr;
190ac1f74a7SAlexandre TORGUE 	unsigned int mii_data = priv->hw->mii.data;
191ac1f74a7SAlexandre TORGUE 
192ac1f74a7SAlexandre TORGUE 	u32 value = (((phyaddr << MII_PHY_ADDR_GMAC4_SHIFT) &
193ac1f74a7SAlexandre TORGUE 		     (MII_PHY_ADDR_GMAC4_MASK)) |
194ac1f74a7SAlexandre TORGUE 		     ((phyreg << MII_PHY_REG_GMAC4_SHIFT) &
195ac1f74a7SAlexandre TORGUE 		     (MII_PHY_REG_GMAC4_MASK))) | MII_GMAC4_WRITE;
196ac1f74a7SAlexandre TORGUE 
197ac1f74a7SAlexandre TORGUE 	value |= MII_BUSY | ((priv->clk_csr & MII_CSR_CLK_GMAC4_MASK)
198ac1f74a7SAlexandre TORGUE 		 << MII_CSR_CLK_GMAC4_SHIFT);
199ac1f74a7SAlexandre TORGUE 
200ac1f74a7SAlexandre TORGUE 	/* Wait until any existing MII operation is complete */
201ac1f74a7SAlexandre TORGUE 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
202ac1f74a7SAlexandre TORGUE 		return -EBUSY;
203ac1f74a7SAlexandre TORGUE 
204ac1f74a7SAlexandre TORGUE 	/* Set the MII address register to write */
205ac1f74a7SAlexandre TORGUE 	writel(phydata, priv->ioaddr + mii_data);
206ac1f74a7SAlexandre TORGUE 	writel(value, priv->ioaddr + mii_address);
207ac1f74a7SAlexandre TORGUE 
208ac1f74a7SAlexandre TORGUE 	/* Wait until any existing MII operation is complete */
209ac1f74a7SAlexandre TORGUE 	return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
210ac1f74a7SAlexandre TORGUE }
211ac1f74a7SAlexandre TORGUE 
212ac1f74a7SAlexandre TORGUE /**
2137ac6653aSJeff Kirsher  * stmmac_mdio_reset
2147ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
2157ac6653aSJeff Kirsher  * Description: reset the MII bus
2167ac6653aSJeff Kirsher  */
217073752aaSSrinivas Kandagatla int stmmac_mdio_reset(struct mii_bus *bus)
2187ac6653aSJeff Kirsher {
219bfab27a1SGiuseppe CAVALLARO #if defined(CONFIG_STMMAC_PLATFORM)
2207ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
2217ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2227ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
2230e076471SSrinivas Kandagatla 	struct stmmac_mdio_bus_data *data = priv->plat->mdio_bus_data;
2247ac6653aSJeff Kirsher 
2250e076471SSrinivas Kandagatla #ifdef CONFIG_OF
2260e076471SSrinivas Kandagatla 	if (priv->device->of_node) {
2270e076471SSrinivas Kandagatla 
2280e076471SSrinivas Kandagatla 		if (data->reset_gpio < 0) {
2290e076471SSrinivas Kandagatla 			struct device_node *np = priv->device->of_node;
2300e076471SSrinivas Kandagatla 			if (!np)
2310e076471SSrinivas Kandagatla 				return 0;
2320e076471SSrinivas Kandagatla 
2330e076471SSrinivas Kandagatla 			data->reset_gpio = of_get_named_gpio(np,
2340e076471SSrinivas Kandagatla 						"snps,reset-gpio", 0);
2350e076471SSrinivas Kandagatla 			if (data->reset_gpio < 0)
2360e076471SSrinivas Kandagatla 				return 0;
2370e076471SSrinivas Kandagatla 
2380e076471SSrinivas Kandagatla 			data->active_low = of_property_read_bool(np,
2390e076471SSrinivas Kandagatla 						"snps,reset-active-low");
2400e076471SSrinivas Kandagatla 			of_property_read_u32_array(np,
2410e076471SSrinivas Kandagatla 				"snps,reset-delays-us", data->delays, 3);
242ae26c1c6SGiuseppe CAVALLARO 
243ae26c1c6SGiuseppe CAVALLARO 			if (gpio_request(data->reset_gpio, "mdio-reset"))
244ae26c1c6SGiuseppe CAVALLARO 				return 0;
2450e076471SSrinivas Kandagatla 		}
2460e076471SSrinivas Kandagatla 
247ae26c1c6SGiuseppe CAVALLARO 		gpio_direction_output(data->reset_gpio,
248ae26c1c6SGiuseppe CAVALLARO 				      data->active_low ? 1 : 0);
249892aa01dSSjoerd Simons 		if (data->delays[0])
250892aa01dSSjoerd Simons 			msleep(DIV_ROUND_UP(data->delays[0], 1000));
251892aa01dSSjoerd Simons 
252ae26c1c6SGiuseppe CAVALLARO 		gpio_set_value(data->reset_gpio, data->active_low ? 0 : 1);
253892aa01dSSjoerd Simons 		if (data->delays[1])
254892aa01dSSjoerd Simons 			msleep(DIV_ROUND_UP(data->delays[1], 1000));
255892aa01dSSjoerd Simons 
256ae26c1c6SGiuseppe CAVALLARO 		gpio_set_value(data->reset_gpio, data->active_low ? 1 : 0);
257892aa01dSSjoerd Simons 		if (data->delays[2])
258892aa01dSSjoerd Simons 			msleep(DIV_ROUND_UP(data->delays[2], 1000));
2590e076471SSrinivas Kandagatla 	}
2600e076471SSrinivas Kandagatla #endif
2610e076471SSrinivas Kandagatla 
2620e076471SSrinivas Kandagatla 	if (data->phy_reset) {
2637ac6653aSJeff Kirsher 		pr_debug("stmmac_mdio_reset: calling phy_reset\n");
2640e076471SSrinivas Kandagatla 		data->phy_reset(priv->plat->bsp_priv);
2657ac6653aSJeff Kirsher 	}
2667ac6653aSJeff Kirsher 
2677ac6653aSJeff Kirsher 	/* This is a workaround for problems with the STE101P PHY.
2687ac6653aSJeff Kirsher 	 * It doesn't complete its reset until at least one clock cycle
269ac1f74a7SAlexandre TORGUE 	 * on MDC, so perform a dummy mdio read. To be upadted for GMAC4
270ac1f74a7SAlexandre TORGUE 	 * if needed.
2717ac6653aSJeff Kirsher 	 */
272ac1f74a7SAlexandre TORGUE 	if (!priv->plat->has_gmac4)
2737ac6653aSJeff Kirsher 		writel(0, priv->ioaddr + mii_address);
274bfab27a1SGiuseppe CAVALLARO #endif
2757ac6653aSJeff Kirsher 	return 0;
2767ac6653aSJeff Kirsher }
2777ac6653aSJeff Kirsher 
2787ac6653aSJeff Kirsher /**
2797ac6653aSJeff Kirsher  * stmmac_mdio_register
2807ac6653aSJeff Kirsher  * @ndev: net device structure
2817ac6653aSJeff Kirsher  * Description: it registers the MII bus
2827ac6653aSJeff Kirsher  */
2837ac6653aSJeff Kirsher int stmmac_mdio_register(struct net_device *ndev)
2847ac6653aSJeff Kirsher {
2857ac6653aSJeff Kirsher 	int err = 0;
2867ac6653aSJeff Kirsher 	struct mii_bus *new_bus;
2877ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2887ac6653aSJeff Kirsher 	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
289a7657f12SGiuseppe CAVALLARO 	struct device_node *mdio_node = priv->plat->mdio_node;
2907ac6653aSJeff Kirsher 	int addr, found;
2917ac6653aSJeff Kirsher 
2927ac6653aSJeff Kirsher 	if (!mdio_bus_data)
2937ac6653aSJeff Kirsher 		return 0;
2947ac6653aSJeff Kirsher 
2957ac6653aSJeff Kirsher 	new_bus = mdiobus_alloc();
2967ac6653aSJeff Kirsher 	if (new_bus == NULL)
2977ac6653aSJeff Kirsher 		return -ENOMEM;
2987ac6653aSJeff Kirsher 
299e7f4dc35SAndrew Lunn 	if (mdio_bus_data->irqs)
300e7f4dc35SAndrew Lunn 		memcpy(new_bus->irq, mdio_bus_data, sizeof(new_bus->irq));
3017ac6653aSJeff Kirsher 
3020e076471SSrinivas Kandagatla #ifdef CONFIG_OF
3030e076471SSrinivas Kandagatla 	if (priv->device->of_node)
3040e076471SSrinivas Kandagatla 		mdio_bus_data->reset_gpio = -1;
3050e076471SSrinivas Kandagatla #endif
3060e076471SSrinivas Kandagatla 
30790b9a545SAlessandro Rubini 	new_bus->name = "stmmac";
308ac1f74a7SAlexandre TORGUE 	if (priv->plat->has_gmac4) {
309ac1f74a7SAlexandre TORGUE 		new_bus->read = &stmmac_mdio_read_gmac4;
310ac1f74a7SAlexandre TORGUE 		new_bus->write = &stmmac_mdio_write_gmac4;
311ac1f74a7SAlexandre TORGUE 	} else {
3127ac6653aSJeff Kirsher 		new_bus->read = &stmmac_mdio_read;
3137ac6653aSJeff Kirsher 		new_bus->write = &stmmac_mdio_write;
314ac1f74a7SAlexandre TORGUE 	}
315ac1f74a7SAlexandre TORGUE 
3167ac6653aSJeff Kirsher 	new_bus->reset = &stmmac_mdio_reset;
317db8857bfSFlorian Fainelli 	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
318d56631a6SSrinivas Kandagatla 		 new_bus->name, priv->plat->bus_id);
3197ac6653aSJeff Kirsher 	new_bus->priv = ndev;
3207ac6653aSJeff Kirsher 	new_bus->phy_mask = mdio_bus_data->phy_mask;
3217ac6653aSJeff Kirsher 	new_bus->parent = priv->device;
322e34d6569SPhil Reid 
3236c672c9bSRomain Perier 	if (mdio_node)
324e34d6569SPhil Reid 		err = of_mdiobus_register(new_bus, mdio_node);
3256c672c9bSRomain Perier 	else
3266c672c9bSRomain Perier 		err = mdiobus_register(new_bus);
3277ac6653aSJeff Kirsher 	if (err != 0) {
3287ac6653aSJeff Kirsher 		pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
3297ac6653aSJeff Kirsher 		goto bus_register_fail;
3307ac6653aSJeff Kirsher 	}
3317ac6653aSJeff Kirsher 
332cc2fa619SPhil Reid 	if (priv->plat->phy_node || mdio_node)
333cc2fa619SPhil Reid 		goto bus_register_done;
334cc2fa619SPhil Reid 
3357ac6653aSJeff Kirsher 	found = 0;
3367ac6653aSJeff Kirsher 	for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
3377f854420SAndrew Lunn 		struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
3387ac6653aSJeff Kirsher 		if (phydev) {
3397ac6653aSJeff Kirsher 			int act = 0;
3407ac6653aSJeff Kirsher 			char irq_num[4];
3417ac6653aSJeff Kirsher 			char *irq_str;
3427ac6653aSJeff Kirsher 
3437ac6653aSJeff Kirsher 			/*
3447ac6653aSJeff Kirsher 			 * If an IRQ was provided to be assigned after
3457ac6653aSJeff Kirsher 			 * the bus probe, do it here.
3467ac6653aSJeff Kirsher 			 */
3477ac6653aSJeff Kirsher 			if ((mdio_bus_data->irqs == NULL) &&
3487ac6653aSJeff Kirsher 			    (mdio_bus_data->probed_phy_irq > 0)) {
349e7f4dc35SAndrew Lunn 				new_bus->irq[addr] =
350e7f4dc35SAndrew Lunn 					mdio_bus_data->probed_phy_irq;
3517ac6653aSJeff Kirsher 				phydev->irq = mdio_bus_data->probed_phy_irq;
3527ac6653aSJeff Kirsher 			}
3537ac6653aSJeff Kirsher 
3547ac6653aSJeff Kirsher 			/*
3557ac6653aSJeff Kirsher 			 * If we're going to bind the MAC to this PHY bus,
3567ac6653aSJeff Kirsher 			 * and no PHY number was provided to the MAC,
3577ac6653aSJeff Kirsher 			 * use the one probed here.
3587ac6653aSJeff Kirsher 			 */
359d56631a6SSrinivas Kandagatla 			if (priv->plat->phy_addr == -1)
3607ac6653aSJeff Kirsher 				priv->plat->phy_addr = addr;
3617ac6653aSJeff Kirsher 
362d56631a6SSrinivas Kandagatla 			act = (priv->plat->phy_addr == addr);
3637ac6653aSJeff Kirsher 			switch (phydev->irq) {
3647ac6653aSJeff Kirsher 			case PHY_POLL:
3657ac6653aSJeff Kirsher 				irq_str = "POLL";
3667ac6653aSJeff Kirsher 				break;
3677ac6653aSJeff Kirsher 			case PHY_IGNORE_INTERRUPT:
3687ac6653aSJeff Kirsher 				irq_str = "IGNORE";
3697ac6653aSJeff Kirsher 				break;
3707ac6653aSJeff Kirsher 			default:
3717ac6653aSJeff Kirsher 				sprintf(irq_num, "%d", phydev->irq);
3727ac6653aSJeff Kirsher 				irq_str = irq_num;
3737ac6653aSJeff Kirsher 				break;
3747ac6653aSJeff Kirsher 			}
3757ac6653aSJeff Kirsher 			pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
3767ac6653aSJeff Kirsher 				ndev->name, phydev->phy_id, addr,
37784eff6d1SAndrew Lunn 				irq_str, phydev_name(phydev),
3787ac6653aSJeff Kirsher 				act ? " active" : "");
3797ac6653aSJeff Kirsher 			found = 1;
3807ac6653aSJeff Kirsher 		}
3817ac6653aSJeff Kirsher 	}
3827ac6653aSJeff Kirsher 
383e34d6569SPhil Reid 	if (!found && !mdio_node) {
384fe3881cfSJoe Perches 		pr_warn("%s: No PHY found\n", ndev->name);
3853955b22bSGiuseppe CAVALLARO 		mdiobus_unregister(new_bus);
3863955b22bSGiuseppe CAVALLARO 		mdiobus_free(new_bus);
3873955b22bSGiuseppe CAVALLARO 		return -ENODEV;
3883955b22bSGiuseppe CAVALLARO 	}
3893955b22bSGiuseppe CAVALLARO 
390cc2fa619SPhil Reid bus_register_done:
3913955b22bSGiuseppe CAVALLARO 	priv->mii = new_bus;
3927ac6653aSJeff Kirsher 
3937ac6653aSJeff Kirsher 	return 0;
3947ac6653aSJeff Kirsher 
3957ac6653aSJeff Kirsher bus_register_fail:
3967ac6653aSJeff Kirsher 	mdiobus_free(new_bus);
3977ac6653aSJeff Kirsher 	return err;
3987ac6653aSJeff Kirsher }
3997ac6653aSJeff Kirsher 
4007ac6653aSJeff Kirsher /**
4017ac6653aSJeff Kirsher  * stmmac_mdio_unregister
4027ac6653aSJeff Kirsher  * @ndev: net device structure
4037ac6653aSJeff Kirsher  * Description: it unregisters the MII bus
4047ac6653aSJeff Kirsher  */
4057ac6653aSJeff Kirsher int stmmac_mdio_unregister(struct net_device *ndev)
4067ac6653aSJeff Kirsher {
4077ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
4087ac6653aSJeff Kirsher 
409a5cf5ce9SSrinivas Kandagatla 	if (!priv->mii)
410a5cf5ce9SSrinivas Kandagatla 		return 0;
411a5cf5ce9SSrinivas Kandagatla 
4127ac6653aSJeff Kirsher 	mdiobus_unregister(priv->mii);
4137ac6653aSJeff Kirsher 	priv->mii->priv = NULL;
4147ac6653aSJeff Kirsher 	mdiobus_free(priv->mii);
4157ac6653aSJeff Kirsher 	priv->mii = NULL;
4167ac6653aSJeff Kirsher 
4177ac6653aSJeff Kirsher 	return 0;
4187ac6653aSJeff Kirsher }
419