diff options
Diffstat (limited to 'drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c')
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c | 105 |
1 files changed, 81 insertions, 24 deletions
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c index fceb6d637235..0227223c06fa 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_mdio.c @@ -50,12 +50,12 @@ static void sxgbe_mdio_ctrl_data(struct sxgbe_priv_data *sp, u32 cmd, } static void sxgbe_mdio_c45(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, - int phyreg, u16 phydata) + int devad, int phyreg, u16 phydata) { u32 reg; /* set mdio address register */ - reg = ((phyreg >> 16) & 0x1f) << 21; + reg = (devad & 0x1f) << 21; reg |= (phyaddr << 16) | (phyreg & 0xffff); writel(reg, sp->ioaddr + sp->hw->mii.addr); @@ -76,8 +76,8 @@ static void sxgbe_mdio_c22(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, sxgbe_mdio_ctrl_data(sp, cmd, phydata); } -static int sxgbe_mdio_access(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, - int phyreg, u16 phydata) +static int sxgbe_mdio_access_c22(struct sxgbe_priv_data *sp, u32 cmd, + int phyaddr, int phyreg, u16 phydata) { const struct mii_regs *mii = &sp->hw->mii; int rc; @@ -86,33 +86,46 @@ static int sxgbe_mdio_access(struct sxgbe_priv_data *sp, u32 cmd, int phyaddr, if (rc < 0) return rc; - if (phyreg & MII_ADDR_C45) { - sxgbe_mdio_c45(sp, cmd, phyaddr, phyreg, phydata); - } else { - /* Ports 0-3 only support C22. */ - if (phyaddr >= 4) - return -ENODEV; + /* Ports 0-3 only support C22. */ + if (phyaddr >= 4) + return -ENODEV; - sxgbe_mdio_c22(sp, cmd, phyaddr, phyreg, phydata); - } + sxgbe_mdio_c22(sp, cmd, phyaddr, phyreg, phydata); + + return sxgbe_mdio_busy_wait(sp->ioaddr, mii->data); +} + +static int sxgbe_mdio_access_c45(struct sxgbe_priv_data *sp, u32 cmd, + int phyaddr, int devad, int phyreg, + u16 phydata) +{ + const struct mii_regs *mii = &sp->hw->mii; + int rc; + + rc = sxgbe_mdio_busy_wait(sp->ioaddr, mii->data); + if (rc < 0) + return rc; + + sxgbe_mdio_c45(sp, cmd, phyaddr, devad, phyreg, phydata); return sxgbe_mdio_busy_wait(sp->ioaddr, mii->data); } /** - * sxgbe_mdio_read + * sxgbe_mdio_read_c22 * @bus: points to the mii_bus structure * @phyaddr: address of phy port * @phyreg: address of register with in phy register - * Description: this function used for C45 and C22 MDIO Read + * Description: this function used for C22 MDIO Read */ -static int sxgbe_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) +static int sxgbe_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg) { struct net_device *ndev = bus->priv; struct sxgbe_priv_data *priv = netdev_priv(ndev); int rc; - rc = sxgbe_mdio_access(priv, SXGBE_SMA_READ_CMD, phyaddr, phyreg, 0); + rc = sxgbe_mdio_access_c22(priv, SXGBE_SMA_READ_CMD, phyaddr, + phyreg, 0); if (rc < 0) return rc; @@ -120,21 +133,63 @@ static int sxgbe_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) } /** - * sxgbe_mdio_write + * sxgbe_mdio_read_c45 + * @bus: points to the mii_bus structure + * @phyaddr: address of phy port + * @devad: device (MMD) address + * @phyreg: address of register with in phy register + * Description: this function used for C45 MDIO Read + */ +static int sxgbe_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad, + int phyreg) +{ + struct net_device *ndev = bus->priv; + struct sxgbe_priv_data *priv = netdev_priv(ndev); + int rc; + + rc = sxgbe_mdio_access_c45(priv, SXGBE_SMA_READ_CMD, phyaddr, + devad, phyreg, 0); + if (rc < 0) + return rc; + + return readl(priv->ioaddr + priv->hw->mii.data) & 0xffff; +} + +/** + * sxgbe_mdio_write_c22 + * @bus: points to the mii_bus structure + * @phyaddr: address of phy port + * @phyreg: address of phy registers + * @phydata: data to be written into phy register + * Description: this function is used for C22 MDIO write + */ +static int sxgbe_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg, + u16 phydata) +{ + struct net_device *ndev = bus->priv; + struct sxgbe_priv_data *priv = netdev_priv(ndev); + + return sxgbe_mdio_access_c22(priv, SXGBE_SMA_WRITE_CMD, phyaddr, phyreg, + phydata); +} + +/** + * sxgbe_mdio_write_c45 * @bus: points to the mii_bus structure * @phyaddr: address of phy port * @phyreg: address of phy registers + * @devad: device (MMD) address * @phydata: data to be written into phy register - * Description: this function is used for C45 and C22 MDIO write + * Description: this function is used for C45 MDIO write */ -static int sxgbe_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, - u16 phydata) +static int sxgbe_mdio_write_c45(struct mii_bus *bus, int phyaddr, int devad, + int phyreg, u16 phydata) { struct net_device *ndev = bus->priv; struct sxgbe_priv_data *priv = netdev_priv(ndev); - return sxgbe_mdio_access(priv, SXGBE_SMA_WRITE_CMD, phyaddr, phyreg, - phydata); + return sxgbe_mdio_access_c45(priv, SXGBE_SMA_WRITE_CMD, phyaddr, + devad, phyreg, phydata); } int sxgbe_mdio_register(struct net_device *ndev) @@ -161,8 +216,10 @@ int sxgbe_mdio_register(struct net_device *ndev) /* assign mii bus fields */ mdio_bus->name = "sxgbe"; - mdio_bus->read = &sxgbe_mdio_read; - mdio_bus->write = &sxgbe_mdio_write; + mdio_bus->read = sxgbe_mdio_read_c22; + mdio_bus->write = sxgbe_mdio_write_c22; + mdio_bus->read_c45 = sxgbe_mdio_read_c45; + mdio_bus->write_c45 = sxgbe_mdio_write_c45; snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%x", mdio_bus->name, priv->plat->bus_id); mdio_bus->priv = ndev; |