ch56x_usbd.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-08-22 Emuzit first version
  9. */
  10. #include <rthw.h>
  11. #include <rtdebug.h>
  12. #include <drivers/usb_common.h>
  13. #include <drivers/usb_device.h>
  14. #include "ch56x_usbhs.h"
  15. #include "ch56x_sys.h"
  16. #include "isr_sp.h"
  17. /*--------------------------------------------------------*/
  18. /* Warning : Not fully tested, use at your own discretion */
  19. /*--------------------------------------------------------*/
  20. #ifdef SOC_SERIES_CH569
  21. #define _attr_uepdma __attribute__((section(".dmadata"), aligned(16)))
  22. #define _ep0_setup_dmabuf _dmadata_start
  23. #else
  24. #define _attr_uepdma __attribute__((aligned(4)))
  25. #define _ep0_setup_dmabuf _dmadata_start
  26. #define usbhs_irq_handler usb1_irq_handler
  27. #define USBHS_IRQn USB1_IRQn
  28. #define USBHS_REG_BASE USB1_REG_BASE
  29. #define RAMX_BASE_ADDRESS RAMS_BASE_ADDRESS
  30. #define UEP0_RT_DMA UEP_DMA[0]
  31. #endif
  32. #define UEP_MPS_64 64
  33. #define UEP_MPS_512 512
  34. #define _get_ep_idx(address) ((address) & USB_EPNO_MASK)
  35. #define _get_ep_dir(address) ((address) & USB_DIR_MASK)
  36. #define uep_dir_is_in(address) (_get_ep_dir(address) == USB_DIR_IN)
  37. #define uep_dir_is_out(address) (_get_ep_dir(address) == USB_DIR_OUT)
  38. extern uint32_t _dmadata_start[];
  39. static uint32_t ep0_dmabuf[UEP_MPS_64 / 4] _attr_uepdma;
  40. static uint32_t epx_dmabuf[UEP_ADDRESS_MAX][UEP_MPS_512 / 4] _attr_uepdma;
  41. static struct ep_id usbhs_ep_pool[] =
  42. {
  43. {0x0, USB_EP_ATTR_CONTROL, USB_DIR_INOUT, 64, ID_ASSIGNED},
  44. {0x1, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED},
  45. {0x1, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED},
  46. {0x2, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED},
  47. {0x2, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED},
  48. {0x3, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED},
  49. {0x3, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED},
  50. #ifdef SOC_SERIES_CH569
  51. /* FIXME: not sure how to deal with EP4, no UEP4_DMA register */
  52. {0x4, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED},
  53. {0x4, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED},
  54. {0x5, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED},
  55. {0x5, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED},
  56. {0x6, USB_EP_ATTR_INT, USB_DIR_IN, 512, ID_UNASSIGNED},
  57. {0x6, USB_EP_ATTR_INT, USB_DIR_OUT, 512, ID_UNASSIGNED},
  58. {0x7, USB_EP_ATTR_BULK, USB_DIR_IN, 512, ID_UNASSIGNED},
  59. {0x7, USB_EP_ATTR_BULK, USB_DIR_OUT, 512, ID_UNASSIGNED},
  60. #endif
  61. {0xff, USB_EP_ATTR_TYPE_MASK, USB_DIR_MASK, 0, ID_ASSIGNED},
  62. };
  63. static struct udcd udc_device;
  64. static uint8_t setup_set_address;
  65. static rt_err_t udc_set_address(uint8_t address)
  66. {
  67. /* DEV_AD should be updated after status stage IN token of SET_ADDRESS
  68. * such that that IN token could still reach our device.
  69. */
  70. setup_set_address = address | 0x80;
  71. return RT_EOK;
  72. }
  73. static rt_err_t udc_set_config(uint8_t address)
  74. {
  75. return RT_EOK;
  76. }
  77. static rt_err_t udc_ep_set_stall(uint8_t address)
  78. {
  79. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  80. uint8_t ep_idx = _get_ep_idx(address);
  81. if (uep_dir_is_in(address))
  82. usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_STALL;
  83. else
  84. usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_STALL;
  85. return RT_EOK;
  86. }
  87. static rt_err_t udc_ep_clear_stall(uint8_t address)
  88. {
  89. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  90. uint8_t ep_idx = _get_ep_idx(address);
  91. if (uep_dir_is_in(address))
  92. usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_NAK;
  93. else
  94. usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_NAK;
  95. return RT_EOK;
  96. }
  97. static rt_err_t udc_ep_enable(struct uendpoint *ep)
  98. {
  99. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  100. uint8_t ep_idx, address, mod;
  101. RT_ASSERT(ep != RT_NULL);
  102. RT_ASSERT(ep->ep_desc != RT_NULL);
  103. address = EP_ADDRESS(ep);
  104. ep_idx = _get_ep_idx(address);
  105. if (ep_idx > 0 && ep_idx <= UEP_ADDRESS_MAX)
  106. {
  107. mod = uep_dir_is_in(address) ? RB_UEP_TX_EN : RB_UEP_RX_EN;
  108. mod = _uep_mod_get(usbhs, ep_idx) | mod;
  109. _uep_mod_set(usbhs, ep_idx, mod);
  110. }
  111. return RT_EOK;
  112. }
  113. static rt_err_t udc_ep_disable(struct uendpoint *ep)
  114. {
  115. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  116. uint8_t ep_idx, address, mod;
  117. RT_ASSERT(ep != RT_NULL);
  118. RT_ASSERT(ep->ep_desc != RT_NULL);
  119. address = EP_ADDRESS(ep);
  120. ep_idx = _get_ep_idx(address);
  121. if (ep_idx > 0 && ep_idx <= UEP_ADDRESS_MAX)
  122. {
  123. mod = uep_dir_is_in(address) ? RB_UEP_TX_EN : RB_UEP_RX_EN;
  124. mod = _uep_mod_get(usbhs, ep_idx) & ~mod;
  125. _uep_mod_set(usbhs, ep_idx, mod);
  126. }
  127. return RT_EOK;
  128. }
  129. static rt_ssize_t udc_ep_read_prepare(uint8_t address, void *buffer, rt_size_t size)
  130. {
  131. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  132. uint8_t ep_idx = _get_ep_idx(address);
  133. uint32_t dmabuf = (uint32_t)buffer;
  134. if (uep_dir_is_in(address))
  135. return 0;
  136. if (size > (ep_idx ? UEP_MPS_512 : UEP_MPS_64))
  137. size = (ep_idx ? UEP_MPS_512 : UEP_MPS_64);
  138. /* need extra `buffer` copy if H/W requirement not met
  139. * CH565/CH569 : DMA buffer resides in RAMX, 16-byte aligned
  140. * CH567/CH568 : 4-byte aligned
  141. */
  142. #ifdef SOC_SERIES_CH569
  143. if (size > 0 && (dmabuf < RAMX_BASE_ADDRESS || (dmabuf & 0xf)))
  144. {
  145. dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf);
  146. }
  147. /* Note : usbhs->UEP_RX_DMA[0] maps to usbhs->UEP0_RT_DMA actually */
  148. usbhs->UEP_RX_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK;
  149. #else
  150. if (size > 0 && (dmabuf & 3))
  151. {
  152. dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf);
  153. }
  154. usbhs->UEP_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK;
  155. #endif
  156. if (ep_idx == 0 && size == 0)
  157. {
  158. /* SETUP status stage, expect DATA1 */
  159. usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_ACK | RB_UEP_TOG_DATA1;
  160. }
  161. else
  162. {
  163. /* keep TOG_MASK & AUTOTOG */
  164. usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_ACK;
  165. }
  166. return size;
  167. }
  168. static rt_ssize_t udc_ep_read(uint8_t address, void *buffer)
  169. {
  170. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  171. uint8_t ep_idx = _get_ep_idx(address);
  172. uint32_t dmabuf;
  173. rt_size_t size;
  174. if (uep_dir_is_in(address))
  175. return 0;
  176. #ifdef SOC_SERIES_CH569
  177. /* Note : usbhs->UEP_RX_DMA[0] maps to usbhs->UEP0_RT_DMA actually */
  178. dmabuf = usbhs->UEP_RX_DMA[ep_idx] & UEP_RT_DMA_MASK;
  179. #else
  180. dmabuf = usbhs->UEP_DMA[ep_idx] & UEP_RT_DMA_MASK;
  181. #endif
  182. size = usbhs->RX_LEN;
  183. /* copy if proxy buffer */
  184. if (size > 0 && ((uint32_t)buffer & UEP_RT_DMA_MASK) != dmabuf)
  185. {
  186. dmabuf |= RAMX_BASE_ADDRESS;
  187. rt_memcpy(buffer, (void *)dmabuf, size);
  188. }
  189. return size;
  190. }
  191. static rt_ssize_t udc_ep_write(uint8_t address, void *buffer, rt_size_t size)
  192. {
  193. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  194. uint8_t ep_idx = _get_ep_idx(address);
  195. uint32_t dmabuf = (uint32_t)buffer;
  196. union _uh_rt_ctrl ctrl;
  197. if (uep_dir_is_out(address))
  198. return 0;
  199. if (size > (ep_idx ? UEP_MPS_512 : UEP_MPS_64))
  200. size = (ep_idx ? UEP_MPS_512 : UEP_MPS_64);
  201. /* need extra `buffer` copy if H/W requirement not met
  202. * CH565/CH569 : DMA buffer resides in RAMX, 16-byte aligned
  203. * CH567/CH568 : 4-byte aligned
  204. */
  205. #ifdef SOC_SERIES_CH569
  206. if (size > 0 && (dmabuf < RAMX_BASE_ADDRESS || (dmabuf & 0xf)))
  207. {
  208. dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf);
  209. rt_memcpy((void *)dmabuf, buffer, size);
  210. }
  211. if (ep_idx == 0)
  212. usbhs->UEP0_RT_DMA = dmabuf & UEP_RT_DMA_MASK;
  213. else
  214. usbhs->UEP_TX_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK;
  215. #else
  216. if (size > 0 && (dmabuf & 3))
  217. {
  218. dmabuf = (uint32_t)(ep_idx ? epx_dmabuf[ep_idx] : ep0_dmabuf);
  219. rt_memcpy((void *)dmabuf, buffer, size);
  220. }
  221. usbhs->UEP_DMA[ep_idx] = dmabuf & UEP_RT_DMA_MASK;
  222. #endif
  223. usbhs->UEP_CTRL[ep_idx].t_len = size;
  224. /* keep TOG_MASK & AUTOTOG */
  225. usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_ACK;
  226. return size;
  227. }
  228. static rt_err_t udc_ep0_send_status(void)
  229. {
  230. volatile struct usbhs_registers *usbhs = (void *)USBHS_REG_BASE;
  231. /* SETUP status stage : zero data length, always DATA1 */
  232. usbhs->UEP_CTRL[0].t_len = 0;
  233. /* This is the only case UEP0_RT_DMA is set to 0. */
  234. usbhs->UEP0_RT_DMA = 0;
  235. usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_ACK | RB_UEP_TOG_DATA1;
  236. return RT_EOK;
  237. }
  238. static rt_err_t udc_suspend(void)
  239. {
  240. return RT_EOK;
  241. }
  242. static rt_err_t udc_wakeup(void)
  243. {
  244. return RT_EOK;
  245. }
  246. static const struct udcd_ops udcd_ops =
  247. {
  248. .set_address = udc_set_address,
  249. .set_config = udc_set_config,
  250. .ep_set_stall = udc_ep_set_stall,
  251. .ep_clear_stall = udc_ep_clear_stall,
  252. .ep_enable = udc_ep_enable,
  253. .ep_disable = udc_ep_disable,
  254. .ep_read_prepare = udc_ep_read_prepare,
  255. .ep_read = udc_ep_read,
  256. .ep_write = udc_ep_write,
  257. .ep0_send_status = udc_ep0_send_status,
  258. .suspend = udc_suspend,
  259. .wakeup = udc_wakeup,
  260. };
  261. static void _hsbhs_device_mode_init(volatile struct usbhs_registers *usbhs)
  262. {
  263. uint8_t ep_idx;
  264. /* disable all endpoints, use single buffer mode (BUF_MOD : 0) */
  265. usbhs->UHOST_CTRL.reg = 0;
  266. usbhs->SUSPEND.reg = 0;
  267. usbhs->R32_UEP_MOD = 0;
  268. usbhs->DEV_AD = 0;
  269. usbhs->CTRL.reg = RB_USB_RESET_SIE | RB_USB_CLR_ALL;
  270. usbhs->CTRL.reg = RB_USB_DEVICE_MODE |
  271. RB_SPTP_HIGH_SPEED |
  272. RB_DEV_PU_EN |
  273. RB_USB_INT_BUSY |
  274. RB_USB_DMA_EN;
  275. usbhs->INT_EN.reg = RB_USB_IE_BUSRST |
  276. RB_USB_IE_TRANS |
  277. RB_USB_IE_FIFOOV |
  278. RB_USB_IE_SETUPACT;
  279. usbhs->UEP_MAX_LEN[0].reg = UEP_MPS_64;
  280. /*
  281. * It seems EP0 SETUP uses the first 8 bytes of RAMX as dmabuf and
  282. * handles DATA0 transfer & ACK on its own. Here we still needs to
  283. * RES_NAK TX/RX to block SETUP data stage till dma data is ready.
  284. */
  285. usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1;
  286. usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1;
  287. for (ep_idx = 1; ep_idx <= UEP_ADDRESS_MAX; ep_idx++)
  288. {
  289. usbhs->UEP_MAX_LEN[ep_idx].reg = UEP_MPS_512;
  290. /* set to DATA0, remains to be initialized (SET_CONFIGURATION...) */
  291. usbhs->UEP_CTRL[ep_idx].TX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_AUTOTOG;
  292. usbhs->UEP_CTRL[ep_idx].RX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_AUTOTOG;
  293. }
  294. }
  295. static rt_err_t udc_device_init(struct rt_device *device)
  296. {
  297. volatile struct usbhs_registers *usbhs = device->user_data;
  298. sys_clk_off_by_irqn(USBHS_IRQn, SYS_SLP_CLK_ON);
  299. _hsbhs_device_mode_init(usbhs);
  300. rt_hw_interrupt_umask(USBHS_IRQn);
  301. return RT_EOK;
  302. }
  303. #ifdef RT_USING_DEVICE_OPS
  304. static struct rt_device_ops device_ops;
  305. #endif
  306. static int rt_hw_usbd_init(void)
  307. {
  308. int ret;
  309. udc_device.parent.type = RT_Device_Class_USBDevice;
  310. #ifdef RT_USING_DEVICE_OPS
  311. device_ops.init = udc_device_init;
  312. udc_device.parent.ops = &device_ops;
  313. #else
  314. udc_device.parent.init = udc_device_init;
  315. #endif
  316. udc_device.parent.user_data = (void *)USBHS_REG_BASE;
  317. udc_device.ops = &udcd_ops;
  318. udc_device.ep_pool = usbhs_ep_pool;
  319. udc_device.ep0.id = &usbhs_ep_pool[0];
  320. udc_device.device_is_hs = RT_TRUE;
  321. ret = rt_device_register(&udc_device.parent, "usbd", 0);
  322. if (ret == RT_EOK)
  323. ret = rt_usb_device_init();
  324. return ret;
  325. }
  326. INIT_DEVICE_EXPORT(rt_hw_usbd_init);
  327. rt_inline uint8_t _uep_tog_datax(uint8_t tog)
  328. {
  329. /* Note: treat tog as RB_UEP_TOG_DATA0 if not RB_UEP_TOG_DATA1 */
  330. return (tog == RB_UEP_TOG_DATA1) ? RB_UEP_TOG_DATA0 : RB_UEP_TOG_DATA1;
  331. }
  332. static void _isr_ep_stall(volatile struct usbhs_registers *usbhs)
  333. {
  334. uint8_t ep_idx = usbhs->INT_ST.dev_endp_mask;
  335. usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask == UEP_RES_STALL;
  336. usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask == UEP_RES_STALL;
  337. }
  338. static void _isr_handle_setup(volatile struct usbhs_registers *usbhs)
  339. {
  340. struct urequest setup, *packet;
  341. uint8_t ep_idx, xctrl, recipient;
  342. /* RES_NAK to block data stage, will expect or response DATA1 */
  343. usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1;
  344. usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_NAK | RB_UEP_TOG_DATA1;
  345. packet = (struct urequest *)_ep0_setup_dmabuf;
  346. setup.request_type = packet->request_type;
  347. setup.bRequest = packet->bRequest;
  348. setup.wValue = packet->wValue;
  349. setup.wIndex = packet->wIndex;
  350. setup.wLength = packet->wLength;
  351. /* Init data toggle bit. Not sure if it has been done by h/w.*/
  352. xctrl = RB_UEP_RES_NAK | RB_UEP_AUTOTOG | RB_UEP_TOG_DATA0;
  353. recipient = setup.request_type & USB_REQ_TYPE_RECIPIENT_MASK;
  354. if (recipient == USB_REQ_TYPE_DEVICE &&
  355. setup.bRequest == USB_REQ_SET_CONFIGURATION)
  356. {
  357. for (ep_idx = 1; ep_idx <= UEP_ADDRESS_MAX; ep_idx++)
  358. {
  359. usbhs->UEP_CTRL[ep_idx].TX_CTRL.reg = xctrl;
  360. usbhs->UEP_CTRL[ep_idx].RX_CTRL.reg = xctrl;
  361. }
  362. }
  363. else if (recipient == USB_REQ_TYPE_ENDPOINT &&
  364. setup.bRequest == USB_REQ_CLEAR_FEATURE &&
  365. setup.wValue == USB_EP_HALT)
  366. {
  367. ep_idx = setup.wIndex;
  368. if (ep_idx > 0 && ep_idx <= UEP_ADDRESS_MAX)
  369. {
  370. usbhs->UEP_CTRL[ep_idx].TX_CTRL.reg = xctrl;
  371. usbhs->UEP_CTRL[ep_idx].RX_CTRL.reg = xctrl;
  372. }
  373. }
  374. rt_usbd_ep0_setup_handler(&udc_device, &setup);
  375. }
  376. static void _isr_handle_transfer(volatile struct usbhs_registers *usbhs)
  377. {
  378. rt_size_t size;
  379. uint8_t ep_idx, token, tog;
  380. ep_idx = usbhs->INT_ST.dev_endp_mask;
  381. token = usbhs->INT_ST.dev_token_mask;
  382. if (ep_idx == 0)
  383. {
  384. if (token == DEV_TOKEN_IN)
  385. {
  386. /* UEP0 does not support AUTOTOG, generate DATAx manually */
  387. tog = usbhs->UEP_CTRL[0].TX_CTRL.reg & RB_UEP_TOG_MASK;
  388. tog = _uep_tog_datax(tog);
  389. /* wait for udc_ep_write or udc_ep0_send_status to RES_ACK */
  390. usbhs->UEP_CTRL[0].TX_CTRL.reg = RB_UEP_RES_NAK | tog;
  391. if (setup_set_address != 0 && usbhs->UEP_CTRL[0].t_len == 0)
  392. {
  393. usbhs->DEV_AD = setup_set_address & 0x7f;
  394. setup_set_address = 0;
  395. }
  396. /* don't call in_handler if send_status */
  397. if (usbhs->UEP0_RT_DMA != 0)
  398. {
  399. rt_usbd_ep0_in_handler(&udc_device);
  400. }
  401. }
  402. else if (token == DEV_TOKEN_OUT)
  403. {
  404. if (usbhs->INT_ST.st_togok)
  405. {
  406. /* UEP0 does not support AUTOTOG, generate DATAx manually */
  407. tog = usbhs->UEP_CTRL[0].RX_CTRL.reg & RB_UEP_TOG_MASK;
  408. tog = _uep_tog_datax(tog);
  409. /* wait for udc_ep_read_prepare to RES_ACK */
  410. usbhs->UEP_CTRL[0].RX_CTRL.reg = RB_UEP_RES_NAK | tog;
  411. rt_usbd_ep0_out_handler(&udc_device, usbhs->RX_LEN);
  412. }
  413. else
  414. {
  415. /* Corrupted ACK Handshake => ignore data, keep sequence bit */
  416. usbhs->UEP_CTRL[0].RX_CTRL.res_mask = UEP_RES_NAK;
  417. }
  418. }
  419. }
  420. else if (token == DEV_TOKEN_IN)
  421. {
  422. /* wait for udc_ep_write to RES_ACK */
  423. usbhs->UEP_CTRL[ep_idx].TX_CTRL.res_mask = UEP_RES_NAK;
  424. size = usbhs->UEP_CTRL[ep_idx].t_len;
  425. rt_usbd_ep_in_handler(&udc_device, ep_idx | USB_DIR_IN, size);
  426. }
  427. else if (token == DEV_TOKEN_OUT)
  428. {
  429. /* wait for udc_ep_read_prepare to RES_ACK */
  430. usbhs->UEP_CTRL[ep_idx].RX_CTRL.res_mask = UEP_RES_NAK;
  431. /* ignore data if Corrupted ACK Handshake */
  432. if (usbhs->INT_ST.st_togok)
  433. {
  434. /* size:0 to trigger dcd_ep_read() in _data_notify() */
  435. rt_usbd_ep_out_handler(&udc_device, ep_idx | USB_DIR_OUT, 0);
  436. }
  437. }
  438. }
  439. /*
  440. * CAVEAT: The usbd design of ch56x relies on instant isr to RES_NAK
  441. * UEP_CTRL[n].TX_CTRL/RX_CTRL. A long tarried isr may leave RES_ACK
  442. * in UEP_CTRL[n] and starts unintended DMA upon arrival of IN/OUT.
  443. */
  444. void usbhs_irq_handler(void) __attribute__((interrupt()));
  445. void usbhs_irq_handler(void)
  446. {
  447. volatile struct usbhs_registers *usbhs;
  448. union _usb_int_fg intflag;
  449. isr_sp_enter();
  450. rt_interrupt_enter();
  451. usbhs = (struct usbhs_registers *)USBHS_REG_BASE;
  452. intflag.reg = usbhs->INT_FG.reg;
  453. if (intflag.fifoov)
  454. {
  455. /* FIXME: fifo overflow */
  456. _isr_ep_stall(usbhs);
  457. }
  458. else
  459. {
  460. if (intflag.transfer)
  461. _isr_handle_transfer(usbhs);
  462. if (intflag.setupact)
  463. _isr_handle_setup(usbhs);
  464. }
  465. if (intflag.busrst)
  466. {
  467. _hsbhs_device_mode_init(usbhs);
  468. rt_usbd_reset_handler(&udc_device);
  469. }
  470. /* clear all pending intflag (suspend, isoact & nak ignored) */
  471. usbhs->INT_FG.reg = intflag.reg;
  472. rt_interrupt_leave();
  473. isr_sp_leave();
  474. }