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 <gch981213@gmail.com>
v19.07.3_mercusys_ac12_duma
Chuanhong Guo 5 years ago committed by Petr Štetiar
parent da64a8c656
commit 7d504f68a6

@ -24,6 +24,7 @@
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/of_device.h>
#include <linux/of_mdio.h>
#include <linux/bitops.h>
#include <net/genetlink.h>
#include <linux/switch.h>
@ -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");

Loading…
Cancel
Save