Commit 4f6746dc7f7f1691dfdc73a69831e61c9507708f
Committed by
Joe Hershberger
1 parent
8d7f06bbbe
Exists in
smarc_8mq_lf_v2020.04
and in
9 other branches
net: phy: Add generic helpers to access MMD PHY registers
Two new helper functions (phy_read_mmd() and phy_write_mmd()) are added to allow access to the MMD PHY registers. The MMD PHY registers can be accessed by several means: 1. Using two new MMD access function hooks in the PHY driver. These functions can be implemented when the PHY driver does not support the standard IEEE Compatible clause 45 access mechanism described in clause 22 or if the PHY uses its own non-standard access mechanism. 2. Direct access for C45 PHYs and C22 PHYs when accessing the reachable DEVADs. 3. The standard clause 45 access extensions to the MMD registers through the indirection registers (clause 22) in all the other cases. Signed-off-by: Carlo Caione <ccaione@baylibre.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Showing 2 changed files with 74 additions and 0 deletions Side-by-side Diff
drivers/net/phy/phy.c
... | ... | @@ -549,6 +549,10 @@ |
549 | 549 | drv->readext += gd->reloc_off; |
550 | 550 | if (drv->writeext) |
551 | 551 | drv->writeext += gd->reloc_off; |
552 | + if (drv->read_mmd) | |
553 | + drv->read_mmd += gd->reloc_off; | |
554 | + if (drv->write_mmd) | |
555 | + drv->write_mmd += gd->reloc_off; | |
552 | 556 | #endif |
553 | 557 | return 0; |
554 | 558 | } |
include/phy.h
... | ... | @@ -101,6 +101,14 @@ |
101 | 101 | int (*readext)(struct phy_device *phydev, int addr, int devad, int reg); |
102 | 102 | int (*writeext)(struct phy_device *phydev, int addr, int devad, int reg, |
103 | 103 | u16 val); |
104 | + | |
105 | + /* Phy specific driver override for reading a MMD register */ | |
106 | + int (*read_mmd)(struct phy_device *phydev, int devad, int reg); | |
107 | + | |
108 | + /* Phy specific driver override for writing a MMD register */ | |
109 | + int (*write_mmd)(struct phy_device *phydev, int devad, int reg, | |
110 | + u16 val); | |
111 | + | |
104 | 112 | struct list_head list; |
105 | 113 | }; |
106 | 114 | |
... | ... | @@ -163,6 +171,68 @@ |
163 | 171 | struct mii_dev *bus = phydev->bus; |
164 | 172 | |
165 | 173 | return bus->write(bus, phydev->addr, devad, regnum, val); |
174 | +} | |
175 | + | |
176 | +static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad, | |
177 | + int regnum) | |
178 | +{ | |
179 | + /* Write the desired MMD Devad */ | |
180 | + phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad); | |
181 | + | |
182 | + /* Write the desired MMD register address */ | |
183 | + phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum); | |
184 | + | |
185 | + /* Select the Function : DATA with no post increment */ | |
186 | + phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, | |
187 | + (devad | MII_MMD_CTRL_NOINCR)); | |
188 | +} | |
189 | + | |
190 | +static inline int phy_read_mmd(struct phy_device *phydev, int devad, | |
191 | + int regnum) | |
192 | +{ | |
193 | + struct phy_driver *drv = phydev->drv; | |
194 | + | |
195 | + if (regnum > (u16)~0 || devad > 32) | |
196 | + return -EINVAL; | |
197 | + | |
198 | + /* driver-specific access */ | |
199 | + if (drv->read_mmd) | |
200 | + return drv->read_mmd(phydev, devad, regnum); | |
201 | + | |
202 | + /* direct C45 / C22 access */ | |
203 | + if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES || | |
204 | + devad == MDIO_DEVAD_NONE || !devad) | |
205 | + return phy_read(phydev, devad, regnum); | |
206 | + | |
207 | + /* indirect C22 access */ | |
208 | + phy_mmd_start_indirect(phydev, devad, regnum); | |
209 | + | |
210 | + /* Read the content of the MMD's selected register */ | |
211 | + return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA); | |
212 | +} | |
213 | + | |
214 | +static inline int phy_write_mmd(struct phy_device *phydev, int devad, | |
215 | + int regnum, u16 val) | |
216 | +{ | |
217 | + struct phy_driver *drv = phydev->drv; | |
218 | + | |
219 | + if (regnum > (u16)~0 || devad > 32) | |
220 | + return -EINVAL; | |
221 | + | |
222 | + /* driver-specific access */ | |
223 | + if (drv->write_mmd) | |
224 | + return drv->write_mmd(phydev, devad, regnum, val); | |
225 | + | |
226 | + /* direct C45 / C22 access */ | |
227 | + if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES || | |
228 | + devad == MDIO_DEVAD_NONE || !devad) | |
229 | + return phy_write(phydev, devad, regnum, val); | |
230 | + | |
231 | + /* indirect C22 access */ | |
232 | + phy_mmd_start_indirect(phydev, devad, regnum); | |
233 | + | |
234 | + /* Write the data into MMD's selected register */ | |
235 | + return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val); | |
166 | 236 | } |
167 | 237 | |
168 | 238 | #ifdef CONFIG_PHYLIB_10G |