mdio_device.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  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. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  12. #include <linux/errno.h>
  13. #include <linux/gpio.h>
  14. #include <linux/gpio/consumer.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. #include <linux/delay.h>
  26. void mdio_device_free(struct mdio_device *mdiodev)
  27. {
  28. put_device(&mdiodev->dev);
  29. }
  30. EXPORT_SYMBOL(mdio_device_free);
  31. static void mdio_device_release(struct device *dev)
  32. {
  33. kfree(to_mdio_device(dev));
  34. }
  35. int mdio_device_bus_match(struct device *dev, struct device_driver *drv)
  36. {
  37. struct mdio_device *mdiodev = to_mdio_device(dev);
  38. struct mdio_driver *mdiodrv = to_mdio_driver(drv);
  39. if (mdiodrv->mdiodrv.flags & MDIO_DEVICE_IS_PHY)
  40. return 0;
  41. return strcmp(mdiodev->modalias, drv->name) == 0;
  42. }
  43. struct mdio_device *mdio_device_create(struct mii_bus *bus, int addr)
  44. {
  45. struct mdio_device *mdiodev;
  46. /* We allocate the device, and initialize the default values */
  47. mdiodev = kzalloc(sizeof(*mdiodev), GFP_KERNEL);
  48. if (!mdiodev)
  49. return ERR_PTR(-ENOMEM);
  50. mdiodev->dev.release = mdio_device_release;
  51. mdiodev->dev.parent = &bus->dev;
  52. mdiodev->dev.bus = &mdio_bus_type;
  53. mdiodev->device_free = mdio_device_free;
  54. mdiodev->device_remove = mdio_device_remove;
  55. mdiodev->bus = bus;
  56. mdiodev->addr = addr;
  57. dev_set_name(&mdiodev->dev, PHY_ID_FMT, bus->id, addr);
  58. device_initialize(&mdiodev->dev);
  59. return mdiodev;
  60. }
  61. EXPORT_SYMBOL(mdio_device_create);
  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. */
  66. int mdio_device_register(struct mdio_device *mdiodev)
  67. {
  68. int err;
  69. dev_dbg(&mdiodev->dev, "mdio_device_register\n");
  70. err = mdiobus_register_device(mdiodev);
  71. if (err)
  72. return err;
  73. err = device_add(&mdiodev->dev);
  74. if (err) {
  75. pr_err("MDIO %d failed to add\n", mdiodev->addr);
  76. goto out;
  77. }
  78. return 0;
  79. out:
  80. mdiobus_unregister_device(mdiodev);
  81. return err;
  82. }
  83. EXPORT_SYMBOL(mdio_device_register);
  84. /**
  85. * mdio_device_remove - Remove a previously registered mdio device from the
  86. * MDIO bus
  87. * @mdiodev: mdio_device structure to remove
  88. *
  89. * This doesn't free the mdio_device itself, it merely reverses the effects
  90. * of mdio_device_register(). Use mdio_device_free() to free the device
  91. * after calling this function.
  92. */
  93. void mdio_device_remove(struct mdio_device *mdiodev)
  94. {
  95. device_del(&mdiodev->dev);
  96. mdiobus_unregister_device(mdiodev);
  97. }
  98. EXPORT_SYMBOL(mdio_device_remove);
  99. void mdio_device_reset(struct mdio_device *mdiodev, int value)
  100. {
  101. unsigned int d;
  102. if (!mdiodev->reset)
  103. return;
  104. gpiod_set_value(mdiodev->reset, value);
  105. d = value ? mdiodev->reset_assert_delay : mdiodev->reset_deassert_delay;
  106. if (d)
  107. usleep_range(d, d + max_t(unsigned int, d / 10, 100));
  108. }
  109. EXPORT_SYMBOL(mdio_device_reset);
  110. /**
  111. * mdio_probe - probe an MDIO device
  112. * @dev: device to probe
  113. *
  114. * Description: Take care of setting up the mdio_device structure
  115. * and calling the driver to probe the device.
  116. */
  117. static int mdio_probe(struct device *dev)
  118. {
  119. struct mdio_device *mdiodev = to_mdio_device(dev);
  120. struct device_driver *drv = mdiodev->dev.driver;
  121. struct mdio_driver *mdiodrv = to_mdio_driver(drv);
  122. int err = 0;
  123. if (mdiodrv->probe) {
  124. /* Deassert the reset signal */
  125. mdio_device_reset(mdiodev, 0);
  126. err = mdiodrv->probe(mdiodev);
  127. if (err) {
  128. /* Assert the reset signal */
  129. mdio_device_reset(mdiodev, 1);
  130. }
  131. }
  132. return err;
  133. }
  134. static int mdio_remove(struct device *dev)
  135. {
  136. struct mdio_device *mdiodev = to_mdio_device(dev);
  137. struct device_driver *drv = mdiodev->dev.driver;
  138. struct mdio_driver *mdiodrv = to_mdio_driver(drv);
  139. if (mdiodrv->remove) {
  140. mdiodrv->remove(mdiodev);
  141. /* Assert the reset signal */
  142. mdio_device_reset(mdiodev, 1);
  143. }
  144. return 0;
  145. }
  146. /**
  147. * mdio_driver_register - register an mdio_driver with the MDIO layer
  148. * @new_driver: new mdio_driver to register
  149. */
  150. int mdio_driver_register(struct mdio_driver *drv)
  151. {
  152. struct mdio_driver_common *mdiodrv = &drv->mdiodrv;
  153. int retval;
  154. pr_debug("mdio_driver_register: %s\n", mdiodrv->driver.name);
  155. mdiodrv->driver.bus = &mdio_bus_type;
  156. mdiodrv->driver.probe = mdio_probe;
  157. mdiodrv->driver.remove = mdio_remove;
  158. retval = driver_register(&mdiodrv->driver);
  159. if (retval) {
  160. pr_err("%s: Error %d in registering driver\n",
  161. mdiodrv->driver.name, retval);
  162. return retval;
  163. }
  164. return 0;
  165. }
  166. EXPORT_SYMBOL(mdio_driver_register);
  167. void mdio_driver_unregister(struct mdio_driver *drv)
  168. {
  169. struct mdio_driver_common *mdiodrv = &drv->mdiodrv;
  170. driver_unregister(&mdiodrv->driver);
  171. }
  172. EXPORT_SYMBOL(mdio_driver_unregister);