summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKweh Hock Leong <hock.leong.kweh@intel.com>2019-07-05 13:33:27 -0400
committerDavid S. Miller <davem@davemloft.net>2019-07-08 19:08:55 -0400
commitd4117d63a30876a3654f587c3a419db63d8b529d (patch)
tree2d5b14fe951fa991e70b081616b661eb09837332
parent44e3725943b706d3625ad91b1a1069a18fd0775c (diff)
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: Li, Yifan <yifan2.li@intel.com> Signed-off-by: Kweh Hock Leong <hock.leong.kweh@intel.com> Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com> Signed-off-by: Voon Weifeng <weifeng.voon@intel.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c43
-rw-r--r--include/linux/phy.h2
2 files changed, 37 insertions, 8 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index 18cadf0b0d66..4304c1abc5d1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -24,11 +24,14 @@
24 24
25#define MII_BUSY 0x00000001 25#define MII_BUSY 0x00000001
26#define MII_WRITE 0x00000002 26#define MII_WRITE 0x00000002
27#define MII_DATA_MASK GENMASK(15, 0)
27 28
28/* GMAC4 defines */ 29/* GMAC4 defines */
29#define MII_GMAC4_GOC_SHIFT 2 30#define MII_GMAC4_GOC_SHIFT 2
31#define MII_GMAC4_REG_ADDR_SHIFT 16
30#define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT) 32#define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)
31#define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT) 33#define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT)
34#define MII_GMAC4_C45E BIT(1)
32 35
33/* XGMAC defines */ 36/* XGMAC defines */
34#define MII_XGMAC_SADDR BIT(18) 37#define MII_XGMAC_SADDR BIT(18)
@@ -155,22 +158,34 @@ static int stmmac_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
155 struct stmmac_priv *priv = netdev_priv(ndev); 158 struct stmmac_priv *priv = netdev_priv(ndev);
156 unsigned int mii_address = priv->hw->mii.addr; 159 unsigned int mii_address = priv->hw->mii.addr;
157 unsigned int mii_data = priv->hw->mii.data; 160 unsigned int mii_data = priv->hw->mii.data;
158 u32 v;
159 int data;
160 u32 value = MII_BUSY; 161 u32 value = MII_BUSY;
162 int data = 0;
163 u32 v;
161 164
162 value |= (phyaddr << priv->hw->mii.addr_shift) 165 value |= (phyaddr << priv->hw->mii.addr_shift)
163 & priv->hw->mii.addr_mask; 166 & priv->hw->mii.addr_mask;
164 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; 167 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;
165 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) 168 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
166 & priv->hw->mii.clk_csr_mask; 169 & priv->hw->mii.clk_csr_mask;
167 if (priv->plat->has_gmac4) 170 if (priv->plat->has_gmac4) {
168 value |= MII_GMAC4_READ; 171 value |= MII_GMAC4_READ;
172 if (phyreg & MII_ADDR_C45) {
173 value |= MII_GMAC4_C45E;
174 value &= ~priv->hw->mii.reg_mask;
175 value |= ((phyreg >> MII_DEVADDR_C45_SHIFT) <<
176 priv->hw->mii.reg_shift) &
177 priv->hw->mii.reg_mask;
178
179 data |= (phyreg & MII_REGADDR_C45_MASK) <<
180 MII_GMAC4_REG_ADDR_SHIFT;
181 }
182 }
169 183
170 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), 184 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),
171 100, 10000)) 185 100, 10000))
172 return -EBUSY; 186 return -EBUSY;
173 187
188 writel(data, priv->ioaddr + mii_data);
174 writel(value, priv->ioaddr + mii_address); 189 writel(value, priv->ioaddr + mii_address);
175 190
176 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), 191 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 return -EBUSY; 193 return -EBUSY;
179 194
180 /* Read the data from the MII data register */ 195 /* Read the data from the MII data register */
181 data = (int)readl(priv->ioaddr + mii_data); 196 data = (int)readl(priv->ioaddr + mii_data) & MII_DATA_MASK;
182 197
183 return data; 198 return data;
184} 199}
@@ -198,8 +213,9 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
198 struct stmmac_priv *priv = netdev_priv(ndev); 213 struct stmmac_priv *priv = netdev_priv(ndev);
199 unsigned int mii_address = priv->hw->mii.addr; 214 unsigned int mii_address = priv->hw->mii.addr;
200 unsigned int mii_data = priv->hw->mii.data; 215 unsigned int mii_data = priv->hw->mii.data;
201 u32 v;
202 u32 value = MII_BUSY; 216 u32 value = MII_BUSY;
217 int data = phydata;
218 u32 v;
203 219
204 value |= (phyaddr << priv->hw->mii.addr_shift) 220 value |= (phyaddr << priv->hw->mii.addr_shift)
205 & priv->hw->mii.addr_mask; 221 & priv->hw->mii.addr_mask;
@@ -207,10 +223,21 @@ static int stmmac_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
207 223
208 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) 224 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
209 & priv->hw->mii.clk_csr_mask; 225 & priv->hw->mii.clk_csr_mask;
210 if (priv->plat->has_gmac4) 226 if (priv->plat->has_gmac4) {
211 value |= MII_GMAC4_WRITE; 227 value |= MII_GMAC4_WRITE;
212 else 228 if (phyreg & MII_ADDR_C45) {
229 value |= MII_GMAC4_C45E;
230 value &= ~priv->hw->mii.reg_mask;
231 value |= ((phyreg >> MII_DEVADDR_C45_SHIFT) <<
232 priv->hw->mii.reg_shift) &
233 priv->hw->mii.reg_mask;
234
235 data |= (phyreg & MII_REGADDR_C45_MASK) <<
236 MII_GMAC4_REG_ADDR_SHIFT;
237 }
238 } else {
213 value |= MII_WRITE; 239 value |= MII_WRITE;
240 }
214 241
215 /* Wait until any existing MII operation is complete */ 242 /* Wait until any existing MII operation is complete */
216 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), 243 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 return -EBUSY; 245 return -EBUSY;
219 246
220 /* Set the MII address register to write */ 247 /* Set the MII address register to write */
221 writel(phydata, priv->ioaddr + mii_data); 248 writel(data, priv->ioaddr + mii_data);
222 writel(value, priv->ioaddr + mii_address); 249 writel(value, priv->ioaddr + mii_address);
223 250
224 /* Wait until any existing MII operation is complete */ 251 /* Wait until any existing MII operation is complete */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index d0af7d37fdf9..1739c6dc470e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -195,6 +195,8 @@ static inline const char *phy_modes(phy_interface_t interface)
195/* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit 195/* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
196 IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */ 196 IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */
197#define MII_ADDR_C45 (1<<30) 197#define MII_ADDR_C45 (1<<30)
198#define MII_DEVADDR_C45_SHIFT 16
199#define MII_REGADDR_C45_MASK GENMASK(15, 0)
198 200
199struct device; 201struct device;
200struct phylink; 202struct phylink;