Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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);