]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
mscc.c: Add support for additional VSC PHYs
authorBryan Whitehead <Bryan.Whitehead@microchip.com>
Wed, 13 Nov 2019 16:33:15 +0000 (11:33 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 13 Nov 2019 20:34:38 +0000 (12:34 -0800)
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>
drivers/net/phy/mscc.c

index 805cda3465d73f8bf62da7e5bcde4ae96ac1db72..aadee8db0ff8786ac9f3d36bbf08f0ac3f41ab41 100644 (file)
@@ -252,13 +252,21 @@ enum rgmii_rx_clock_delay {
 #define MSCC_PHY_TR_LSB                          17
 #define MSCC_PHY_TR_MSB                          18
 
-/* Microsemi PHY ID's */
+/* Microsemi PHY ID's
+ *   Code assumes lowest nibble is 0
+ */
+#define PHY_ID_VSC8504                   0x000704c0
 #define PHY_ID_VSC8514                   0x00070670
 #define PHY_ID_VSC8530                   0x00070560
 #define PHY_ID_VSC8531                   0x00070570
 #define PHY_ID_VSC8540                   0x00070760
 #define PHY_ID_VSC8541                   0x00070770
+#define PHY_ID_VSC8552                   0x000704e0
+#define PHY_ID_VSC856X                   0x000707e0
+#define PHY_ID_VSC8572                   0x000704d0
 #define PHY_ID_VSC8574                   0x000704a0
+#define PHY_ID_VSC8575                   0x000707d0
+#define PHY_ID_VSC8582                   0x000707b0
 #define PHY_ID_VSC8584                   0x000707c0
 
 #define MSCC_VDDMAC_1500                 1500
@@ -1595,6 +1603,9 @@ static bool vsc8584_is_pkg_init(struct phy_device *phydev, bool reversed)
                else
                        addr = vsc8531->base_addr + i;
 
+               if (!map[addr])
+                       continue;
+
                phy = container_of(map[addr], struct phy_device, mdio);
 
                if ((phy->phy_id & phydev->drv->phy_id_mask) !=
@@ -1647,14 +1658,29 @@ static int vsc8584_config_init(struct phy_device *phydev)
         * in this pre-init function.
         */
        if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0)) {
-               if ((phydev->phy_id & phydev->drv->phy_id_mask) ==
-                   (PHY_ID_VSC8574 & phydev->drv->phy_id_mask))
+               /* The following switch statement assumes that the lowest
+                * nibble of the phy_id_mask is always 0. This works because
+                * the lowest nibble of the PHY_ID's below are also 0.
+                */
+               WARN_ON(phydev->drv->phy_id_mask & 0xf);
+
+               switch (phydev->phy_id & phydev->drv->phy_id_mask) {
+               case PHY_ID_VSC8504:
+               case PHY_ID_VSC8552:
+               case PHY_ID_VSC8572:
+               case PHY_ID_VSC8574:
                        ret = vsc8574_config_pre_init(phydev);
-               else if ((phydev->phy_id & phydev->drv->phy_id_mask) ==
-                        (PHY_ID_VSC8584 & phydev->drv->phy_id_mask))
+                       break;
+               case PHY_ID_VSC856X:
+               case PHY_ID_VSC8575:
+               case PHY_ID_VSC8582:
+               case PHY_ID_VSC8584:
                        ret = vsc8584_config_pre_init(phydev);
-               else
+                       break;
+               default:
                        ret = -EINVAL;
+                       break;
+               };
 
                if (ret)
                        goto err;
@@ -2321,6 +2347,32 @@ static int vsc85xx_probe(struct phy_device *phydev)
 
 /* Microsemi VSC85xx PHYs */
 static struct phy_driver vsc85xx_driver[] = {
+{
+       .phy_id         = PHY_ID_VSC8504,
+       .name           = "Microsemi GE VSC8504 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_GBIT_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc8584_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &vsc85xx_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .did_interrupt  = &vsc8584_did_interrupt,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc8574_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
 {
        .phy_id         = PHY_ID_VSC8514,
        .name           = "Microsemi GE VSC8514 SyncE",
@@ -2444,6 +2496,82 @@ static struct phy_driver vsc85xx_driver[] = {
        .get_strings    = &vsc85xx_get_strings,
        .get_stats      = &vsc85xx_get_stats,
 },
+{
+       .phy_id         = PHY_ID_VSC8552,
+       .name           = "Microsemi GE VSC8552 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_GBIT_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc8584_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &vsc85xx_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .did_interrupt  = &vsc8584_did_interrupt,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc8574_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
+{
+       .phy_id         = PHY_ID_VSC856X,
+       .name           = "Microsemi GE VSC856X SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_GBIT_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc8584_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &vsc85xx_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .did_interrupt  = &vsc8584_did_interrupt,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc8584_probe,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
+{
+       .phy_id         = PHY_ID_VSC8572,
+       .name           = "Microsemi GE VSC8572 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_GBIT_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc8584_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &vsc85xx_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .did_interrupt  = &vsc8584_did_interrupt,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc8574_probe,
+       .set_wol        = &vsc85xx_wol_set,
+       .get_wol        = &vsc85xx_wol_get,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
 {
        .phy_id         = PHY_ID_VSC8574,
        .name           = "Microsemi GE VSC8574 SyncE",
@@ -2470,6 +2598,54 @@ static struct phy_driver vsc85xx_driver[] = {
        .get_strings    = &vsc85xx_get_strings,
        .get_stats      = &vsc85xx_get_stats,
 },
+{
+       .phy_id         = PHY_ID_VSC8575,
+       .name           = "Microsemi GE VSC8575 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_GBIT_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc8584_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &vsc85xx_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .did_interrupt  = &vsc8584_did_interrupt,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc8584_probe,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
+{
+       .phy_id         = PHY_ID_VSC8582,
+       .name           = "Microsemi GE VSC8582 SyncE",
+       .phy_id_mask    = 0xfffffff0,
+       /* PHY_GBIT_FEATURES */
+       .soft_reset     = &genphy_soft_reset,
+       .config_init    = &vsc8584_config_init,
+       .config_aneg    = &vsc85xx_config_aneg,
+       .aneg_done      = &genphy_aneg_done,
+       .read_status    = &vsc85xx_read_status,
+       .ack_interrupt  = &vsc85xx_ack_interrupt,
+       .config_intr    = &vsc85xx_config_intr,
+       .did_interrupt  = &vsc8584_did_interrupt,
+       .suspend        = &genphy_suspend,
+       .resume         = &genphy_resume,
+       .probe          = &vsc8584_probe,
+       .get_tunable    = &vsc85xx_get_tunable,
+       .set_tunable    = &vsc85xx_set_tunable,
+       .read_page      = &vsc85xx_phy_read_page,
+       .write_page     = &vsc85xx_phy_write_page,
+       .get_sset_count = &vsc85xx_get_sset_count,
+       .get_strings    = &vsc85xx_get_strings,
+       .get_stats      = &vsc85xx_get_stats,
+},
 {
        .phy_id         = PHY_ID_VSC8584,
        .name           = "Microsemi GE VSC8584 SyncE",
@@ -2500,12 +2676,18 @@ static struct phy_driver vsc85xx_driver[] = {
 module_phy_driver(vsc85xx_driver);
 
 static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = {
+       { PHY_ID_VSC8504, 0xfffffff0, },
        { PHY_ID_VSC8514, 0xfffffff0, },
        { PHY_ID_VSC8530, 0xfffffff0, },
        { PHY_ID_VSC8531, 0xfffffff0, },
        { PHY_ID_VSC8540, 0xfffffff0, },
        { PHY_ID_VSC8541, 0xfffffff0, },
+       { PHY_ID_VSC8552, 0xfffffff0, },
+       { PHY_ID_VSC856X, 0xfffffff0, },
+       { PHY_ID_VSC8572, 0xfffffff0, },
        { PHY_ID_VSC8574, 0xfffffff0, },
+       { PHY_ID_VSC8575, 0xfffffff0, },
+       { PHY_ID_VSC8582, 0xfffffff0, },
        { PHY_ID_VSC8584, 0xfffffff0, },
        { }
 };