diff options
author | Kweh Hock Leong <hock.leong.kweh@intel.com> | 2019-07-05 13:33:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-07-08 19:08:55 -0400 |
commit | d4117d63a30876a3654f587c3a419db63d8b529d (patch) | |
tree | 2d5b14fe951fa991e70b081616b661eb09837332 | |
parent | 44e3725943b706d3625ad91b1a1069a18fd0775c (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.c | 43 | ||||
-rw-r--r-- | include/linux/phy.h | 2 |
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 | ||
199 | struct device; | 201 | struct device; |
200 | struct phylink; | 202 | struct phylink; |