airport.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* airport.c
  2. *
  3. * A driver for "Hermes" chipset based Apple Airport wireless
  4. * card.
  5. *
  6. * Copyright notice & release notes in file main.c
  7. *
  8. * Note specific to airport stub:
  9. *
  10. * 0.05 : first version of the new split driver
  11. * 0.06 : fix possible hang on powerup, add sleep support
  12. */
  13. #define DRIVER_NAME "airport"
  14. #define PFX DRIVER_NAME ": "
  15. #include <linux/module.h>
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/delay.h>
  19. #include <asm/pmac_feature.h>
  20. #include "orinoco.h"
  21. #define AIRPORT_IO_LEN (0x1000) /* one page */
  22. struct airport {
  23. struct macio_dev *mdev;
  24. void __iomem *vaddr;
  25. unsigned int irq;
  26. int irq_requested;
  27. int ndev_registered;
  28. };
  29. static int
  30. airport_suspend(struct macio_dev *mdev, pm_message_t state)
  31. {
  32. struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
  33. struct net_device *dev = priv->ndev;
  34. struct airport *card = priv->card;
  35. unsigned long flags;
  36. int err;
  37. printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
  38. err = orinoco_lock(priv, &flags);
  39. if (err) {
  40. printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
  41. dev->name);
  42. return 0;
  43. }
  44. orinoco_down(priv);
  45. orinoco_unlock(priv, &flags);
  46. disable_irq(card->irq);
  47. pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  48. macio_get_of_node(mdev), 0, 0);
  49. return 0;
  50. }
  51. static int
  52. airport_resume(struct macio_dev *mdev)
  53. {
  54. struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
  55. struct net_device *dev = priv->ndev;
  56. struct airport *card = priv->card;
  57. unsigned long flags;
  58. int err;
  59. printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
  60. pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  61. macio_get_of_node(mdev), 0, 1);
  62. msleep(200);
  63. enable_irq(card->irq);
  64. priv->hw.ops->lock_irqsave(&priv->lock, &flags);
  65. err = orinoco_up(priv);
  66. priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
  67. return err;
  68. }
  69. static int
  70. airport_detach(struct macio_dev *mdev)
  71. {
  72. struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev);
  73. struct airport *card = priv->card;
  74. if (card->ndev_registered)
  75. orinoco_if_del(priv);
  76. card->ndev_registered = 0;
  77. if (card->irq_requested)
  78. free_irq(card->irq, priv);
  79. card->irq_requested = 0;
  80. if (card->vaddr)
  81. iounmap(card->vaddr);
  82. card->vaddr = NULL;
  83. macio_release_resource(mdev, 0);
  84. pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  85. macio_get_of_node(mdev), 0, 0);
  86. ssleep(1);
  87. macio_set_drvdata(mdev, NULL);
  88. free_orinocodev(priv);
  89. return 0;
  90. }
  91. static int airport_hard_reset(struct orinoco_private *priv)
  92. {
  93. /* It would be nice to power cycle the Airport for a real hard
  94. * reset, but for some reason although it appears to
  95. * re-initialize properly, it falls in a screaming heap
  96. * shortly afterwards. */
  97. #if 0
  98. struct airport *card = priv->card;
  99. /* Vitally important. If we don't do this it seems we get an
  100. * interrupt somewhere during the power cycle, since
  101. * hw_unavailable is already set it doesn't get ACKed, we get
  102. * into an interrupt loop and the PMU decides to turn us
  103. * off. */
  104. disable_irq(card->irq);
  105. pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  106. macio_get_of_node(card->mdev), 0, 0);
  107. ssleep(1);
  108. pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  109. macio_get_of_node(card->mdev), 0, 1);
  110. ssleep(1);
  111. enable_irq(card->irq);
  112. ssleep(1);
  113. #endif
  114. return 0;
  115. }
  116. static int
  117. airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
  118. {
  119. struct orinoco_private *priv;
  120. struct airport *card;
  121. unsigned long phys_addr;
  122. struct hermes *hw;
  123. if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
  124. printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
  125. return -ENODEV;
  126. }
  127. /* Allocate space for private device-specific data */
  128. priv = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
  129. airport_hard_reset, NULL);
  130. if (!priv) {
  131. printk(KERN_ERR PFX "Cannot allocate network device\n");
  132. return -ENODEV;
  133. }
  134. card = priv->card;
  135. hw = &priv->hw;
  136. card->mdev = mdev;
  137. if (macio_request_resource(mdev, 0, DRIVER_NAME)) {
  138. printk(KERN_ERR PFX "can't request IO resource !\n");
  139. free_orinocodev(priv);
  140. return -EBUSY;
  141. }
  142. macio_set_drvdata(mdev, priv);
  143. /* Setup interrupts & base address */
  144. card->irq = macio_irq(mdev, 0);
  145. phys_addr = macio_resource_start(mdev, 0); /* Physical address */
  146. printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
  147. card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
  148. if (!card->vaddr) {
  149. printk(KERN_ERR PFX "ioremap() failed\n");
  150. goto failed;
  151. }
  152. hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
  153. /* Power up card */
  154. pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE,
  155. macio_get_of_node(mdev), 0, 1);
  156. ssleep(1);
  157. /* Reset it before we get the interrupt */
  158. hw->ops->init(hw);
  159. if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
  160. printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
  161. goto failed;
  162. }
  163. card->irq_requested = 1;
  164. /* Initialise the main driver */
  165. if (orinoco_init(priv) != 0) {
  166. printk(KERN_ERR PFX "orinoco_init() failed\n");
  167. goto failed;
  168. }
  169. /* Register an interface with the stack */
  170. if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {
  171. printk(KERN_ERR PFX "orinoco_if_add() failed\n");
  172. goto failed;
  173. }
  174. card->ndev_registered = 1;
  175. return 0;
  176. failed:
  177. airport_detach(mdev);
  178. return -ENODEV;
  179. } /* airport_attach */
  180. static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
  181. " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
  182. MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
  183. MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
  184. MODULE_LICENSE("Dual MPL/GPL");
  185. static const struct of_device_id airport_match[] = {
  186. {
  187. .name = "radio",
  188. },
  189. {},
  190. };
  191. MODULE_DEVICE_TABLE(of, airport_match);
  192. static struct macio_driver airport_driver = {
  193. .driver = {
  194. .name = DRIVER_NAME,
  195. .owner = THIS_MODULE,
  196. .of_match_table = airport_match,
  197. },
  198. .probe = airport_attach,
  199. .remove = airport_detach,
  200. .suspend = airport_suspend,
  201. .resume = airport_resume,
  202. };
  203. static int __init
  204. init_airport(void)
  205. {
  206. printk(KERN_DEBUG "%s\n", version);
  207. return macio_register_driver(&airport_driver);
  208. }
  209. static void __exit
  210. exit_airport(void)
  211. {
  212. macio_unregister_driver(&airport_driver);
  213. }
  214. module_init(init_airport);
  215. module_exit(exit_airport);