Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.8-rc2 171 lines 4.1 kB view raw
1/* Framework for MDIO devices, other than PHYs. 2 * 3 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 * 10 */ 11 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14#include <linux/errno.h> 15#include <linux/init.h> 16#include <linux/interrupt.h> 17#include <linux/kernel.h> 18#include <linux/mdio.h> 19#include <linux/mii.h> 20#include <linux/module.h> 21#include <linux/phy.h> 22#include <linux/slab.h> 23#include <linux/string.h> 24#include <linux/unistd.h> 25 26void mdio_device_free(struct mdio_device *mdiodev) 27{ 28 put_device(&mdiodev->dev); 29} 30EXPORT_SYMBOL(mdio_device_free); 31 32static void mdio_device_release(struct device *dev) 33{ 34 kfree(to_mdio_device(dev)); 35} 36 37struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr) 38{ 39 struct mdio_device *mdiodev; 40 41 /* We allocate the device, and initialize the default values */ 42 mdiodev = kzalloc(sizeof(*mdiodev), GFP_KERNEL); 43 if (!mdiodev) 44 return ERR_PTR(-ENOMEM); 45 46 mdiodev->dev.release = mdio_device_release; 47 mdiodev->dev.parent = &bus->dev; 48 mdiodev->dev.bus = &mdio_bus_type; 49 mdiodev->device_free = mdio_device_free; 50 mdiodev->device_remove = mdio_device_remove; 51 mdiodev->bus = bus; 52 mdiodev->addr = addr; 53 54 dev_set_name(&mdiodev->dev, PHY_ID_FMT, bus->id, addr); 55 56 device_initialize(&mdiodev->dev); 57 58 return mdiodev; 59} 60EXPORT_SYMBOL(mdio_device_create); 61 62/** 63 * mdio_device_register - Register the mdio device on the MDIO bus 64 * @mdiodev: mdio_device structure to be added to the MDIO bus 65 */ 66int mdio_device_register(struct mdio_device *mdiodev) 67{ 68 int err; 69 70 dev_info(&mdiodev->dev, "mdio_device_register\n"); 71 72 err = mdiobus_register_device(mdiodev); 73 if (err) 74 return err; 75 76 err = device_add(&mdiodev->dev); 77 if (err) { 78 pr_err("MDIO %d failed to add\n", mdiodev->addr); 79 goto out; 80 } 81 82 return 0; 83 84 out: 85 mdiobus_unregister_device(mdiodev); 86 return err; 87} 88EXPORT_SYMBOL(mdio_device_register); 89 90/** 91 * mdio_device_remove - Remove a previously registered mdio device from the 92 * MDIO bus 93 * @mdiodev: mdio_device structure to remove 94 * 95 * This doesn't free the mdio_device itself, it merely reverses the effects 96 * of mdio_device_register(). Use mdio_device_free() to free the device 97 * after calling this function. 98 */ 99void mdio_device_remove(struct mdio_device *mdiodev) 100{ 101 device_del(&mdiodev->dev); 102 mdiobus_unregister_device(mdiodev); 103} 104EXPORT_SYMBOL(mdio_device_remove); 105 106/** 107 * mdio_probe - probe an MDIO device 108 * @dev: device to probe 109 * 110 * Description: Take care of setting up the mdio_device structure 111 * and calling the driver to probe the device. 112 */ 113static int mdio_probe(struct device *dev) 114{ 115 struct mdio_device *mdiodev = to_mdio_device(dev); 116 struct device_driver *drv = mdiodev->dev.driver; 117 struct mdio_driver *mdiodrv = to_mdio_driver(drv); 118 int err = 0; 119 120 if (mdiodrv->probe) 121 err = mdiodrv->probe(mdiodev); 122 123 return err; 124} 125 126static int mdio_remove(struct device *dev) 127{ 128 struct mdio_device *mdiodev = to_mdio_device(dev); 129 struct device_driver *drv = mdiodev->dev.driver; 130 struct mdio_driver *mdiodrv = to_mdio_driver(drv); 131 132 if (mdiodrv->remove) 133 mdiodrv->remove(mdiodev); 134 135 return 0; 136} 137 138/** 139 * mdio_driver_register - register an mdio_driver with the MDIO layer 140 * @new_driver: new mdio_driver to register 141 */ 142int mdio_driver_register(struct mdio_driver *drv) 143{ 144 struct mdio_driver_common *mdiodrv = &drv->mdiodrv; 145 int retval; 146 147 pr_info("mdio_driver_register: %s\n", mdiodrv->driver.name); 148 149 mdiodrv->driver.bus = &mdio_bus_type; 150 mdiodrv->driver.probe = mdio_probe; 151 mdiodrv->driver.remove = mdio_remove; 152 153 retval = driver_register(&mdiodrv->driver); 154 if (retval) { 155 pr_err("%s: Error %d in registering driver\n", 156 mdiodrv->driver.name, retval); 157 158 return retval; 159 } 160 161 return 0; 162} 163EXPORT_SYMBOL(mdio_driver_register); 164 165void mdio_driver_unregister(struct mdio_driver *drv) 166{ 167 struct mdio_driver_common *mdiodrv = &drv->mdiodrv; 168 169 driver_unregister(&mdiodrv->driver); 170} 171EXPORT_SYMBOL(mdio_driver_unregister);