ehci-atmel.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * Driver for EHCI UHP on Atmel chips
  3. *
  4. * Copyright (C) 2009 Atmel Corporation,
  5. * Nicolas Ferre <nicolas.ferre@atmel.com>
  6. *
  7. * Based on various ehci-*.c drivers
  8. *
  9. * This file is subject to the terms and conditions of the GNU General Public
  10. * License. See the file COPYING in the main directory of this archive for
  11. * more details.
  12. */
  13. #include <linux/clk.h>
  14. #include <linux/dma-mapping.h>
  15. #include <linux/io.h>
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/of.h>
  19. #include <linux/of_platform.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/usb.h>
  22. #include <linux/usb/hcd.h>
  23. #include "ehci.h"
  24. #define DRIVER_DESC "EHCI Atmel driver"
  25. static const char hcd_name[] = "ehci-atmel";
  26. static struct hc_driver __read_mostly ehci_atmel_hc_driver;
  27. /* interface and function clocks */
  28. static struct clk *iclk, *fclk;
  29. static int clocked;
  30. /*-------------------------------------------------------------------------*/
  31. static void atmel_start_clock(void)
  32. {
  33. clk_prepare_enable(iclk);
  34. clk_prepare_enable(fclk);
  35. clocked = 1;
  36. }
  37. static void atmel_stop_clock(void)
  38. {
  39. clk_disable_unprepare(fclk);
  40. clk_disable_unprepare(iclk);
  41. clocked = 0;
  42. }
  43. static void atmel_start_ehci(struct platform_device *pdev)
  44. {
  45. dev_dbg(&pdev->dev, "start\n");
  46. atmel_start_clock();
  47. }
  48. static void atmel_stop_ehci(struct platform_device *pdev)
  49. {
  50. dev_dbg(&pdev->dev, "stop\n");
  51. atmel_stop_clock();
  52. }
  53. /*-------------------------------------------------------------------------*/
  54. static int ehci_atmel_drv_probe(struct platform_device *pdev)
  55. {
  56. struct usb_hcd *hcd;
  57. const struct hc_driver *driver = &ehci_atmel_hc_driver;
  58. struct resource *res;
  59. struct ehci_hcd *ehci;
  60. int irq;
  61. int retval;
  62. if (usb_disabled())
  63. return -ENODEV;
  64. pr_debug("Initializing Atmel-SoC USB Host Controller\n");
  65. irq = platform_get_irq(pdev, 0);
  66. if (irq <= 0) {
  67. dev_err(&pdev->dev,
  68. "Found HC with no IRQ. Check %s setup!\n",
  69. dev_name(&pdev->dev));
  70. retval = -ENODEV;
  71. goto fail_create_hcd;
  72. }
  73. /* Right now device-tree probed devices don't get dma_mask set.
  74. * Since shared usb code relies on it, set it here for now.
  75. * Once we have dma capability bindings this can go away.
  76. */
  77. if (!pdev->dev.dma_mask)
  78. pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
  79. if (!pdev->dev.coherent_dma_mask)
  80. pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
  81. hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
  82. if (!hcd) {
  83. retval = -ENOMEM;
  84. goto fail_create_hcd;
  85. }
  86. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  87. if (!res) {
  88. dev_err(&pdev->dev,
  89. "Found HC with no register addr. Check %s setup!\n",
  90. dev_name(&pdev->dev));
  91. retval = -ENODEV;
  92. goto fail_request_resource;
  93. }
  94. hcd->rsrc_start = res->start;
  95. hcd->rsrc_len = resource_size(res);
  96. hcd->regs = devm_ioremap_resource(&pdev->dev, res);
  97. if (IS_ERR(hcd->regs)) {
  98. retval = PTR_ERR(hcd->regs);
  99. goto fail_request_resource;
  100. }
  101. iclk = devm_clk_get(&pdev->dev, "ehci_clk");
  102. if (IS_ERR(iclk)) {
  103. dev_err(&pdev->dev, "Error getting interface clock\n");
  104. retval = -ENOENT;
  105. goto fail_request_resource;
  106. }
  107. fclk = devm_clk_get(&pdev->dev, "uhpck");
  108. if (IS_ERR(fclk)) {
  109. dev_err(&pdev->dev, "Error getting function clock\n");
  110. retval = -ENOENT;
  111. goto fail_request_resource;
  112. }
  113. ehci = hcd_to_ehci(hcd);
  114. /* registers start at offset 0x0 */
  115. ehci->caps = hcd->regs;
  116. atmel_start_ehci(pdev);
  117. retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
  118. if (retval)
  119. goto fail_add_hcd;
  120. return retval;
  121. fail_add_hcd:
  122. atmel_stop_ehci(pdev);
  123. fail_request_resource:
  124. usb_put_hcd(hcd);
  125. fail_create_hcd:
  126. dev_err(&pdev->dev, "init %s fail, %d\n",
  127. dev_name(&pdev->dev), retval);
  128. return retval;
  129. }
  130. static int ehci_atmel_drv_remove(struct platform_device *pdev)
  131. {
  132. struct usb_hcd *hcd = platform_get_drvdata(pdev);
  133. usb_remove_hcd(hcd);
  134. usb_put_hcd(hcd);
  135. atmel_stop_ehci(pdev);
  136. fclk = iclk = NULL;
  137. return 0;
  138. }
  139. #ifdef CONFIG_OF
  140. static const struct of_device_id atmel_ehci_dt_ids[] = {
  141. { .compatible = "atmel,at91sam9g45-ehci" },
  142. { /* sentinel */ }
  143. };
  144. MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids);
  145. #endif
  146. static struct platform_driver ehci_atmel_driver = {
  147. .probe = ehci_atmel_drv_probe,
  148. .remove = ehci_atmel_drv_remove,
  149. .shutdown = usb_hcd_platform_shutdown,
  150. .driver = {
  151. .name = "atmel-ehci",
  152. .of_match_table = of_match_ptr(atmel_ehci_dt_ids),
  153. },
  154. };
  155. static int __init ehci_atmel_init(void)
  156. {
  157. if (usb_disabled())
  158. return -ENODEV;
  159. pr_info("%s: " DRIVER_DESC "\n", hcd_name);
  160. ehci_init_driver(&ehci_atmel_hc_driver, NULL);
  161. return platform_driver_register(&ehci_atmel_driver);
  162. }
  163. module_init(ehci_atmel_init);
  164. static void __exit ehci_atmel_cleanup(void)
  165. {
  166. platform_driver_unregister(&ehci_atmel_driver);
  167. }
  168. module_exit(ehci_atmel_cleanup);
  169. MODULE_DESCRIPTION(DRIVER_DESC);
  170. MODULE_ALIAS("platform:atmel-ehci");
  171. MODULE_AUTHOR("Nicolas Ferre");
  172. MODULE_LICENSE("GPL");