ehci-fotg2.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Gemini EHCI Host Controller driver
  3. *
  4. * Copyright (C) 2014 Roman Yeryomin <roman@advem.lv>
  5. * Copyright (C) 2012 Tobias Waldvogel
  6. * based on GPLd code from Sony Computer Entertainment Inc.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; version 2 of the License.
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/hrtimer.h>
  14. #include <linux/io.h>
  15. #include <linux/module.h>
  16. #include <linux/platform_device.h>
  17. #include <linux/usb.h>
  18. #include <linux/usb/hcd.h>
  19. #include <linux/usb/ehci_pdriver.h>
  20. #include <mach/hardware.h>
  21. #include <mach/global_reg.h>
  22. #include "ehci.h"
  23. #define DRV_NAME "ehci-fotg2"
  24. #define HCD_MISC 0x40
  25. #define OTGC_SCR 0x80
  26. #define OTGC_INT_STS 0x84
  27. #define OTGC_INT_EN 0x88
  28. #define GLOBAL_ISR 0xC0
  29. #define GLOBAL_ICR 0xC4
  30. #define GLOBAL_INT_POLARITY (1 << 3)
  31. #define GLOBAL_INT_MASK_HC (1 << 2)
  32. #define GLOBAL_INT_MASK_OTG (1 << 1)
  33. #define GLOBAL_INT_MASK_DEV (1 << 0)
  34. #define OTGC_SCR_ID (1 << 21)
  35. #define OTGC_SCR_CROLE (1 << 20)
  36. #define OTGC_SCR_VBUS_VLD (1 << 19)
  37. #define OTGC_SCR_A_SRP_RESP_TYPE (1 << 8)
  38. #define OTGC_SCR_A_SRP_DET_EN (1 << 7)
  39. #define OTGC_SCR_A_SET_B_HNP_EN (1 << 6)
  40. #define OTGC_SCR_A_BUS_DROP (1 << 5)
  41. #define OTGC_SCR_A_BUS_REQ (1 << 4)
  42. #define OTGC_INT_APLGRMV (1 << 12)
  43. #define OTGC_INT_BPLGRMV (1 << 11)
  44. #define OTGC_INT_OVC (1 << 10)
  45. #define OTGC_INT_IDCHG (1 << 9)
  46. #define OTGC_INT_RLCHG (1 << 8)
  47. #define OTGC_INT_AVBUSERR (1 << 5)
  48. #define OTGC_INT_ASRPDET (1 << 4)
  49. #define OTGC_INT_BSRPDN (1 << 0)
  50. #define OTGC_INT_A_TYPE ( \
  51. OTGC_INT_ASRPDET | \
  52. OTGC_INT_AVBUSERR | \
  53. OTGC_INT_OVC | \
  54. OTGC_INT_RLCHG | \
  55. OTGC_INT_IDCHG | \
  56. OTGC_INT_APLGRMV \
  57. )
  58. #define OTGC_INT_B_TYPE ( \
  59. OTGC_INT_AVBUSERR | \
  60. OTGC_INT_OVC | \
  61. OTGC_INT_RLCHG | \
  62. OTGC_INT_IDCHG \
  63. )
  64. static void fotg2_otg_init(struct usb_hcd *hcd)
  65. {
  66. u32 val;
  67. writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
  68. GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
  69. hcd->regs + GLOBAL_ICR);
  70. val = readl(hcd->regs + OTGC_SCR);
  71. val &= ~(OTGC_SCR_A_SRP_RESP_TYPE | OTGC_SCR_A_SRP_DET_EN |
  72. OTGC_SCR_A_BUS_DROP | OTGC_SCR_A_SET_B_HNP_EN);
  73. val |= OTGC_SCR_A_BUS_REQ;
  74. writel(val, hcd->regs + OTGC_SCR);
  75. writel(OTGC_INT_A_TYPE, hcd->regs + OTGC_INT_EN);
  76. /* setup MISC register, fixes timing problems */
  77. val = readl(hcd->regs + HCD_MISC);
  78. val |= 0xD;
  79. writel(val, hcd->regs + HCD_MISC);
  80. writel(~0, hcd->regs + GLOBAL_ISR);
  81. writel(~0, hcd->regs + OTGC_INT_STS);
  82. }
  83. static int fotg2_ehci_reset(struct usb_hcd *hcd)
  84. {
  85. int retval;
  86. retval = ehci_setup(hcd);
  87. if (retval)
  88. return retval;
  89. writel(GLOBAL_INT_POLARITY, hcd->regs + GLOBAL_ICR);
  90. return 0;
  91. }
  92. static const struct hc_driver fotg2_ehci_hc_driver = {
  93. .description = hcd_name,
  94. .product_desc = "FOTG2 EHCI Host Controller",
  95. .hcd_priv_size = sizeof(struct ehci_hcd),
  96. .irq = ehci_irq,
  97. .flags = HCD_MEMORY | HCD_USB2,
  98. .reset = fotg2_ehci_reset,
  99. .start = ehci_run,
  100. .stop = ehci_stop,
  101. .shutdown = ehci_shutdown,
  102. .urb_enqueue = ehci_urb_enqueue,
  103. .urb_dequeue = ehci_urb_dequeue,
  104. .endpoint_disable = ehci_endpoint_disable,
  105. .endpoint_reset = ehci_endpoint_reset,
  106. .get_frame_number = ehci_get_frame,
  107. .hub_status_data = ehci_hub_status_data,
  108. .hub_control = ehci_hub_control,
  109. #if defined(CONFIG_PM)
  110. .bus_suspend = ehci_bus_suspend,
  111. .bus_resume = ehci_bus_resume,
  112. #endif
  113. .relinquish_port = ehci_relinquish_port,
  114. .port_handed_over = ehci_port_handed_over,
  115. .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
  116. };
  117. static irqreturn_t fotg2_ehci_irq(int irq, void *data)
  118. {
  119. struct usb_hcd *hcd = data;
  120. u32 icr, sts;
  121. irqreturn_t retval;
  122. icr = readl(hcd->regs + GLOBAL_ICR);
  123. writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
  124. GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
  125. hcd->regs + GLOBAL_ICR);
  126. retval = IRQ_NONE;
  127. sts = ~icr;
  128. sts &= GLOBAL_INT_MASK_HC | GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV;
  129. sts &= readl(hcd->regs + GLOBAL_ISR);
  130. writel(sts, hcd->regs + GLOBAL_ISR);
  131. if (unlikely(sts & GLOBAL_INT_MASK_DEV)) {
  132. ehci_warn(hcd_to_ehci(hcd),
  133. "Received unexpected irq for device role\n");
  134. retval = IRQ_HANDLED;
  135. }
  136. if (unlikely(sts & GLOBAL_INT_MASK_OTG)) {
  137. u32 otg_sts;
  138. otg_sts = readl(hcd->regs + OTGC_INT_STS);
  139. writel(otg_sts, hcd->regs + OTGC_INT_STS);
  140. ehci_warn(hcd_to_ehci(hcd),
  141. "Received unexpected irq for OTG management\n");
  142. retval = IRQ_HANDLED;
  143. }
  144. if (sts & GLOBAL_INT_MASK_HC) {
  145. retval = IRQ_NONE;
  146. }
  147. writel(icr, hcd->regs + GLOBAL_ICR);
  148. return retval;
  149. }
  150. static int fotg2_ehci_probe(struct platform_device *pdev)
  151. {
  152. struct usb_hcd *hcd;
  153. struct resource *res;
  154. int irq , err;
  155. irq = platform_get_irq(pdev, 0);
  156. if (irq < 0) {
  157. pr_err("no irq provided");
  158. return irq;
  159. }
  160. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  161. if (!res) {
  162. pr_err("no memory resource provided");
  163. return -ENXIO;
  164. }
  165. hcd = usb_create_hcd(&fotg2_ehci_hc_driver, &pdev->dev,
  166. dev_name(&pdev->dev));
  167. if (!hcd)
  168. return -ENOMEM;
  169. hcd->rsrc_start = res->start;
  170. hcd->rsrc_len = resource_size(res);
  171. hcd->regs = devm_ioremap_resource(&pdev->dev, res);
  172. if (IS_ERR(hcd->regs)) {
  173. err = -ENOMEM;
  174. goto err_put_hcd;
  175. }
  176. hcd->has_tt = 1;
  177. hcd_to_ehci(hcd)->caps = hcd->regs;
  178. fotg2_otg_init(hcd);
  179. err = request_irq(irq, &fotg2_ehci_irq, IRQF_SHARED, "fotg2", hcd);
  180. if (err)
  181. goto err_put_hcd;
  182. err = usb_add_hcd(hcd, irq, IRQF_SHARED);
  183. if (err)
  184. goto err_put_hcd;
  185. platform_set_drvdata(pdev, hcd);
  186. return 0;
  187. err_put_hcd:
  188. usb_put_hcd(hcd);
  189. return err;
  190. }
  191. static int fotg2_ehci_remove(struct platform_device *pdev)
  192. {
  193. struct usb_hcd *hcd = platform_get_drvdata(pdev);
  194. writel(GLOBAL_INT_POLARITY | GLOBAL_INT_MASK_HC |
  195. GLOBAL_INT_MASK_OTG | GLOBAL_INT_MASK_DEV,
  196. hcd->regs + GLOBAL_ICR);
  197. free_irq(hcd->irq, hcd);
  198. usb_remove_hcd(hcd);
  199. usb_put_hcd(hcd);
  200. platform_set_drvdata(pdev, NULL);
  201. return 0;
  202. }
  203. MODULE_ALIAS("platform:" DRV_NAME);
  204. static struct platform_driver ehci_fotg2_driver = {
  205. .probe = fotg2_ehci_probe,
  206. .remove = fotg2_ehci_remove,
  207. .driver.name = DRV_NAME,
  208. };