From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jose Abreu Subject: [PATCH net-next 5/9] net: stmmac: Add MDIO related functions for XGMAC2 Date: Wed, 1 Aug 2018 13:10:33 +0100 Message-ID: <5a7f4264b01f863dbf79b4f6d5e62cd2a55c758f.1533125016.git.joabreu@synopsys.com> References: Cc: Jose Abreu , "David S. Miller" , Joao Pinto , Giuseppe Cavallaro , Alexandre Torgue To: netdev@vger.kernel.org Return-path: Received: from us01smtprelay-2.synopsys.com ([198.182.60.111]:34207 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389050AbeHAN4g (ORCPT ); Wed, 1 Aug 2018 09:56:36 -0400 In-Reply-To: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org List-ID: Add the MDIO related funcionalities for the new IP block XGMAC2. Signed-off-by: Jose Abreu Cc: David S. Miller Cc: Joao Pinto Cc: Giuseppe Cavallaro Cc: Alexandre Torgue --- drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 88 +++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 5df1a608e566..e6bf86dc14eb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -39,6 +39,88 @@ #define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT) #define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT) +/* XGMAC defines */ +#define MII_XGMAC_CMD_SHIFT 16 +#define MII_XGMAC_WRITE (1 << MII_XGMAC_CMD_SHIFT) +#define MII_XGMAC_READ (3 << MII_XGMAC_CMD_SHIFT) +#define MII_XGMAC_BUSY BIT(22) + +static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, int phyaddr, + int phyreg) +{ + unsigned int mii_address = priv->hw->mii.addr; + unsigned int mii_data = priv->hw->mii.data; + u32 tmp, addr, value = MII_XGMAC_BUSY; + int data; + + if (phyreg & MII_ADDR_C45) { + addr = ((phyreg >> 16) & 0x1f) << 21; + addr |= (phyaddr << 16) | (phyreg & 0xffff); + } else { + if (phyaddr >= 4) + return -ENODEV; + writel(~0x0, priv->ioaddr + 0x220); + addr = (phyaddr << 16) | (phyreg & 0x1f); + } + + value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) + & priv->hw->mii.clk_csr_mask; + value |= BIT(18); + value |= MII_XGMAC_READ; + + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, + !(tmp & MII_XGMAC_BUSY), 100, 10000)) + return -EBUSY; + + writel(addr, priv->ioaddr + mii_address); + writel(value, priv->ioaddr + mii_data); + + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, + !(tmp & MII_XGMAC_BUSY), 100, 10000)) + return -EBUSY; + + /* Read the data from the MII data register */ + data = (int)readl(priv->ioaddr + mii_data) & GENMASK(15, 0); + + return data; +} + +static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, int phyaddr, + int phyreg, u16 phydata) +{ + unsigned int mii_address = priv->hw->mii.addr; + unsigned int mii_data = priv->hw->mii.data; + u32 addr, tmp, value = MII_XGMAC_BUSY; + + if (phyreg & MII_ADDR_C45) { + addr = ((phyreg >> 16) & 0x1f) << 21; + addr |= (phyaddr << 16) | (phyreg & 0xffff); + } else { + if (phyaddr >= 4) + return -ENODEV; + writel(~0x0, priv->ioaddr + 0x220); + addr = (phyaddr << 16) | (phyreg & 0x1f); + } + + value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) + & priv->hw->mii.clk_csr_mask; + value |= phydata | BIT(18); + value |= MII_XGMAC_WRITE; + + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, + !(tmp & MII_XGMAC_BUSY), 100, 10000)) + return -EBUSY; + + /* Set the MII address register to write */ + writel(addr, priv->ioaddr + mii_address); + writel(value, priv->ioaddr + mii_data); + + /* Wait until any existing MII operation is complete */ + return readl_poll_timeout(priv->ioaddr + mii_data, tmp, + !(tmp & MII_XGMAC_BUSY), 100, 10000); +} + /** * stmmac_mdio_read * @bus: points to the mii_bus structure @@ -59,6 +141,9 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) int data; u32 value = MII_BUSY; + if (priv->plat->has_xgmac) + return stmmac_xgmac2_mdio_read(priv, phyaddr, phyreg); + value |= (phyaddr << priv->hw->mii.addr_shift) & priv->hw->mii.addr_mask; value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; @@ -101,6 +186,9 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, u32 v; u32 value = MII_BUSY; + if (priv->plat->has_xgmac) + return stmmac_xgmac2_mdio_write(priv, phyaddr, phyreg, phydata); + value |= (phyaddr << priv->hw->mii.addr_shift) & priv->hw->mii.addr_mask; value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; -- 2.7.4