aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru Ardelean <alexandru.ardelean@analog.com>2019-08-16 09:10:07 -0400
committerDavid S. Miller <davem@davemloft.net>2019-08-16 14:56:26 -0400
commitc6aa697c41fd3bbd0d8697a7462109ffe605a867 (patch)
treed6769744968485824de034c7aabb3eab1110375f
parentb422d1b6f761bf336e0219fee6901481d33453a0 (diff)
net: phy: adin: add EEE translation layer from Clause 45 to Clause 22
The ADIN1200 & ADIN1300 PHYs support EEE by using standard Clause 45 access to access MMD registers for EEE. The EEE register addresses (when using Clause 22) are available at different addresses (than Clause 45), and since accessing these regs (via Clause 22) needs a special mechanism, a translation table is required to convert these addresses. For Clause 45, this is not needed since the driver will likely never use this access mode. Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/adin.c68
1 files changed, 66 insertions, 2 deletions
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index 51c0d17577de..131b7f85ae32 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -40,6 +40,16 @@
40#define ADIN1300_PHY_STATUS1 0x001a 40#define ADIN1300_PHY_STATUS1 0x001a
41#define ADIN1300_PAIR_01_SWAP BIT(11) 41#define ADIN1300_PAIR_01_SWAP BIT(11)
42 42
43/* EEE register addresses, accessible via Clause 22 access using
44 * ADIN1300_MII_EXT_REG_PTR & ADIN1300_MII_EXT_REG_DATA.
45 * The bit-fields are the same as specified by IEEE for EEE.
46 */
47#define ADIN1300_EEE_CAP_REG 0x8000
48#define ADIN1300_EEE_ADV_REG 0x8001
49#define ADIN1300_EEE_LPABLE_REG 0x8002
50#define ADIN1300_CLOCK_STOP_REG 0x9400
51#define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000
52
43#define ADIN1300_GE_RGMII_CFG_REG 0xff23 53#define ADIN1300_GE_RGMII_CFG_REG 0xff23
44#define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6) 54#define ADIN1300_GE_RGMII_RX_MSK GENMASK(8, 6)
45#define ADIN1300_GE_RGMII_RX_SEL(x) \ 55#define ADIN1300_GE_RGMII_RX_SEL(x) \
@@ -101,6 +111,26 @@ static const struct adin_cfg_reg_map adin_rmii_fifo_depths[] = {
101 { }, 111 { },
102}; 112};
103 113
114/**
115 * struct adin_clause45_mmd_map - map to convert Clause 45 regs to Clause 22
116 * @devad device address used in Clause 45 access
117 * @cl45_regnum register address defined by Clause 45
118 * @adin_regnum equivalent register address accessible via Clause 22
119 */
120struct adin_clause45_mmd_map {
121 int devad;
122 u16 cl45_regnum;
123 u16 adin_regnum;
124};
125
126static struct adin_clause45_mmd_map adin_clause45_mmd_map[] = {
127 { MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE, ADIN1300_EEE_CAP_REG },
128 { MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, ADIN1300_EEE_LPABLE_REG },
129 { MDIO_MMD_AN, MDIO_AN_EEE_ADV, ADIN1300_EEE_ADV_REG },
130 { MDIO_MMD_PCS, MDIO_CTRL1, ADIN1300_CLOCK_STOP_REG },
131 { MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR, ADIN1300_LPI_WAKE_ERR_CNT_REG },
132};
133
104static int adin_lookup_reg_value(const struct adin_cfg_reg_map *tbl, int cfg) 134static int adin_lookup_reg_value(const struct adin_cfg_reg_map *tbl, int cfg)
105{ 135{
106 size_t i; 136 size_t i;
@@ -251,13 +281,41 @@ static int adin_phy_config_intr(struct phy_device *phydev)
251 ADIN1300_INT_MASK_EN); 281 ADIN1300_INT_MASK_EN);
252} 282}
253 283
284static int adin_cl45_to_adin_reg(struct phy_device *phydev, int devad,
285 u16 cl45_regnum)
286{
287 struct adin_clause45_mmd_map *m;
288 int i;
289
290 if (devad == MDIO_MMD_VEND1)
291 return cl45_regnum;
292
293 for (i = 0; i < ARRAY_SIZE(adin_clause45_mmd_map); i++) {
294 m = &adin_clause45_mmd_map[i];
295 if (m->devad == devad && m->cl45_regnum == cl45_regnum)
296 return m->adin_regnum;
297 }
298
299 phydev_err(phydev,
300 "No translation available for devad: %d reg: %04x\n",
301 devad, cl45_regnum);
302
303 return -EINVAL;
304}
305
254static int adin_read_mmd(struct phy_device *phydev, int devad, u16 regnum) 306static int adin_read_mmd(struct phy_device *phydev, int devad, u16 regnum)
255{ 307{
256 struct mii_bus *bus = phydev->mdio.bus; 308 struct mii_bus *bus = phydev->mdio.bus;
257 int phy_addr = phydev->mdio.addr; 309 int phy_addr = phydev->mdio.addr;
310 int adin_regnum;
258 int err; 311 int err;
259 312
260 err = __mdiobus_write(bus, phy_addr, ADIN1300_MII_EXT_REG_PTR, regnum); 313 adin_regnum = adin_cl45_to_adin_reg(phydev, devad, regnum);
314 if (adin_regnum < 0)
315 return adin_regnum;
316
317 err = __mdiobus_write(bus, phy_addr, ADIN1300_MII_EXT_REG_PTR,
318 adin_regnum);
261 if (err) 319 if (err)
262 return err; 320 return err;
263 321
@@ -269,9 +327,15 @@ static int adin_write_mmd(struct phy_device *phydev, int devad, u16 regnum,
269{ 327{
270 struct mii_bus *bus = phydev->mdio.bus; 328 struct mii_bus *bus = phydev->mdio.bus;
271 int phy_addr = phydev->mdio.addr; 329 int phy_addr = phydev->mdio.addr;
330 int adin_regnum;
272 int err; 331 int err;
273 332
274 err = __mdiobus_write(bus, phy_addr, ADIN1300_MII_EXT_REG_PTR, regnum); 333 adin_regnum = adin_cl45_to_adin_reg(phydev, devad, regnum);
334 if (adin_regnum < 0)
335 return adin_regnum;
336
337 err = __mdiobus_write(bus, phy_addr, ADIN1300_MII_EXT_REG_PTR,
338 adin_regnum);
275 if (err) 339 if (err)
276 return err; 340 return err;
277 341