kernel: b53: add support for kernels 5.0+
[openwrt/openwrt.git] / target / linux / generic / files / drivers / net / phy / b53 / b53_mdio.c
index 9283af6072aa54568da2ac6264520ea1b2eb9867..6de86236123c62b6093bba4c0eb06e16d6f3aa1e 100644 (file)
@@ -238,6 +238,24 @@ static int b53_mdio_write64(struct b53_device *dev, u8 page, u8 reg,
        return b53_mdio_op(dev, page, reg, REG_MII_ADDR_WRITE);
 }
 
+static int b53_mdio_phy_read16(struct b53_device *dev, int addr, u8 reg,
+                              u16 *value)
+{
+       struct mii_bus *bus = dev->priv;
+
+       *value = mdiobus_read(bus, addr, reg);
+
+       return 0;
+}
+
+static int b53_mdio_phy_write16(struct b53_device *dev, int addr, u8 reg,
+                               u16 value)
+{
+       struct mii_bus *bus = dev->priv;
+
+       return mdiobus_write(bus, addr, reg, value);
+}
+
 static struct b53_io_ops b53_mdio_ops = {
        .read8 = b53_mdio_read8,
        .read16 = b53_mdio_read16,
@@ -249,59 +267,70 @@ static struct b53_io_ops b53_mdio_ops = {
        .write32 = b53_mdio_write32,
        .write48 = b53_mdio_write48,
        .write64 = b53_mdio_write64,
+       .phy_read16 = b53_mdio_phy_read16,
+       .phy_write16 = b53_mdio_phy_write16,
 };
 
 static int b53_phy_probe(struct phy_device *phydev)
 {
-       struct b53_device dev;
+       struct b53_device *dev;
        int ret;
 
        /* allow the generic phy driver to take over */
-       if (phydev->addr != B53_PSEUDO_PHY && phydev->addr != 0)
+       if (phydev->mdio.addr != B53_PSEUDO_PHY && phydev->mdio.addr != 0)
                return -ENODEV;
 
-       dev.current_page = 0xff;
-       dev.priv = phydev->bus;
-       dev.ops = &b53_mdio_ops;
-       dev.pdata = NULL;
-       mutex_init(&dev.reg_mutex);
+       dev = b53_switch_alloc(&phydev->mdio.dev, &b53_mdio_ops, phydev->mdio.bus);
+       if (!dev)
+               return -ENOMEM;
 
-       ret = b53_switch_detect(&dev);
-       if (!ret)
+       dev->current_page = 0xff;
+       dev->priv = phydev->mdio.bus;
+       dev->ops = &b53_mdio_ops;
+       dev->pdata = NULL;
+       mutex_init(&dev->reg_mutex);
+
+       ret = b53_switch_detect(dev);
+       if (ret)
                return ret;
 
-       if (is5325(&dev) || is5365(&dev))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+       linkmode_zero(phydev->supported);
+       if (is5325(dev) || is5365(dev))
+               linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phydev->supported);
+       else
+               linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phydev->supported);
+
+       linkmode_copy(phydev->advertising, phydev->supported);
+#else
+       if (is5325(dev) || is5365(dev))
                phydev->supported = SUPPORTED_100baseT_Full;
        else
                phydev->supported = SUPPORTED_1000baseT_Full;
 
        phydev->advertising = phydev->supported;
+#endif
+
+       ret = b53_switch_register(dev);
+       if (ret) {
+               dev_err(dev->dev, "failed to register switch: %i\n", ret);
+               return ret;
+       }
+
+       phydev->priv = dev;
 
        return 0;
 }
 
 static int b53_phy_config_init(struct phy_device *phydev)
 {
-       struct b53_device *dev;
-       int ret;
-
-       dev = b53_switch_alloc(&phydev->dev, &b53_mdio_ops, phydev->bus);
-       if (!dev)
-               return -ENOMEM;
+       struct b53_device *dev = phydev->priv;
 
        /* we don't use page 0xff, so force a page set */
        dev->current_page = 0xff;
        /* force the ethX as alias */
        dev->sw_dev.alias = phydev->attached_dev->name;
 
-       ret = b53_switch_register(dev);
-       if (ret) {
-               pr_info("failed to register switch: %i\n", ret);
-               return ret;
-       }
-
-       phydev->priv = dev;
-
        return 0;
 }
 
@@ -352,12 +381,9 @@ static struct phy_driver b53_phy_driver_id1 = {
        .config_aneg    = b53_phy_config_aneg,
        .config_init    = b53_phy_config_init,
        .read_status    = b53_phy_read_status,
-       .driver = {
-               .owner = THIS_MODULE,
-       },
 };
 
-/* BCM53125 */
+/* BCM53125, BCM53128 */
 static struct phy_driver b53_phy_driver_id2 = {
        .phy_id         = 0x03625c00,
        .name           = "Broadcom B53 (2)",
@@ -368,28 +394,46 @@ static struct phy_driver b53_phy_driver_id2 = {
        .config_aneg    = b53_phy_config_aneg,
        .config_init    = b53_phy_config_init,
        .read_status    = b53_phy_read_status,
-       .driver = {
-               .owner = THIS_MODULE,
-       },
+};
+
+/* BCM5365 */
+static struct phy_driver b53_phy_driver_id3 = {
+       .phy_id         = 0x00406000,
+       .name           = "Broadcom B53 (3)",
+       .phy_id_mask    = 0x1ffffc00,
+       .features       = 0,
+       .probe          = b53_phy_probe,
+       .remove         = b53_phy_remove,
+       .config_aneg    = b53_phy_config_aneg,
+       .config_init    = b53_phy_config_init,
+       .read_status    = b53_phy_read_status,
 };
 
 int __init b53_phy_driver_register(void)
 {
        int ret;
 
-       ret = phy_driver_register(&b53_phy_driver_id1);
+       ret = phy_driver_register(&b53_phy_driver_id1, THIS_MODULE);
        if (ret)
                return ret;
 
-       ret = phy_driver_register(&b53_phy_driver_id2);
+       ret = phy_driver_register(&b53_phy_driver_id2, THIS_MODULE);
        if (ret)
-               phy_driver_unregister(&b53_phy_driver_id1);
+               goto err1;
+
+       ret = phy_driver_register(&b53_phy_driver_id3, THIS_MODULE);
+       if (!ret)
+               return 0;
 
+       phy_driver_unregister(&b53_phy_driver_id2);
+err1:
+       phy_driver_unregister(&b53_phy_driver_id1);
        return ret;
 }
 
 void __exit b53_phy_driver_unregister(void)
 {
+       phy_driver_unregister(&b53_phy_driver_id3);
        phy_driver_unregister(&b53_phy_driver_id2);
        phy_driver_unregister(&b53_phy_driver_id1);
 }