hw_dwc_otg.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  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. static int conf_iface;
  13. static bool_t is_hs;
  14. static struct rx_buf {
  15. uint32_t data[USB_HS_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. bool_t hw_has_highspeed(void)
  25. {
  26. return conf_iface == IFACE_HS_EMBEDDED;
  27. }
  28. bool_t usb_is_highspeed(void)
  29. {
  30. return is_hs;
  31. }
  32. static 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 hsphyc_init(void)
  39. {
  40. /* Enable the LDO and wait for it to be ready. */
  41. hsphyc->ldo |= HSPHYC_LDO_ENABLE;
  42. do { delay_us(1); } while (!(hsphyc->ldo & HSPHYC_LDO_STATUS));
  43. /* This is correct only for HSE = 16Mhz. */
  44. hsphyc->pll1 |= HSPHYC_PLL1_SEL(3);
  45. /* Magic values from the LL driver. We can probably discard them. */
  46. hsphyc->tune |= (HSPHYC_TUNE_HSDRVCHKITRIM(7) |
  47. HSPHYC_TUNE_HSDRVRFRED |
  48. HSPHYC_TUNE_HSDRVDCCUR |
  49. HSPHYC_TUNE_INCURRINT |
  50. HSPHYC_TUNE_INCURREN);
  51. /* Enable the PLL and wait to stabilise. */
  52. hsphyc->pll1 |= HSPHYC_PLL1_EN;
  53. delay_ms(2);
  54. }
  55. static void flush_tx_fifo(int num)
  56. {
  57. otg->grstctl = OTG_GRSTCTL_TXFFLSH | OTG_GRSTCTL_TXFNUM(num);
  58. do { delay_us(1); } while (otg->grstctl & OTG_GRSTCTL_TXFFLSH);
  59. }
  60. static void flush_rx_fifo(void)
  61. {
  62. otg->grstctl = OTG_GRSTCTL_RXFFLSH;
  63. do { delay_us(1); } while (otg->grstctl & OTG_GRSTCTL_RXFFLSH);
  64. }
  65. static void ep0_out_start(void)
  66. {
  67. otg_doep[0].tsiz = (OTG_DOEPTSZ_STUPCNT |
  68. OTG_DOEPTSZ_PKTCNT(1)) |
  69. OTG_DOEPTSZ_XFERSIZ(3*8);
  70. }
  71. static bool_t is_high_speed(void)
  72. {
  73. /* 0 == DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ */
  74. return ((otgd->dsts >> 1) & 3) == 0;
  75. }
  76. static void prepare_rx(uint8_t epnr)
  77. {
  78. struct ep *ep = &eps[epnr];
  79. OTG_DOEP doep = &otg_doep[epnr];
  80. uint16_t mps, nr;
  81. uint32_t tsiz;
  82. if (ep->rx_active)
  83. return;
  84. nr = ep->rxp - ep->rxc;
  85. nr = ep->rx_nr - nr;
  86. if (nr <= ep->rx_nr/2)
  87. return;
  88. mps = (epnr == 0) ? EP0_MPS : (doep->ctl & 0x7ff);
  89. tsiz = doep->tsiz & 0xe0000000;
  90. tsiz |= OTG_DOEPTSZ_PKTCNT(nr);
  91. tsiz |= OTG_DOEPTSZ_XFERSIZ(mps * nr);
  92. doep->tsiz = tsiz;
  93. doep->ctl |= OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA;
  94. ep->rx_active = TRUE;
  95. }
  96. static void read_packet(void *p, int len)
  97. {
  98. uint32_t *_p = p;
  99. unsigned int n = (len + 3) / 4;
  100. while (n--)
  101. *_p++ = otg_dfifo[0].x[0];
  102. }
  103. static void write_packet(const void *p, uint8_t epnr, int len)
  104. {
  105. const uint32_t *_p = p;
  106. unsigned int n = (len + 3) / 4;
  107. while (n--)
  108. otg_dfifo[epnr].x[0] = *_p++;
  109. }
  110. static void fifos_init(void)
  111. {
  112. unsigned int i, base, tx_sz, rx_sz, fifo_sz;
  113. /* F7 OTG: FS 1.25k FIFO RAM, HS 4k FIFO RAM. */
  114. fifo_sz = ((conf_port == PORT_FS) ? 0x500 : 0x1000) >> 2;
  115. rx_sz = fifo_sz / 2;
  116. tx_sz = fifo_sz / (2 * conf_nr_ep);
  117. otg->grxfsiz = rx_sz;
  118. base = rx_sz;
  119. otg->dieptxf0 = (tx_sz << 16) | base;
  120. for (i = 1; i < conf_nr_ep; i++) {
  121. base += tx_sz;
  122. otg->dieptxf[i-1] = (tx_sz << 16) | base;
  123. }
  124. }
  125. void hw_usb_init(void)
  126. {
  127. int i;
  128. /* Determine which PHY we use based on hardware submodel ID. */
  129. switch (gw_info.hw_submodel) {
  130. case F7SM_lightning:
  131. conf_iface = IFACE_HS_EMBEDDED;
  132. break;
  133. default:
  134. conf_iface = IFACE_FS;
  135. break;
  136. }
  137. /*
  138. * HAL_PCD_MspInit
  139. */
  140. switch (conf_port) {
  141. case PORT_FS:
  142. ASSERT(conf_iface == IFACE_FS);
  143. gpio_set_af(gpioa, 11, 10);
  144. gpio_set_af(gpioa, 12, 10);
  145. gpio_configure_pin(gpioa, 11, AFO_pushpull(IOSPD_HIGH));
  146. gpio_configure_pin(gpioa, 12, AFO_pushpull(IOSPD_HIGH));
  147. rcc->ahb2enr |= RCC_AHB2ENR_OTGFSEN;
  148. break;
  149. case PORT_HS:
  150. ASSERT((conf_iface == IFACE_FS) || (conf_iface == IFACE_HS_EMBEDDED));
  151. if (conf_iface == IFACE_FS) {
  152. gpio_set_af(gpiob, 14, 12);
  153. gpio_set_af(gpiob, 15, 12);
  154. gpio_configure_pin(gpiob, 14, AFO_pushpull(IOSPD_HIGH));
  155. gpio_configure_pin(gpiob, 15, AFO_pushpull(IOSPD_HIGH));
  156. rcc->ahb1enr |= RCC_AHB1ENR_OTGHSEN;
  157. } else {
  158. rcc->ahb1enr |= RCC_AHB1ENR_OTGHSEN;
  159. rcc->ahb1enr |= RCC_AHB1ENR_OTGHSULPIEN;
  160. rcc->apb2enr |= RCC_APB2ENR_OTGPHYCEN;
  161. }
  162. break;
  163. default:
  164. ASSERT(0);
  165. }
  166. peripheral_clock_delay();
  167. /*
  168. * USB_CoreInit
  169. */
  170. if (conf_iface == IFACE_FS) {
  171. /* Select Full Speed PHY. */
  172. otg->gusbcfg |= OTG_GUSBCFG_PHYSEL;
  173. /* PHY selection must be followed by a core reset. */
  174. core_reset();
  175. /* Activate FS transceiver. */
  176. otg->gccfg |= OTG_GCCFG_PWRDWN;
  177. } else {
  178. /* Disable the FS transceiver, enable the HS transceiver. */
  179. otg->gccfg &= ~OTG_GCCFG_PWRDWN;
  180. otg->gccfg |= OTG_GCCFG_PHYHSEN;
  181. hsphyc_init();
  182. core_reset();
  183. }
  184. /*
  185. * USB_SetCurrentMode
  186. */
  187. /* Mode select followed by required 25ms delay. */
  188. otg->gusbcfg |= OTG_GUSBCFG_FDMOD;
  189. delay_ms(25);
  190. /*
  191. * USB_DevInit
  192. */
  193. for (i = 0; i < ARRAY_SIZE(otg->dieptxf); i++)
  194. otg->dieptxf[i] = 0;
  195. /* Override Vbus sense */
  196. otg->gccfg &= ~OTG_GCCFG_VBDEN;
  197. otg->gotgctl |= (OTG_GOTGCTL_BVALOVAL | OTG_GOTGCTL_BVALOEN);
  198. /* Restart PHY clock. */
  199. otg_pcgcctl->pcgcctl = 0;
  200. /* USB_SetDevSpeed */
  201. if (conf_iface == IFACE_FS) {
  202. otgd->dcfg = OTG_DCFG_DSPD(DSPD_FULL);
  203. } else {
  204. otgd->dcfg = OTG_DCFG_DSPD(DSPD_HIGH);
  205. }
  206. flush_tx_fifo(0x10);
  207. flush_rx_fifo();
  208. /* Clear endpoints state. */
  209. otgd->diepmsk = otgd->doepmsk = otgd->daintmsk = 0;
  210. for (i = 0; i < conf_nr_ep; i++) {
  211. bool_t ena = !!(otg_diep[i].ctl & OTG_DIEPCTL_EPENA);
  212. otg_diep[i].ctl =
  213. (!ena ? 0 : ((i == 0)
  214. ? OTG_DIEPCTL_SNAK
  215. : OTG_DIEPCTL_SNAK | OTG_DIEPCTL_EPDIS));
  216. otg_diep[i].tsiz = 0;
  217. otg_diep[i].intsts = 0xffff;
  218. }
  219. for (i = 0; i < conf_nr_ep; i++) {
  220. bool_t ena = !!(otg_doep[i].ctl & OTG_DOEPCTL_EPENA);
  221. otg_doep[i].ctl =
  222. (!ena ? 0 : ((i == 0)
  223. ? OTG_DOEPCTL_SNAK
  224. : OTG_DOEPCTL_SNAK | OTG_DOEPCTL_EPDIS));
  225. otg_doep[i].tsiz = 0;
  226. otg_doep[i].intsts = 0xffff;
  227. }
  228. otg->gintsts = ~0;
  229. otg->gintmsk = (OTG_GINT_USBRST |
  230. OTG_GINT_ENUMDNE |
  231. OTG_GINT_IEPINT |
  232. OTG_GINT_OEPINT |
  233. OTG_GINT_RXFLVL);
  234. fifos_init();
  235. /* HAL_PCD_Start, USB_DevConnect */
  236. otgd->dctl &= ~OTG_DCTL_SDIS;
  237. delay_ms(3);
  238. }
  239. void hw_usb_deinit(void)
  240. {
  241. switch (conf_port) {
  242. case PORT_FS:
  243. gpio_configure_pin(gpioa, 11, GPI_floating);
  244. gpio_configure_pin(gpioa, 12, GPI_floating);
  245. rcc->ahb2enr &= ~RCC_AHB2ENR_OTGFSEN;
  246. break;
  247. case PORT_HS:
  248. gpio_configure_pin(gpiob, 14, GPI_floating);
  249. gpio_configure_pin(gpiob, 15, GPI_floating);
  250. rcc->ahb1enr &= ~RCC_AHB1ENR_OTGHSEN;
  251. break;
  252. default:
  253. ASSERT(0);
  254. }
  255. }
  256. int ep_rx_ready(uint8_t epnr)
  257. {
  258. struct ep *ep = &eps[epnr];
  259. return (ep->rxc != ep->rxp) ? ep->rx[RX_MASK(ep, rxc)].count : -1;
  260. }
  261. bool_t ep_tx_ready(uint8_t epnr)
  262. {
  263. return eps[epnr].tx_ready;
  264. }
  265. void usb_read(uint8_t epnr, void *buf, uint32_t len)
  266. {
  267. struct ep *ep = &eps[epnr];
  268. memcpy(buf, ep->rx[RX_MASK(ep, rxc++)].data, len);
  269. prepare_rx(epnr);
  270. }
  271. void usb_write(uint8_t epnr, const void *buf, uint32_t len)
  272. {
  273. OTG_DIEP diep = &otg_diep[epnr];
  274. diep->tsiz = OTG_DIEPTSIZ_PKTCNT(1) | len;
  275. // if (len != 0)
  276. // otgd->diepempmsk |= 1u << epnr;
  277. diep->ctl |= OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA;
  278. write_packet(buf, epnr, len);
  279. eps[epnr].tx_ready = FALSE;
  280. }
  281. void usb_stall(uint8_t epnr)
  282. {
  283. otg_diep[epnr].ctl |= OTG_DIEPCTL_STALL;
  284. otg_doep[epnr].ctl |= OTG_DOEPCTL_STALL;
  285. }
  286. void usb_configure_ep(uint8_t epnr, uint8_t type, uint32_t size)
  287. {
  288. int i;
  289. struct ep *ep;
  290. bool_t in = !!(epnr & 0x80);
  291. epnr &= 0x7f;
  292. ep = &eps[epnr];
  293. if (type == EPT_DBLBUF)
  294. type = EPT_BULK;
  295. if (in || (epnr == 0)) {
  296. otgd->daintmsk |= 1u << epnr;
  297. if (!(otg_diep[epnr].ctl & OTG_DIEPCTL_USBAEP)) {
  298. otg_diep[epnr].ctl |=
  299. OTG_DIEPCTL_MPSIZ(size) |
  300. OTG_DIEPCTL_EPTYP(type) |
  301. OTG_DIEPCTL_TXFNUM(epnr) |
  302. OTG_DIEPCTL_SD0PID |
  303. OTG_DIEPCTL_USBAEP;
  304. }
  305. ep->tx_ready = TRUE;
  306. }
  307. if (!in) {
  308. otgd->daintmsk |= 1u << (epnr + 16);
  309. if (!(otg_doep[epnr].ctl & OTG_DOEPCTL_USBAEP)) {
  310. otg_doep[epnr].ctl |=
  311. OTG_DOEPCTL_MPSIZ(size) |
  312. OTG_DOEPCTL_EPTYP(type) |
  313. OTG_DIEPCTL_SD0PID |
  314. OTG_DOEPCTL_USBAEP;
  315. }
  316. ep->rxc = ep->rxp = 0;
  317. if (epnr == 0) {
  318. ep->rx = rx_buf0;
  319. ep->rx_nr = ARRAY_SIZE(rx_buf0);
  320. } else {
  321. /* We have one statically-allocated multi-packet buffer.
  322. * Check we aren't trying to map it to multiple endpoints. */
  323. ep->rx = NULL;
  324. for (i = 0; i < conf_nr_ep; i++)
  325. ASSERT(ep->rx != rx_bufn);
  326. ep->rx = rx_bufn;
  327. ep->rx_nr = ARRAY_SIZE(rx_bufn);
  328. }
  329. ep->rxc = ep->rxp = 0;
  330. ep->rx_active = FALSE;
  331. prepare_rx(epnr);
  332. }
  333. }
  334. void usb_setaddr(uint8_t addr)
  335. {
  336. otgd->dcfg = (otgd->dcfg & ~OTG_DCFG_DAD(0x7f)) | OTG_DCFG_DAD(addr);
  337. }
  338. static void handle_reset(void)
  339. {
  340. int i;
  341. /* Initialise core. */
  342. otgd->dctl &= ~OTG_DCTL_RWUSIG;
  343. flush_tx_fifo(0x10);
  344. for (i = 0; i < conf_nr_ep; i++) {
  345. otg_diep[i].ctl &= ~(OTG_DIEPCTL_STALL |
  346. OTG_DIEPCTL_USBAEP |
  347. OTG_DIEPCTL_MPSIZ(0x7ff) |
  348. OTG_DIEPCTL_TXFNUM(0xf) |
  349. OTG_DIEPCTL_SD0PID |
  350. OTG_DIEPCTL_EPTYP(3));
  351. otg_doep[i].ctl &= ~(OTG_DOEPCTL_STALL |
  352. OTG_DOEPCTL_USBAEP |
  353. OTG_DOEPCTL_MPSIZ(0x7ff) |
  354. OTG_DOEPCTL_SD0PID |
  355. OTG_DOEPCTL_EPTYP(3));
  356. }
  357. otgd->daintmsk = 0x10001u;
  358. otgd->doepmsk |= (OTG_DOEPMSK_STUPM |
  359. OTG_DOEPMSK_XFRCM |
  360. OTG_DOEPMSK_EPDM |
  361. OTG_DOEPMSK_STSPHSRXM |
  362. OTG_DOEPMSK_NAKM);
  363. otgd->diepmsk |= (OTG_DIEPMSK_TOM |
  364. OTG_DIEPMSK_XFRCM |
  365. OTG_DIEPMSK_EPDM);
  366. /* Set address 0. */
  367. otgd->dcfg &= ~OTG_DCFG_DAD(0x7f);
  368. ep0_out_start();
  369. /* Reinitialise class-specific subsystem. */
  370. usb_cdc_acm_ops.reset();
  371. /* Clear endpoint soft state. */
  372. memset(eps, 0, sizeof(eps));
  373. /* Clear any in-progress Control Transfer. */
  374. ep0.data_len = -1;
  375. ep0.tx.todo = -1;
  376. }
  377. static void handle_rx_transfer(void)
  378. {
  379. uint32_t grxsts = otg->grxstsp;
  380. unsigned int bcnt = OTG_RXSTS_BCNT(grxsts);
  381. unsigned int epnr = OTG_RXSTS_CHNUM(grxsts);
  382. unsigned int rxp;
  383. struct ep *ep = &eps[epnr];
  384. switch (OTG_RXSTS_PKTSTS(grxsts)) {
  385. case STS_SETUP_UPDT:
  386. bcnt = 8;
  387. case STS_DATA_UPDT:
  388. ASSERT(ep->rx_active);
  389. ASSERT((uint16_t)(ep->rxp - ep->rxc) < ep->rx_nr);
  390. rxp = RX_MASK(ep, rxp++);
  391. read_packet(ep->rx[rxp].data, bcnt);
  392. ep->rx[rxp].count = bcnt;
  393. break;
  394. default:
  395. break;
  396. }
  397. }
  398. static void handle_oepint(uint8_t epnr)
  399. {
  400. uint32_t oepint = otg_doep[epnr].intsts & otgd->doepmsk;
  401. struct ep *ep = &eps[epnr];
  402. otg_doep[epnr].intsts = oepint;
  403. if (oepint & OTG_DOEPMSK_XFRCM) {
  404. ASSERT(ep->rx_active);
  405. ep->rx_active = FALSE;
  406. if (epnr == 0)
  407. handle_rx_ep0(FALSE);
  408. }
  409. if (oepint & OTG_DOEPMSK_STUPM) {
  410. ASSERT(ep->rx_active);
  411. ep->rx_active = FALSE;
  412. if (epnr == 0)
  413. handle_rx_ep0(TRUE);
  414. }
  415. prepare_rx(epnr);
  416. }
  417. static void handle_iepint(uint8_t epnr)
  418. {
  419. uint32_t iepint = otg_diep[epnr].intsts, iepmsk;
  420. iepmsk = otgd->diepmsk | (((otgd->diepempmsk >> epnr) & 1) << 7);
  421. iepint = otg_diep[epnr].intsts & iepmsk;
  422. otg_diep[epnr].intsts = iepint;
  423. if (iepint & OTG_DIEPINT_XFRC) {
  424. otgd->diepempmsk &= ~(1 << epnr);
  425. eps[epnr].tx_ready = TRUE;
  426. if (epnr == 0)
  427. handle_tx_ep0();
  428. }
  429. if (iepint & OTG_DIEPINT_TXFE) {
  430. ASSERT(0);
  431. }
  432. }
  433. void usb_process(void)
  434. {
  435. uint32_t gintsts = otg->gintsts & otg->gintmsk;
  436. if (gintsts & OTG_GINT_OEPINT) {
  437. uint16_t mask = (otgd->daint & otgd->daintmsk) >> 16;
  438. int epnr;
  439. for (epnr = 0; mask != 0; mask >>= 1, epnr++) {
  440. if (mask & 1)
  441. handle_oepint(epnr);
  442. }
  443. }
  444. if (gintsts & OTG_GINT_IEPINT) {
  445. uint16_t mask = otgd->daint & otgd->daintmsk;
  446. int epnr;
  447. for (epnr = 0; mask != 0; mask >>= 1, epnr++) {
  448. if (mask & 1)
  449. handle_iepint(epnr);
  450. }
  451. }
  452. if (gintsts & OTG_GINT_ENUMDNE) {
  453. /* USB_ActivateSetup */
  454. otg_diep[0].ctl &= ~OTG_DIEPCTL_MPSIZ(0x7ff);
  455. otgd->dctl |= OTG_DCTL_CGINAK;
  456. /* USB_SetTurnaroundTime */
  457. is_hs = is_high_speed();
  458. usb_bulk_mps = is_hs ? USB_HS_MPS : USB_FS_MPS;
  459. /* Ref. Table 232, FS Mode */
  460. otg->gusbcfg |= OTG_GUSBCFG_TRDT(is_hs ? 9 : 6);
  461. usb_configure_ep(0, EPT_CONTROL, EP0_MPS);
  462. otg->gintsts = OTG_GINT_ENUMDNE;
  463. printk("[ENUMDNE: %cS]\n", is_hs ? 'H' : 'F');
  464. }
  465. if (gintsts & OTG_GINT_USBRST) {
  466. printk("[USBRST]\n");
  467. handle_reset();
  468. otg->gintsts = OTG_GINT_USBRST;
  469. }
  470. if (gintsts & OTG_GINT_RXFLVL) {
  471. handle_rx_transfer();
  472. }
  473. }
  474. /*
  475. * Local variables:
  476. * mode: C
  477. * c-file-style: "Linux"
  478. * c-basic-offset: 4
  479. * tab-width: 4
  480. * indent-tabs-mode: nil
  481. * End:
  482. */