usbehciomap.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*
  2. * OMAP3-specific code for
  3. * USB Enhanced Host Controller Interface (EHCI) driver
  4. * High speed USB 2.0.
  5. */
  6. #include "u.h"
  7. #include "../port/lib.h"
  8. #include "mem.h"
  9. #include "dat.h"
  10. #include "fns.h"
  11. #include "io.h"
  12. #include "../port/error.h"
  13. #include "../port/usb.h"
  14. #include "../port/portusbehci.h"
  15. #include "usbehci.h"
  16. static Ctlr* ctlrs[Nhcis];
  17. static void
  18. ehcireset(Ctlr *ctlr)
  19. {
  20. Eopio *opio;
  21. int i;
  22. ilock(ctlr);
  23. dprint("ehci %#p reset\n", ctlr->capio);
  24. opio = ctlr->opio;
  25. /*
  26. * Turn off legacy mode. Some controllers won't
  27. * interrupt us as expected otherwise.
  28. */
  29. ehcirun(ctlr, 0);
  30. /* clear high 32 bits of address signals if it's 64 bits capable.
  31. * This is probably not needed but it does not hurt and others do it.
  32. */
  33. if((ctlr->capio->capparms & C64) != 0){
  34. dprint("ehci: 64 bits\n");
  35. opio->seg = 0;
  36. }
  37. if(ehcidebugcapio != ctlr->capio){
  38. opio->cmd |= Chcreset; /* controller reset */
  39. coherence();
  40. for(i = 0; i < 100; i++){
  41. if((opio->cmd & Chcreset) == 0)
  42. break;
  43. delay(1);
  44. }
  45. if(i == 100)
  46. print("ehci %#p controller reset timed out\n", ctlr->capio);
  47. }
  48. /* requesting more interrupts per µframe may miss interrupts */
  49. opio->cmd &= ~Citcmask;
  50. opio->cmd |= 1 << Citcshift; /* max of 1 intr. per 125 µs */
  51. coherence();
  52. switch(opio->cmd & Cflsmask){
  53. case Cfls1024:
  54. ctlr->nframes = 1024;
  55. break;
  56. case Cfls512:
  57. ctlr->nframes = 512;
  58. break;
  59. case Cfls256:
  60. ctlr->nframes = 256;
  61. break;
  62. default:
  63. panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
  64. }
  65. coherence();
  66. dprint("ehci: %d frames\n", ctlr->nframes);
  67. iunlock(ctlr);
  68. }
  69. static void
  70. setdebug(Hci*, int d)
  71. {
  72. ehcidebug = d;
  73. }
  74. static void
  75. shutdown(Hci *hp)
  76. {
  77. int i;
  78. Ctlr *ctlr;
  79. Eopio *opio;
  80. ctlr = hp->aux;
  81. ilock(ctlr);
  82. opio = ctlr->opio;
  83. opio->cmd |= Chcreset; /* controller reset */
  84. coherence();
  85. for(i = 0; i < 100; i++){
  86. if((opio->cmd & Chcreset) == 0)
  87. break;
  88. delay(1);
  89. }
  90. if(i >= 100)
  91. print("ehci %#p controller reset timed out\n", ctlr->capio);
  92. delay(100);
  93. ehcirun(ctlr, 0);
  94. opio->frbase = 0;
  95. coherence();
  96. iunlock(ctlr);
  97. }
  98. /*
  99. * omap3-specific ehci code
  100. */
  101. enum {
  102. /* opio->insn[5] bits */
  103. Control = 1<<31, /* set to start access, cleared when done */
  104. Write = 2<<22,
  105. Read = 3<<22,
  106. Portsh = 24,
  107. Regaddrsh = 16, /* 0x2f means use extended reg addr */
  108. Eregaddrsh = 8,
  109. /* phy reg addresses */
  110. Funcctlreg = 4,
  111. Ifcctlreg = 7,
  112. Phystppullupoff = 0x90, /* on is 0x10 */
  113. Phyrstport2 = 147, /* gpio # */
  114. };
  115. static void
  116. wrulpi(Eopio *opio, int port, int reg, uchar data)
  117. {
  118. opio->insn[5] = Control | port << Portsh | Write | reg << Regaddrsh |
  119. data;
  120. coherence();
  121. /*
  122. * this seems contrary to the skimpy documentation in the manual
  123. * but inverting the test hangs forever.
  124. */
  125. while (!(opio->insn[5] & Control))
  126. ;
  127. }
  128. static int
  129. reset(Hci *hp)
  130. {
  131. Ctlr *ctlr;
  132. Ecapio *capio;
  133. Eopio *opio;
  134. Uhh *uhh;
  135. static int beenhere;
  136. if (beenhere)
  137. return -1;
  138. beenhere = 1;
  139. if(getconf("*nousbehci") != nil || probeaddr(PHYSEHCI) < 0)
  140. return -1;
  141. ctlr = smalloc(sizeof(Ctlr));
  142. /*
  143. * don't bother with vmap; i/o space is all mapped anyway,
  144. * and a size less than 1MB will blow an assertion in mmukmap.
  145. */
  146. ctlr->capio = capio = (Ecapio *)PHYSEHCI;
  147. ctlr->opio = opio = (Eopio*)((uintptr)capio + (capio->cap & 0xff));
  148. hp->aux = ctlr;
  149. hp->port = (uintptr)ctlr->capio;
  150. hp->irq = 77;
  151. hp->nports = capio->parms & Cnports;
  152. ddprint("echi: %s, ncc %lud npcc %lud\n",
  153. capio->parms & 0x10000 ? "leds" : "no leds",
  154. (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
  155. ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
  156. capio->parms & 0x40 ? "explicit" : "automatic",
  157. capio->parms & 0x10 ? "" : "no ", hp->nports);
  158. ehcireset(ctlr);
  159. ehcimeminit(ctlr);
  160. /* omap35-specific set up */
  161. /* bit 5 `must be set to 1 for proper behavior', spruf98d §23.2.6.7.17 */
  162. opio->insn[4] |= 1<<5;
  163. coherence();
  164. /* insn[5] is for both utmi and ulpi, depending on hostconfig mode */
  165. uhh = (Uhh *)PHYSUHH;
  166. if (uhh->hostconfig & P1ulpi_bypass) { /* utmi port 1 active */
  167. /* not doing this */
  168. iprint("usbehci: bypassing ulpi on port 1!\n");
  169. opio->insn[5] &= ~(MASK(4) << 13);
  170. opio->insn[5] |= 1 << 13; /* select port 1 */
  171. coherence();
  172. } else { /* ulpi port 1 active */
  173. /* TODO may need to reset gpio port2 here */
  174. /* disable integrated stp pull-up resistor */
  175. wrulpi(opio, 1, Ifcctlreg, Phystppullupoff);
  176. /* force phy to `high-speed' */
  177. wrulpi(opio, 1, Funcctlreg, 0x40);
  178. }
  179. /*
  180. * Linkage to the generic HCI driver.
  181. */
  182. ehcilinkage(hp);
  183. hp->shutdown = shutdown;
  184. hp->debug = setdebug;
  185. intrenable(78, hp->interrupt, hp, UNKNOWN, "usbtll");
  186. intrenable(92, hp->interrupt, hp, UNKNOWN, "usb otg");
  187. intrenable(93, hp->interrupt, hp, UNKNOWN, "usb otg dma");
  188. return 0;
  189. }
  190. void
  191. usbehcilink(void)
  192. {
  193. addhcitype("ehci", reset);
  194. }