Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netdev/phy: Handle IEEE802.3 clause 45 Ethernet PHYs

The IEEE802.3 clause 45 MDIO bus protocol allows for directly
addressing PHY registers using a 21 bit address, and is used by many
10G Ethernet PHYS. Already existing is the ability of MDIO bus
drivers to use clause 45, with the MII_ADDR_C45 flag. Here we add
struct phy_c45_device_ids to hold the device identifier registers
present in clause 45. struct phy_device gets a couple of new fields:
c45_ids to hold the identifiers and is_c45 to signal that it is clause
45.

get_phy_device() gets a new parameter is_c45 to indicate that the PHY
device should use the clause 45 protocol, and its callers are adjusted
to pass false. The follow-on patch to of_mdio.c will pass true where
appropriate.

EXPORT phy_device_create() so that the follow-on patch to of_mdio.c
can use it to create phy devices for PHYs, that have non-standard
device identifier registers, based on the device tree bindings.

Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Daney and committed by
David S. Miller
ac28b9f8 a3caad0a

+116 -11
+1 -1
drivers/net/phy/mdio_bus.c
··· 232 232 struct phy_device *phydev; 233 233 int err; 234 234 235 - phydev = get_phy_device(bus, addr); 235 + phydev = get_phy_device(bus, addr, false); 236 236 if (IS_ERR(phydev) || phydev == NULL) 237 237 return phydev; 238 238
+97 -8
drivers/net/phy/phy_device.c
··· 152 152 } 153 153 EXPORT_SYMBOL(phy_scan_fixups); 154 154 155 - static struct phy_device* phy_device_create(struct mii_bus *bus, 156 - int addr, int phy_id) 155 + struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, 156 + bool is_c45, struct phy_c45_device_ids *c45_ids) 157 157 { 158 158 struct phy_device *dev; 159 159 ··· 174 174 175 175 dev->autoneg = AUTONEG_ENABLE; 176 176 177 + dev->is_c45 = is_c45; 177 178 dev->addr = addr; 178 179 dev->phy_id = phy_id; 180 + if (c45_ids) 181 + dev->c45_ids = *c45_ids; 179 182 dev->bus = bus; 180 183 dev->dev.parent = bus->parent; 181 184 dev->dev.bus = &mdio_bus_type; ··· 203 200 204 201 return dev; 205 202 } 203 + EXPORT_SYMBOL(phy_device_create); 204 + 205 + /** 206 + * get_phy_c45_ids - reads the specified addr for its 802.3-c45 IDs. 207 + * @bus: the target MII bus 208 + * @addr: PHY address on the MII bus 209 + * @phy_id: where to store the ID retrieved. 210 + * @c45_ids: where to store the c45 ID information. 211 + * 212 + * If the PHY devices-in-package appears to be valid, it and the 213 + * corresponding identifiers are stored in @c45_ids, zero is stored 214 + * in @phy_id. Otherwise 0xffffffff is stored in @phy_id. Returns 215 + * zero on success. 216 + * 217 + */ 218 + static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id, 219 + struct phy_c45_device_ids *c45_ids) { 220 + int phy_reg; 221 + int i, reg_addr; 222 + const int num_ids = ARRAY_SIZE(c45_ids->device_ids); 223 + 224 + /* Find first non-zero Devices In package. Device 225 + * zero is reserved, so don't probe it. 226 + */ 227 + for (i = 1; 228 + i < num_ids && c45_ids->devices_in_package == 0; 229 + i++) { 230 + reg_addr = MII_ADDR_C45 | i << 16 | 6; 231 + phy_reg = mdiobus_read(bus, addr, reg_addr); 232 + if (phy_reg < 0) 233 + return -EIO; 234 + c45_ids->devices_in_package = (phy_reg & 0xffff) << 16; 235 + 236 + reg_addr = MII_ADDR_C45 | i << 16 | 5; 237 + phy_reg = mdiobus_read(bus, addr, reg_addr); 238 + if (phy_reg < 0) 239 + return -EIO; 240 + c45_ids->devices_in_package |= (phy_reg & 0xffff); 241 + 242 + /* If mostly Fs, there is no device there, 243 + * let's get out of here. 244 + */ 245 + if ((c45_ids->devices_in_package & 0x1fffffff) == 0x1fffffff) { 246 + *phy_id = 0xffffffff; 247 + return 0; 248 + } 249 + } 250 + 251 + /* Now probe Device Identifiers for each device present. */ 252 + for (i = 1; i < num_ids; i++) { 253 + if (!(c45_ids->devices_in_package & (1 << i))) 254 + continue; 255 + 256 + reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID1; 257 + phy_reg = mdiobus_read(bus, addr, reg_addr); 258 + if (phy_reg < 0) 259 + return -EIO; 260 + c45_ids->device_ids[i] = (phy_reg & 0xffff) << 16; 261 + 262 + reg_addr = MII_ADDR_C45 | i << 16 | MII_PHYSID2; 263 + phy_reg = mdiobus_read(bus, addr, reg_addr); 264 + if (phy_reg < 0) 265 + return -EIO; 266 + c45_ids->device_ids[i] |= (phy_reg & 0xffff); 267 + } 268 + *phy_id = 0; 269 + return 0; 270 + } 206 271 207 272 /** 208 273 * get_phy_id - reads the specified addr for its ID. 209 274 * @bus: the target MII bus 210 275 * @addr: PHY address on the MII bus 211 276 * @phy_id: where to store the ID retrieved. 277 + * @is_c45: If true the PHY uses the 802.3 clause 45 protocol 278 + * @c45_ids: where to store the c45 ID information. 212 279 * 213 - * Description: Reads the ID registers of the PHY at @addr on the 214 - * @bus, stores it in @phy_id and returns zero on success. 280 + * Description: In the case of a 802.3-c22 PHY, reads the ID registers 281 + * of the PHY at @addr on the @bus, stores it in @phy_id and returns 282 + * zero on success. 283 + * 284 + * In the case of a 802.3-c45 PHY, get_phy_c45_ids() is invoked, and 285 + * its return value is in turn returned. 286 + * 215 287 */ 216 - static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id) 288 + static int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id, 289 + bool is_c45, struct phy_c45_device_ids *c45_ids) 217 290 { 218 291 int phy_reg; 292 + 293 + if (is_c45) 294 + return get_phy_c45_ids(bus, addr, phy_id, c45_ids); 219 295 220 296 /* Grab the bits from PHYIR1, and put them 221 297 * in the upper half */ ··· 320 238 * get_phy_device - reads the specified PHY device and returns its @phy_device struct 321 239 * @bus: the target MII bus 322 240 * @addr: PHY address on the MII bus 241 + * @is_c45: If true the PHY uses the 802.3 clause 45 protocol 323 242 * 324 243 * Description: Reads the ID registers of the PHY at @addr on the 325 244 * @bus, then allocates and returns the phy_device to represent it. 326 245 */ 327 - struct phy_device * get_phy_device(struct mii_bus *bus, int addr) 246 + struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45) 328 247 { 329 248 struct phy_device *dev = NULL; 330 249 u32 phy_id; 250 + struct phy_c45_device_ids c45_ids = {0}; 331 251 int r; 332 252 333 - r = get_phy_id(bus, addr, &phy_id); 253 + r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids); 334 254 if (r) 335 255 return ERR_PTR(r); 336 256 ··· 340 256 if ((phy_id & 0x1fffffff) == 0x1fffffff) 341 257 return NULL; 342 258 343 - dev = phy_device_create(bus, addr, phy_id); 259 + dev = phy_device_create(bus, addr, phy_id, is_c45, &c45_ids); 344 260 345 261 return dev; 346 262 } ··· 533 449 /* Assume that if there is no driver, that it doesn't 534 450 * exist, and we should use the genphy driver. */ 535 451 if (NULL == d->driver) { 452 + if (phydev->is_c45) { 453 + pr_err("No driver for phy %x\n", phydev->phy_id); 454 + return -ENODEV; 455 + } 456 + 536 457 d->driver = &genphy_driver.driver; 537 458 538 459 err = d->driver->probe(d);
+1 -1
drivers/of/of_mdio.c
··· 79 79 mdio->irq[addr] = PHY_POLL; 80 80 } 81 81 82 - phy = get_phy_device(mdio, addr); 82 + phy = get_phy_device(mdio, addr, false); 83 83 if (!phy || IS_ERR(phy)) { 84 84 dev_err(&mdio->dev, "error probing PHY at address %i\n", 85 85 addr);
+17 -1
include/linux/phy.h
··· 243 243 PHY_RESUMING 244 244 }; 245 245 246 + /** 247 + * struct phy_c45_device_ids - 802.3-c45 Device Identifiers 248 + * @devices_in_package: Bit vector of devices present. 249 + * @device_ids: The device identifer for each present device. 250 + */ 251 + struct phy_c45_device_ids { 252 + u32 devices_in_package; 253 + u32 device_ids[8]; 254 + }; 246 255 247 256 /* phy_device: An instance of a PHY 248 257 * ··· 259 250 * bus: Pointer to the bus this PHY is on 260 251 * dev: driver model device structure for this PHY 261 252 * phy_id: UID for this device found during discovery 253 + * c45_ids: 802.3-c45 Device Identifers if is_c45. 254 + * is_c45: Set to true if this phy uses clause 45 addressing. 262 255 * state: state of the PHY for management purposes 263 256 * dev_flags: Device-specific flags used by the PHY driver. 264 257 * addr: Bus address of PHY ··· 295 284 struct device dev; 296 285 297 286 u32 phy_id; 287 + 288 + struct phy_c45_device_ids c45_ids; 289 + bool is_c45; 298 290 299 291 enum phy_state state; 300 292 ··· 494 480 return mdiobus_write(phydev->bus, phydev->addr, regnum, val); 495 481 } 496 482 497 - struct phy_device* get_phy_device(struct mii_bus *bus, int addr); 483 + struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, 484 + bool is_c45, struct phy_c45_device_ids *c45_ids); 485 + struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45); 498 486 int phy_device_register(struct phy_device *phy); 499 487 int phy_init_hw(struct phy_device *phydev); 500 488 struct phy_device * phy_attach(struct net_device *dev,