hw_dwc_otg.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * hw_dwc_otg.c
  3. *
  4. * USB handling for DWC-OTG USB 2.0 controller.
  5. *
  6. * Written & released by Keir Fraser <keir.xen@gmail.com>
  7. *
  8. * This is free and unencumbered software released into the public domain.
  9. * See the file COPYING for more details, or visit <http://unlicense.org>.
  10. */
  11. #include "hw_dwc_otg.h"
  12. int conf_iface;
  13. static bool_t is_hs;
  14. static struct rx_buf {
  15. uint32_t data[MAX_MPS / 4];
  16. uint32_t count;
  17. } rx_buf0[1], rx_bufn[32] section_ext_ram;
  18. #define RX_MASK(_ep, _idx) (((_ep)->_idx) & ((_ep)->rx_nr - 1))
  19. static struct ep {
  20. struct rx_buf *rx;
  21. uint16_t rxc, rxp, rx_nr;
  22. bool_t rx_active, tx_ready;
  23. } eps[conf_nr_ep];
  24. static bool_t dwc_otg_has_highspeed(void)
  25. {
  26. return conf_iface == IFACE_HS_EMBEDDED;
  27. }
  28. static bool_t dwc_otg_is_highspeed(void)
  29. {
  30. return is_hs;
  31. }
  32. void core_reset(void)
  33. {
  34. do { delay_us(1); } while (!(otg->grstctl & OTG_GRSTCTL_AHBIDL));
  35. otg->grstctl |= OTG_GRSTCTL_CSRST;
  36. do { delay_us(1); } while (otg->grstctl & OTG_GRSTCTL_CSRST);
  37. }
  38. static void flush_tx_fifo(int num)
  39. {
  40. otg->grstctl = OTG_GRSTCTL_TXFFLSH | OTG_GRSTCTL_TXFNUM(num);
  41. do { delay_us(1); } while (otg->grstctl & OTG_GRSTCTL_TXFFLSH);
  42. }
  43. static void flush_rx_fifo(void)
  44. {
  45. otg->grstctl = OTG_GRSTCTL_RXFFLSH;
  46. do { delay_us(1); } while (otg->grstctl & OTG_GRSTCTL_RXFFLSH);
  47. }
  48. static void ep0_out_start(void)
  49. {
  50. otg_doep[0].tsiz = (OTG_DOEPTSZ_STUPCNT |
  51. OTG_DOEPTSZ_PKTCNT(1)) |
  52. OTG_DOEPTSZ_XFERSIZ(3*8);
  53. }
  54. static bool_t is_high_speed(void)
  55. {
  56. /* 0 == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ */
  57. return ((otgd->dsts >> 1) & 3) == 0;
  58. }
  59. static void prepare_rx(uint8_t epnr)
  60. {
  61. struct ep *ep = &eps[epnr];
  62. OTG_DOEP doep = &otg_doep[epnr];
  63. uint16_t mps, nr;
  64. uint32_t tsiz;
  65. if (ep->rx_active)
  66. return;
  67. nr = ep->rxp - ep->rxc;
  68. nr = ep->rx_nr - nr;
  69. if (nr <= ep->rx_nr/2)
  70. return;
  71. mps = (epnr == 0) ? EP0_MPS : (doep->ctl & 0x7ff);
  72. tsiz = doep->tsiz & 0xe0000000;
  73. tsiz |= OTG_DOEPTSZ_PKTCNT(nr);
  74. tsiz |= OTG_DOEPTSZ_XFERSIZ(mps * nr);
  75. doep->tsiz = tsiz;
  76. doep->ctl |= OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA;
  77. ep->rx_active = TRUE;
  78. }
  79. static void read_packet(void *p, int len)
  80. {
  81. uint32_t *_p = p;
  82. unsigned int n = (len + 3) / 4;
  83. while (n--)
  84. *_p++ = otg_dfifo[0].x[0];
  85. }
  86. static void write_packet(const void *p, uint8_t epnr, int len)
  87. {
  88. const uint32_t *_p = p;
  89. unsigned int n = (len + 3) / 4;
  90. while (n--)
  91. otg_dfifo[epnr].x[0] = *_p++;
  92. }
  93. static void fifos_init(void)
  94. {
  95. unsigned int i, base, tx_sz, rx_sz, fifo_sz;
  96. /* F7 OTG: FS 1.25k FIFO RAM, HS 4k FIFO RAM. */
  97. fifo_sz = ((conf_port == PORT_FS) ? 0x500 : 0x1000) >> 2;
  98. rx_sz = fifo_sz / 2;
  99. tx_sz = fifo_sz / (2 * conf_nr_ep);
  100. otg->grxfsiz = rx_sz;
  101. base = rx_sz;
  102. otg->dieptxf0 = (tx_sz << 16) | base;
  103. for (i = 1; i < conf_nr_ep; i++) {
  104. base += tx_sz;
  105. otg->dieptxf[i-1] = (tx_sz << 16) | base;
  106. }
  107. }
  108. static void dwc_otg_init(void)
  109. {
  110. int i;
  111. /*
  112. * USB_SetCurrentMode
  113. */
  114. /* Mode select followed by required 25ms delay. */
  115. otg->gusbcfg |= OTG_GUSBCFG_FDMOD;
  116. delay_ms(25);
  117. /*
  118. * USB_DevInit
  119. */
  120. for (i = 0; i < ARRAY_SIZE(otg->dieptxf); i++)
  121. otg->dieptxf[i] = 0;
  122. /* Override Vbus sense */
  123. otg->gccfg &= ~OTG_GCCFG_VBDEN;
  124. otg->gotgctl |= (OTG_GOTGCTL_BVALOVAL | OTG_GOTGCTL_BVALOEN);
  125. /* Restart PHY clock. */
  126. otg_pcgcctl->pcgcctl = 0;
  127. /* USB_SetDevSpeed */
  128. if (conf_iface == IFACE_FS) {
  129. otgd->dcfg = OTG_DCFG_DSPD(DSPD_FULL);
  130. } else {
  131. otgd->dcfg = OTG_DCFG_DSPD(DSPD_HIGH);
  132. }
  133. flush_tx_fifo(0x10);
  134. flush_rx_fifo();
  135. /* Clear endpoints state. */
  136. otgd->diepmsk = otgd->doepmsk = otgd->daintmsk = 0;
  137. for (i = 0; i < conf_nr_ep; i++) {
  138. bool_t ena = !!(otg_diep[i].ctl & OTG_DIEPCTL_EPENA);
  139. otg_diep[i].ctl =
  140. (!ena ? 0 : ((i == 0)
  141. ? OTG_DIEPCTL_SNAK
  142. : OTG_DIEPCTL_SNAK | OTG_DIEPCTL_EPDIS));
  143. otg_diep[i].tsiz = 0;
  144. otg_diep[i].intsts = 0xffff;
  145. }
  146. for (i = 0; i < conf_nr_ep; i++) {
  147. bool_t ena = !!(otg_doep[i].ctl & OTG_DOEPCTL_EPENA);
  148. otg_doep[i].ctl =
  149. (!ena ? 0 : ((i == 0)
  150. ? OTG_DOEPCTL_SNAK
  151. : OTG_DOEPCTL_SNAK | OTG_DOEPCTL_EPDIS));
  152. otg_doep[i].tsiz = 0;
  153. otg_doep[i].intsts = 0xffff;
  154. }
  155. otg->gintsts = ~0;
  156. otg->gintmsk = (OTG_GINT_USBRST |
  157. OTG_GINT_ENUMDNE |
  158. OTG_GINT_IEPINT |
  159. OTG_GINT_OEPINT |
  160. OTG_GINT_RXFLVL);
  161. fifos_init();
  162. /* HAL_PCD_Start, USB_DevConnect */
  163. otgd->dctl &= ~OTG_DCTL_SDIS;
  164. delay_ms(3);
  165. }
  166. static void dwc_otg_deinit(void)
  167. {
  168. /* HAL_PCD_Stop, USB_DevDisconnect */
  169. otgd->dctl |= OTG_DCTL_SDIS;
  170. peripheral_clock_delay();
  171. }
  172. static int dwc_otg_ep_rx_ready(uint8_t epnr)
  173. {
  174. struct ep *ep = &eps[epnr];
  175. return (ep->rxc != ep->rxp) ? ep->rx[RX_MASK(ep, rxc)].count : -1;
  176. }
  177. static bool_t dwc_otg_ep_tx_ready(uint8_t epnr)
  178. {
  179. return eps[epnr].tx_ready;
  180. }
  181. static void dwc_otg_read(uint8_t epnr, void *buf, uint32_t len)
  182. {
  183. struct ep *ep = &eps[epnr];
  184. memcpy(buf, ep->rx[RX_MASK(ep, rxc++)].data, len);
  185. prepare_rx(epnr);
  186. }
  187. static void dwc_otg_write(uint8_t epnr, const void *buf, uint32_t len)
  188. {
  189. OTG_DIEP diep = &otg_diep[epnr];
  190. diep->tsiz = OTG_DIEPTSIZ_PKTCNT(1) | len;
  191. // if (len != 0)
  192. // otgd->diepempmsk |= 1u << epnr;
  193. diep->ctl |= OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA;
  194. write_packet(buf, epnr, len);
  195. eps[epnr].tx_ready = FALSE;
  196. }
  197. static void dwc_otg_stall(uint8_t epnr)
  198. {
  199. otg_diep[epnr].ctl |= OTG_DIEPCTL_STALL;
  200. otg_doep[epnr].ctl |= OTG_DOEPCTL_STALL;
  201. }
  202. static void dwc_otg_configure_ep(uint8_t epnr, uint8_t type, uint32_t size)
  203. {
  204. int i;
  205. struct ep *ep;
  206. bool_t in = !!(epnr & 0x80);
  207. epnr &= 0x7f;
  208. ep = &eps[epnr];
  209. if (type == EPT_DBLBUF)
  210. type = EPT_BULK;
  211. if (in || (epnr == 0)) {
  212. otgd->daintmsk |= 1u << epnr;
  213. if (!(otg_diep[epnr].ctl & OTG_DIEPCTL_USBAEP)) {
  214. otg_diep[epnr].ctl |=
  215. OTG_DIEPCTL_MPSIZ(size) |
  216. OTG_DIEPCTL_EPTYP(type) |
  217. OTG_DIEPCTL_TXFNUM(epnr) |
  218. OTG_DIEPCTL_SD0PID |
  219. OTG_DIEPCTL_USBAEP;
  220. }
  221. ep->tx_ready = TRUE;
  222. }
  223. if (!in) {
  224. otgd->daintmsk |= 1u << (epnr + 16);
  225. if (!(otg_doep[epnr].ctl & OTG_DOEPCTL_USBAEP)) {
  226. otg_doep[epnr].ctl |=
  227. OTG_DOEPCTL_MPSIZ(size) |
  228. OTG_DOEPCTL_EPTYP(type) |
  229. OTG_DIEPCTL_SD0PID |
  230. OTG_DOEPCTL_USBAEP;
  231. }
  232. ep->rxc = ep->rxp = 0;
  233. if (epnr == 0) {
  234. ep->rx = rx_buf0;
  235. ep->rx_nr = ARRAY_SIZE(rx_buf0);
  236. } else {
  237. /* We have one statically-allocated multi-packet buffer.
  238. * Check we aren't trying to map it to multiple endpoints. */
  239. ep->rx = NULL;
  240. for (i = 0; i < conf_nr_ep; i++)
  241. ASSERT(eps[i].rx != rx_bufn);
  242. ep->rx = rx_bufn;
  243. ep->rx_nr = ARRAY_SIZE(rx_bufn);
  244. }
  245. ep->rxc = ep->rxp = 0;
  246. ep->rx_active = FALSE;
  247. prepare_rx(epnr);
  248. }
  249. }
  250. static void dwc_otg_setaddr(uint8_t addr)
  251. {
  252. otgd->dcfg = (otgd->dcfg & ~OTG_DCFG_DAD(0x7f)) | OTG_DCFG_DAD(addr);
  253. }
  254. static void handle_reset(void)
  255. {
  256. int i;
  257. /* Initialise core. */
  258. otgd->dctl &= ~OTG_DCTL_RWUSIG;
  259. flush_tx_fifo(0x10);
  260. for (i = 0; i < conf_nr_ep; i++) {
  261. otg_diep[i].ctl &= ~(OTG_DIEPCTL_STALL |
  262. OTG_DIEPCTL_USBAEP |
  263. OTG_DIEPCTL_MPSIZ(0x7ff) |
  264. OTG_DIEPCTL_TXFNUM(0xf) |
  265. OTG_DIEPCTL_SD0PID |
  266. OTG_DIEPCTL_EPTYP(3));
  267. otg_doep[i].ctl &= ~(OTG_DOEPCTL_STALL |
  268. OTG_DOEPCTL_USBAEP |
  269. OTG_DOEPCTL_MPSIZ(0x7ff) |
  270. OTG_DOEPCTL_SD0PID |
  271. OTG_DOEPCTL_EPTYP(3));
  272. }
  273. otgd->daintmsk = 0x10001u;
  274. otgd->doepmsk |= (OTG_DOEPMSK_STUPM |
  275. OTG_DOEPMSK_XFRCM |
  276. OTG_DOEPMSK_EPDM |
  277. OTG_DOEPMSK_STSPHSRXM |
  278. OTG_DOEPMSK_NAKM);
  279. otgd->diepmsk |= (OTG_DIEPMSK_TOM |
  280. OTG_DIEPMSK_XFRCM |
  281. OTG_DIEPMSK_EPDM);
  282. /* Set address 0. */
  283. otgd->dcfg &= ~OTG_DCFG_DAD(0x7f);
  284. ep0_out_start();
  285. /* Reinitialise class-specific subsystem. */
  286. usb_cdc_acm_ops.reset();
  287. /* Clear endpoint soft state. */
  288. memset(eps, 0, sizeof(eps));
  289. /* Clear any in-progress Control Transfer. */
  290. ep0.data_len = -1;
  291. ep0.tx.todo = -1;
  292. }
  293. static void handle_rx_transfer(void)
  294. {
  295. uint32_t grxsts = otg->grxstsp;
  296. unsigned int bcnt = OTG_RXSTS_BCNT(grxsts);
  297. unsigned int epnr = OTG_RXSTS_CHNUM(grxsts);
  298. unsigned int rxp;
  299. struct ep *ep = &eps[epnr];
  300. switch (OTG_RXSTS_PKTSTS(grxsts)) {
  301. case STS_SETUP_UPDT:
  302. bcnt = 8;
  303. case STS_DATA_UPDT:
  304. ASSERT(ep->rx_active);
  305. ASSERT((uint16_t)(ep->rxp - ep->rxc) < ep->rx_nr);
  306. rxp = RX_MASK(ep, rxp++);
  307. read_packet(ep->rx[rxp].data, bcnt);
  308. ep->rx[rxp].count = bcnt;
  309. break;
  310. default:
  311. break;
  312. }
  313. }
  314. static void handle_oepint(uint8_t epnr)
  315. {
  316. uint32_t oepint = otg_doep[epnr].intsts & otgd->doepmsk;
  317. struct ep *ep = &eps[epnr];
  318. otg_doep[epnr].intsts = oepint;
  319. if (oepint & OTG_DOEPMSK_XFRCM) {
  320. ASSERT(ep->rx_active);
  321. ep->rx_active = FALSE;
  322. if (epnr == 0)
  323. handle_rx_ep0(FALSE);
  324. }
  325. if (oepint & OTG_DOEPMSK_STUPM) {
  326. ASSERT(ep->rx_active);
  327. ep->rx_active = FALSE;
  328. if (epnr == 0)
  329. handle_rx_ep0(TRUE);
  330. }
  331. prepare_rx(epnr);
  332. }
  333. static void handle_iepint(uint8_t epnr)
  334. {
  335. uint32_t iepint = otg_diep[epnr].intsts, iepmsk;
  336. iepmsk = otgd->diepmsk | (((otgd->diepempmsk >> epnr) & 1) << 7);
  337. iepint = otg_diep[epnr].intsts & iepmsk;
  338. otg_diep[epnr].intsts = iepint;
  339. if (iepint & OTG_DIEPINT_XFRC) {
  340. otgd->diepempmsk &= ~(1 << epnr);
  341. eps[epnr].tx_ready = TRUE;
  342. if (epnr == 0)
  343. handle_tx_ep0();
  344. }
  345. /* We don't set DIEPEMPMSK bits so TXFE notification is impossible. */
  346. ASSERT(!(iepint & OTG_DIEPINT_TXFE));
  347. }
  348. static void dwc_otg_process(void)
  349. {
  350. uint32_t gintsts = otg->gintsts & otg->gintmsk;
  351. if (gintsts & OTG_GINT_OEPINT) {
  352. uint16_t mask = (otgd->daint & otgd->daintmsk) >> 16;
  353. int epnr;
  354. for (epnr = 0; mask != 0; mask >>= 1, epnr++) {
  355. if (mask & 1)
  356. handle_oepint(epnr);
  357. }
  358. }
  359. if (gintsts & OTG_GINT_IEPINT) {
  360. uint16_t mask = otgd->daint & otgd->daintmsk;
  361. int epnr;
  362. for (epnr = 0; mask != 0; mask >>= 1, epnr++) {
  363. if (mask & 1)
  364. handle_iepint(epnr);
  365. }
  366. }
  367. if (gintsts & OTG_GINT_ENUMDNE) {
  368. /* USB_ActivateSetup */
  369. otg_diep[0].ctl &= ~OTG_DIEPCTL_MPSIZ(0x7ff);
  370. otgd->dctl |= OTG_DCTL_CGINAK;
  371. /* USB_SetTurnaroundTime */
  372. is_hs = is_high_speed();
  373. usb_bulk_mps = is_hs ? USB_HS_MPS : USB_FS_MPS;
  374. /* Ref. Table 232, FS Mode */
  375. otg->gusbcfg |= OTG_GUSBCFG_TRDT(is_hs ? 9 : 6);
  376. usb_configure_ep(0, EPT_CONTROL, EP0_MPS);
  377. otg->gintsts = OTG_GINT_ENUMDNE;
  378. printk("[ENUMDNE: %cS]\n", is_hs ? 'H' : 'F');
  379. }
  380. if (gintsts & OTG_GINT_USBRST) {
  381. printk("[USBRST]\n");
  382. handle_reset();
  383. otg->gintsts = OTG_GINT_USBRST;
  384. }
  385. if (gintsts & OTG_GINT_RXFLVL) {
  386. handle_rx_transfer();
  387. }
  388. }
  389. const struct usb_driver dwc_otg = {
  390. .init = dwc_otg_init,
  391. .deinit = dwc_otg_deinit,
  392. .process = dwc_otg_process,
  393. .has_highspeed = dwc_otg_has_highspeed,
  394. .is_highspeed = dwc_otg_is_highspeed,
  395. .setaddr = dwc_otg_setaddr,
  396. .configure_ep = dwc_otg_configure_ep,
  397. .ep_rx_ready = dwc_otg_ep_rx_ready,
  398. .ep_tx_ready = dwc_otg_ep_tx_ready,
  399. .read = dwc_otg_read,
  400. .write = dwc_otg_write,
  401. .stall = dwc_otg_stall
  402. };
  403. /*
  404. * Local variables:
  405. * mode: C
  406. * c-file-style: "Linux"
  407. * c-basic-offset: 4
  408. * tab-width: 4
  409. * indent-tabs-mode: nil
  410. * End:
  411. */