1 /*******************************************************************************
2 * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * PolarFire SoC MSS USB Driver Stack
7 * USB Core Interface Layer (USB-CIFL)
8 * USB-CIF driver
9 *
10 * USB-CIF driver implementation:
11 * This source file implements MSS USB Interrupt handler functions. This file
12 * also implements core interface function for the logical layer to control
13 * the MSS USB core. These interface functions are independent of the USB mode.
14 *
15 */
16 #include "mpfs_hal/mss_hal.h"
17 #include "mss_usb_common_cif.h"
18 #include "mss_usb_common_reg_io.h"
19
20 #ifdef MSS_USB_HOST_ENABLED
21 #include "mss_usb_host_cif.h"
22 #include "mss_usb_host_reg_io.h"
23 #endif /* MSS_USB_HOST_ENABLED */
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 #ifdef MSS_USB_HOST_ENABLED
30 static uint8_t MSS_USB_CIF_host_rx_errchk(mss_usb_ep_num_t ep_num);
31 static uint8_t MSS_USB_CIF_host_tx_errchk(mss_usb_ep_num_t ep_num);
32 #endif /* MSS_USB_HOST_ENABLED */
33
34 #ifdef MSS_USB_DEVICE_ENABLED
35 static uint8_t MSS_USB_CIF_device_rx_errchk(mss_usb_ep_num_t ep_num);
36 static uint8_t MSS_USB_CIF_device_tx_errchk(mss_usb_ep_num_t ep_num);
37 #endif /* MSS_USB_HOST_ENABLED */
38
39 /***************************************************************************//**
40 * Global variables shared by mss_usb_device_cif.c and mss_usb_common_cif.c
41 */
42 #ifdef MSS_USB_DEVICE_ENABLED
43 extern mss_usbd_cb_t g_mss_usbd_cb;
44 extern volatile mss_usbd_cep_state_t cep_state;
45 #endif /* MSS_USB_HOST_ENABLED */
46
47 #ifdef MSS_USB_HOST_ENABLED
48 extern mss_usbh_cb_t g_mss_usbh_cb;
49 #endif /* MSS_USB_HOST_ENABLED */
50
51 /***************************************************************************//**
52 * Private functions declarations of USB-CIF.
53 ******************************************************************************/
54 static void
55 MSS_USB_CIF_handle_cep_irq
56 (
57 void
58 );
59
60 static void
61 MSS_USB_CIF_handle_tx_ep_irq
62 (
63 uint16_t irq_num
64 );
65
66 static void
67 MSS_USB_CIF_handle_rx_ep_irq
68 (
69 uint16_t irq_num
70 );
71
72 /***************************************************************************//**
73 * Main USB interrupt handler. It checks for TX/RX endpoint interrupts and USB
74 * system level interrupts and calls the appropriate routine.
75 */
usb_mc_plic_IRQHandler(void)76 uint8_t usb_mc_plic_IRQHandler
77 (
78 void
79 )
80 {
81 volatile uint8_t usb_irq;
82 volatile uint16_t tx_ep_irq;
83 volatile uint16_t rx_ep_irq;
84 volatile uint8_t role;
85
86 usb_irq = MSS_USB_CIF_read_irq_reg();
87 tx_ep_irq = MSS_USB_CIF_read_tx_ep_irq_reg();
88 rx_ep_irq = MSS_USB_CIF_read_rx_ep_irq_reg();
89
90 /*
91 When operating in Host mode, on detecting Disconnect event, Disconnect
92 Interrupt occurs but the HostMode bit in DevCtl is also cleared.
93 Hence moving Disconnect handling out of get_mode condition.
94 In the event of Disconnection, The decision is made based on the B-Device
95 bit(DevCtl-D7).
96 */
97 if (usb_irq & DISCONNECT_IRQ_MASK)
98 {
99 role = MSS_USB_CIF_get_role();
100
101 #ifdef MSS_USB_DEVICE_ENABLED
102 if (MSS_USB_DEVICE_ROLE_DEVICE_B == role)
103 {
104 MSS_USB_CIF_enable_usbirq(RESET_IRQ_MASK);
105 g_mss_usbd_cb.usbd_disconnect();
106 }
107 #endif /* MSS_USB_DEVICE_ENABLED */
108
109 #ifdef MSS_USB_HOST_ENABLED
110 if (MSS_USB_DEVICE_ROLE_DEVICE_A == role)
111 {
112 /*In Host mode, On removing the attached B-device the session bit
113 somehow remains set.
114 This bit need to be cleared otherwise RESET interrupt is not occurring
115 when B-Device is connected after removing A-Device*/
116 if (MSS_USB_CIF_is_session_on())
117 {
118 MSS_USB_CIF_stop_session();
119 }
120
121 MSS_USBH_CIF_read_vbus_level();
122 g_mss_usbh_cb.usbh_disconnect();
123 }
124 #endif /* MSS_USB_HOST_ENABLED */
125 }
126
127 #ifdef MSS_USB_DEVICE_ENABLED
128 if (MSS_USB_CORE_MODE_DEVICE == MSS_USB_CIF_get_mode())
129 {
130 if (usb_irq & RESUME_IRQ_MASK)
131 {
132 g_mss_usbd_cb.usbd_resume();
133 }
134 if (usb_irq & SUSPEND_IRQ_MASK)
135 {
136 g_mss_usbd_cb.usbd_suspend();
137 }
138 if (usb_irq & RESET_IRQ_MASK)
139 {
140 MSS_USB_CIF_set_index_reg(MSS_USB_CEP);
141 MSS_USB_CIF_enable_usbirq(DISCONNECT_IRQ_MASK | SUSPEND_IRQ_MASK);
142 cep_state = MSS_USB_CTRL_EP_IDLE;
143 MSS_USB_CIF_clr_usb_irq_reg();
144 MSS_USB_CIF_cep_clr_setupend();
145 MSS_USB_CIF_cep_clr_stall_sent();
146 g_mss_usbd_cb.usbd_reset();
147 }
148 }
149 #endif /* MSS_USB_DEVICE_ENABLED */
150
151 #ifdef MSS_USB_HOST_ENABLED
152 if (MSS_USB_CORE_MODE_HOST == MSS_USB_CIF_get_mode())
153 {
154 role = MSS_USB_CIF_get_role();
155 if (usb_irq & RESUME_IRQ_MASK)
156 {
157 /* Resume interrupt in Host mode means Remote Wakeup request */
158 }
159
160 /* Vbus_err and session request interrupts are valid only in A device */
161 if (MSS_USB_DEVICE_ROLE_DEVICE_A == role)
162 {
163 if (usb_irq & SESSION_REQUEST_IRQ_MASK)
164 {
165 /* This means SRP initiated by Target device. */
166 }
167 if (usb_irq & VBUS_ERROR_IRQ_MASK)
168 {
169 /* Power management */
170 MSS_USBH_CIF_read_vbus_level();
171 }
172 }
173
174 if (usb_irq & CONNECT_IRQ_MASK)
175 {
176 MSS_USBH_CIF_handle_connect_irq();
177 }
178
179 if (usb_irq & BABBLE_IRQ_MASK)
180 {
181 /* Not supported yet */
182 }
183
184 #if 0 /* SOF interrupt is not processed */
185 if (usb_irq & SOF_IRQ_MASK)
186 {
187 g_mss_usbd_cb.usb_device_sof(0);
188 }
189 #endif /* SOF interrupt is not processed */
190
191 }
192 #endif /* MSS_USB_HOST_ENABLED */
193
194 if (tx_ep_irq & 0x0001u)
195 {
196 /* handle EP0 IRQ */
197 MSS_USB_CIF_handle_cep_irq();
198 }
199
200 if (tx_ep_irq & 0xFFFEu) /* EP0 is handled above */
201 {
202 /* Handle TX EP here, pass on the EP numbers.Mask EP0 bit */
203 tx_ep_irq &= 0xFFFEu;
204 MSS_USB_CIF_handle_tx_ep_irq(tx_ep_irq);
205 }
206
207 if (rx_ep_irq & 0xFFFEu) /* bit0 is not defined */
208 {
209 /* Handle RX EP here, pass on the EP numbers */
210 MSS_USB_CIF_handle_rx_ep_irq(rx_ep_irq);
211 }
212
213 return EXT_IRQ_KEEP_ENABLED;
214 }
215
216 /***************************************************************************//**
217 * Routine to handle the interrupt on Control Endpoint.(EP0)
218 */
219 static void
MSS_USB_CIF_handle_cep_irq(void)220 MSS_USB_CIF_handle_cep_irq
221 (
222 void
223 )
224 {
225 uint8_t status = 0u;
226
227 MSS_USB_CIF_set_index_reg(MSS_USB_CEP);
228
229 #ifdef MSS_USB_DEVICE_ENABLED
230 if (MSS_USB_CORE_MODE_DEVICE == MSS_USB_CIF_get_mode())
231 {
232 if (MSS_USB_CIF_cep_is_stall_sent())
233 {
234 status |= CTRL_EP_STALL_ERROR;
235 MSS_USB_CIF_cep_clr_stall_sent();
236 g_mss_usbd_cb.usbd_cep_setup(status);
237 }
238 else
239 {
240 if (MSS_USB_CIF_cep_is_setupend())
241 {
242 MSS_USB_CIF_cep_clr_setupend();
243
244 if (!MSS_USB_CIF_cep_is_rxpktrdy())
245 {
246 status |= CTRL_EP_SETUP_END_ERROR;
247 }
248 else
249 {
250 status &= ~CTRL_EP_SETUP_END_ERROR;
251 }
252
253 g_mss_usbd_cb.usbd_cep_setup(status);
254 }
255 else
256 {
257 if (cep_state == MSS_USB_CTRL_EP_IDLE)
258 {
259 if (MSS_USB_CIF_cep_is_rxpktrdy())
260 {
261 g_mss_usbd_cb.usbd_cep_setup(status);
262 }
263 }
264 else if (cep_state == MSS_USB_CTRL_EP_TX)
265 {
266 g_mss_usbd_cb.usbd_cep_tx_complete(status);
267 }
268 else if (cep_state == MSS_USB_CTRL_EP_RX)
269 {
270 if (MSS_USB_CIF_cep_is_rxpktrdy())
271 {
272 g_mss_usbd_cb.usbd_cep_rx(status);
273 }
274 }
275 else
276 {
277 ASSERT(0);
278 }
279 }
280 }
281 }
282 #endif /* MSS_USB_DEVICE_ENABLED */
283
284 #ifdef MSS_USB_HOST_ENABLED
285 if (MSS_USB_CORE_MODE_HOST == MSS_USB_CIF_get_mode())
286 {
287 if (MSS_USBH_CIF_cep_is_rxstall_err())
288 {
289 status |= MSS_USB_EP_STALL_RCVD;
290 MSS_USBH_CIF_cep_clr_rxstall_err();
291 }
292 if (MSS_USBH_CIF_cep_is_retry_err())
293 {
294 status |= MSS_USB_EP_NO_RESPONSE;
295 MSS_USBH_CIF_cep_clr_retry_err();
296 }
297 if (MSS_USBH_CIF_cep_is_naktimeout_err())
298 {
299 status |= MSS_USB_EP_NAK_TOUT;
300 MSS_USBH_CIF_cep_clr_naktimeout_err();
301 }
302 if (status == 0u) /* No error was found */
303 {
304 status = MSS_USB_EP_TXN_SUCCESS;
305 }
306 g_mss_usbh_cb.usbh_cep(status);
307 }
308 #endif /* MSS_USB_HOST_ENABLED */
309
310 }
311
312 /***************************************************************************//**
313 * Routine to handle the interrupt on TX_EP
314 */
MSS_USB_CIF_handle_tx_ep_irq(uint16_t irq_num)315 static void MSS_USB_CIF_handle_tx_ep_irq
316 (
317 uint16_t irq_num
318 )
319 {
320 mss_usb_ep_num_t ep_num = MSS_USB_TX_EP_1;
321 uint8_t status = 0u;
322
323 while (irq_num)
324 {
325 irq_num >>= 1u; /*EP1 starts from D1*/
326
327 if (irq_num & MSS_USB_WORD_BIT_0_MASK)
328 {
329 MSS_USB_CIF_tx_ep_disable_irq(ep_num);
330 #ifdef MSS_USB_DEVICE_ENABLED
331 if (MSS_USB_CORE_MODE_DEVICE == MSS_USB_CIF_get_mode())
332 {
333 status = MSS_USB_CIF_device_tx_errchk(ep_num);
334 g_mss_usbd_cb.usbd_ep_tx_complete(ep_num,status);
335 }
336 #endif /* MSS_USB_DEVICE_ENABLED */
337
338 #ifdef MSS_USB_HOST_ENABLED
339 if (MSS_USB_CORE_MODE_HOST == MSS_USB_CIF_get_mode())
340 {
341 status = MSS_USB_CIF_host_tx_errchk(ep_num);
342 g_mss_usbh_cb.usbh_tx_complete((uint8_t)ep_num, status);
343 }
344 #endif /* MSS_USB_HOST_ENABLED */
345
346 MSS_USB_CIF_tx_ep_enable_irq(ep_num);
347 }
348 status = 0u; /*resetting for next EP status*/
349 ++ep_num;
350 }
351 }
352
353 /***************************************************************************//**
354 * Routine to handle the interrupt on RX EP
355 */
MSS_USB_CIF_handle_rx_ep_irq(uint16_t irq_num)356 static void MSS_USB_CIF_handle_rx_ep_irq
357 (
358 uint16_t irq_num
359 )
360 {
361 mss_usb_ep_num_t ep_num = MSS_USB_RX_EP_1;
362 uint8_t status = 0u;
363
364 while (irq_num)
365 {
366 irq_num >>= 1u; /*EP1 starts from D1*/
367
368 if (irq_num & MSS_USB_WORD_BIT_0_MASK)
369 {
370 MSS_USB_CIF_rx_ep_disable_irq(ep_num);
371 #ifdef MSS_USB_DEVICE_ENABLED
372 if (MSS_USB_CORE_MODE_DEVICE == MSS_USB_CIF_get_mode())
373 {
374 status = MSS_USB_CIF_device_rx_errchk(ep_num);
375 g_mss_usbd_cb.usbd_ep_rx(ep_num, status);
376 }
377 #endif /* MSS_USB_DEVICE_ENABLED */
378
379 #ifdef MSS_USB_HOST_ENABLED
380 if (MSS_USB_CORE_MODE_HOST == MSS_USB_CIF_get_mode())
381 {
382 status = MSS_USB_CIF_host_rx_errchk(ep_num);
383 g_mss_usbh_cb.usbh_rx((uint8_t)ep_num, status);
384 }
385 #endif /* MSS_USB_HOST_ENABLED */
386 MSS_USB_CIF_rx_ep_enable_irq(ep_num);
387 }
388 status = 0u; /*resetting for next EP status*/
389 ++ep_num;
390 }
391 }
392
393 /***************************************************************************//**
394 * Handler for DMA interrupt. Checks for the DMA channel on which interrupt has
395 * Occurred and corresponding EP number then calls-back to upper layer to indicate
396 * the event.
397 */
usb_dma_plic_IRQHandler(void)398 uint8_t usb_dma_plic_IRQHandler(void)
399 {
400 mss_usb_dma_channel_t dma_channel= MSS_USB_DMA_CHANNEL1;
401 uint8_t status = 0;
402 mss_usb_dma_dir_t dma_dir;
403 mss_usb_ep_num_t ep_num;
404 uint8_t dma_irq;
405 uint32_t increamented_addr=0;
406
407 dma_irq = MSS_USB_CIF_dma_read_irq();
408
409 while (dma_irq)
410 {
411 if (dma_irq & MSS_USB_BYTE_BIT_0_MASK)
412 {
413 /* DMA Transfer for this channel is complete.Clear Start_transfer
414 bit
415 */
416 MSS_USB_CIF_dma_stop_xfr(dma_channel);
417
418 ep_num = (mss_usb_ep_num_t)MSS_USB_CIF_dma_get_epnum(dma_channel);
419 dma_dir = (mss_usb_dma_dir_t)MSS_USB_CIF_dma_get_dir(dma_channel);
420
421 if (MSS_USB_CIF_dma_is_bus_err(dma_channel))
422 {
423 status |=DMA_XFR_ERROR;
424 MSS_USB_CIF_dma_clr_bus_err(dma_channel);
425 }
426 else
427 {
428 increamented_addr = MSS_USB_CIF_dma_read_addr(dma_channel);
429 if (MSS_USB_DMA_READ == dma_dir) /*TX EP*/
430 {
431 if (MSS_USB_CIF_tx_ep_is_dma_enabled(ep_num))
432 {
433 MSS_USB_CIF_tx_ep_disable_dma(ep_num);
434 }
435 }
436 #ifdef MSS_USB_HOST_ENABLED
437 if (MSS_USB_CORE_MODE_HOST == MSS_USB_CIF_get_mode())
438 {
439 /* Call the host mode logical layer driver callback
440 function
441 */
442 g_mss_usbh_cb.usbh_dma_handler(ep_num, dma_dir, status,
443 increamented_addr);
444 }
445 #endif /* MSS_USB_HOST_ENABLED */
446 #ifdef MSS_USB_DEVICE_ENABLED
447 if (MSS_USB_CORE_MODE_DEVICE == MSS_USB_CIF_get_mode())
448 {
449 /* Call the device mode logical layer driver callback
450 function
451 */
452 g_mss_usbd_cb.usbd_dma_handler(ep_num, dma_dir, status,
453 increamented_addr);
454 }
455 #endif /* MSS_USB_DEVICE_ENABLED */
456
457 }
458 }
459 dma_channel++;
460 dma_irq >>= 1u;
461 }
462
463 return EXT_IRQ_KEEP_ENABLED;
464 }
465
466 /***************************************************************************//**
467 * Prepares the RX EP for receiving data as per parameters provided by upper layer
468 */
469 void
MSS_USB_CIF_rx_ep_read_prepare(mss_usb_ep_num_t ep_num,uint8_t * buf_addr,uint8_t dma_enable,mss_usb_dma_channel_t dma_channel,mss_usb_xfr_type_t xfr_type,uint32_t xfr_length)470 MSS_USB_CIF_rx_ep_read_prepare
471 (
472 mss_usb_ep_num_t ep_num,
473 uint8_t* buf_addr,
474 uint8_t dma_enable,
475 mss_usb_dma_channel_t dma_channel,
476 mss_usb_xfr_type_t xfr_type,
477 uint32_t xfr_length
478 )
479 {
480 /*
481 * Fixed Buffer overwriting issue found with printer driver and issue with
482 * interrupt transfer with DMA by moving the location of interrupt enable
483 * function.
484 */
485 if (DMA_ENABLE == dma_enable)
486 {
487 /* Make sure that address is Modulo-4.Bits D0-D1 are read only.*/
488 ASSERT(!(((uint32_t)buf_addr) & 0x00000002U));
489
490 MSS_USB_CIF_dma_write_addr(dma_channel, (uint32_t)buf_addr);
491
492 /*
493 * DMA Count register will be loaded after receive interrupt occurs.
494 * Mode need to be set every time since M1 to M0 transition might have
495 * happened for "short packet".
496 */
497 if (MSS_USB_XFR_BULK == xfr_type)
498 {
499 MSS_USB_CIF_rx_ep_set_dma_mode1(ep_num);
500 MSS_USB_CIF_rx_ep_set_autoclr(ep_num);
501 MSS_USB_CIF_rx_ep_enable_dma(ep_num);
502
503 MSS_USB_CIF_dma_write_count(dma_channel,
504 xfr_length);
505
506 /* Handling single NULL packet reception */
507 if (0u != xfr_length )
508 {
509 MSS_USB_CIF_dma_start_xfr(dma_channel);
510 }
511 }
512 else
513 {
514 MSS_USB_CIF_rx_ep_clr_autoclr(ep_num);
515 MSS_USB_CIF_rx_ep_set_dma_mode0(ep_num);
516 MSS_USB_CIF_rx_ep_disable_dma(ep_num);
517 }
518 }
519 }
520
521 /***************************************************************************//**
522 * Writes packet on TX EP
523 */
524 void
MSS_USB_CIF_ep_write_pkt(mss_usb_ep_num_t ep_num,uint8_t * buf_addr,uint8_t dma_enable,mss_usb_dma_channel_t dma_channel,mss_usb_xfr_type_t xfr_type,uint32_t xfr_length,uint32_t txn_length)525 MSS_USB_CIF_ep_write_pkt
526 (
527 mss_usb_ep_num_t ep_num,
528 uint8_t* buf_addr,
529 uint8_t dma_enable,
530 mss_usb_dma_channel_t dma_channel,
531 mss_usb_xfr_type_t xfr_type,
532 uint32_t xfr_length,
533 uint32_t txn_length
534 )
535 {
536 if (ep_num && (buf_addr != 0))
537 {
538 if (DMA_ENABLE == dma_enable)
539 {
540 /* Make sure that address is Modulo-4.Bits D0-D1 are read only.*/
541 ASSERT(!(((uint32_t)buf_addr) & 0x00000002u));
542
543 MSS_USB_CIF_dma_write_addr(dma_channel,(uint32_t)(buf_addr));
544
545 if (MSS_USB_XFR_BULK == xfr_type)
546 {
547 MSS_USB_CIF_tx_ep_enable_dma(ep_num);
548
549 /*
550 * DMA-m1 will take care of transferring 'xfr_length' data
551 * as IN packets arrive.
552 * DMA interrupt will occur when all TxMaxPkt size packets
553 * are transferred.
554 */
555 MSS_USB_CIF_dma_write_count(dma_channel, xfr_length);
556 }
557 else
558 {
559 /*
560 * DMA Enable bit in TxCSR is not needed. If set,TX EP
561 * Interrupt will not occur.
562 */
563 MSS_USB_CIF_tx_ep_disable_dma(ep_num);
564
565 /* Transfer only one packet with DMA-m0 */
566 MSS_USB_CIF_dma_write_count(dma_channel, txn_length);
567 }
568
569 /*
570 * This will start DMA transfer.
571 * TODO: For Null transfer DMA is not needed, but not setting
572 * TxPktRdy bit here, is not invoking EP interrupt.
573 * EP interrupt does get called when Null DMA transfer is done.
574 */
575 MSS_USB_CIF_dma_start_xfr(dma_channel);
576
577
578 /*
579 * DMA interrupt will occur when all bytes are written to FIFO
580 * TxPktRdy should be set when the DMA interrupt occurs.
581 */
582 }
583 else /* no DMA */
584 {
585 MSS_USB_CIF_load_tx_fifo(ep_num,
586 buf_addr,
587 txn_length);
588 MSS_USB_CIF_tx_ep_set_txpktrdy(ep_num);
589 }
590 }
591 }
592
593 /***************************************************************************//**
594 * Configures DMA for data transfer operations.
595 */
596 void
MSS_USB_CIF_configure_ep_dma(mss_usb_dma_channel_t dma_channel,mss_usb_dma_dir_t dma_dir,mss_usb_dma_mode_t dma_mode,mss_usb_dma_burst_mode_t burst_mode,mss_usb_ep_num_t ep_num,uint32_t buf_addr)597 MSS_USB_CIF_configure_ep_dma
598 (
599 mss_usb_dma_channel_t dma_channel,
600 mss_usb_dma_dir_t dma_dir,
601 mss_usb_dma_mode_t dma_mode,
602 mss_usb_dma_burst_mode_t burst_mode,
603 mss_usb_ep_num_t ep_num,
604 uint32_t buf_addr
605 )
606 {
607 MSS_USB_CIF_dma_assign_to_epnum(dma_channel, ep_num);
608 MSS_USB_CIF_dma_set_dir(dma_channel, dma_dir);
609 MSS_USB_CIF_dma_set_mode(dma_channel, dma_mode);
610 MSS_USB_CIF_dma_set_burst_mode(dma_channel, burst_mode);
611 MSS_USB_CIF_dma_write_addr(dma_channel, buf_addr);
612 MSS_USB_CIF_dma_enable_irq(dma_channel);
613 }
614
615 /***************************************************************************//**
616 * Configures the TX EP for data transfer operations as per the parameters
617 * provided by upper layer.
618 */
619 void
MSS_USB_CIF_tx_ep_configure(mss_usb_ep_t * core_ep)620 MSS_USB_CIF_tx_ep_configure
621
622 (
623 mss_usb_ep_t* core_ep
624 )
625 {
626 uint8_t dpb = 1u;
627 mss_usb_dma_mode_t mode;
628
629 if (DPB_ENABLE == core_ep->dpb_enable)
630 {
631 dpb = 2u;
632 }
633
634 MSS_USB_CIF_tx_ep_set_fifo_size(core_ep->num,
635 ((core_ep->fifo_size) / dpb),
636 core_ep->dpb_enable);
637
638 MSS_USB_CIF_tx_ep_set_fifo_addr(core_ep->num, core_ep->fifo_addr);
639
640 if (DPB_ENABLE == core_ep->dpb_enable)
641 {
642 MSS_USB_enable_tx_ep_dpb(core_ep->num);
643 }
644 else if (DPB_DISABLE == core_ep->dpb_enable)
645 {
646 MSS_USB_disable_tx_ep_dpb(core_ep->num);
647 }
648 else
649 {
650 ASSERT(0);
651 }
652
653 MSS_USB_CIF_tx_ep_set_max_pkt(core_ep->num,
654 core_ep->xfr_type,
655 core_ep->max_pkt_size,
656 core_ep->num_usb_pkt);
657
658 MSS_USB_CIF_tx_ep_clr_data_tog(core_ep->num);
659
660 if (DMA_ENABLE == core_ep->dma_enable)
661 {
662 if (MSS_USB_XFR_BULK == core_ep->xfr_type )
663 {
664 MSS_USB_CIF_tx_ep_set_dma_mode1(core_ep->num);
665 MSS_USB_CIF_tx_ep_enable_dma(core_ep->num);
666 mode = MSS_USB_DMA_MODE1;
667 }
668 else
669 {
670 /*
671 * DMA_ENable bit in TXCSRL is not required to be set for m0. if it
672 * is set TX interrupt would not occur.
673 */
674 MSS_USB_CIF_tx_ep_set_dma_mode0(core_ep->num);
675 MSS_USB_CIF_tx_ep_disable_dma(core_ep->num);
676 mode = MSS_USB_DMA_MODE0;
677 }
678
679 MSS_USB_CIF_configure_ep_dma(core_ep->dma_channel,
680 MSS_USB_DMA_READ,
681 mode,
682 MSS_USB_DMA_BURST_MODE3,
683 core_ep->num,
684 (uint32_t)(core_ep->buf_addr));
685 }
686
687 MSS_USB_CIF_tx_ep_enable_irq(core_ep->num);
688 }
689
690 /***************************************************************************//**
691 * Configures the RX EP for data transfer operations as per the parameters
692 * provided by upper layer.
693 */
694 void
MSS_USB_CIF_rx_ep_configure(mss_usb_ep_t * core_ep)695 MSS_USB_CIF_rx_ep_configure
696
697 (
698 mss_usb_ep_t* core_ep
699 )
700 {
701 uint8_t dpb = 1u;
702 mss_usb_dma_mode_t mode;
703
704 if (DPB_ENABLE == core_ep->dpb_enable)
705 {
706 dpb = 2u;
707 }
708
709 MSS_USB_CIF_rx_ep_set_fifo_size(core_ep->num,
710 ((core_ep->fifo_size) / dpb),
711 core_ep->dpb_enable);
712
713 MSS_USB_CIF_rx_ep_set_fifo_addr(core_ep->num,
714 core_ep->fifo_addr);
715
716 if (DPB_ENABLE == core_ep->dpb_enable)
717 {
718 MSS_USB_CIF_enable_rx_ep_dpb(core_ep->num);
719 }
720 else if (DPB_DISABLE == core_ep->dpb_enable)
721 {
722 MSS_USB_CIF_disable_rx_ep_dpb(core_ep->num);
723 }
724 else
725 {
726 ASSERT(0);
727 }
728
729 MSS_USB_CIF_rx_ep_set_max_pkt(core_ep->num,
730 core_ep->xfr_type,
731 core_ep->max_pkt_size,
732 core_ep->num_usb_pkt);
733
734 MSS_USB_CIF_rx_ep_clr_data_tog(core_ep->num);
735 MSS_USB_CIF_rx_ep_clr_rxpktrdy(core_ep->num);
736
737 if (DMA_ENABLE == core_ep->dma_enable)
738 {
739 if (MSS_USB_XFR_BULK == core_ep->xfr_type)
740 {
741 MSS_USB_CIF_rx_ep_set_dma_mode1(core_ep->num);
742 MSS_USB_CIF_rx_ep_enable_dma(core_ep->num);
743 mode = MSS_USB_DMA_MODE1;
744 }
745 else
746 {
747 /*
748 * DMA_ENable bit in RXCSRL is not required to be set in m0. if it is
749 * set RX interrupt would not occur.
750 */
751 MSS_USB_CIF_rx_ep_set_dma_mode0(core_ep->num);
752 MSS_USB_CIF_rx_ep_disable_dma(core_ep->num);
753 mode = MSS_USB_DMA_MODE0;
754 }
755
756 MSS_USB_CIF_configure_ep_dma(core_ep->dma_channel,
757 MSS_USB_DMA_WRITE,
758 mode,
759 MSS_USB_DMA_BURST_MODE3,
760 core_ep->num,
761 (uint32_t)(core_ep->buf_addr));
762 }
763
764 MSS_USB_CIF_rx_ep_enable_irq(core_ep->num);
765 }
766
767 /***************************************************************************//**
768 * Starts sending Test packet as specified in the USB2.0
769 * This is USB-IF certification requirement.
770 */
MSS_USB_CIF_start_testpacket(void)771 void MSS_USB_CIF_start_testpacket(void)
772 {
773 uint8_t test_pkt[53] =
774 {
775 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
776 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xAAU, 0xEEU,
777 0xEEU, 0xEEU, 0xEEU, 0xEEU, 0xEEU, 0xEEU, 0xEEU, 0xFEU, 0xFFU,
778 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU,
779 0xFFU, 0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFCU,
780 0x7EU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0x7EU
781 };
782 MSS_USB_CIF_load_tx_fifo(MSS_USB_CEP, test_pkt, 53u);
783 MSS_USB_CIF_start_testpacket_bit();
784 MSS_USB_CIF_cep_set_txpktrdy();
785 MSS_USB_CIF_cep_disable_irq();
786 }
787
788 #ifdef MSS_USB_HOST_ENABLED
MSS_USB_CIF_host_rx_errchk(mss_usb_ep_num_t ep_num)789 static uint8_t MSS_USB_CIF_host_rx_errchk(mss_usb_ep_num_t ep_num)
790 {
791 uint8_t status = 0u;
792
793 if (MSS_USBH_CIF_rx_ep_is_rxpktrdy(ep_num))
794 {
795 status = 0u;
796 }
797 if (MSS_USBH_CIF_rx_ep_is_rxstall_err(ep_num))
798 {
799 status |= MSS_USB_EP_STALL_RCVD;
800 MSS_USBH_CIF_rx_ep_clr_rxstall_err(ep_num);
801 }
802 if (MSS_USBH_CIF_rx_ep_is_naktimeout_err(ep_num))
803 {
804 status |= MSS_USB_EP_NAK_TOUT;
805 /* Not clearing NAKTIMEOUT error here. Application may want to abort
806 * transfer. Clearing it here makes Scheduler keep trying the transfer
807 */
808 }
809 if (MSS_USBH_CIF_rx_ep_is_retry_err(ep_num))
810 {
811 status |= MSS_USB_EP_NO_RESPONSE;
812 MSS_USBH_CIF_rx_ep_clr_retry_err(ep_num);
813 }
814
815 return (status);
816 }
817
MSS_USB_CIF_host_tx_errchk(mss_usb_ep_num_t ep_num)818 static uint8_t MSS_USB_CIF_host_tx_errchk(mss_usb_ep_num_t ep_num)
819 {
820 uint8_t status = 0;
821
822 if (MSS_USBH_CIF_tx_ep_is_retry_err(ep_num))
823 {
824 status |= MSS_USB_EP_NO_RESPONSE;
825 MSS_USBH_CIF_tx_ep_clr_retry_err(ep_num);
826 }
827 if (MSS_USBH_CIF_tx_ep_is_rxstall_err(ep_num))
828 {
829 status |= MSS_USB_EP_STALL_RCVD;
830 MSS_USBH_CIF_tx_ep_clr_rxstall_err(ep_num);
831 }
832 if (MSS_USBH_CIF_tx_ep_is_naktimeout_err(ep_num))
833 {
834 status |= MSS_USB_EP_NAK_TOUT;
835 /* Not clearing NAKTIMEOUT error here. Application may want to abort
836 * transfer. Clearing it here makes Scheduler keep trying the transfer
837 */
838 }
839
840 return(status);
841 }
842 #endif /* MSS_USB_HOST_ENABLED */
843
844 #ifdef MSS_USB_DEVICE_ENABLED
MSS_USB_CIF_device_rx_errchk(mss_usb_ep_num_t ep_num)845 static uint8_t MSS_USB_CIF_device_rx_errchk(mss_usb_ep_num_t ep_num)
846 {
847 uint8_t status = 0u;
848
849 if (MSS_USB_CIF_rx_ep_is_overrun(ep_num))
850 {
851 status |= RX_EP_OVER_RUN_ERROR;
852 MSS_USB_CIF_rx_ep_clr_overrun(ep_num);
853 }
854 if (MSS_USB_CIF_rx_ep_is_stall_sent_bit(ep_num))
855 {
856 status |= RX_EP_STALL_ERROR;
857 /*
858 * "sent stall" bit should be cleared."Send Stall" bit is still set.
859 * it should be cleared via Clear feature command or reset"
860 */
861 MSS_USB_CIF_rx_ep_clr_stall_sent_bit(ep_num);
862 }
863 if (MSS_USB_CIF_rx_ep_is_dataerr(ep_num))
864 {
865 /* This error will be cleared when RxPktRdy bit is cleared.
866 */
867 status |= RX_EP_DATA_ERROR;
868
869 }
870 #if 0
871 /*
872 * PID error and INCOMP error should be checked only in ISO transfers.
873 * This should be moved to logical layer
874 */
875 if (MSS_USB_CIF_rx_ep_is_piderr(ep_num))
876 {
877 status |= RX_EP_PID_ERROR;
878 /* Data sheet doesn't mention about how this error bit is cleared
879 * Assuming that this will be cleared when RxPKTRdy is cleared.*/
880 }
881 if (MSS_USB_CIF_rx_ep_is_isoincomp(ep_num))
882 {
883 status |= RX_EP_ISO_INCOMP_ERROR;
884 /* This error will be cleared when RxPktRdy bit is cleared.*/
885 }
886 #endif /* if 0 */
887
888 return(status);
889 }
890
MSS_USB_CIF_device_tx_errchk(mss_usb_ep_num_t ep_num)891 static uint8_t MSS_USB_CIF_device_tx_errchk(mss_usb_ep_num_t ep_num)
892 {
893 uint8_t status = 0u;
894
895 if (MSS_USB_CIF_tx_ep_is_underrun(ep_num))
896 {
897 /* Under-run errors should happen only for ISO endpoints.*/
898 status |= TX_EP_UNDER_RUN_ERROR;
899 MSS_USB_CIF_tx_ep_clr_underrun(ep_num);
900 }
901 if (MSS_USB_CIF_tx_ep_is_stall_sent_bit(ep_num))
902 {
903 status |= TX_EP_STALL_ERROR;
904 MSS_USB_CIF_tx_ep_clr_stall_sent_bit(ep_num);
905 }
906
907 return(status);
908 }
909 #endif /* MSS_USB_DEVICE_ENABLED */
910
911 #ifdef __cplusplus
912 }
913 #endif
914