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> 320e076471SSrinivas Kandagatla 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 4039b401dbSDeepak SIKRI static int stmmac_mdio_busy_wait(void __iomem *ioaddr, unsigned int mii_addr) 4139b401dbSDeepak SIKRI { 4239b401dbSDeepak SIKRI unsigned long curr; 4339b401dbSDeepak SIKRI unsigned long finish = jiffies + 3 * HZ; 4439b401dbSDeepak SIKRI 4539b401dbSDeepak SIKRI do { 4639b401dbSDeepak SIKRI curr = jiffies; 4739b401dbSDeepak SIKRI if (readl(ioaddr + mii_addr) & MII_BUSY) 4839b401dbSDeepak SIKRI cpu_relax(); 4939b401dbSDeepak SIKRI else 5039b401dbSDeepak SIKRI return 0; 5139b401dbSDeepak SIKRI } while (!time_after_eq(curr, finish)); 5239b401dbSDeepak SIKRI 5339b401dbSDeepak SIKRI return -EBUSY; 5439b401dbSDeepak SIKRI } 5539b401dbSDeepak SIKRI 567ac6653aSJeff Kirsher /** 577ac6653aSJeff Kirsher * stmmac_mdio_read 587ac6653aSJeff Kirsher * @bus: points to the mii_bus structure 597ac6653aSJeff Kirsher * @phyaddr: MII addr reg bits 15-11 607ac6653aSJeff Kirsher * @phyreg: MII addr reg bits 10-6 617ac6653aSJeff Kirsher * Description: it reads data from the MII register from within the phy device. 627ac6653aSJeff Kirsher * For the 7111 GMAC, we must set the bit 0 in the MII address register while 637ac6653aSJeff Kirsher * accessing the PHY registers. 647ac6653aSJeff Kirsher * Fortunately, it seems this has no drawback for the 7109 MAC. 657ac6653aSJeff Kirsher */ 667ac6653aSJeff Kirsher static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) 677ac6653aSJeff Kirsher { 687ac6653aSJeff Kirsher struct net_device *ndev = bus->priv; 697ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 707ac6653aSJeff Kirsher unsigned int mii_address = priv->hw->mii.addr; 717ac6653aSJeff Kirsher unsigned int mii_data = priv->hw->mii.data; 727ac6653aSJeff Kirsher 737ac6653aSJeff Kirsher int data; 747ac6653aSJeff Kirsher u16 regValue = (((phyaddr << 11) & (0x0000F800)) | 757ac6653aSJeff Kirsher ((phyreg << 6) & (0x000007C0))); 76cd7201f4SGiuseppe CAVALLARO regValue |= MII_BUSY | ((priv->clk_csr & 0xF) << 2); 777ac6653aSJeff Kirsher 7839b401dbSDeepak SIKRI if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) 7939b401dbSDeepak SIKRI return -EBUSY; 8039b401dbSDeepak SIKRI 817ac6653aSJeff Kirsher writel(regValue, priv->ioaddr + mii_address); 8239b401dbSDeepak SIKRI 8339b401dbSDeepak SIKRI if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) 8439b401dbSDeepak SIKRI return -EBUSY; 857ac6653aSJeff Kirsher 867ac6653aSJeff Kirsher /* Read the data from the MII data register */ 877ac6653aSJeff Kirsher data = (int)readl(priv->ioaddr + mii_data); 887ac6653aSJeff Kirsher 897ac6653aSJeff Kirsher return data; 907ac6653aSJeff Kirsher } 917ac6653aSJeff Kirsher 927ac6653aSJeff Kirsher /** 937ac6653aSJeff Kirsher * stmmac_mdio_write 947ac6653aSJeff Kirsher * @bus: points to the mii_bus structure 957ac6653aSJeff Kirsher * @phyaddr: MII addr reg bits 15-11 967ac6653aSJeff Kirsher * @phyreg: MII addr reg bits 10-6 977ac6653aSJeff Kirsher * @phydata: phy data 987ac6653aSJeff Kirsher * Description: it writes the data into the MII register from within the device. 997ac6653aSJeff Kirsher */ 1007ac6653aSJeff Kirsher static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, 1017ac6653aSJeff Kirsher u16 phydata) 1027ac6653aSJeff Kirsher { 1037ac6653aSJeff Kirsher struct net_device *ndev = bus->priv; 1047ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 1057ac6653aSJeff Kirsher unsigned int mii_address = priv->hw->mii.addr; 1067ac6653aSJeff Kirsher unsigned int mii_data = priv->hw->mii.data; 1077ac6653aSJeff Kirsher 1087ac6653aSJeff Kirsher u16 value = 1097ac6653aSJeff Kirsher (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))) 1107ac6653aSJeff Kirsher | MII_WRITE; 1117ac6653aSJeff Kirsher 112cd7201f4SGiuseppe CAVALLARO value |= MII_BUSY | ((priv->clk_csr & 0xF) << 2); 1137ac6653aSJeff Kirsher 1147ac6653aSJeff Kirsher /* Wait until any existing MII operation is complete */ 11539b401dbSDeepak SIKRI if (stmmac_mdio_busy_wait(priv->ioaddr, mii_address)) 11639b401dbSDeepak SIKRI return -EBUSY; 1177ac6653aSJeff Kirsher 1187ac6653aSJeff Kirsher /* Set the MII address register to write */ 1197ac6653aSJeff Kirsher writel(phydata, priv->ioaddr + mii_data); 1207ac6653aSJeff Kirsher writel(value, priv->ioaddr + mii_address); 1217ac6653aSJeff Kirsher 1227ac6653aSJeff Kirsher /* Wait until any existing MII operation is complete */ 12339b401dbSDeepak SIKRI return stmmac_mdio_busy_wait(priv->ioaddr, mii_address); 1247ac6653aSJeff Kirsher } 1257ac6653aSJeff Kirsher 1267ac6653aSJeff Kirsher /** 1277ac6653aSJeff Kirsher * stmmac_mdio_reset 1287ac6653aSJeff Kirsher * @bus: points to the mii_bus structure 1297ac6653aSJeff Kirsher * Description: reset the MII bus 1307ac6653aSJeff Kirsher */ 1317ac6653aSJeff Kirsher static int stmmac_mdio_reset(struct mii_bus *bus) 1327ac6653aSJeff Kirsher { 133bfab27a1SGiuseppe CAVALLARO #if defined(CONFIG_STMMAC_PLATFORM) 1347ac6653aSJeff Kirsher struct net_device *ndev = bus->priv; 1357ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 1367ac6653aSJeff Kirsher unsigned int mii_address = priv->hw->mii.addr; 1370e076471SSrinivas Kandagatla struct stmmac_mdio_bus_data *data = priv->plat->mdio_bus_data; 1387ac6653aSJeff Kirsher 1390e076471SSrinivas Kandagatla #ifdef CONFIG_OF 1400e076471SSrinivas Kandagatla if (priv->device->of_node) { 1410e076471SSrinivas Kandagatla int reset_gpio, active_low; 1420e076471SSrinivas Kandagatla 1430e076471SSrinivas Kandagatla if (data->reset_gpio < 0) { 1440e076471SSrinivas Kandagatla struct device_node *np = priv->device->of_node; 1450e076471SSrinivas Kandagatla if (!np) 1460e076471SSrinivas Kandagatla return 0; 1470e076471SSrinivas Kandagatla 1480e076471SSrinivas Kandagatla data->reset_gpio = of_get_named_gpio(np, 1490e076471SSrinivas Kandagatla "snps,reset-gpio", 0); 1500e076471SSrinivas Kandagatla if (data->reset_gpio < 0) 1510e076471SSrinivas Kandagatla return 0; 1520e076471SSrinivas Kandagatla 1530e076471SSrinivas Kandagatla data->active_low = of_property_read_bool(np, 1540e076471SSrinivas Kandagatla "snps,reset-active-low"); 1550e076471SSrinivas Kandagatla of_property_read_u32_array(np, 1560e076471SSrinivas Kandagatla "snps,reset-delays-us", data->delays, 3); 1570e076471SSrinivas Kandagatla } 1580e076471SSrinivas Kandagatla 1590e076471SSrinivas Kandagatla reset_gpio = data->reset_gpio; 1600e076471SSrinivas Kandagatla active_low = data->active_low; 1610e076471SSrinivas Kandagatla 1620e076471SSrinivas Kandagatla if (!gpio_request(reset_gpio, "mdio-reset")) { 1630e076471SSrinivas Kandagatla gpio_direction_output(reset_gpio, active_low ? 1 : 0); 1640e076471SSrinivas Kandagatla udelay(data->delays[0]); 1650e076471SSrinivas Kandagatla gpio_set_value(reset_gpio, active_low ? 0 : 1); 1660e076471SSrinivas Kandagatla udelay(data->delays[1]); 1670e076471SSrinivas Kandagatla gpio_set_value(reset_gpio, active_low ? 1 : 0); 1680e076471SSrinivas Kandagatla udelay(data->delays[2]); 1690e076471SSrinivas Kandagatla gpio_free(reset_gpio); 1700e076471SSrinivas Kandagatla } 1710e076471SSrinivas Kandagatla } 1720e076471SSrinivas Kandagatla #endif 1730e076471SSrinivas Kandagatla 1740e076471SSrinivas Kandagatla if (data->phy_reset) { 1757ac6653aSJeff Kirsher pr_debug("stmmac_mdio_reset: calling phy_reset\n"); 1760e076471SSrinivas Kandagatla data->phy_reset(priv->plat->bsp_priv); 1777ac6653aSJeff Kirsher } 1787ac6653aSJeff Kirsher 1797ac6653aSJeff Kirsher /* This is a workaround for problems with the STE101P PHY. 1807ac6653aSJeff Kirsher * It doesn't complete its reset until at least one clock cycle 1817ac6653aSJeff Kirsher * on MDC, so perform a dummy mdio read. 1827ac6653aSJeff Kirsher */ 1837ac6653aSJeff Kirsher writel(0, priv->ioaddr + mii_address); 184bfab27a1SGiuseppe CAVALLARO #endif 1857ac6653aSJeff Kirsher return 0; 1867ac6653aSJeff Kirsher } 1877ac6653aSJeff Kirsher 1887ac6653aSJeff Kirsher /** 1897ac6653aSJeff Kirsher * stmmac_mdio_register 1907ac6653aSJeff Kirsher * @ndev: net device structure 1917ac6653aSJeff Kirsher * Description: it registers the MII bus 1927ac6653aSJeff Kirsher */ 1937ac6653aSJeff Kirsher int stmmac_mdio_register(struct net_device *ndev) 1947ac6653aSJeff Kirsher { 1957ac6653aSJeff Kirsher int err = 0; 1967ac6653aSJeff Kirsher struct mii_bus *new_bus; 1977ac6653aSJeff Kirsher int *irqlist; 1987ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 1997ac6653aSJeff Kirsher struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; 2007ac6653aSJeff Kirsher int addr, found; 2017ac6653aSJeff Kirsher 2027ac6653aSJeff Kirsher if (!mdio_bus_data) 2037ac6653aSJeff Kirsher return 0; 2047ac6653aSJeff Kirsher 2057ac6653aSJeff Kirsher new_bus = mdiobus_alloc(); 2067ac6653aSJeff Kirsher if (new_bus == NULL) 2077ac6653aSJeff Kirsher return -ENOMEM; 2087ac6653aSJeff Kirsher 2097ac6653aSJeff Kirsher if (mdio_bus_data->irqs) 2107ac6653aSJeff Kirsher irqlist = mdio_bus_data->irqs; 2117ac6653aSJeff Kirsher else 2127ac6653aSJeff Kirsher irqlist = priv->mii_irq; 2137ac6653aSJeff Kirsher 2140e076471SSrinivas Kandagatla #ifdef CONFIG_OF 2150e076471SSrinivas Kandagatla if (priv->device->of_node) 2160e076471SSrinivas Kandagatla mdio_bus_data->reset_gpio = -1; 2170e076471SSrinivas Kandagatla #endif 2180e076471SSrinivas Kandagatla 21990b9a545SAlessandro Rubini new_bus->name = "stmmac"; 2207ac6653aSJeff Kirsher new_bus->read = &stmmac_mdio_read; 2217ac6653aSJeff Kirsher new_bus->write = &stmmac_mdio_write; 2227ac6653aSJeff Kirsher new_bus->reset = &stmmac_mdio_reset; 223db8857bfSFlorian Fainelli snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", 224d56631a6SSrinivas Kandagatla new_bus->name, priv->plat->bus_id); 2257ac6653aSJeff Kirsher new_bus->priv = ndev; 2267ac6653aSJeff Kirsher new_bus->irq = irqlist; 2277ac6653aSJeff Kirsher new_bus->phy_mask = mdio_bus_data->phy_mask; 2287ac6653aSJeff Kirsher new_bus->parent = priv->device; 2297ac6653aSJeff Kirsher err = mdiobus_register(new_bus); 2307ac6653aSJeff Kirsher if (err != 0) { 2317ac6653aSJeff Kirsher pr_err("%s: Cannot register as MDIO bus\n", new_bus->name); 2327ac6653aSJeff Kirsher goto bus_register_fail; 2337ac6653aSJeff Kirsher } 2347ac6653aSJeff Kirsher 2357ac6653aSJeff Kirsher found = 0; 2367ac6653aSJeff Kirsher for (addr = 0; addr < PHY_MAX_ADDR; addr++) { 2377ac6653aSJeff Kirsher struct phy_device *phydev = new_bus->phy_map[addr]; 2387ac6653aSJeff Kirsher if (phydev) { 2397ac6653aSJeff Kirsher int act = 0; 2407ac6653aSJeff Kirsher char irq_num[4]; 2417ac6653aSJeff Kirsher char *irq_str; 2427ac6653aSJeff Kirsher 2437ac6653aSJeff Kirsher /* 2447ac6653aSJeff Kirsher * If an IRQ was provided to be assigned after 2457ac6653aSJeff Kirsher * the bus probe, do it here. 2467ac6653aSJeff Kirsher */ 2477ac6653aSJeff Kirsher if ((mdio_bus_data->irqs == NULL) && 2487ac6653aSJeff Kirsher (mdio_bus_data->probed_phy_irq > 0)) { 2497ac6653aSJeff Kirsher irqlist[addr] = mdio_bus_data->probed_phy_irq; 2507ac6653aSJeff Kirsher phydev->irq = mdio_bus_data->probed_phy_irq; 2517ac6653aSJeff Kirsher } 2527ac6653aSJeff Kirsher 2537ac6653aSJeff Kirsher /* 2547ac6653aSJeff Kirsher * If we're going to bind the MAC to this PHY bus, 2557ac6653aSJeff Kirsher * and no PHY number was provided to the MAC, 2567ac6653aSJeff Kirsher * use the one probed here. 2577ac6653aSJeff Kirsher */ 258d56631a6SSrinivas Kandagatla if (priv->plat->phy_addr == -1) 2597ac6653aSJeff Kirsher priv->plat->phy_addr = addr; 2607ac6653aSJeff Kirsher 261d56631a6SSrinivas Kandagatla act = (priv->plat->phy_addr == addr); 2627ac6653aSJeff Kirsher switch (phydev->irq) { 2637ac6653aSJeff Kirsher case PHY_POLL: 2647ac6653aSJeff Kirsher irq_str = "POLL"; 2657ac6653aSJeff Kirsher break; 2667ac6653aSJeff Kirsher case PHY_IGNORE_INTERRUPT: 2677ac6653aSJeff Kirsher irq_str = "IGNORE"; 2687ac6653aSJeff Kirsher break; 2697ac6653aSJeff Kirsher default: 2707ac6653aSJeff Kirsher sprintf(irq_num, "%d", phydev->irq); 2717ac6653aSJeff Kirsher irq_str = irq_num; 2727ac6653aSJeff Kirsher break; 2737ac6653aSJeff Kirsher } 2747ac6653aSJeff Kirsher pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n", 2757ac6653aSJeff Kirsher ndev->name, phydev->phy_id, addr, 2767ac6653aSJeff Kirsher irq_str, dev_name(&phydev->dev), 2777ac6653aSJeff Kirsher act ? " active" : ""); 2787ac6653aSJeff Kirsher found = 1; 2797ac6653aSJeff Kirsher } 2807ac6653aSJeff Kirsher } 2817ac6653aSJeff Kirsher 2823955b22bSGiuseppe CAVALLARO if (!found) { 2837ac6653aSJeff Kirsher pr_warning("%s: No PHY found\n", ndev->name); 2843955b22bSGiuseppe CAVALLARO mdiobus_unregister(new_bus); 2853955b22bSGiuseppe CAVALLARO mdiobus_free(new_bus); 2863955b22bSGiuseppe CAVALLARO return -ENODEV; 2873955b22bSGiuseppe CAVALLARO } 2883955b22bSGiuseppe CAVALLARO 2893955b22bSGiuseppe CAVALLARO priv->mii = new_bus; 2907ac6653aSJeff Kirsher 2917ac6653aSJeff Kirsher return 0; 2927ac6653aSJeff Kirsher 2937ac6653aSJeff Kirsher bus_register_fail: 2947ac6653aSJeff Kirsher mdiobus_free(new_bus); 2957ac6653aSJeff Kirsher return err; 2967ac6653aSJeff Kirsher } 2977ac6653aSJeff Kirsher 2987ac6653aSJeff Kirsher /** 2997ac6653aSJeff Kirsher * stmmac_mdio_unregister 3007ac6653aSJeff Kirsher * @ndev: net device structure 3017ac6653aSJeff Kirsher * Description: it unregisters the MII bus 3027ac6653aSJeff Kirsher */ 3037ac6653aSJeff Kirsher int stmmac_mdio_unregister(struct net_device *ndev) 3047ac6653aSJeff Kirsher { 3057ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 3067ac6653aSJeff Kirsher 307a5cf5ce9SSrinivas Kandagatla if (!priv->mii) 308a5cf5ce9SSrinivas Kandagatla return 0; 309a5cf5ce9SSrinivas Kandagatla 3107ac6653aSJeff Kirsher mdiobus_unregister(priv->mii); 3117ac6653aSJeff Kirsher priv->mii->priv = NULL; 3127ac6653aSJeff Kirsher mdiobus_free(priv->mii); 3137ac6653aSJeff Kirsher priv->mii = NULL; 3147ac6653aSJeff Kirsher 3157ac6653aSJeff Kirsher return 0; 3167ac6653aSJeff Kirsher } 317