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>
This commit is contained in:
		 Chuanhong Guo
					Chuanhong Guo
				
			
				
					committed by
					
						 Petr Štetiar
						Petr Štetiar
					
				
			
			
				
	
			
			
			 Petr Štetiar
						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"); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user