Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /* Framework for MDIO devices, other than PHYs.
0003  *
0004  * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
0005  */
0006 
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008 
0009 #include <linux/delay.h>
0010 #include <linux/errno.h>
0011 #include <linux/gpio.h>
0012 #include <linux/gpio/consumer.h>
0013 #include <linux/init.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/kernel.h>
0016 #include <linux/mdio.h>
0017 #include <linux/mii.h>
0018 #include <linux/module.h>
0019 #include <linux/phy.h>
0020 #include <linux/reset.h>
0021 #include <linux/slab.h>
0022 #include <linux/string.h>
0023 #include <linux/unistd.h>
0024 
0025 void mdio_device_free(struct mdio_device *mdiodev)
0026 {
0027     put_device(&mdiodev->dev);
0028 }
0029 EXPORT_SYMBOL(mdio_device_free);
0030 
0031 static void mdio_device_release(struct device *dev)
0032 {
0033     kfree(to_mdio_device(dev));
0034 }
0035 
0036 int mdio_device_bus_match(struct device *dev, struct device_driver *drv)
0037 {
0038     struct mdio_device *mdiodev = to_mdio_device(dev);
0039     struct mdio_driver *mdiodrv = to_mdio_driver(drv);
0040 
0041     if (mdiodrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY)
0042         return 0;
0043 
0044     return strcmp(mdiodev->modalias, drv->name) == 0;
0045 }
0046 
0047 struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr)
0048 {
0049     struct mdio_device *mdiodev;
0050 
0051     /* We allocate the device, and initialize the default values */
0052     mdiodev = kzalloc(sizeof(*mdiodev), GFP_KERNEL);
0053     if (!mdiodev)
0054         return ERR_PTR(-ENOMEM);
0055 
0056     mdiodev->dev.release = mdio_device_release;
0057     mdiodev->dev.parent = &bus->dev;
0058     mdiodev->dev.bus = &mdio_bus_type;
0059     mdiodev->device_free = mdio_device_free;
0060     mdiodev->device_remove = mdio_device_remove;
0061     mdiodev->bus = bus;
0062     mdiodev->addr = addr;
0063 
0064     dev_set_name(&mdiodev->dev, PHY_ID_FMT, bus->id, addr);
0065 
0066     device_initialize(&mdiodev->dev);
0067 
0068     return mdiodev;
0069 }
0070 EXPORT_SYMBOL(mdio_device_create);
0071 
0072 /**
0073  * mdio_device_register - Register the mdio device on the MDIO bus
0074  * @mdiodev: mdio_device structure to be added to the MDIO bus
0075  */
0076 int mdio_device_register(struct mdio_device *mdiodev)
0077 {
0078     int err;
0079 
0080     dev_dbg(&mdiodev->dev, "%s\n", __func__);
0081 
0082     err = mdiobus_register_device(mdiodev);
0083     if (err)
0084         return err;
0085 
0086     err = device_add(&mdiodev->dev);
0087     if (err) {
0088         pr_err("MDIO %d failed to add\n", mdiodev->addr);
0089         goto out;
0090     }
0091 
0092     return 0;
0093 
0094  out:
0095     mdiobus_unregister_device(mdiodev);
0096     return err;
0097 }
0098 EXPORT_SYMBOL(mdio_device_register);
0099 
0100 /**
0101  * mdio_device_remove - Remove a previously registered mdio device from the
0102  *          MDIO bus
0103  * @mdiodev: mdio_device structure to remove
0104  *
0105  * This doesn't free the mdio_device itself, it merely reverses the effects
0106  * of mdio_device_register(). Use mdio_device_free() to free the device
0107  * after calling this function.
0108  */
0109 void mdio_device_remove(struct mdio_device *mdiodev)
0110 {
0111     device_del(&mdiodev->dev);
0112     mdiobus_unregister_device(mdiodev);
0113 }
0114 EXPORT_SYMBOL(mdio_device_remove);
0115 
0116 void mdio_device_reset(struct mdio_device *mdiodev, int value)
0117 {
0118     unsigned int d;
0119 
0120     if (!mdiodev->reset_gpio && !mdiodev->reset_ctrl)
0121         return;
0122 
0123     if (mdiodev->reset_gpio)
0124         gpiod_set_value_cansleep(mdiodev->reset_gpio, value);
0125 
0126     if (mdiodev->reset_ctrl) {
0127         if (value)
0128             reset_control_assert(mdiodev->reset_ctrl);
0129         else
0130             reset_control_deassert(mdiodev->reset_ctrl);
0131     }
0132 
0133     d = value ? mdiodev->reset_assert_delay : mdiodev->reset_deassert_delay;
0134     if (d)
0135         fsleep(d);
0136 }
0137 EXPORT_SYMBOL(mdio_device_reset);
0138 
0139 /**
0140  * mdio_probe - probe an MDIO device
0141  * @dev: device to probe
0142  *
0143  * Description: Take care of setting up the mdio_device structure
0144  * and calling the driver to probe the device.
0145  */
0146 static int mdio_probe(struct device *dev)
0147 {
0148     struct mdio_device *mdiodev = to_mdio_device(dev);
0149     struct device_driver *drv = mdiodev->dev.driver;
0150     struct mdio_driver *mdiodrv = to_mdio_driver(drv);
0151     int err = 0;
0152 
0153     /* Deassert the reset signal */
0154     mdio_device_reset(mdiodev, 0);
0155 
0156     if (mdiodrv->probe) {
0157         err = mdiodrv->probe(mdiodev);
0158         if (err) {
0159             /* Assert the reset signal */
0160             mdio_device_reset(mdiodev, 1);
0161         }
0162     }
0163 
0164     return err;
0165 }
0166 
0167 static int mdio_remove(struct device *dev)
0168 {
0169     struct mdio_device *mdiodev = to_mdio_device(dev);
0170     struct device_driver *drv = mdiodev->dev.driver;
0171     struct mdio_driver *mdiodrv = to_mdio_driver(drv);
0172 
0173     if (mdiodrv->remove)
0174         mdiodrv->remove(mdiodev);
0175 
0176     /* Assert the reset signal */
0177     mdio_device_reset(mdiodev, 1);
0178 
0179     return 0;
0180 }
0181 
0182 static void mdio_shutdown(struct device *dev)
0183 {
0184     struct mdio_device *mdiodev = to_mdio_device(dev);
0185     struct device_driver *drv = mdiodev->dev.driver;
0186     struct mdio_driver *mdiodrv = to_mdio_driver(drv);
0187 
0188     if (mdiodrv->shutdown)
0189         mdiodrv->shutdown(mdiodev);
0190 }
0191 
0192 /**
0193  * mdio_driver_register - register an mdio_driver with the MDIO layer
0194  * @drv: new mdio_driver to register
0195  */
0196 int mdio_driver_register(struct mdio_driver *drv)
0197 {
0198     struct mdio_driver_common *mdiodrv = &drv->mdiodrv;
0199     int retval;
0200 
0201     pr_debug("%s: %s\n", __func__, mdiodrv->driver.name);
0202 
0203     mdiodrv->driver.bus = &mdio_bus_type;
0204     mdiodrv->driver.probe = mdio_probe;
0205     mdiodrv->driver.remove = mdio_remove;
0206     mdiodrv->driver.shutdown = mdio_shutdown;
0207 
0208     retval = driver_register(&mdiodrv->driver);
0209     if (retval) {
0210         pr_err("%s: Error %d in registering driver\n",
0211                mdiodrv->driver.name, retval);
0212 
0213         return retval;
0214     }
0215 
0216     return 0;
0217 }
0218 EXPORT_SYMBOL(mdio_driver_register);
0219 
0220 void mdio_driver_unregister(struct mdio_driver *drv)
0221 {
0222     struct mdio_driver_common *mdiodrv = &drv->mdiodrv;
0223 
0224     driver_unregister(&mdiodrv->driver);
0225 }
0226 EXPORT_SYMBOL(mdio_driver_unregister);