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>
307ac6653aSJeff Kirsher #include <asm/io.h>
317ac6653aSJeff Kirsher 
327ac6653aSJeff Kirsher #include "stmmac.h"
337ac6653aSJeff Kirsher 
347ac6653aSJeff Kirsher #define MII_BUSY 0x00000001
357ac6653aSJeff Kirsher #define MII_WRITE 0x00000002
367ac6653aSJeff Kirsher 
3739b401dbSDeepak SIKRI static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr)
3839b401dbSDeepak SIKRI {
3939b401dbSDeepak SIKRI 	unsigned long curr;
4039b401dbSDeepak SIKRI 	unsigned long finish = jiffies + 3 * HZ;
4139b401dbSDeepak SIKRI 
4239b401dbSDeepak SIKRI 	do {
4339b401dbSDeepak SIKRI 		curr = jiffies;
4439b401dbSDeepak SIKRI 		if (readl(ioaddr + mii_addr) & MII_BUSY)
4539b401dbSDeepak SIKRI 			cpu_relax();
4639b401dbSDeepak SIKRI 		else
4739b401dbSDeepak SIKRI 			return 0;
4839b401dbSDeepak SIKRI 	} while (!time_after_eq(curr, finish));
4939b401dbSDeepak SIKRI 
5039b401dbSDeepak SIKRI 	return -EBUSY;
5139b401dbSDeepak SIKRI }
5239b401dbSDeepak SIKRI 
537ac6653aSJeff Kirsher /**
547ac6653aSJeff Kirsher  * stmmac_mdio_read
557ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
567ac6653aSJeff Kirsher  * @phyaddr: MII addr reg bits 15-11
577ac6653aSJeff Kirsher  * @phyreg: MII addr reg bits 10-6
587ac6653aSJeff Kirsher  * Description: it reads data from the MII register from within the phy device.
597ac6653aSJeff Kirsher  * For the 7111 GMAC, we must set the bit 0 in the MII address register while
607ac6653aSJeff Kirsher  * accessing the PHY registers.
617ac6653aSJeff Kirsher  * Fortunately, it seems this has no drawback for the 7109 MAC.
627ac6653aSJeff Kirsher  */
637ac6653aSJeff Kirsher static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
647ac6653aSJeff Kirsher {
657ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
667ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
677ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
687ac6653aSJeff Kirsher 	unsigned int mii_data = priv->hw->mii.data;
697ac6653aSJeff Kirsher 
707ac6653aSJeff Kirsher 	int data;
717ac6653aSJeff Kirsher 	u16 regValue = (((phyaddr << 11) & (0x0000F800)) |
727ac6653aSJeff Kirsher 			((phyreg << 6) & (0x000007C0)));
73cd7201f4SGiuseppe CAVALLARO 	regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
747ac6653aSJeff Kirsher 
7539b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
7639b401dbSDeepak SIKRI 		return -EBUSY;
7739b401dbSDeepak SIKRI 
787ac6653aSJeff Kirsher 	writel(regValue, priv->ioaddr + mii_address);
7939b401dbSDeepak SIKRI 
8039b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
8139b401dbSDeepak SIKRI 		return -EBUSY;
827ac6653aSJeff Kirsher 
837ac6653aSJeff Kirsher 	/* Read the data from the MII data register */
847ac6653aSJeff Kirsher 	data = (int)readl(priv->ioaddr + mii_data);
857ac6653aSJeff Kirsher 
867ac6653aSJeff Kirsher 	return data;
877ac6653aSJeff Kirsher }
887ac6653aSJeff Kirsher 
897ac6653aSJeff Kirsher /**
907ac6653aSJeff Kirsher  * stmmac_mdio_write
917ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
927ac6653aSJeff Kirsher  * @phyaddr: MII addr reg bits 15-11
937ac6653aSJeff Kirsher  * @phyreg: MII addr reg bits 10-6
947ac6653aSJeff Kirsher  * @phydata: phy data
957ac6653aSJeff Kirsher  * Description: it writes the data into the MII register from within the device.
967ac6653aSJeff Kirsher  */
977ac6653aSJeff Kirsher static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
987ac6653aSJeff Kirsher 			     u16 phydata)
997ac6653aSJeff Kirsher {
1007ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
1017ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
1027ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
1037ac6653aSJeff Kirsher 	unsigned int mii_data = priv->hw->mii.data;
1047ac6653aSJeff Kirsher 
1057ac6653aSJeff Kirsher 	u16 value =
1067ac6653aSJeff Kirsher 	    (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0)))
1077ac6653aSJeff Kirsher 	    | MII_WRITE;
1087ac6653aSJeff Kirsher 
109cd7201f4SGiuseppe CAVALLARO 	value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2);
1107ac6653aSJeff Kirsher 
1117ac6653aSJeff Kirsher 	/* Wait until any existing MII operation is complete */
11239b401dbSDeepak SIKRI 	if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address))
11339b401dbSDeepak SIKRI 		return -EBUSY;
1147ac6653aSJeff Kirsher 
1157ac6653aSJeff Kirsher 	/* Set the MII address register to write */
1167ac6653aSJeff Kirsher 	writel(phydata, priv->ioaddr + mii_data);
1177ac6653aSJeff Kirsher 	writel(value, priv->ioaddr + mii_address);
1187ac6653aSJeff Kirsher 
1197ac6653aSJeff Kirsher 	/* Wait until any existing MII operation is complete */
12039b401dbSDeepak SIKRI 	return stmmac_mdio_busy_wait(priv->ioaddr, mii_address);
1217ac6653aSJeff Kirsher }
1227ac6653aSJeff Kirsher 
1237ac6653aSJeff Kirsher /**
1247ac6653aSJeff Kirsher  * stmmac_mdio_reset
1257ac6653aSJeff Kirsher  * @bus: points to the mii_bus structure
1267ac6653aSJeff Kirsher  * Description: reset the MII bus
1277ac6653aSJeff Kirsher  */
1287ac6653aSJeff Kirsher static int stmmac_mdio_reset(struct mii_bus *bus)
1297ac6653aSJeff Kirsher {
130bfab27a1SGiuseppe CAVALLARO #if defined(CONFIG_STMMAC_PLATFORM)
1317ac6653aSJeff Kirsher 	struct net_device *ndev = bus->priv;
1327ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
1337ac6653aSJeff Kirsher 	unsigned int mii_address = priv->hw->mii.addr;
1347ac6653aSJeff Kirsher 
1357ac6653aSJeff Kirsher 	if (priv->plat->mdio_bus_data->phy_reset) {
1367ac6653aSJeff Kirsher 		pr_debug("stmmac_mdio_reset: calling phy_reset\n");
1377ac6653aSJeff Kirsher 		priv->plat->mdio_bus_data->phy_reset(priv->plat->bsp_priv);
1387ac6653aSJeff Kirsher 	}
1397ac6653aSJeff Kirsher 
1407ac6653aSJeff Kirsher 	/* This is a workaround for problems with the STE101P PHY.
1417ac6653aSJeff Kirsher 	 * It doesn't complete its reset until at least one clock cycle
1427ac6653aSJeff Kirsher 	 * on MDC, so perform a dummy mdio read.
1437ac6653aSJeff Kirsher 	 */
1447ac6653aSJeff Kirsher 	writel(0, priv->ioaddr + mii_address);
145bfab27a1SGiuseppe CAVALLARO #endif
1467ac6653aSJeff Kirsher 	return 0;
1477ac6653aSJeff Kirsher }
1487ac6653aSJeff Kirsher 
1497ac6653aSJeff Kirsher /**
1507ac6653aSJeff Kirsher  * stmmac_mdio_register
1517ac6653aSJeff Kirsher  * @ndev: net device structure
1527ac6653aSJeff Kirsher  * Description: it registers the MII bus
1537ac6653aSJeff Kirsher  */
1547ac6653aSJeff Kirsher int stmmac_mdio_register(struct net_device *ndev)
1557ac6653aSJeff Kirsher {
1567ac6653aSJeff Kirsher 	int err = 0;
1577ac6653aSJeff Kirsher 	struct mii_bus *new_bus;
1587ac6653aSJeff Kirsher 	int *irqlist;
1597ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
1607ac6653aSJeff Kirsher 	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
1617ac6653aSJeff Kirsher 	int addr, found;
1627ac6653aSJeff Kirsher 
1637ac6653aSJeff Kirsher 	if (!mdio_bus_data)
1647ac6653aSJeff Kirsher 		return 0;
1657ac6653aSJeff Kirsher 
1667ac6653aSJeff Kirsher 	new_bus = mdiobus_alloc();
1677ac6653aSJeff Kirsher 	if (new_bus == NULL)
1687ac6653aSJeff Kirsher 		return -ENOMEM;
1697ac6653aSJeff Kirsher 
1707ac6653aSJeff Kirsher 	if (mdio_bus_data->irqs)
1717ac6653aSJeff Kirsher 		irqlist = mdio_bus_data->irqs;
1727ac6653aSJeff Kirsher 	else
1737ac6653aSJeff Kirsher 		irqlist = priv->mii_irq;
1747ac6653aSJeff Kirsher 
17590b9a545SAlessandro Rubini 	new_bus->name = "stmmac";
1767ac6653aSJeff Kirsher 	new_bus->read = &stmmac_mdio_read;
1777ac6653aSJeff Kirsher 	new_bus->write = &stmmac_mdio_write;
1787ac6653aSJeff Kirsher 	new_bus->reset = &stmmac_mdio_reset;
179db8857bfSFlorian Fainelli 	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
180db8857bfSFlorian Fainelli 		new_bus->name, mdio_bus_data->bus_id);
1817ac6653aSJeff Kirsher 	new_bus->priv = ndev;
1827ac6653aSJeff Kirsher 	new_bus->irq = irqlist;
1837ac6653aSJeff Kirsher 	new_bus->phy_mask = mdio_bus_data->phy_mask;
1847ac6653aSJeff Kirsher 	new_bus->parent = priv->device;
1857ac6653aSJeff Kirsher 	err = mdiobus_register(new_bus);
1867ac6653aSJeff Kirsher 	if (err != 0) {
1877ac6653aSJeff Kirsher 		pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
1887ac6653aSJeff Kirsher 		goto bus_register_fail;
1897ac6653aSJeff Kirsher 	}
1907ac6653aSJeff Kirsher 
1917ac6653aSJeff Kirsher 	priv->mii = new_bus;
1927ac6653aSJeff Kirsher 
1937ac6653aSJeff Kirsher 	found = 0;
1947ac6653aSJeff Kirsher 	for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
1957ac6653aSJeff Kirsher 		struct phy_device *phydev = new_bus->phy_map[addr];
1967ac6653aSJeff Kirsher 		if (phydev) {
1977ac6653aSJeff Kirsher 			int act = 0;
1987ac6653aSJeff Kirsher 			char irq_num[4];
1997ac6653aSJeff Kirsher 			char *irq_str;
2007ac6653aSJeff Kirsher 
2017ac6653aSJeff Kirsher 			/*
2027ac6653aSJeff Kirsher 			 * If an IRQ was provided to be assigned after
2037ac6653aSJeff Kirsher 			 * the bus probe, do it here.
2047ac6653aSJeff Kirsher 			 */
2057ac6653aSJeff Kirsher 			if ((mdio_bus_data->irqs == NULL) &&
2067ac6653aSJeff Kirsher 			    (mdio_bus_data->probed_phy_irq > 0)) {
2077ac6653aSJeff Kirsher 				irqlist[addr] = mdio_bus_data->probed_phy_irq;
2087ac6653aSJeff Kirsher 				phydev->irq = mdio_bus_data->probed_phy_irq;
2097ac6653aSJeff Kirsher 			}
2107ac6653aSJeff Kirsher 
2117ac6653aSJeff Kirsher 			/*
2127ac6653aSJeff Kirsher 			 * If we're  going to bind the MAC to this PHY bus,
2137ac6653aSJeff Kirsher 			 * and no PHY number was provided to the MAC,
2147ac6653aSJeff Kirsher 			 * use the one probed here.
2157ac6653aSJeff Kirsher 			 */
2167ac6653aSJeff Kirsher 			if ((priv->plat->bus_id == mdio_bus_data->bus_id) &&
2177ac6653aSJeff Kirsher 			    (priv->plat->phy_addr == -1))
2187ac6653aSJeff Kirsher 				priv->plat->phy_addr = addr;
2197ac6653aSJeff Kirsher 
2207ac6653aSJeff Kirsher 			act = (priv->plat->bus_id == mdio_bus_data->bus_id) &&
2217ac6653aSJeff Kirsher 				(priv->plat->phy_addr == addr);
2227ac6653aSJeff Kirsher 			switch (phydev->irq) {
2237ac6653aSJeff Kirsher 			case PHY_POLL:
2247ac6653aSJeff Kirsher 				irq_str = "POLL";
2257ac6653aSJeff Kirsher 				break;
2267ac6653aSJeff Kirsher 			case PHY_IGNORE_INTERRUPT:
2277ac6653aSJeff Kirsher 				irq_str = "IGNORE";
2287ac6653aSJeff Kirsher 				break;
2297ac6653aSJeff Kirsher 			default:
2307ac6653aSJeff Kirsher 				sprintf(irq_num, "%d", phydev->irq);
2317ac6653aSJeff Kirsher 				irq_str = irq_num;
2327ac6653aSJeff Kirsher 				break;
2337ac6653aSJeff Kirsher 			}
2347ac6653aSJeff Kirsher 			pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
2357ac6653aSJeff Kirsher 				ndev->name, phydev->phy_id, addr,
2367ac6653aSJeff Kirsher 				irq_str, dev_name(&phydev->dev),
2377ac6653aSJeff Kirsher 				act ? " active" : "");
2387ac6653aSJeff Kirsher 			found = 1;
2397ac6653aSJeff Kirsher 		}
2407ac6653aSJeff Kirsher 	}
2417ac6653aSJeff Kirsher 
2427ac6653aSJeff Kirsher 	if (!found)
2437ac6653aSJeff Kirsher 		pr_warning("%s: No PHY found\n", ndev->name);
2447ac6653aSJeff Kirsher 
2457ac6653aSJeff Kirsher 	return 0;
2467ac6653aSJeff Kirsher 
2477ac6653aSJeff Kirsher bus_register_fail:
2487ac6653aSJeff Kirsher 	mdiobus_free(new_bus);
2497ac6653aSJeff Kirsher 	return err;
2507ac6653aSJeff Kirsher }
2517ac6653aSJeff Kirsher 
2527ac6653aSJeff Kirsher /**
2537ac6653aSJeff Kirsher  * stmmac_mdio_unregister
2547ac6653aSJeff Kirsher  * @ndev: net device structure
2557ac6653aSJeff Kirsher  * Description: it unregisters the MII bus
2567ac6653aSJeff Kirsher  */
2577ac6653aSJeff Kirsher int stmmac_mdio_unregister(struct net_device *ndev)
2587ac6653aSJeff Kirsher {
2597ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2607ac6653aSJeff Kirsher 
261a5cf5ce9SSrinivas Kandagatla 	if (!priv->mii)
262a5cf5ce9SSrinivas Kandagatla 		return 0;
263a5cf5ce9SSrinivas Kandagatla 
2647ac6653aSJeff Kirsher 	mdiobus_unregister(priv->mii);
2657ac6653aSJeff Kirsher 	priv->mii->priv = NULL;
2667ac6653aSJeff Kirsher 	mdiobus_free(priv->mii);
2677ac6653aSJeff Kirsher 	priv->mii = NULL;
2687ac6653aSJeff Kirsher 
2697ac6653aSJeff Kirsher 	return 0;
2707ac6653aSJeff Kirsher }
271