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 377ac6653aSJeff Kirsher /** 387ac6653aSJeff Kirsher * stmmac_mdio_read 397ac6653aSJeff Kirsher * @bus: points to the mii_bus structure 407ac6653aSJeff Kirsher * @phyaddr: MII addr reg bits 15-11 417ac6653aSJeff Kirsher * @phyreg: MII addr reg bits 10-6 427ac6653aSJeff Kirsher * Description: it reads data from the MII register from within the phy device. 437ac6653aSJeff Kirsher * For the 7111 GMAC, we must set the bit 0 in the MII address register while 447ac6653aSJeff Kirsher * accessing the PHY registers. 457ac6653aSJeff Kirsher * Fortunately, it seems this has no drawback for the 7109 MAC. 467ac6653aSJeff Kirsher */ 477ac6653aSJeff Kirsher static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) 487ac6653aSJeff Kirsher { 497ac6653aSJeff Kirsher struct net_device *ndev = bus->priv; 507ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 517ac6653aSJeff Kirsher unsigned int mii_address = priv->hw->mii.addr; 527ac6653aSJeff Kirsher unsigned int mii_data = priv->hw->mii.data; 537ac6653aSJeff Kirsher 547ac6653aSJeff Kirsher int data; 557ac6653aSJeff Kirsher u16 regValue = (((phyaddr << 11) & (0x0000F800)) | 567ac6653aSJeff Kirsher ((phyreg << 6) & (0x000007C0))); 577ac6653aSJeff Kirsher regValue |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2); 587ac6653aSJeff Kirsher 597ac6653aSJeff Kirsher do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); 607ac6653aSJeff Kirsher writel(regValue, priv->ioaddr + mii_address); 617ac6653aSJeff Kirsher do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); 627ac6653aSJeff Kirsher 637ac6653aSJeff Kirsher /* Read the data from the MII data register */ 647ac6653aSJeff Kirsher data = (int)readl(priv->ioaddr + mii_data); 657ac6653aSJeff Kirsher 667ac6653aSJeff Kirsher return data; 677ac6653aSJeff Kirsher } 687ac6653aSJeff Kirsher 697ac6653aSJeff Kirsher /** 707ac6653aSJeff Kirsher * stmmac_mdio_write 717ac6653aSJeff Kirsher * @bus: points to the mii_bus structure 727ac6653aSJeff Kirsher * @phyaddr: MII addr reg bits 15-11 737ac6653aSJeff Kirsher * @phyreg: MII addr reg bits 10-6 747ac6653aSJeff Kirsher * @phydata: phy data 757ac6653aSJeff Kirsher * Description: it writes the data into the MII register from within the device. 767ac6653aSJeff Kirsher */ 777ac6653aSJeff Kirsher static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, 787ac6653aSJeff Kirsher u16 phydata) 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 u16 value = 867ac6653aSJeff Kirsher (((phyaddr << 11) & (0x0000F800)) | ((phyreg << 6) & (0x000007C0))) 877ac6653aSJeff Kirsher | MII_WRITE; 887ac6653aSJeff Kirsher 897ac6653aSJeff Kirsher value |= MII_BUSY | ((priv->plat->clk_csr & 7) << 2); 907ac6653aSJeff Kirsher 917ac6653aSJeff Kirsher 927ac6653aSJeff Kirsher /* Wait until any existing MII operation is complete */ 937ac6653aSJeff Kirsher do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); 947ac6653aSJeff Kirsher 957ac6653aSJeff Kirsher /* Set the MII address register to write */ 967ac6653aSJeff Kirsher writel(phydata, priv->ioaddr + mii_data); 977ac6653aSJeff Kirsher writel(value, priv->ioaddr + mii_address); 987ac6653aSJeff Kirsher 997ac6653aSJeff Kirsher /* Wait until any existing MII operation is complete */ 1007ac6653aSJeff Kirsher do {} while (((readl(priv->ioaddr + mii_address)) & MII_BUSY) == 1); 1017ac6653aSJeff Kirsher 1027ac6653aSJeff Kirsher return 0; 1037ac6653aSJeff Kirsher } 1047ac6653aSJeff Kirsher 1057ac6653aSJeff Kirsher /** 1067ac6653aSJeff Kirsher * stmmac_mdio_reset 1077ac6653aSJeff Kirsher * @bus: points to the mii_bus structure 1087ac6653aSJeff Kirsher * Description: reset the MII bus 1097ac6653aSJeff Kirsher */ 1107ac6653aSJeff Kirsher static int stmmac_mdio_reset(struct mii_bus *bus) 1117ac6653aSJeff Kirsher { 112bfab27a1SGiuseppe CAVALLARO #if defined(CONFIG_STMMAC_PLATFORM) 1137ac6653aSJeff Kirsher struct net_device *ndev = bus->priv; 1147ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 1157ac6653aSJeff Kirsher unsigned int mii_address = priv->hw->mii.addr; 1167ac6653aSJeff Kirsher 1177ac6653aSJeff Kirsher if (priv->plat->mdio_bus_data->phy_reset) { 1187ac6653aSJeff Kirsher pr_debug("stmmac_mdio_reset: calling phy_reset\n"); 1197ac6653aSJeff Kirsher priv->plat->mdio_bus_data->phy_reset(priv->plat->bsp_priv); 1207ac6653aSJeff Kirsher } 1217ac6653aSJeff Kirsher 1227ac6653aSJeff Kirsher /* This is a workaround for problems with the STE101P PHY. 1237ac6653aSJeff Kirsher * It doesn't complete its reset until at least one clock cycle 1247ac6653aSJeff Kirsher * on MDC, so perform a dummy mdio read. 1257ac6653aSJeff Kirsher */ 1267ac6653aSJeff Kirsher writel(0, priv->ioaddr + mii_address); 127bfab27a1SGiuseppe CAVALLARO #endif 1287ac6653aSJeff Kirsher return 0; 1297ac6653aSJeff Kirsher } 1307ac6653aSJeff Kirsher 1317ac6653aSJeff Kirsher /** 1327ac6653aSJeff Kirsher * stmmac_mdio_register 1337ac6653aSJeff Kirsher * @ndev: net device structure 1347ac6653aSJeff Kirsher * Description: it registers the MII bus 1357ac6653aSJeff Kirsher */ 1367ac6653aSJeff Kirsher int stmmac_mdio_register(struct net_device *ndev) 1377ac6653aSJeff Kirsher { 1387ac6653aSJeff Kirsher int err = 0; 1397ac6653aSJeff Kirsher struct mii_bus *new_bus; 1407ac6653aSJeff Kirsher int *irqlist; 1417ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 1427ac6653aSJeff Kirsher struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; 1437ac6653aSJeff Kirsher int addr, found; 1447ac6653aSJeff Kirsher 1457ac6653aSJeff Kirsher if (!mdio_bus_data) 1467ac6653aSJeff Kirsher return 0; 1477ac6653aSJeff Kirsher 1487ac6653aSJeff Kirsher new_bus = mdiobus_alloc(); 1497ac6653aSJeff Kirsher if (new_bus == NULL) 1507ac6653aSJeff Kirsher return -ENOMEM; 1517ac6653aSJeff Kirsher 1527ac6653aSJeff Kirsher if (mdio_bus_data->irqs) 1537ac6653aSJeff Kirsher irqlist = mdio_bus_data->irqs; 1547ac6653aSJeff Kirsher else 1557ac6653aSJeff Kirsher irqlist = priv->mii_irq; 1567ac6653aSJeff Kirsher 1577ac6653aSJeff Kirsher new_bus->name = "STMMAC MII Bus"; 1587ac6653aSJeff Kirsher new_bus->read = &stmmac_mdio_read; 1597ac6653aSJeff Kirsher new_bus->write = &stmmac_mdio_write; 1607ac6653aSJeff Kirsher new_bus->reset = &stmmac_mdio_reset; 161db8857bfSFlorian Fainelli snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", 162db8857bfSFlorian Fainelli new_bus->name, mdio_bus_data->bus_id); 1637ac6653aSJeff Kirsher new_bus->priv = ndev; 1647ac6653aSJeff Kirsher new_bus->irq = irqlist; 1657ac6653aSJeff Kirsher new_bus->phy_mask = mdio_bus_data->phy_mask; 1667ac6653aSJeff Kirsher new_bus->parent = priv->device; 1677ac6653aSJeff Kirsher err = mdiobus_register(new_bus); 1687ac6653aSJeff Kirsher if (err != 0) { 1697ac6653aSJeff Kirsher pr_err("%s: Cannot register as MDIO bus\n", new_bus->name); 1707ac6653aSJeff Kirsher goto bus_register_fail; 1717ac6653aSJeff Kirsher } 1727ac6653aSJeff Kirsher 1737ac6653aSJeff Kirsher priv->mii = new_bus; 1747ac6653aSJeff Kirsher 1757ac6653aSJeff Kirsher found = 0; 1767ac6653aSJeff Kirsher for (addr = 0; addr < PHY_MAX_ADDR; addr++) { 1777ac6653aSJeff Kirsher struct phy_device *phydev = new_bus->phy_map[addr]; 1787ac6653aSJeff Kirsher if (phydev) { 1797ac6653aSJeff Kirsher int act = 0; 1807ac6653aSJeff Kirsher char irq_num[4]; 1817ac6653aSJeff Kirsher char *irq_str; 1827ac6653aSJeff Kirsher 1837ac6653aSJeff Kirsher /* 1847ac6653aSJeff Kirsher * If an IRQ was provided to be assigned after 1857ac6653aSJeff Kirsher * the bus probe, do it here. 1867ac6653aSJeff Kirsher */ 1877ac6653aSJeff Kirsher if ((mdio_bus_data->irqs == NULL) && 1887ac6653aSJeff Kirsher (mdio_bus_data->probed_phy_irq > 0)) { 1897ac6653aSJeff Kirsher irqlist[addr] = mdio_bus_data->probed_phy_irq; 1907ac6653aSJeff Kirsher phydev->irq = mdio_bus_data->probed_phy_irq; 1917ac6653aSJeff Kirsher } 1927ac6653aSJeff Kirsher 1937ac6653aSJeff Kirsher /* 1947ac6653aSJeff Kirsher * If we're going to bind the MAC to this PHY bus, 1957ac6653aSJeff Kirsher * and no PHY number was provided to the MAC, 1967ac6653aSJeff Kirsher * use the one probed here. 1977ac6653aSJeff Kirsher */ 1987ac6653aSJeff Kirsher if ((priv->plat->bus_id == mdio_bus_data->bus_id) && 1997ac6653aSJeff Kirsher (priv->plat->phy_addr == -1)) 2007ac6653aSJeff Kirsher priv->plat->phy_addr = addr; 2017ac6653aSJeff Kirsher 2027ac6653aSJeff Kirsher act = (priv->plat->bus_id == mdio_bus_data->bus_id) && 2037ac6653aSJeff Kirsher (priv->plat->phy_addr == addr); 2047ac6653aSJeff Kirsher switch (phydev->irq) { 2057ac6653aSJeff Kirsher case PHY_POLL: 2067ac6653aSJeff Kirsher irq_str = "POLL"; 2077ac6653aSJeff Kirsher break; 2087ac6653aSJeff Kirsher case PHY_IGNORE_INTERRUPT: 2097ac6653aSJeff Kirsher irq_str = "IGNORE"; 2107ac6653aSJeff Kirsher break; 2117ac6653aSJeff Kirsher default: 2127ac6653aSJeff Kirsher sprintf(irq_num, "%d", phydev->irq); 2137ac6653aSJeff Kirsher irq_str = irq_num; 2147ac6653aSJeff Kirsher break; 2157ac6653aSJeff Kirsher } 2167ac6653aSJeff Kirsher pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n", 2177ac6653aSJeff Kirsher ndev->name, phydev->phy_id, addr, 2187ac6653aSJeff Kirsher irq_str, dev_name(&phydev->dev), 2197ac6653aSJeff Kirsher act ? " active" : ""); 2207ac6653aSJeff Kirsher found = 1; 2217ac6653aSJeff Kirsher } 2227ac6653aSJeff Kirsher } 2237ac6653aSJeff Kirsher 2247ac6653aSJeff Kirsher if (!found) 2257ac6653aSJeff Kirsher pr_warning("%s: No PHY found\n", ndev->name); 2267ac6653aSJeff Kirsher 2277ac6653aSJeff Kirsher return 0; 2287ac6653aSJeff Kirsher 2297ac6653aSJeff Kirsher bus_register_fail: 2307ac6653aSJeff Kirsher mdiobus_free(new_bus); 2317ac6653aSJeff Kirsher return err; 2327ac6653aSJeff Kirsher } 2337ac6653aSJeff Kirsher 2347ac6653aSJeff Kirsher /** 2357ac6653aSJeff Kirsher * stmmac_mdio_unregister 2367ac6653aSJeff Kirsher * @ndev: net device structure 2377ac6653aSJeff Kirsher * Description: it unregisters the MII bus 2387ac6653aSJeff Kirsher */ 2397ac6653aSJeff Kirsher int stmmac_mdio_unregister(struct net_device *ndev) 2407ac6653aSJeff Kirsher { 2417ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 2427ac6653aSJeff Kirsher 2437ac6653aSJeff Kirsher mdiobus_unregister(priv->mii); 2447ac6653aSJeff Kirsher priv->mii->priv = NULL; 2457ac6653aSJeff Kirsher mdiobus_free(priv->mii); 2467ac6653aSJeff Kirsher priv->mii = NULL; 2477ac6653aSJeff Kirsher 2487ac6653aSJeff Kirsher return 0; 2497ac6653aSJeff Kirsher } 250