From 7d504f68a651f328ae78beccd2f647d6f62fe39b Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Thu, 10 Jan 2019 15:31:53 +0800 Subject: [PATCH] generic: ar8216: add mdio-device probing support currently only ar8327 and ar8236 are added since they are the only two I could verify. Signed-off-by: Chuanhong Guo --- .../generic/files/drivers/net/phy/ar8216.c | 135 +++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c index b8cc2c8f4c..d091f60dac 100644 --- a/target/linux/generic/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic/files/drivers/net/phy/ar8216.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2333,5 +2334,137 @@ static struct phy_driver ar8xxx_phy_driver[] = { } }; -module_phy_driver(ar8xxx_phy_driver); +static const struct of_device_id ar8xxx_mdiodev_of_match[] = { + { + .compatible = "qca,ar8236", + .data = &ar8236_chip, + }, { + .compatible = "qca,ar8327", + .data = &ar8327_chip, + }, + { /* sentinel */ }, +}; + +static int +ar8xxx_mdiodev_probe(struct mdio_device *mdiodev) +{ + const struct of_device_id *match; + struct ar8xxx_priv *priv; + struct switch_dev *swdev; + int ret; + + match = of_match_device(ar8xxx_mdiodev_of_match, &mdiodev->dev); + if (!match) + return -EINVAL; + + priv = ar8xxx_create(); + if (priv == NULL) + return -ENOMEM; + + priv->mii_bus = mdiodev->bus; + priv->pdev = &mdiodev->dev; + priv->chip = (const struct ar8xxx_chip *) match->data; + + ret = ar8xxx_read_id(priv); + if (ret) + goto free_priv; + + ret = ar8xxx_probe_switch(priv); + if (ret) + goto free_priv; + + swdev = &priv->dev; + swdev->alias = dev_name(&mdiodev->dev); + ret = register_switch(swdev, NULL); + if (ret) + goto free_priv; + + pr_info("%s: %s rev. %u switch registered on %s\n", + swdev->devname, swdev->name, priv->chip_rev, + dev_name(&priv->mii_bus->dev)); + + mutex_lock(&ar8xxx_dev_list_lock); + list_add(&priv->list, &ar8xxx_dev_list); + mutex_unlock(&ar8xxx_dev_list_lock); + + priv->use_count++; + + ret = ar8xxx_start(priv); + if (ret) + goto err_unregister_switch; + + dev_set_drvdata(&mdiodev->dev, priv); + + return 0; + +err_unregister_switch: + if (--priv->use_count) + return ret; + + unregister_switch(&priv->dev); + +free_priv: + ar8xxx_free(priv); + return ret; +} + +static void +ar8xxx_mdiodev_remove(struct mdio_device *mdiodev) +{ + struct ar8xxx_priv *priv = dev_get_drvdata(&mdiodev->dev); + + if (WARN_ON(!priv)) + return; + + mutex_lock(&ar8xxx_dev_list_lock); + + if (--priv->use_count > 0) { + mutex_unlock(&ar8xxx_dev_list_lock); + return; + } + + list_del(&priv->list); + mutex_unlock(&ar8xxx_dev_list_lock); + + unregister_switch(&priv->dev); + ar8xxx_mib_stop(priv); + ar8xxx_free(priv); +} + +static struct mdio_driver ar8xxx_mdio_driver = { + .probe = ar8xxx_mdiodev_probe, + .remove = ar8xxx_mdiodev_remove, + .mdiodrv.driver = { + .name = "ar8xxx-switch", + .of_match_table = ar8xxx_mdiodev_of_match, + }, +}; + +static int __init ar8216_init(void) +{ + int ret; + + ret = phy_drivers_register(ar8xxx_phy_driver, + ARRAY_SIZE(ar8xxx_phy_driver), + THIS_MODULE); + if (ret) + return ret; + + ret = mdio_driver_register(&ar8xxx_mdio_driver); + if (ret) + phy_drivers_unregister(ar8xxx_phy_driver, + ARRAY_SIZE(ar8xxx_phy_driver)); + + return ret; +} +module_init(ar8216_init); + +static void __exit ar8216_exit(void) +{ + mdio_driver_unregister(&ar8xxx_mdio_driver); + phy_drivers_unregister(ar8xxx_phy_driver, + ARRAY_SIZE(ar8xxx_phy_driver)); +} +module_exit(ar8216_exit); + MODULE_LICENSE("GPL"); -- 2.25.1