Commit d4117d63 authored by Kweh Hock Leong's avatar Kweh Hock Leong Committed by David S. Miller

net: stmmac: enable clause 45 mdio support

DWMAC4 is capable to support clause 45 mdio communication.
This patch enable the feature on stmmac_mdio_write() and
stmmac_mdio_read() by following phy_write_mmd() and
phy_read_mmd() mdiobus read write implementation format.
Reviewed-by: default avatarLi, Yifan <yifan2.li@intel.com>
Signed-off-by: default avatarKweh Hock Leong <hock.leong.kweh@intel.com>
Signed-off-by: default avatarOng Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: default avatarVoon Weifeng <weifeng.voon@intel.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 44e37259
...@@ -24,11 +24,14 @@ ...@@ -24,11 +24,14 @@
#define MII_BUSY 0x00000001 #define MII_BUSY 0x00000001
#define MII_WRITE 0x00000002 #define MII_WRITE 0x00000002
#define MII_DATA_MASK GENMASK(15, 0)
/* GMAC4 defines */ /* GMAC4 defines */
#define MII_GMAC4_GOC_SHIFT 2 #define MII_GMAC4_GOC_SHIFT 2
#define MII_GMAC4_REG_ADDR_SHIFT 16
#define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT) #define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)
#define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT) #define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT)
#define MII_GMAC4_C45E BIT(1)
/* XGMAC defines */ /* XGMAC defines */
#define MII_XGMAC_SADDR BIT(18) #define MII_XGMAC_SADDR BIT(18)
...@@ -155,22 +158,34 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) ...@@ -155,22 +158,34 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_address = priv->hw->mii.addr;
unsigned int mii_data = priv->hw->mii.data; unsigned int mii_data = priv->hw->mii.data;
u32 v;
int data;
u32 value = MII_BUSY; u32 value = MII_BUSY;
int data = 0;
u32 v;
value |= (phyaddr << priv->hw->mii.addr_shift) value |= (phyaddr << priv->hw->mii.addr_shift)
& priv->hw->mii.addr_mask; & priv->hw->mii.addr_mask;
value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
& priv->hw->mii.clk_csr_mask; & priv->hw->mii.clk_csr_mask;
if (priv->plat->has_gmac4) if (priv->plat->has_gmac4) {
value |= MII_GMAC4_READ; value |= MII_GMAC4_READ;
if (phyreg & MII_ADDR_C45) {
value |= MII_GMAC4_C45E;
value &= ~priv->hw->mii.reg_mask;
value |= ((phyreg >> MII_DEVADDR_C45_SHIFT) <<
priv->hw->mii.reg_shift) &
priv->hw->mii.reg_mask;
data |= (phyreg & MII_REGADDR_C45_MASK) <<
MII_GMAC4_REG_ADDR_SHIFT;
}
}
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
100, 10000)) 100, 10000))
return -EBUSY; return -EBUSY;
writel(data, priv->ioaddr + mii_data);
writel(value, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_address);
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
...@@ -178,7 +193,7 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg) ...@@ -178,7 +193,7 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
return -EBUSY; return -EBUSY;
/* Read the data from the MII data register */ /* Read the data from the MII data register */
data = (int)readl(priv->ioaddr + mii_data); data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK;
return data; return data;
} }
...@@ -198,8 +213,9 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, ...@@ -198,8 +213,9 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_address = priv->hw->mii.addr;
unsigned int mii_data = priv->hw->mii.data; unsigned int mii_data = priv->hw->mii.data;
u32 v;
u32 value = MII_BUSY; u32 value = MII_BUSY;
int data = phydata;
u32 v;
value |= (phyaddr << priv->hw->mii.addr_shift) value |= (phyaddr << priv->hw->mii.addr_shift)
& priv->hw->mii.addr_mask; & priv->hw->mii.addr_mask;
...@@ -207,10 +223,21 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, ...@@ -207,10 +223,21 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
& priv->hw->mii.clk_csr_mask; & priv->hw->mii.clk_csr_mask;
if (priv->plat->has_gmac4) if (priv->plat->has_gmac4) {
value |= MII_GMAC4_WRITE; value |= MII_GMAC4_WRITE;
else if (phyreg & MII_ADDR_C45) {
value |= MII_GMAC4_C45E;
value &= ~priv->hw->mii.reg_mask;
value |= ((phyreg >> MII_DEVADDR_C45_SHIFT) <<
priv->hw->mii.reg_shift) &
priv->hw->mii.reg_mask;
data |= (phyreg & MII_REGADDR_C45_MASK) <<
MII_GMAC4_REG_ADDR_SHIFT;
}
} else {
value |= MII_WRITE; value |= MII_WRITE;
}
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
...@@ -218,7 +245,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg, ...@@ -218,7 +245,7 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
return -EBUSY; return -EBUSY;
/* Set the MII address register to write */ /* Set the MII address register to write */
writel(phydata, priv->ioaddr + mii_data); writel(data, priv->ioaddr + mii_data);
writel(value, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_address);
/* Wait until any existing MII operation is complete */ /* Wait until any existing MII operation is complete */
......
...@@ -195,6 +195,8 @@ static inline const char *phy_modes(phy_interface_t interface) ...@@ -195,6 +195,8 @@ static inline const char *phy_modes(phy_interface_t interface)
/* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */ IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */
#define MII_ADDR_C45 (1<<30) #define MII_ADDR_C45 (1<<30)
#define MII_DEVADDR_C45_SHIFT 16
#define MII_REGADDR_C45_MASK GENMASK(15, 0)
struct device; struct device;
struct phylink; struct phylink;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment