mdio-ofgpio.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * OpenFirmware GPIO based MDIO bitbang driver.
  3. *
  4. * Copyright (c) 2008 CSE Semaphore Belgium.
  5. * by Laurent Pinchart <laurentp@cse-semaphore.com>
  6. *
  7. * Based on earlier work by
  8. *
  9. * Copyright (c) 2003 Intracom S.A.
  10. * by Pantelis Antoniou <panto@intracom.gr>
  11. *
  12. * 2005 (c) MontaVista Software, Inc.
  13. * Vitaly Bordug <vbordug@ru.mvista.com>
  14. *
  15. * This file is licensed under the terms of the GNU General Public License
  16. * version 2. This program is licensed "as is" without any warranty of any
  17. * kind, whether express or implied.
  18. */
  19. #include <linux/module.h>
  20. #include <linux/slab.h>
  21. #include <linux/init.h>
  22. #include <linux/interrupt.h>
  23. #include <linux/mdio-bitbang.h>
  24. #include <linux/of_gpio.h>
  25. #include <linux/of_platform.h>
  26. struct mdio_gpio_info {
  27. struct mdiobb_ctrl ctrl;
  28. int mdc, mdio;
  29. };
  30. static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
  31. {
  32. struct mdio_gpio_info *bitbang =
  33. container_of(ctrl, struct mdio_gpio_info, ctrl);
  34. if (dir)
  35. gpio_direction_output(bitbang->mdio, 1);
  36. else
  37. gpio_direction_input(bitbang->mdio);
  38. }
  39. static int mdio_read(struct mdiobb_ctrl *ctrl)
  40. {
  41. struct mdio_gpio_info *bitbang =
  42. container_of(ctrl, struct mdio_gpio_info, ctrl);
  43. return gpio_get_value(bitbang->mdio);
  44. }
  45. static void mdio(struct mdiobb_ctrl *ctrl, int what)
  46. {
  47. struct mdio_gpio_info *bitbang =
  48. container_of(ctrl, struct mdio_gpio_info, ctrl);
  49. gpio_set_value(bitbang->mdio, what);
  50. }
  51. static void mdc(struct mdiobb_ctrl *ctrl, int what)
  52. {
  53. struct mdio_gpio_info *bitbang =
  54. container_of(ctrl, struct mdio_gpio_info, ctrl);
  55. gpio_set_value(bitbang->mdc, what);
  56. }
  57. static struct mdiobb_ops mdio_gpio_ops = {
  58. .owner = THIS_MODULE,
  59. .set_mdc = mdc,
  60. .set_mdio_dir = mdio_dir,
  61. .set_mdio_data = mdio,
  62. .get_mdio_data = mdio_read,
  63. };
  64. static int __devinit mdio_ofgpio_bitbang_init(struct mii_bus *bus,
  65. struct device_node *np)
  66. {
  67. struct mdio_gpio_info *bitbang = bus->priv;
  68. bitbang->mdc = of_get_gpio(np, 0);
  69. bitbang->mdio = of_get_gpio(np, 1);
  70. if (bitbang->mdc < 0 || bitbang->mdio < 0)
  71. return -ENODEV;
  72. snprintf(bus->id, MII_BUS_ID_SIZE, "%x", bitbang->mdc);
  73. return 0;
  74. }
  75. static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
  76. {
  77. const u32 *data;
  78. int len, id, irq;
  79. data = of_get_property(np, "reg", &len);
  80. if (!data || len != 4)
  81. return;
  82. id = *data;
  83. bus->phy_mask &= ~(1 << id);
  84. irq = of_irq_to_resource(np, 0, NULL);
  85. if (irq != NO_IRQ)
  86. bus->irq[id] = irq;
  87. }
  88. static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
  89. const struct of_device_id *match)
  90. {
  91. struct device_node *np = NULL;
  92. struct mii_bus *new_bus;
  93. struct mdio_gpio_info *bitbang;
  94. int ret = -ENOMEM;
  95. int i;
  96. bitbang = kzalloc(sizeof(struct mdio_gpio_info), GFP_KERNEL);
  97. if (!bitbang)
  98. goto out;
  99. bitbang->ctrl.ops = &mdio_gpio_ops;
  100. new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
  101. if (!new_bus)
  102. goto out_free_bitbang;
  103. new_bus->name = "GPIO Bitbanged MII",
  104. ret = mdio_ofgpio_bitbang_init(new_bus, ofdev->node);
  105. if (ret)
  106. goto out_free_bus;
  107. new_bus->phy_mask = ~0;
  108. new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
  109. if (!new_bus->irq)
  110. goto out_free_bus;
  111. for (i = 0; i < PHY_MAX_ADDR; i++)
  112. new_bus->irq[i] = -1;
  113. while ((np = of_get_next_child(ofdev->node, np)))
  114. if (!strcmp(np->type, "ethernet-phy"))
  115. add_phy(new_bus, np);
  116. new_bus->parent = &ofdev->dev;
  117. dev_set_drvdata(&ofdev->dev, new_bus);
  118. ret = mdiobus_register(new_bus);
  119. if (ret)
  120. goto out_free_irqs;
  121. return 0;
  122. out_free_irqs:
  123. dev_set_drvdata(&ofdev->dev, NULL);
  124. kfree(new_bus->irq);
  125. out_free_bus:
  126. free_mdio_bitbang(new_bus);
  127. out_free_bitbang:
  128. kfree(bitbang);
  129. out:
  130. return ret;
  131. }
  132. static int mdio_ofgpio_remove(struct of_device *ofdev)
  133. {
  134. struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
  135. struct mdio_gpio_info *bitbang = bus->priv;
  136. mdiobus_unregister(bus);
  137. kfree(bus->irq);
  138. free_mdio_bitbang(bus);
  139. dev_set_drvdata(&ofdev->dev, NULL);
  140. kfree(bitbang);
  141. return 0;
  142. }
  143. static struct of_device_id mdio_ofgpio_match[] = {
  144. {
  145. .compatible = "virtual,mdio-gpio",
  146. },
  147. {},
  148. };
  149. static struct of_platform_driver mdio_ofgpio_driver = {
  150. .name = "mdio-gpio",
  151. .match_table = mdio_ofgpio_match,
  152. .probe = mdio_ofgpio_probe,
  153. .remove = mdio_ofgpio_remove,
  154. };
  155. static int mdio_ofgpio_init(void)
  156. {
  157. return of_register_platform_driver(&mdio_ofgpio_driver);
  158. }
  159. static void mdio_ofgpio_exit(void)
  160. {
  161. of_unregister_platform_driver(&mdio_ofgpio_driver);
  162. }
  163. module_init(mdio_ofgpio_init);
  164. module_exit(mdio_ofgpio_exit);