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

mscc.c: Add support for additional VSC PHYs

Add support for the following VSC PHYs
VSC8504, VSC8552, VSC8572
VSC8562, VSC8564, VSC8575, VSC8582

Updates for v2:
Checked for NULL on input to container_of
Changed a large if else series to a switch statement.
Added a WARN_ON to make sure lowest nibble of mask is 0

Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Bryan Whitehead and committed by
David S. Miller
75a1ccfe 945fe457

+188 -6
+188 -6
drivers/net/phy/mscc.c
··· 252 252 #define MSCC_PHY_TR_LSB 17 253 253 #define MSCC_PHY_TR_MSB 18 254 254 255 - /* Microsemi PHY ID's */ 255 + /* Microsemi PHY ID's 256 + * Code assumes lowest nibble is 0 257 + */ 258 + #define PHY_ID_VSC8504 0x000704c0 256 259 #define PHY_ID_VSC8514 0x00070670 257 260 #define PHY_ID_VSC8530 0x00070560 258 261 #define PHY_ID_VSC8531 0x00070570 259 262 #define PHY_ID_VSC8540 0x00070760 260 263 #define PHY_ID_VSC8541 0x00070770 264 + #define PHY_ID_VSC8552 0x000704e0 265 + #define PHY_ID_VSC856X 0x000707e0 266 + #define PHY_ID_VSC8572 0x000704d0 261 267 #define PHY_ID_VSC8574 0x000704a0 268 + #define PHY_ID_VSC8575 0x000707d0 269 + #define PHY_ID_VSC8582 0x000707b0 262 270 #define PHY_ID_VSC8584 0x000707c0 263 271 264 272 #define MSCC_VDDMAC_1500 1500 ··· 1603 1595 else 1604 1596 addr = vsc8531->base_addr + i; 1605 1597 1598 + if (!map[addr]) 1599 + continue; 1600 + 1606 1601 phy = container_of(map[addr], struct phy_device, mdio); 1607 1602 1608 1603 if ((phy->phy_id & phydev->drv->phy_id_mask) != ··· 1658 1647 * in this pre-init function. 1659 1648 */ 1660 1649 if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0)) { 1661 - if ((phydev->phy_id & phydev->drv->phy_id_mask) == 1662 - (PHY_ID_VSC8574 & phydev->drv->phy_id_mask)) 1650 + /* The following switch statement assumes that the lowest 1651 + * nibble of the phy_id_mask is always 0. This works because 1652 + * the lowest nibble of the PHY_ID's below are also 0. 1653 + */ 1654 + WARN_ON(phydev->drv->phy_id_mask & 0xf); 1655 + 1656 + switch (phydev->phy_id & phydev->drv->phy_id_mask) { 1657 + case PHY_ID_VSC8504: 1658 + case PHY_ID_VSC8552: 1659 + case PHY_ID_VSC8572: 1660 + case PHY_ID_VSC8574: 1663 1661 ret = vsc8574_config_pre_init(phydev); 1664 - else if ((phydev->phy_id & phydev->drv->phy_id_mask) == 1665 - (PHY_ID_VSC8584 & phydev->drv->phy_id_mask)) 1662 + break; 1663 + case PHY_ID_VSC856X: 1664 + case PHY_ID_VSC8575: 1665 + case PHY_ID_VSC8582: 1666 + case PHY_ID_VSC8584: 1666 1667 ret = vsc8584_config_pre_init(phydev); 1667 - else 1668 + break; 1669 + default: 1668 1670 ret = -EINVAL; 1671 + break; 1672 + }; 1669 1673 1670 1674 if (ret) 1671 1675 goto err; ··· 2348 2322 /* Microsemi VSC85xx PHYs */ 2349 2323 static struct phy_driver vsc85xx_driver[] = { 2350 2324 { 2325 + .phy_id = PHY_ID_VSC8504, 2326 + .name = "Microsemi GE VSC8504 SyncE", 2327 + .phy_id_mask = 0xfffffff0, 2328 + /* PHY_GBIT_FEATURES */ 2329 + .soft_reset = &genphy_soft_reset, 2330 + .config_init = &vsc8584_config_init, 2331 + .config_aneg = &vsc85xx_config_aneg, 2332 + .aneg_done = &genphy_aneg_done, 2333 + .read_status = &vsc85xx_read_status, 2334 + .ack_interrupt = &vsc85xx_ack_interrupt, 2335 + .config_intr = &vsc85xx_config_intr, 2336 + .did_interrupt = &vsc8584_did_interrupt, 2337 + .suspend = &genphy_suspend, 2338 + .resume = &genphy_resume, 2339 + .probe = &vsc8574_probe, 2340 + .set_wol = &vsc85xx_wol_set, 2341 + .get_wol = &vsc85xx_wol_get, 2342 + .get_tunable = &vsc85xx_get_tunable, 2343 + .set_tunable = &vsc85xx_set_tunable, 2344 + .read_page = &vsc85xx_phy_read_page, 2345 + .write_page = &vsc85xx_phy_write_page, 2346 + .get_sset_count = &vsc85xx_get_sset_count, 2347 + .get_strings = &vsc85xx_get_strings, 2348 + .get_stats = &vsc85xx_get_stats, 2349 + }, 2350 + { 2351 2351 .phy_id = PHY_ID_VSC8514, 2352 2352 .name = "Microsemi GE VSC8514 SyncE", 2353 2353 .phy_id_mask = 0xfffffff0, ··· 2497 2445 .get_stats = &vsc85xx_get_stats, 2498 2446 }, 2499 2447 { 2448 + .phy_id = PHY_ID_VSC8552, 2449 + .name = "Microsemi GE VSC8552 SyncE", 2450 + .phy_id_mask = 0xfffffff0, 2451 + /* PHY_GBIT_FEATURES */ 2452 + .soft_reset = &genphy_soft_reset, 2453 + .config_init = &vsc8584_config_init, 2454 + .config_aneg = &vsc85xx_config_aneg, 2455 + .aneg_done = &genphy_aneg_done, 2456 + .read_status = &vsc85xx_read_status, 2457 + .ack_interrupt = &vsc85xx_ack_interrupt, 2458 + .config_intr = &vsc85xx_config_intr, 2459 + .did_interrupt = &vsc8584_did_interrupt, 2460 + .suspend = &genphy_suspend, 2461 + .resume = &genphy_resume, 2462 + .probe = &vsc8574_probe, 2463 + .set_wol = &vsc85xx_wol_set, 2464 + .get_wol = &vsc85xx_wol_get, 2465 + .get_tunable = &vsc85xx_get_tunable, 2466 + .set_tunable = &vsc85xx_set_tunable, 2467 + .read_page = &vsc85xx_phy_read_page, 2468 + .write_page = &vsc85xx_phy_write_page, 2469 + .get_sset_count = &vsc85xx_get_sset_count, 2470 + .get_strings = &vsc85xx_get_strings, 2471 + .get_stats = &vsc85xx_get_stats, 2472 + }, 2473 + { 2474 + .phy_id = PHY_ID_VSC856X, 2475 + .name = "Microsemi GE VSC856X SyncE", 2476 + .phy_id_mask = 0xfffffff0, 2477 + /* PHY_GBIT_FEATURES */ 2478 + .soft_reset = &genphy_soft_reset, 2479 + .config_init = &vsc8584_config_init, 2480 + .config_aneg = &vsc85xx_config_aneg, 2481 + .aneg_done = &genphy_aneg_done, 2482 + .read_status = &vsc85xx_read_status, 2483 + .ack_interrupt = &vsc85xx_ack_interrupt, 2484 + .config_intr = &vsc85xx_config_intr, 2485 + .did_interrupt = &vsc8584_did_interrupt, 2486 + .suspend = &genphy_suspend, 2487 + .resume = &genphy_resume, 2488 + .probe = &vsc8584_probe, 2489 + .get_tunable = &vsc85xx_get_tunable, 2490 + .set_tunable = &vsc85xx_set_tunable, 2491 + .read_page = &vsc85xx_phy_read_page, 2492 + .write_page = &vsc85xx_phy_write_page, 2493 + .get_sset_count = &vsc85xx_get_sset_count, 2494 + .get_strings = &vsc85xx_get_strings, 2495 + .get_stats = &vsc85xx_get_stats, 2496 + }, 2497 + { 2498 + .phy_id = PHY_ID_VSC8572, 2499 + .name = "Microsemi GE VSC8572 SyncE", 2500 + .phy_id_mask = 0xfffffff0, 2501 + /* PHY_GBIT_FEATURES */ 2502 + .soft_reset = &genphy_soft_reset, 2503 + .config_init = &vsc8584_config_init, 2504 + .config_aneg = &vsc85xx_config_aneg, 2505 + .aneg_done = &genphy_aneg_done, 2506 + .read_status = &vsc85xx_read_status, 2507 + .ack_interrupt = &vsc85xx_ack_interrupt, 2508 + .config_intr = &vsc85xx_config_intr, 2509 + .did_interrupt = &vsc8584_did_interrupt, 2510 + .suspend = &genphy_suspend, 2511 + .resume = &genphy_resume, 2512 + .probe = &vsc8574_probe, 2513 + .set_wol = &vsc85xx_wol_set, 2514 + .get_wol = &vsc85xx_wol_get, 2515 + .get_tunable = &vsc85xx_get_tunable, 2516 + .set_tunable = &vsc85xx_set_tunable, 2517 + .read_page = &vsc85xx_phy_read_page, 2518 + .write_page = &vsc85xx_phy_write_page, 2519 + .get_sset_count = &vsc85xx_get_sset_count, 2520 + .get_strings = &vsc85xx_get_strings, 2521 + .get_stats = &vsc85xx_get_stats, 2522 + }, 2523 + { 2500 2524 .phy_id = PHY_ID_VSC8574, 2501 2525 .name = "Microsemi GE VSC8574 SyncE", 2502 2526 .phy_id_mask = 0xfffffff0, ··· 2590 2462 .probe = &vsc8574_probe, 2591 2463 .set_wol = &vsc85xx_wol_set, 2592 2464 .get_wol = &vsc85xx_wol_get, 2465 + .get_tunable = &vsc85xx_get_tunable, 2466 + .set_tunable = &vsc85xx_set_tunable, 2467 + .read_page = &vsc85xx_phy_read_page, 2468 + .write_page = &vsc85xx_phy_write_page, 2469 + .get_sset_count = &vsc85xx_get_sset_count, 2470 + .get_strings = &vsc85xx_get_strings, 2471 + .get_stats = &vsc85xx_get_stats, 2472 + }, 2473 + { 2474 + .phy_id = PHY_ID_VSC8575, 2475 + .name = "Microsemi GE VSC8575 SyncE", 2476 + .phy_id_mask = 0xfffffff0, 2477 + /* PHY_GBIT_FEATURES */ 2478 + .soft_reset = &genphy_soft_reset, 2479 + .config_init = &vsc8584_config_init, 2480 + .config_aneg = &vsc85xx_config_aneg, 2481 + .aneg_done = &genphy_aneg_done, 2482 + .read_status = &vsc85xx_read_status, 2483 + .ack_interrupt = &vsc85xx_ack_interrupt, 2484 + .config_intr = &vsc85xx_config_intr, 2485 + .did_interrupt = &vsc8584_did_interrupt, 2486 + .suspend = &genphy_suspend, 2487 + .resume = &genphy_resume, 2488 + .probe = &vsc8584_probe, 2489 + .get_tunable = &vsc85xx_get_tunable, 2490 + .set_tunable = &vsc85xx_set_tunable, 2491 + .read_page = &vsc85xx_phy_read_page, 2492 + .write_page = &vsc85xx_phy_write_page, 2493 + .get_sset_count = &vsc85xx_get_sset_count, 2494 + .get_strings = &vsc85xx_get_strings, 2495 + .get_stats = &vsc85xx_get_stats, 2496 + }, 2497 + { 2498 + .phy_id = PHY_ID_VSC8582, 2499 + .name = "Microsemi GE VSC8582 SyncE", 2500 + .phy_id_mask = 0xfffffff0, 2501 + /* PHY_GBIT_FEATURES */ 2502 + .soft_reset = &genphy_soft_reset, 2503 + .config_init = &vsc8584_config_init, 2504 + .config_aneg = &vsc85xx_config_aneg, 2505 + .aneg_done = &genphy_aneg_done, 2506 + .read_status = &vsc85xx_read_status, 2507 + .ack_interrupt = &vsc85xx_ack_interrupt, 2508 + .config_intr = &vsc85xx_config_intr, 2509 + .did_interrupt = &vsc8584_did_interrupt, 2510 + .suspend = &genphy_suspend, 2511 + .resume = &genphy_resume, 2512 + .probe = &vsc8584_probe, 2593 2513 .get_tunable = &vsc85xx_get_tunable, 2594 2514 .set_tunable = &vsc85xx_set_tunable, 2595 2515 .read_page = &vsc85xx_phy_read_page, ··· 2676 2500 module_phy_driver(vsc85xx_driver); 2677 2501 2678 2502 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { 2503 + { PHY_ID_VSC8504, 0xfffffff0, }, 2679 2504 { PHY_ID_VSC8514, 0xfffffff0, }, 2680 2505 { PHY_ID_VSC8530, 0xfffffff0, }, 2681 2506 { PHY_ID_VSC8531, 0xfffffff0, }, 2682 2507 { PHY_ID_VSC8540, 0xfffffff0, }, 2683 2508 { PHY_ID_VSC8541, 0xfffffff0, }, 2509 + { PHY_ID_VSC8552, 0xfffffff0, }, 2510 + { PHY_ID_VSC856X, 0xfffffff0, }, 2511 + { PHY_ID_VSC8572, 0xfffffff0, }, 2684 2512 { PHY_ID_VSC8574, 0xfffffff0, }, 2513 + { PHY_ID_VSC8575, 0xfffffff0, }, 2514 + { PHY_ID_VSC8582, 0xfffffff0, }, 2685 2515 { PHY_ID_VSC8584, 0xfffffff0, }, 2686 2516 { } 2687 2517 };