You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

449 line
12 KiB

  1. /*
  2. * This file is part of the libopencm3 project.
  3. *
  4. * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
  5. *
  6. * This library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this library. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <string.h>
  20. #include <libopencm3/cm3/common.h>
  21. #include <libopencm3/usb/usbd.h>
  22. #include <libopencm3/usb/dwc/otg_common.h>
  23. #include "usb_private.h"
  24. #include "usb_dwc_common.h"
  25. /* The FS core and the HS core have the same register layout.
  26. * As the code can be used on both cores, the registers offset is modified
  27. * according to the selected cores base address. */
  28. #define dev_base_address (usbd_dev->driver->base_address)
  29. #define REBASE(x) MMIO32((x) + (dev_base_address))
  30. void dwc_set_address(usbd_device *usbd_dev, uint8_t addr)
  31. {
  32. REBASE(OTG_DCFG) = (REBASE(OTG_DCFG) & ~OTG_DCFG_DAD) | (addr << 4);
  33. }
  34. void dwc_ep_setup(usbd_device *usbd_dev, uint8_t addr, uint8_t type,
  35. uint16_t max_size,
  36. void (*callback) (usbd_device *usbd_dev, uint8_t ep))
  37. {
  38. /*
  39. * Configure endpoint address and type. Allocate FIFO memory for
  40. * endpoint. Install callback function.
  41. */
  42. uint8_t dir = addr & 0x80;
  43. addr &= 0x7f;
  44. if (addr == 0) { /* For the default control endpoint */
  45. /* Configure IN part. */
  46. if (max_size >= 64) {
  47. REBASE(OTG_DIEPCTL0) = OTG_DIEPCTL0_MPSIZ_64;
  48. } else if (max_size >= 32) {
  49. REBASE(OTG_DIEPCTL0) = OTG_DIEPCTL0_MPSIZ_32;
  50. } else if (max_size >= 16) {
  51. REBASE(OTG_DIEPCTL0) = OTG_DIEPCTL0_MPSIZ_16;
  52. } else {
  53. REBASE(OTG_DIEPCTL0) = OTG_DIEPCTL0_MPSIZ_8;
  54. }
  55. REBASE(OTG_DIEPTSIZ0) =
  56. (max_size & OTG_DIEPSIZ0_XFRSIZ_MASK);
  57. REBASE(OTG_DIEPCTL0) |=
  58. OTG_DIEPCTL0_EPENA | OTG_DIEPCTL0_SNAK;
  59. /* Configure OUT part. */
  60. usbd_dev->doeptsiz[0] = OTG_DIEPSIZ0_STUPCNT_1 |
  61. OTG_DIEPSIZ0_PKTCNT |
  62. (max_size & OTG_DIEPSIZ0_XFRSIZ_MASK);
  63. REBASE(OTG_DOEPTSIZ(0)) = usbd_dev->doeptsiz[0];
  64. REBASE(OTG_DOEPCTL(0)) |=
  65. OTG_DOEPCTL0_EPENA | OTG_DIEPCTL0_SNAK;
  66. REBASE(OTG_GNPTXFSIZ) = ((max_size / 4) << 16) |
  67. usbd_dev->driver->rx_fifo_size;
  68. usbd_dev->fifo_mem_top += max_size / 4;
  69. usbd_dev->fifo_mem_top_ep0 = usbd_dev->fifo_mem_top;
  70. return;
  71. }
  72. if (dir) {
  73. REBASE(OTG_DIEPTXF(addr)) = ((max_size / 4) << 16) |
  74. usbd_dev->fifo_mem_top;
  75. usbd_dev->fifo_mem_top += max_size / 4;
  76. REBASE(OTG_DIEPTSIZ(addr)) =
  77. (max_size & OTG_DIEPSIZ0_XFRSIZ_MASK);
  78. REBASE(OTG_DIEPCTL(addr)) |=
  79. OTG_DIEPCTL0_EPENA | OTG_DIEPCTL0_SNAK | (type << 18)
  80. | OTG_DIEPCTL0_USBAEP | OTG_DIEPCTLX_SD0PID
  81. | (addr << 22) | max_size;
  82. if (callback) {
  83. usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_IN] =
  84. (void *)callback;
  85. }
  86. }
  87. if (!dir) {
  88. usbd_dev->doeptsiz[addr] = OTG_DIEPSIZ0_PKTCNT |
  89. (max_size & OTG_DIEPSIZ0_XFRSIZ_MASK);
  90. REBASE(OTG_DOEPTSIZ(addr)) = usbd_dev->doeptsiz[addr];
  91. REBASE(OTG_DOEPCTL(addr)) |= OTG_DOEPCTL0_EPENA |
  92. OTG_DOEPCTL0_USBAEP | OTG_DIEPCTL0_CNAK |
  93. OTG_DOEPCTLX_SD0PID | (type << 18) | max_size;
  94. if (callback) {
  95. usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_OUT] =
  96. (void *)callback;
  97. }
  98. }
  99. }
  100. void dwc_endpoints_reset(usbd_device *usbd_dev)
  101. {
  102. int i;
  103. /* The core resets the endpoints automatically on reset. */
  104. usbd_dev->fifo_mem_top = usbd_dev->fifo_mem_top_ep0;
  105. /* Disable any currently active endpoints */
  106. for (i = 1; i < 4; i++) {
  107. if (REBASE(OTG_DOEPCTL(i)) & OTG_DOEPCTL0_EPENA) {
  108. REBASE(OTG_DOEPCTL(i)) |= OTG_DOEPCTL0_EPDIS;
  109. }
  110. if (REBASE(OTG_DIEPCTL(i)) & OTG_DIEPCTL0_EPENA) {
  111. REBASE(OTG_DIEPCTL(i)) |= OTG_DIEPCTL0_EPDIS;
  112. }
  113. }
  114. /* Flush all tx/rx fifos */
  115. REBASE(OTG_GRSTCTL) = OTG_GRSTCTL_TXFFLSH | OTG_GRSTCTL_TXFNUM_ALL
  116. | OTG_GRSTCTL_RXFFLSH;
  117. }
  118. void dwc_ep_stall_set(usbd_device *usbd_dev, uint8_t addr, uint8_t stall)
  119. {
  120. if (addr == 0) {
  121. if (stall) {
  122. REBASE(OTG_DIEPCTL(addr)) |= OTG_DIEPCTL0_STALL;
  123. } else {
  124. REBASE(OTG_DIEPCTL(addr)) &= ~OTG_DIEPCTL0_STALL;
  125. }
  126. }
  127. if (addr & 0x80) {
  128. addr &= 0x7F;
  129. if (stall) {
  130. REBASE(OTG_DIEPCTL(addr)) |= OTG_DIEPCTL0_STALL;
  131. } else {
  132. REBASE(OTG_DIEPCTL(addr)) &= ~OTG_DIEPCTL0_STALL;
  133. REBASE(OTG_DIEPCTL(addr)) |= OTG_DIEPCTLX_SD0PID;
  134. }
  135. } else {
  136. if (stall) {
  137. REBASE(OTG_DOEPCTL(addr)) |= OTG_DOEPCTL0_STALL;
  138. } else {
  139. REBASE(OTG_DOEPCTL(addr)) &= ~OTG_DOEPCTL0_STALL;
  140. REBASE(OTG_DOEPCTL(addr)) |= OTG_DOEPCTLX_SD0PID;
  141. }
  142. }
  143. }
  144. uint8_t dwc_ep_stall_get(usbd_device *usbd_dev, uint8_t addr)
  145. {
  146. /* Return non-zero if STALL set. */
  147. if (addr & 0x80) {
  148. return (REBASE(OTG_DIEPCTL(addr & 0x7f)) &
  149. OTG_DIEPCTL0_STALL) ? 1 : 0;
  150. } else {
  151. return (REBASE(OTG_DOEPCTL(addr)) &
  152. OTG_DOEPCTL0_STALL) ? 1 : 0;
  153. }
  154. }
  155. void dwc_ep_nak_set(usbd_device *usbd_dev, uint8_t addr, uint8_t nak)
  156. {
  157. /* It does not make sense to force NAK on IN endpoints. */
  158. if (addr & 0x80) {
  159. return;
  160. }
  161. usbd_dev->force_nak[addr] = nak;
  162. if (nak) {
  163. REBASE(OTG_DOEPCTL(addr)) |= OTG_DOEPCTL0_SNAK;
  164. } else {
  165. REBASE(OTG_DOEPCTL(addr)) |= OTG_DOEPCTL0_CNAK;
  166. }
  167. }
  168. uint16_t dwc_ep_write_packet(usbd_device *usbd_dev, uint8_t addr,
  169. const void *buf, uint16_t len)
  170. {
  171. const uint32_t *buf32 = buf;
  172. #if defined(__ARM_ARCH_6M__)
  173. const uint8_t *buf8 = buf;
  174. uint32_t word32;
  175. #endif /* defined(__ARM_ARCH_6M__) */
  176. int i;
  177. addr &= 0x7F;
  178. /* Return if endpoint is already enabled. */
  179. if (REBASE(OTG_DIEPTSIZ(addr)) & OTG_DIEPSIZ0_PKTCNT) {
  180. return 0;
  181. }
  182. /* Enable endpoint for transmission. */
  183. REBASE(OTG_DIEPTSIZ(addr)) = OTG_DIEPSIZ0_PKTCNT | len;
  184. REBASE(OTG_DIEPCTL(addr)) |= OTG_DIEPCTL0_EPENA |
  185. OTG_DIEPCTL0_CNAK;
  186. /* Copy buffer to endpoint FIFO, note - memcpy does not work.
  187. * ARMv7M supports non-word-aligned accesses, ARMv6M does not. */
  188. #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
  189. for (i = len; i > 0; i -= 4) {
  190. REBASE(OTG_FIFO(addr)) = *buf32++;
  191. }
  192. #endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */
  193. #if defined(__ARM_ARCH_6M__)
  194. /* Take care of word-aligned and non-word-aligned buffers */
  195. if (((uint32_t)buf8 & 0x3) == 0) {
  196. for (i = len; i > 0; i -= 4) {
  197. REBASE(OTG_FIFO(addr)) = *buf32++;
  198. }
  199. } else {
  200. for (i = len; i > 0; i -= 4) {
  201. memcpy(&word32, buf8, 4);
  202. REBASE(OTG_FIFO(addr)) = word32;
  203. buf8 += 4;
  204. }
  205. }
  206. #endif /* defined(__ARM_ARCH_6M__) */
  207. return len;
  208. }
  209. uint16_t dwc_ep_read_packet(usbd_device *usbd_dev, uint8_t addr,
  210. void *buf, uint16_t len)
  211. {
  212. int i;
  213. uint32_t *buf32 = buf;
  214. #if defined(__ARM_ARCH_6M__)
  215. uint8_t *buf8 = buf;
  216. uint32_t word32;
  217. #endif /* defined(__ARM_ARCH_6M__) */
  218. uint32_t extra;
  219. /* We do not need to know the endpoint address since there is only one
  220. * receive FIFO for all endpoints.
  221. */
  222. (void) addr;
  223. len = MIN(len, usbd_dev->rxbcnt);
  224. /* ARMv7M supports non-word-aligned accesses, ARMv6M does not. */
  225. #if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
  226. for (i = len; i >= 4; i -= 4) {
  227. *buf32++ = REBASE(OTG_FIFO(0));
  228. usbd_dev->rxbcnt -= 4;
  229. }
  230. #endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */
  231. #if defined(__ARM_ARCH_6M__)
  232. /* Take care of word-aligned and non-word-aligned buffers */
  233. if (((uint32_t)buf8 & 0x3) == 0) {
  234. for (i = len; i >= 4; i -= 4) {
  235. *buf32++ = REBASE(OTG_FIFO(0));
  236. usbd_dev->rxbcnt -= 4;
  237. }
  238. } else {
  239. for (i = len; i >= 4; i -= 4) {
  240. word32 = REBASE(OTG_FIFO(0));
  241. memcpy(buf8, &word32, 4);
  242. usbd_dev->rxbcnt -= 4;
  243. buf8 += 4;
  244. }
  245. /* buf32 needs to be updated as it is used for extra */
  246. buf32 = (uint32_t *)buf8;
  247. }
  248. #endif /* defined(__ARM_ARCH_6M__) */
  249. if (i) {
  250. extra = REBASE(OTG_FIFO(0));
  251. /* we read 4 bytes from the fifo, so update rxbcnt */
  252. if (usbd_dev->rxbcnt < 4) {
  253. /* Be careful not to underflow (rxbcnt is unsigned) */
  254. usbd_dev->rxbcnt = 0;
  255. } else {
  256. usbd_dev->rxbcnt -= 4;
  257. }
  258. memcpy(buf32, &extra, i);
  259. }
  260. return len;
  261. }
  262. static void dwc_flush_txfifo(usbd_device *usbd_dev, int ep)
  263. {
  264. uint32_t fifo;
  265. /* set IN endpoint NAK */
  266. REBASE(OTG_DIEPCTL(ep)) |= OTG_DIEPCTL0_SNAK;
  267. /* wait for core to respond */
  268. while (!(REBASE(OTG_DIEPINT(ep)) & OTG_DIEPINTX_INEPNE)) {
  269. /* idle */
  270. }
  271. /* get fifo for this endpoint */
  272. fifo = (REBASE(OTG_DIEPCTL(ep)) & OTG_DIEPCTL0_TXFNUM_MASK) >> 22;
  273. /* wait for core to idle */
  274. while (!(REBASE(OTG_GRSTCTL) & OTG_GRSTCTL_AHBIDL)) {
  275. /* idle */
  276. }
  277. /* flush tx fifo */
  278. REBASE(OTG_GRSTCTL) = (fifo << 6) | OTG_GRSTCTL_TXFFLSH;
  279. /* reset packet counter */
  280. REBASE(OTG_DIEPTSIZ(ep)) = 0;
  281. while ((REBASE(OTG_GRSTCTL) & OTG_GRSTCTL_TXFFLSH)) {
  282. /* idle */
  283. }
  284. }
  285. void dwc_poll(usbd_device *usbd_dev)
  286. {
  287. /* Read interrupt status register. */
  288. uint32_t intsts = REBASE(OTG_GINTSTS);
  289. int i;
  290. if (intsts & OTG_GINTSTS_ENUMDNE) {
  291. /* Handle USB RESET condition. */
  292. REBASE(OTG_GINTSTS) = OTG_GINTSTS_ENUMDNE;
  293. usbd_dev->fifo_mem_top = usbd_dev->driver->rx_fifo_size;
  294. _usbd_reset(usbd_dev);
  295. return;
  296. }
  297. /*
  298. * There is no global interrupt flag for transmit complete.
  299. * The XFRC bit must be checked in each OTG_DIEPINT(x).
  300. */
  301. for (i = 0; i < 4; i++) { /* Iterate over endpoints. */
  302. if (REBASE(OTG_DIEPINT(i)) & OTG_DIEPINTX_XFRC) {
  303. /* Transfer complete. */
  304. if (usbd_dev->user_callback_ctr[i]
  305. [USB_TRANSACTION_IN]) {
  306. usbd_dev->user_callback_ctr[i]
  307. [USB_TRANSACTION_IN](usbd_dev, i);
  308. }
  309. REBASE(OTG_DIEPINT(i)) = OTG_DIEPINTX_XFRC;
  310. }
  311. }
  312. /* Note: RX and TX handled differently in this device. */
  313. if (intsts & OTG_GINTSTS_RXFLVL) {
  314. /* Receive FIFO non-empty. */
  315. uint32_t rxstsp = REBASE(OTG_GRXSTSP);
  316. uint32_t pktsts = rxstsp & OTG_GRXSTSP_PKTSTS_MASK;
  317. uint8_t ep = rxstsp & OTG_GRXSTSP_EPNUM_MASK;
  318. if (pktsts == OTG_GRXSTSP_PKTSTS_SETUP_COMP) {
  319. usbd_dev->user_callback_ctr[ep][USB_TRANSACTION_SETUP] (usbd_dev, ep);
  320. }
  321. if (pktsts == OTG_GRXSTSP_PKTSTS_OUT_COMP
  322. || pktsts == OTG_GRXSTSP_PKTSTS_SETUP_COMP) {
  323. REBASE(OTG_DOEPTSIZ(ep)) = usbd_dev->doeptsiz[ep];
  324. REBASE(OTG_DOEPCTL(ep)) |= OTG_DOEPCTL0_EPENA |
  325. (usbd_dev->force_nak[ep] ?
  326. OTG_DOEPCTL0_SNAK : OTG_DOEPCTL0_CNAK);
  327. return;
  328. }
  329. if ((pktsts != OTG_GRXSTSP_PKTSTS_OUT) &&
  330. (pktsts != OTG_GRXSTSP_PKTSTS_SETUP)) {
  331. return;
  332. }
  333. uint8_t type;
  334. if (pktsts == OTG_GRXSTSP_PKTSTS_SETUP) {
  335. type = USB_TRANSACTION_SETUP;
  336. } else {
  337. type = USB_TRANSACTION_OUT;
  338. }
  339. if (type == USB_TRANSACTION_SETUP
  340. && (REBASE(OTG_DIEPTSIZ(ep)) & OTG_DIEPSIZ0_PKTCNT)) {
  341. /* SETUP received but there is still something stuck
  342. * in the transmit fifo. Flush it.
  343. */
  344. dwc_flush_txfifo(usbd_dev, ep);
  345. }
  346. /* Save packet size for dwc_ep_read_packet(). */
  347. usbd_dev->rxbcnt = (rxstsp & OTG_GRXSTSP_BCNT_MASK) >> 4;
  348. if (type == USB_TRANSACTION_SETUP) {
  349. dwc_ep_read_packet(usbd_dev, ep, &usbd_dev->control_state.req, 8);
  350. } else if (usbd_dev->user_callback_ctr[ep][type]) {
  351. usbd_dev->user_callback_ctr[ep][type] (usbd_dev, ep);
  352. }
  353. /* Discard unread packet data. */
  354. for (i = 0; i < usbd_dev->rxbcnt; i += 4) {
  355. /* There is only one receive FIFO, so use OTG_FIFO(0) */
  356. (void)REBASE(OTG_FIFO(0));
  357. }
  358. usbd_dev->rxbcnt = 0;
  359. }
  360. if (intsts & OTG_GINTSTS_USBSUSP) {
  361. if (usbd_dev->user_callback_suspend) {
  362. usbd_dev->user_callback_suspend();
  363. }
  364. REBASE(OTG_GINTSTS) = OTG_GINTSTS_USBSUSP;
  365. }
  366. if (intsts & OTG_GINTSTS_WKUPINT) {
  367. if (usbd_dev->user_callback_resume) {
  368. usbd_dev->user_callback_resume();
  369. }
  370. REBASE(OTG_GINTSTS) = OTG_GINTSTS_WKUPINT;
  371. }
  372. if (intsts & OTG_GINTSTS_SOF) {
  373. if (usbd_dev->user_callback_sof) {
  374. usbd_dev->user_callback_sof();
  375. }
  376. REBASE(OTG_GINTSTS) = OTG_GINTSTS_SOF;
  377. }
  378. if (usbd_dev->user_callback_sof) {
  379. REBASE(OTG_GINTMSK) |= OTG_GINTMSK_SOFM;
  380. } else {
  381. REBASE(OTG_GINTMSK) &= ~OTG_GINTMSK_SOFM;
  382. }
  383. }
  384. void dwc_disconnect(usbd_device *usbd_dev, bool disconnected)
  385. {
  386. if (disconnected) {
  387. REBASE(OTG_DCTL) |= OTG_DCTL_SDIS;
  388. } else {
  389. REBASE(OTG_DCTL) &= ~OTG_DCTL_SDIS;
  390. }
  391. }