1 /*
2 * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3 * Copyright 2016 - 2017, 2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "usb_host_config.h"
10 #if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI))
11 #include "usb_host.h"
12 #include "usb_host_hci.h"
13 #include "fsl_device_registers.h"
14 #include "usb_host_khci.h"
15 #include "usb_host_devices.h"
16 #include "usb_host_framework.h"
17 /*******************************************************************************
18 * Variables
19 ******************************************************************************/
20 #if defined(USB_STACK_USE_DEDICATED_RAM) && (USB_STACK_USE_DEDICATED_RAM > 0U)
21
22 /* USB_STACK_USE_DEDICATED_RAM */
23 #if defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
24
25 #if (USB_STACK_USE_DEDICATED_RAM == USB_STACK_DEDICATED_RAM_TYPE_BDT_GLOBAL)
26 #if (FSL_FEATURE_USB_KHCI_USB_RAM > 512U)
27 #else
28 #error The dedicated RAM length is not more than 512 Bytes, the SOC does not support this case.
29 #endif
30 #endif /* USB_STACK_USE_DEDICATED_RAM */
31
32 #else
33 #error The SOC does not suppoort dedicated RAM case.
34 #endif /* USB_STACK_USE_DEDICATED_RAM */
35
36 #endif
37 /*for misra 11.3 11.6*/
38 USB_CONTROLLER_DATA USB_RAM_ADDRESS_ALIGNMENT(512) static uint32_t bdt[512U / sizeof(uint32_t)];
39
40 /*******************************************************************************
41 * Code
42 ******************************************************************************/
43 /*!
44 * @brief get the 2 power value of uint32_t.
45 *
46 * @param data input uint32_t value.
47 *
48 */
_USB_HostKhciGetRoundUpPow2(uint32_t data)49 static uint32_t _USB_HostKhciGetRoundUpPow2(uint32_t data)
50 {
51 uint8_t i = 0U;
52
53 if ((data == 1U) || (data == 0U))
54 {
55 return data;
56 }
57 while (data != 1U)
58 {
59 data = data >> 1U;
60 i++;
61 }
62 return 1UL << (i);
63 }
64
65 /*!
66 * @brief get the current host khci frame number count.
67 *
68 * @param handle Pointer of the host KHCI state structure.
69 *
70 * @return current frame number count.
71 */
_USB_HostKhciGetFrameCount(usb_host_controller_handle handle)72 static uint16_t _USB_HostKhciGetFrameCount(usb_host_controller_handle handle)
73 {
74 uint16_t tempFrameCount;
75 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
76
77 tempFrameCount = usbHostPointer->usbRegBase->FRMNUMH;
78
79 return ((tempFrameCount << 8U) | (usbHostPointer->usbRegBase->FRMNUML));
80 }
81
82 /*!
83 * @brief get the total of host khci frame number count.
84 *
85 * @param usbHostPointer Pointer of the host KHCI state structure.
86 *
87 * @return total of frame number count.
88 */
_USB_HostKhciGetFrameCountSum(usb_khci_host_state_struct_t * usbHostPointer)89 static uint32_t _USB_HostKhciGetFrameCountSum(usb_khci_host_state_struct_t *usbHostPointer)
90 {
91 static uint32_t totalFrameNumber = 0U;
92 static uint16_t oldFrameNumber = 0U;
93 uint16_t frameNumber = 0U;
94
95 frameNumber = _USB_HostKhciGetFrameCount((usb_host_controller_handle)usbHostPointer);
96
97 if (frameNumber < oldFrameNumber)
98 {
99 totalFrameNumber += 2048U;
100 }
101
102 oldFrameNumber = frameNumber;
103
104 return (frameNumber + totalFrameNumber);
105 }
106
107 /*!
108 * @brief host khci delay.
109 *
110 * @param usbHostPointer Pointer of the host KHCI state structure.
111 * @param ms milliseconds.
112 *
113 */
_USB_HostKhciDelay(usb_khci_host_state_struct_t * usbHostPointer,uint32_t ms)114 static void _USB_HostKhciDelay(usb_khci_host_state_struct_t *usbHostPointer, uint32_t ms)
115 {
116 uint32_t sofStart;
117 uint32_t sofEnd;
118 sofStart = _USB_HostKhciGetFrameCountSum(usbHostPointer);
119
120 do
121 {
122 sofEnd = _USB_HostKhciGetFrameCountSum(usbHostPointer);
123 } while ((sofEnd - sofStart) < ms);
124 }
125
126 /*!
127 * @brief Device KHCI isr function.
128 *
129 * The function is KHCI interrupt service routine.
130 *
131 * @param hostHandle The host handle.
132 */
USB_HostKhciIsrFunction(void * hostHandle)133 void USB_HostKhciIsrFunction(void *hostHandle)
134 {
135 usb_khci_host_state_struct_t *usbHostPointer;
136
137 uint8_t status;
138
139 if (hostHandle == NULL)
140 {
141 return;
142 }
143
144 usbHostPointer = (usb_khci_host_state_struct_t *)((usb_host_instance_t *)hostHandle)->controllerHandle;
145
146 while (1U == 1U)
147 {
148 status = (uint8_t)((usbHostPointer->usbRegBase->ISTAT));
149 status &= (uint8_t)(usbHostPointer->usbRegBase->INTEN);
150
151 if (0U == status)
152 {
153 break;
154 }
155
156 usbHostPointer->usbRegBase->ISTAT = status;
157
158 if (0U != (status & USB_ISTAT_SOFTOK_MASK))
159 {
160 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_SOF_TOK);
161 }
162
163 if (0U != (status & USB_ISTAT_ATTACH_MASK))
164 {
165 usbHostPointer->usbRegBase->INTEN &= (uint8_t)(~USB_INTEN_ATTACHEN_MASK);
166 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_ATTACH);
167 }
168
169 if (0U != (status & USB_ISTAT_TOKDNE_MASK))
170 {
171 /* atom transaction done - token done */
172 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_TOK_DONE);
173 }
174
175 if (0U != (status & USB_ISTAT_USBRST_MASK))
176 {
177 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
178 usbHostPointer->usbRegBase->USBTRC0 &= (uint8_t)(~USB_USBTRC0_USBRESMEN_MASK);
179 #endif
180 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_RESET);
181 }
182
183 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
184 if (0U != (status & USB_ISTAT_RESUME_MASK))
185 {
186 usb_host_instance_t *hostPointer = (usb_host_instance_t *)hostHandle;
187 usbHostPointer->usbRegBase->INTEN &= (uint8_t)(~USB_INTEN_RESUMEEN_MASK);
188 usbHostPointer->usbRegBase->USBTRC0 &= (uint8_t)(~USB_USBTRC0_USBRESMEN_MASK);
189
190 if (0 == usbHostPointer->deviceAttached)
191 {
192 usbHostPointer->busSuspendStatus = kBus_Idle;
193 }
194 else
195 {
196 (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
197 kUSB_HostEventDetectResume); /* call host callback function */
198 usbHostPointer->busSuspendStatus = kBus_StartResume;
199
200 /* Do USB bus resume here */
201 usbHostPointer->usbRegBase->CTL |= USB_CTL_RESUME_MASK;
202
203 usbHostPointer->matchTick = hostPointer->hwTick;
204
205 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_RESUME);
206 }
207 }
208 #endif
209 }
210 }
211
212 /*!
213 * @brief Handle khci host controller attach event.
214 *
215 * The function is used to handle attach event when a device is attached to khci host controller, the process is detect
216 * the line state, do bus reset, and call device attached function.
217 *
218 * @param usbHostPointer Pointer of the host KHCI state structure.
219 *
220 */
_USB_HostKhciAttach(usb_khci_host_state_struct_t * usbHostPointer)221 static void _USB_HostKhciAttach(usb_khci_host_state_struct_t *usbHostPointer)
222 {
223 uint8_t speed;
224 uint8_t temp;
225 usb_device_handle deviceHandle;
226 uint8_t index = 0U;
227
228 usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
229 usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
230 usbHostPointer->usbRegBase->ADDR = (uint8_t)(((usbHostPointer->usbRegBase->ADDR & (~USB_ADDR_ADDR_MASK)) |
231 ((((0U) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK))));
232 usbHostPointer->usbRegBase->ADDR &= (uint8_t)(~USB_ADDR_LSEN_MASK);
233
234 /* here wait for about 120ms to check line state */
235 for (uint32_t i = 0U; i < 2000000U; i++)
236 {
237 __NOP();
238 }
239
240 do
241 {
242 temp = (0U != ((usbHostPointer->usbRegBase->CTL) & USB_CTL_JSTATE_MASK)) ? 0U : 1U;
243 for (uint32_t j = 0U; j < 100000U; j++)
244 {
245 __NOP();
246 }
247 speed = (0U != ((usbHostPointer->usbRegBase->CTL) & USB_CTL_JSTATE_MASK)) ? 0U : 1U;
248 index++;
249 } while ((temp != speed) && (index < USB_KHCI_MAX_SPEED_DETECTION_COUNT));
250
251 if (temp != speed)
252 {
253 #ifdef HOST_ECHO
254 usb_echo("speed not match!\n");
255 #endif
256 usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
257 return;
258 }
259 if (((usbHostPointer->usbRegBase->CTL) & USB_CTL_SE0_MASK) == USB_CTL_SE0_MASK)
260 {
261 usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
262 return;
263 }
264
265 if (speed == USB_SPEED_FULL)
266 {
267 usbHostPointer->usbRegBase->ADDR &= (uint8_t)(~USB_ADDR_LSEN_MASK);
268 }
269 else if (speed == USB_SPEED_LOW)
270 {
271 usbHostPointer->usbRegBase->ENDPOINT[0U].ENDPT = USB_ENDPT_HOSTWOHUB_MASK;
272 usbHostPointer->usbRegBase->ADDR |= USB_ADDR_LSEN_MASK;
273 }
274 else
275 {
276 /*no action*/
277 }
278
279 usbHostPointer->usbRegBase->ISTAT = 0xffU;
280 usbHostPointer->usbRegBase->INTEN &= (uint8_t)(~(USB_INTEN_TOKDNEEN_MASK | USB_INTEN_USBRSTEN_MASK));
281
282 /* Do USB bus reset here */
283 usbHostPointer->usbRegBase->CTL |= USB_CTL_RESET_MASK;
284 /* here wait for about at least 30ms to reset device */
285 for (uint32_t k = 0U; k < 500000U; k++)
286 {
287 __NOP();
288 }
289 usbHostPointer->usbRegBase->CTL &= (uint8_t)(~USB_CTL_RESET_MASK);
290
291 usbHostPointer->usbRegBase->CTL |= USB_CTL_USBENSOFEN_MASK;
292 #ifdef USBCFG_OTG
293 _USB_HostKhciDelay(usbHostPointer, 30U);
294 #else
295 _USB_HostKhciDelay(usbHostPointer, 100U);
296 #endif
297 usbHostPointer->usbRegBase->CONTROL &= (uint8_t)(~USB_CONTROL_DPPULLUPNONOTG_MASK);
298 usbHostPointer->usbRegBase->INTEN |= (USB_INTEN_TOKDNEEN_MASK | USB_INTEN_USBRSTEN_MASK);
299 usbHostPointer->deviceAttached++;
300 (void)OSA_EventClear(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_TOK_DONE);
301 (void)USB_HostAttachDevice(usbHostPointer->hostHandle, speed, 0U, 0U, 1U, &deviceHandle);
302
303 usbHostPointer->txBd = 0U;
304 usbHostPointer->rxBd = 0U;
305 }
306
307 /*!
308 * @brief Handle khci host controller bus reset event.
309 *
310 * The function is used to handle khci host controller bus reset event, reset event also is used for khci detached
311 * detecction.
312 *
313 * @param usbHostPointer Pointer of the host KHCI state structure.
314 *
315 */
_USB_HostKhciReset(usb_khci_host_state_struct_t * usbHostPointer)316 static void _USB_HostKhciReset(usb_khci_host_state_struct_t *usbHostPointer)
317 {
318 volatile uint32_t i = 0xfffU;
319
320 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
321 usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostPointer->hostHandle;
322
323 usbHostPointer->usbRegBase->INTEN &= (uint8_t)(~USB_INTEN_RESUMEEN_MASK);
324 usbHostPointer->usbRegBase->USBTRC0 &= (uint8_t)(~USB_USBTRC0_USBRESMEN_MASK);
325 usbHostPointer->usbRegBase->CTL |= USB_CTL_USBENSOFEN_MASK;
326 if (kBus_Suspended == usbHostPointer->busSuspendStatus)
327 {
328 (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
329 kUSB_HostEventResumed); /* call host callback function */
330 }
331 usbHostPointer->busSuspendStatus = kBus_Idle;
332 #endif
333
334 /* clear attach flag */
335 usbHostPointer->usbRegBase->ISTAT = USB_ISTAT_ATTACH_MASK;
336 while (0U != i)
337 {
338 i--;
339 __NOP();
340 }
341 /* Test the presence of USB device */
342 if (0U != ((usbHostPointer->usbRegBase->ISTAT) & USB_ISTAT_ATTACH_MASK))
343 {
344 /* device attached, so really normal reset was performed */
345 usbHostPointer->usbRegBase->INTEN |= USB_ISTAT_USBRST_MASK;
346 usbHostPointer->usbRegBase->ADDR = (uint8_t)((usbHostPointer->usbRegBase->ADDR & (~USB_ADDR_ADDR_MASK)) |
347 ((((0U) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK)));
348 usbHostPointer->usbRegBase->ENDPOINT[0U].ENDPT |= USB_ENDPT_HOSTWOHUB_MASK;
349 }
350 else
351 {
352 /* device was detached,, notify about detach */
353 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_DETACH);
354 }
355 }
356
357 /*!
358 * @brief Handle khci host controller bus detach event.
359 *
360 * @param usbHostPointer Pointer of the host KHCI state structure.
361 *
362 */
_USB_HostKhciDetach(usb_khci_host_state_struct_t * usbHostPointer)363 static void _USB_HostKhciDetach(usb_khci_host_state_struct_t *usbHostPointer)
364 {
365 if (usbHostPointer->deviceAttached > 0)
366 {
367 usbHostPointer->deviceAttached--;
368 }
369 else
370 {
371 return;
372 }
373 (void)USB_HostDetachDevice(usbHostPointer->hostHandle, 0U, 0U);
374 /* Enable USB week pull-downs, useful for detecting detach (effectively bus discharge) */
375 usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_PDE_MASK;
376 /* Remove suspend state */
377 usbHostPointer->usbRegBase->USBCTRL &= (uint8_t)(~USB_USBCTRL_SUSP_MASK);
378
379 usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
380
381 usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
382 /*disable sof*/
383 usbHostPointer->usbRegBase->CTL &= (uint8_t)(~USB_CTL_USBENSOFEN_MASK);
384
385 usbHostPointer->txBd = 0U;
386 usbHostPointer->rxBd = 0U;
387
388 usbHostPointer->usbRegBase->ISTAT = 0xffU;
389 (void)OSA_EventClear(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
390 }
391
392 /*!
393 * @brief get a right transfer from periodic and async list.
394 *
395 * This function return a right transfer for khci atom transfer, the function implemented simple USB transaction
396 * dispatch algorithm.
397 *
398 * @param handle Pointer of the host khci controller handle.
399 * @param transfer Pointer of pointer of transfer node struct, will get the a tr quest pointer if operator
400 * success, will get NULL pointer if fail.
401 *
402 */
_USB_HostKhciGetRightTrRequest(usb_host_controller_handle handle,usb_host_transfer_t ** transfer)403 static void _USB_HostKhciGetRightTrRequest(usb_host_controller_handle handle, usb_host_transfer_t **transfer)
404 {
405 usb_host_transfer_t *tempTransfer;
406 usb_host_transfer_t *firstTransfer;
407 usb_host_transfer_t *prevTtransfer;
408 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
409 uint16_t frame_number;
410 prevTtransfer = NULL;
411
412 if (handle == NULL)
413 {
414 *transfer = NULL;
415 return;
416 }
417
418 USB_HostKhciLock();
419 /* First check whether periodic list is active, will get transfer from periodic list */
420 if (0U != usbHostPointer->periodicListAvtive)
421 {
422 tempTransfer = usbHostPointer->periodicListPointer;
423 prevTtransfer = tempTransfer;
424 frame_number = _USB_HostKhciGetFrameCount(usbHostPointer);
425 /* Will get the transfer if the pipe frame count and current frame count is equal */
426 while (tempTransfer != NULL)
427 {
428 if ((tempTransfer->transferPipe->currentCount != frame_number) &&
429 (frame_number % tempTransfer->transferPipe->interval == 0U) &&
430 (tempTransfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT))
431 {
432 tempTransfer->transferPipe->currentCount = frame_number;
433 firstTransfer = tempTransfer;
434 *transfer = firstTransfer;
435 /* Will move the selected interrupt transfer to end of the periodic list */
436 if ((tempTransfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT) && (tempTransfer->next != NULL))
437 {
438 if (tempTransfer == usbHostPointer->periodicListPointer)
439 {
440 usbHostPointer->periodicListPointer = tempTransfer->next;
441 }
442 else
443 {
444 prevTtransfer->next = tempTransfer->next;
445 }
446 while (tempTransfer != NULL)
447 {
448 prevTtransfer = tempTransfer;
449 tempTransfer = tempTransfer->next;
450 }
451 prevTtransfer->next = firstTransfer;
452 firstTransfer->next = NULL;
453 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
454 }
455 USB_HostKhciUnlock();
456 return;
457 }
458 prevTtransfer = tempTransfer;
459 tempTransfer = tempTransfer->next;
460 }
461 }
462 /* will get the first transfer from active list if no active transfer in async list */
463 if ((0U != usbHostPointer->asyncListAvtive) && (NULL != usbHostPointer->asyncListPointer))
464 {
465 tempTransfer = usbHostPointer->asyncListPointer;
466 firstTransfer = tempTransfer;
467 *transfer = firstTransfer;
468
469 if (tempTransfer->next != NULL)
470 {
471 usbHostPointer->asyncListPointer = tempTransfer->next;
472 }
473 else
474 {
475 USB_HostKhciUnlock();
476 return;
477 }
478 tempTransfer = tempTransfer->next;
479 while (tempTransfer != NULL)
480 {
481 prevTtransfer = tempTransfer;
482 tempTransfer = tempTransfer->next;
483 }
484 prevTtransfer->next = firstTransfer;
485 firstTransfer->next = NULL;
486 }
487 USB_HostKhciUnlock();
488 }
489
490 /*!
491 * @brief unlink transfer from periodic and async khci transfer list.
492 *
493 * @param handle Pointer of the host khci controller handle.
494 * @param transfer Pointer of transfer node struct, which will be unlink from transfer list.
495 *
496 */
_USB_HostKhciUnlinkTrRequestFromList(usb_host_controller_handle handle,usb_host_transfer_t * transfer)497 static void _USB_HostKhciUnlinkTrRequestFromList(usb_host_controller_handle handle, usb_host_transfer_t *transfer)
498 {
499 usb_host_transfer_t *temptr = NULL;
500 usb_host_transfer_t *pretr = NULL;
501 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
502
503 if ((handle == NULL) || (transfer == NULL))
504 {
505 return;
506 }
507
508 USB_HostKhciLock();
509 if (usbHostPointer->asyncListAvtive == 1U)
510 {
511 temptr = usbHostPointer->asyncListPointer;
512 if (transfer == temptr)
513 {
514 usbHostPointer->asyncListPointer = temptr->next;
515 }
516 else
517 {
518 while (temptr != NULL)
519 {
520 pretr = temptr;
521 temptr = temptr->next;
522 if (transfer == temptr)
523 {
524 pretr->next = temptr->next;
525 break;
526 }
527 }
528 }
529 if (usbHostPointer->asyncListPointer == NULL)
530 {
531 usbHostPointer->asyncListAvtive = 0U;
532 }
533 }
534 if (usbHostPointer->periodicListAvtive == 1U)
535 {
536 temptr = usbHostPointer->periodicListPointer;
537 if (transfer == temptr)
538 {
539 usbHostPointer->periodicListPointer = temptr->next;
540 }
541 else
542 {
543 while (temptr != NULL)
544 {
545 pretr = temptr;
546 temptr = temptr->next;
547 if (transfer == temptr)
548 {
549 pretr->next = temptr->next;
550 break;
551 }
552 }
553 }
554 if (usbHostPointer->periodicListPointer == NULL)
555 {
556 usbHostPointer->periodicListAvtive = 0U;
557 }
558 }
559 USB_HostKhciUnlock();
560 }
561
562 /*!
563 * @brief link transfer to periodic and async khci transfer list.
564 *
565 * @param handle Pointer of the host khci controller handle.
566 * @param transfer Pointer of transfer node struct, which will be link to transfer list.
567 *
568 */
_USB_HostKhciLinkTrRequestToList(usb_host_controller_handle controllerHandle,usb_host_transfer_t * transfer)569 static usb_status_t _USB_HostKhciLinkTrRequestToList(usb_host_controller_handle controllerHandle,
570 usb_host_transfer_t *transfer)
571 {
572 usb_host_transfer_t *temptransfer;
573 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
574
575 if ((transfer == NULL))
576 {
577 return kStatus_USB_InvalidParameter;
578 }
579
580 USB_HostKhciLock();
581 if ((transfer->transferPipe->pipeType == USB_ENDPOINT_ISOCHRONOUS) ||
582 (transfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT))
583 {
584 if (usbHostPointer->periodicListAvtive == 0U)
585 {
586 usbHostPointer->periodicListPointer = transfer;
587 transfer->next = NULL;
588 usbHostPointer->periodicListAvtive = 1U;
589 }
590 else
591 {
592 temptransfer = usbHostPointer->periodicListPointer;
593 while (temptransfer->next != NULL)
594 {
595 temptransfer = temptransfer->next;
596 }
597 temptransfer->next = transfer;
598 transfer->next = NULL;
599 }
600 }
601 else if ((transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL) ||
602 (transfer->transferPipe->pipeType == USB_ENDPOINT_BULK))
603 {
604 if (usbHostPointer->asyncListAvtive == 0U)
605 {
606 usbHostPointer->asyncListPointer = transfer;
607 transfer->next = NULL;
608 usbHostPointer->asyncListAvtive = 1U;
609 }
610 else
611 {
612 temptransfer = usbHostPointer->asyncListPointer;
613 while (temptransfer->next != NULL)
614 {
615 temptransfer = temptransfer->next;
616 }
617 temptransfer->next = transfer;
618 transfer->next = NULL;
619 }
620 }
621 else
622 {
623 /*no action*/
624 }
625 USB_HostKhciUnlock();
626 return kStatus_USB_Success;
627 }
628
629 /*!
630 * @brief khci process transfer callback function.
631 *
632 * @param controllerHandle Pointer of the host khci controller handle.
633 * @param transfer Pointer of transfer , which will be process callback.
634 * @param err The return value of transfer.
635 *
636 */
_USB_HostKhciProcessTrCallback(usb_host_controller_handle controllerHandle,usb_host_transfer_t * transfer,int32_t err)637 static void _USB_HostKhciProcessTrCallback(usb_host_controller_handle controllerHandle,
638 usb_host_transfer_t *transfer,
639 int32_t err)
640 {
641 usb_status_t status = kStatus_USB_Success;
642 usb_host_pipe_t *pipePointer = NULL;
643
644 if (err == USB_KHCI_ATOM_TR_STALL)
645 {
646 status = kStatus_USB_TransferStall;
647 }
648 else if ((err == USB_KHCI_ATOM_TR_NAK) || (err >= 0))
649 {
650 status = kStatus_USB_Success;
651
652 if (err == USB_KHCI_ATOM_TR_NAK)
653 {
654 status = kStatus_USB_TransferFailed;
655 }
656 }
657 else if (err < 0)
658 {
659 status = kStatus_USB_TransferFailed;
660 }
661 else
662 {
663 }
664
665 if (status == kStatus_USB_Success)
666 {
667 if ((transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL) &&
668 (transfer->setupPacket->bRequest == USB_REQUEST_STANDARD_CLEAR_FEATURE) &&
669 (transfer->setupPacket->bmRequestType == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT) &&
670 ((USB_SHORT_FROM_LITTLE_ENDIAN(transfer->setupPacket->wValue) & 0x00FFu) ==
671 USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT))
672 {
673 pipePointer = ((usb_khci_host_state_struct_t *)controllerHandle)->pipeDescriptorBasePointer;
674 while (NULL != pipePointer)
675 {
676 /* only compute bulk and interrupt pipe */
677 if (((pipePointer->endpointAddress |
678 (pipePointer->direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)) ==
679 (uint8_t)(USB_SHORT_FROM_LITTLE_ENDIAN(transfer->setupPacket->wIndex))) &&
680 (pipePointer->deviceHandle == transfer->transferPipe->deviceHandle))
681 {
682 break;
683 }
684 pipePointer = pipePointer->next;
685 }
686
687 if ((pipePointer != NULL) &&
688 ((pipePointer->pipeType == USB_ENDPOINT_INTERRUPT) || (pipePointer->pipeType == USB_ENDPOINT_BULK)))
689 {
690 pipePointer->nextdata01 = 0;
691 }
692 }
693 }
694
695 /* callback function is different from the current condition */
696 transfer->callbackFn(transfer->callbackParam, transfer, status);
697 }
698
699 /*!
700 * @brief khci transaction done process function.
701 *
702 * @param usbHostPointer Pointer of the host khci controller handle.
703 * @param transfer Pointer of transfer node struct, which will be handled process done.
704 *1400
705 */
_USB_HostKhciTransactionDone(usb_khci_host_state_struct_t * usbHostPointer,usb_host_transfer_t * transfer)706 static int32_t _USB_HostKhciTransactionDone(usb_khci_host_state_struct_t *usbHostPointer, usb_host_transfer_t *transfer)
707 {
708 uint32_t bd;
709 uint8_t err;
710 int32_t transferResult = 0;
711 tr_type_t type = kTr_Unknown;
712 uint32_t *bdPointer = NULL;
713 usb_host_pipe_t *pipeDescPointer = transfer->transferPipe;
714 uint32_t result;
715
716 if (pipeDescPointer->pipeType == USB_ENDPOINT_CONTROL)
717 {
718 if (transfer->setupStatus == (uint8_t)kTransfer_Setup0)
719 {
720 type = kTr_Ctrl;
721 }
722 else if ((transfer->setupStatus == (uint8_t)kTransfer_Setup1))
723 {
724 if (0U != transfer->transferLength)
725 {
726 if (transfer->direction == USB_IN)
727 {
728 type = kTr_In;
729 }
730 else
731 {
732 type = kTr_Out;
733 }
734 }
735 else
736 {
737 type = kTr_In;
738 }
739 }
740 else if (transfer->setupStatus == (uint8_t)kTransfer_Setup2)
741 {
742 if (0U != transfer->transferLength)
743 {
744 if (transfer->direction == USB_IN)
745 {
746 type = kTr_Out;
747 }
748 else
749 {
750 type = kTr_In;
751 }
752 }
753 else
754 {
755 type = kTr_In;
756 }
757 }
758 else if (transfer->setupStatus == (uint8_t)kTransfer_Setup3)
759 {
760 type = kTr_In;
761 }
762 else
763 {
764 /*no action*/
765 }
766 }
767 else
768 {
769 if (pipeDescPointer->direction == USB_IN)
770 {
771 type = kTr_In;
772 }
773 else if (pipeDescPointer->direction == USB_OUT)
774 {
775 type = kTr_Out;
776 }
777 else
778 {
779 /*no action*/
780 }
781 }
782 switch (type)
783 {
784 case kTr_Ctrl:
785 case kTr_Out:
786 usbHostPointer->txBd ^= 1U;
787 bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 1U, usbHostPointer->txBd);
788 usbHostPointer->txBd ^= 1U;
789 break;
790
791 case kTr_In:
792 usbHostPointer->rxBd ^= 1U;
793 bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 0U, usbHostPointer->rxBd);
794 usbHostPointer->rxBd ^= 1U;
795 break;
796
797 default:
798 bdPointer = NULL;
799 break;
800 }
801
802 if (bdPointer == NULL)
803 {
804 return -1;
805 }
806
807 bd = *bdPointer;
808 err = usbHostPointer->usbRegBase->ERRSTAT;
809 if (0U != (err & (USB_ERRSTAT_PIDERR_MASK | USB_ERRSTAT_CRC5EOF_MASK | USB_ERRSTAT_CRC16_MASK |
810 USB_ERRSTAT_DFN8_MASK | USB_ERRSTAT_DMAERR_MASK | USB_ERRSTAT_BTSERR_MASK)))
811 {
812 transferResult = -(int32_t)err;
813 return transferResult;
814 }
815 else
816 {
817 if (0U != (bd & USB_KHCI_BD_OWN))
818 {
819 #ifdef HOST_ECHO
820 usb_echo("Own bit is not clear 0x%x\n", (unsigned int)bd);
821 #endif
822 *bdPointer = 0U;
823 }
824 if ((pipeDescPointer->pipeType == USB_ENDPOINT_ISOCHRONOUS))
825 {
826 /*misra 10.8*/
827 result = ((bd >> 16) & 0x3ffU);
828 transferResult = (int32_t)result;
829 }
830 else
831 {
832 switch (bd >> 2 & 0xfU)
833 {
834 case 0x03: /* Last Transfer status is DATA0 */
835 case 0x0b: /* Last Transfer status is DATA1 */
836 case 0x02: /* Last Transfer status is ACK */
837 /*misra 10.8*/
838 result = ((bd >> 16) & 0x3ffU);
839 transferResult = (int32_t)result;
840 /* switch data toggle */
841 pipeDescPointer->nextdata01 ^= 1U;
842 break;
843
844 case 0x0e: /* Last Transfer status is STALL */
845 transferResult = USB_KHCI_ATOM_TR_STALL;
846 break;
847
848 case 0x0a: /* Last Transfer status is NAK */
849 transferResult = USB_KHCI_ATOM_TR_NAK;
850 break;
851
852 case 0x00: /* Last Transfer status is bus timeout **/
853 transferResult = USB_KHCI_ATOM_TR_BUS_TIMEOUT;
854 break;
855
856 case 0x0f: /* Last Transfer status is data error */
857 transferResult = USB_KHCI_ATOM_TR_DATA_ERROR;
858 break;
859 default:
860 /*no action*/
861 break;
862 }
863 }
864 }
865
866 if ((kTr_In == type) && (0U == usbHostPointer->sXferSts.isDmaAlign))
867 {
868 usbHostPointer->sXferSts.isDmaAlign = 1U;
869 if (transferResult > 0)
870 {
871 (void)memcpy((void *)usbHostPointer->sXferSts.rxBufOrig, (void *)usbHostPointer->sXferSts.rxBuf,
872 (uint32_t)transferResult);
873 }
874 }
875 return transferResult;
876 }
877
878 /*!
879 * @brief khci atom transaction process function.
880 *
881 * @param usbHostPointer Pointer of the host khci controller instance.
882 * @param type The USB transfer type.
883 * @param pipeDescPointer Pointer of usb pipe desc.
884 * @param bufPointer The memory address is needed to be transferred.
885 * @param len Transferred data length.
886 *
887 * @return 0 mean success or other operator failure error code.
888 *
889 */
_USB_HostKhciAtomNonblockingTransaction(usb_khci_host_state_struct_t * usbHostPointer,uint32_t type,usb_host_pipe_t * pipeDescPointer,uint8_t * bufPointer,uint32_t len)890 static int32_t _USB_HostKhciAtomNonblockingTransaction(usb_khci_host_state_struct_t *usbHostPointer,
891 uint32_t type,
892 usb_host_pipe_t *pipeDescPointer,
893 uint8_t *bufPointer,
894 uint32_t len)
895 {
896 uint32_t *bdPointer = NULL;
897 uint8_t *buf = bufPointer;
898 int32_t transferResult;
899 uint32_t speed = 0U;
900 uint32_t address = 0U;
901 uint32_t level = 0U;
902 uint8_t counter = 0U;
903 uint32_t eventBit;
904 osa_status_t osaStatus;
905 uint8_t epCtlVal;
906 tr_type_t trType;
907
908 len = (len > pipeDescPointer->maxPacketSize) ? pipeDescPointer->maxPacketSize : len;
909 (void)USB_HostHelperGetPeripheralInformation(pipeDescPointer->deviceHandle, (uint32_t)kUSB_HostGetDeviceLevel,
910 &level);
911 (void)USB_HostHelperGetPeripheralInformation(pipeDescPointer->deviceHandle, (uint32_t)kUSB_HostGetDeviceSpeed,
912 &speed);
913 (void)USB_HostHelperGetPeripheralInformation(pipeDescPointer->deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
914 &address);
915
916 if (speed == USB_SPEED_LOW)
917 {
918 usbHostPointer->usbRegBase->ADDR |= USB_ADDR_LSEN_MASK;
919 }
920 else
921 {
922 usbHostPointer->usbRegBase->ADDR &= (uint8_t)(~USB_ADDR_LSEN_MASK);
923 }
924 usbHostPointer->usbRegBase->ADDR = (uint8_t)((usbHostPointer->usbRegBase->ADDR & ((uint8_t)(~USB_ADDR_ADDR_MASK))) |
925 (((((uint8_t)address) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK)));
926
927 #if (FSL_FEATURE_USB_KHCI_HOST_ENABLED)
928 epCtlVal = (level == 1U ? USB_ENDPT_HOSTWOHUB_MASK : 0U) | USB_ENDPT_RETRYDIS_MASK | USB_ENDPT_EPTXEN_MASK |
929 USB_ENDPT_EPRXEN_MASK |
930 ((pipeDescPointer->pipeType == USB_ENDPOINT_ISOCHRONOUS ? 0U : USB_ENDPT_EPHSHK_MASK));
931 #else
932 epCtlVal = USB_ENDPT_EPTXEN_MASK | USB_ENDPT_EPRXEN_MASK |
933 ((pipeDescPointer->pipeType == USB_ENDPOINT_ISOCHRONOUS ? 0U : USB_ENDPT_EPHSHK_MASK));
934 #endif
935 usbHostPointer->usbRegBase->ENDPOINT[0U].ENDPT = epCtlVal;
936
937 transferResult = 0;
938 counter = 0U;
939 /* wait for USB controller is ready, and with timeout */
940 while (0U != ((usbHostPointer->usbRegBase->CTL) & USB_CTL_TXSUSPENDTOKENBUSY_MASK))
941 {
942 _USB_HostKhciDelay(usbHostPointer, 1U);
943 osaStatus = OSA_EventWait(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_TOK_DONE, 0U, 1, &eventBit);
944 if (osaStatus == KOSA_StatusSuccess)
945 {
946 transferResult = USB_KHCI_ATOM_TR_RESET;
947 break;
948 }
949 else
950 {
951 counter++;
952 if (counter >= 3U)
953 {
954 transferResult = USB_KHCI_ATOM_TR_CRC_ERROR;
955 return transferResult;
956 }
957 }
958 }
959
960 if (0 == transferResult)
961 {
962 #if defined(FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED) && \
963 (FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED == 1U)
964 if (speed == USB_SPEED_LOW)
965 {
966 usbHostPointer->usbRegBase->SOFTHLD = (uint8_t)((len * 12U * 7U / 6U + KHCICFG_THSLD_DELAY) / 8U);
967 }
968 else
969 {
970 usbHostPointer->usbRegBase->SOFTHLD = (uint8_t)((len * 7U / 6U + KHCICFG_THSLD_DELAY) / 8U);
971 }
972 #endif
973 usbHostPointer->usbRegBase->ERRSTAT = 0xffU;
974
975 if (((uint32_t)kTr_In == type) &&
976 ((0U != (len & USB_MEM4_ALIGN_MASK)) || (0U != ((uint32_t)bufPointer & USB_MEM4_ALIGN_MASK))))
977 {
978 if ((usbHostPointer->khciSwapBufPointer != NULL) && (len <= USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER))
979 {
980 buf = (uint8_t *)USB_MEM4_ALIGN((uint32_t)(usbHostPointer->khciSwapBufPointer + 4));
981 usbHostPointer->sXferSts.rxBuf = buf;
982 usbHostPointer->sXferSts.rxBufOrig = bufPointer;
983 usbHostPointer->sXferSts.rxLen = len;
984 usbHostPointer->sXferSts.isDmaAlign = 0U;
985 }
986 }
987 else
988 {
989 usbHostPointer->sXferSts.isDmaAlign = 1U;
990 }
991
992 trType = (tr_type_t)type;
993 switch (trType)
994 {
995 case kTr_Ctrl:
996 bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 1U, usbHostPointer->txBd);
997 *(bdPointer + 1U) = USB_LONG_TO_LITTLE_ENDIAN((uint32_t)buf);
998 *bdPointer = USB_LONG_TO_LITTLE_ENDIAN(USB_KHCI_BD_BC(len) | USB_KHCI_BD_OWN);
999 __DSB(); /* make sure the bdt is updated before TOKEN update */
1000 usbHostPointer->usbRegBase->TOKEN =
1001 (USB_TOKEN_TOKENENDPT((uint8_t)pipeDescPointer->endpointAddress) | USB_TOKEN_TOKENPID(0xD));
1002 usbHostPointer->txBd ^= 1U;
1003 break;
1004 case kTr_In:
1005 bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 0U, usbHostPointer->rxBd);
1006 *(bdPointer + 1U) = USB_LONG_TO_LITTLE_ENDIAN((uint32_t)buf);
1007 *bdPointer = USB_LONG_TO_LITTLE_ENDIAN(USB_KHCI_BD_BC(len) | USB_KHCI_BD_OWN |
1008 USB_KHCI_BD_DATA01(pipeDescPointer->nextdata01));
1009 __DSB(); /* make sure the bdt is updated before TOKEN update */
1010 usbHostPointer->usbRegBase->TOKEN =
1011 (USB_TOKEN_TOKENENDPT((uint8_t)pipeDescPointer->endpointAddress) | USB_TOKEN_TOKENPID(0x9));
1012 usbHostPointer->rxBd ^= 1U;
1013 break;
1014 case kTr_Out:
1015 bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 1U, usbHostPointer->txBd);
1016 *(bdPointer + 1U) = USB_LONG_TO_LITTLE_ENDIAN((uint32_t)buf);
1017 *bdPointer = USB_LONG_TO_LITTLE_ENDIAN(USB_KHCI_BD_BC(len) | USB_KHCI_BD_OWN |
1018 USB_KHCI_BD_DATA01(pipeDescPointer->nextdata01));
1019 __DSB(); /* make sure the bdt is updated before TOKEN update */
1020 usbHostPointer->usbRegBase->TOKEN =
1021 (USB_TOKEN_TOKENENDPT((uint8_t)pipeDescPointer->endpointAddress) | USB_TOKEN_TOKENPID(0x1));
1022 usbHostPointer->txBd ^= 1U;
1023 break;
1024 default:
1025 /*no action*/
1026 break;
1027 }
1028 }
1029
1030 return transferResult;
1031 }
1032
1033 /*!
1034 * @brief khci host start transfer.
1035 *
1036 * @param handle Pointer of the host khci controller handle.
1037 * @param transfer Pointer of transfer node struct, which will transfer.
1038 *
1039 * @retval kKhci_TrTransmiting khci host transaction prime successfully, will enter next stage.
1040 * @retval kKhci_TrTransmitDone khci host transaction prime unsuccessfully, will enter exit stage.
1041 *
1042 */
_USB_HostKhciStartTranfer(usb_host_controller_handle handle,usb_host_transfer_t * transfer)1043 static khci_tr_state_t _USB_HostKhciStartTranfer(usb_host_controller_handle handle, usb_host_transfer_t *transfer)
1044 {
1045 static int32_t transferResult;
1046 uint8_t *buf;
1047 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
1048
1049 if (transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL)
1050 {
1051 if ((transfer->setupStatus == (uint8_t)kTransfer_Setup0))
1052 {
1053 transferResult = _USB_HostKhciAtomNonblockingTransaction(
1054 usbHostPointer, (uint32_t)kTr_Ctrl, transfer->transferPipe, (uint8_t *)transfer->setupPacket, 8U);
1055 }
1056 else if (transfer->setupStatus == (uint8_t)kTransfer_Setup1)
1057 {
1058 if (0U != transfer->transferLength)
1059 {
1060 buf = transfer->transferBuffer;
1061 buf += transfer->transferSofar;
1062 transferResult = _USB_HostKhciAtomNonblockingTransaction(
1063 usbHostPointer, (transfer->direction == USB_IN) ? (uint32_t)kTr_In : (uint32_t)kTr_Out,
1064 transfer->transferPipe, buf, transfer->transferLength - transfer->transferSofar);
1065 }
1066 else
1067 {
1068 transfer->transferPipe->nextdata01 = 1U;
1069 transfer->setupStatus = (uint8_t)kTransfer_Setup3;
1070 transferResult = _USB_HostKhciAtomNonblockingTransaction(usbHostPointer, (uint32_t)kTr_In,
1071 transfer->transferPipe, NULL, 0U);
1072 }
1073 }
1074 else if (transfer->setupStatus == (uint8_t)kTransfer_Setup2)
1075 {
1076 if (0U != transfer->transferLength)
1077 {
1078 transfer->transferPipe->nextdata01 = 1U;
1079
1080 transferResult = _USB_HostKhciAtomNonblockingTransaction(
1081 usbHostPointer, (transfer->direction == USB_IN) ? (uint32_t)kTr_Out : (uint32_t)kTr_In,
1082 transfer->transferPipe, NULL, 0U);
1083 }
1084 else
1085 {
1086 transfer->transferPipe->nextdata01 = 1U;
1087 transferResult = _USB_HostKhciAtomNonblockingTransaction(usbHostPointer, (uint32_t)kTr_In,
1088 transfer->transferPipe, NULL, 0U);
1089 }
1090 }
1091 else if (transfer->setupStatus == (uint8_t)kTransfer_Setup3)
1092 {
1093 transfer->transferPipe->nextdata01 = 1U;
1094 transferResult = _USB_HostKhciAtomNonblockingTransaction(usbHostPointer, (uint32_t)kTr_In,
1095 transfer->transferPipe, NULL, 0U);
1096 }
1097 else
1098 {
1099 /*no action*/
1100 }
1101 }
1102 else
1103 {
1104 buf = transfer->transferBuffer;
1105 buf += transfer->transferSofar;
1106 transferResult = _USB_HostKhciAtomNonblockingTransaction(
1107 usbHostPointer, (transfer->transferPipe->direction == USB_IN) ? (uint32_t)kTr_In : (uint32_t)kTr_Out,
1108 transfer->transferPipe, buf, transfer->transferLength - transfer->transferSofar);
1109 }
1110
1111 transfer->union1.transferResult = transferResult;
1112
1113 if (transfer->union1.transferResult == 0)
1114 {
1115 usbHostPointer->trState = (uint32_t)kKhci_TrTransmiting;
1116 }
1117 else
1118 {
1119 usbHostPointer->trState = (uint32_t)kKhci_TrTransmitDone;
1120 }
1121 return (khci_tr_state_t)usbHostPointer->trState;
1122 }
1123
1124 /*!
1125 * @brief khci host finish transfer.
1126 *
1127 * @param handle Pointer of the host khci controller handle.
1128 * @param transfer Pointer of transfer node struct, which will be transfer.
1129 *
1130 * @retval kKhci_TrGetMsg The current of transaction is transfer done, will enter first stage.
1131 * @retval kKhci_TrTransmitDone All of khci host transaction of the transfer have transfer done, will enter exit
1132 * stage.
1133 *
1134 */
_USB_HostKhciFinishTranfer(usb_host_controller_handle handle,usb_host_transfer_t * transfer)1135 static khci_tr_state_t _USB_HostKhciFinishTranfer(usb_host_controller_handle handle, usb_host_transfer_t *transfer)
1136 {
1137 static int32_t transferResult;
1138 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
1139
1140 transferResult = _USB_HostKhciTransactionDone(usbHostPointer, transfer);
1141 transfer->union1.transferResult = transferResult;
1142 if (transferResult >= 0)
1143 {
1144 if (transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL)
1145 {
1146 if ((transfer->setupStatus == (uint8_t)kTransfer_Setup2) ||
1147 (transfer->setupStatus == (uint8_t)kTransfer_Setup3))
1148 {
1149 usbHostPointer->trState = (uint32_t)kKhci_TrTransmitDone;
1150 }
1151 else
1152 {
1153 usbHostPointer->trState = (uint32_t)kKhci_TrStartTransmit;
1154 if (transfer->setupStatus == (uint8_t)kTransfer_Setup1)
1155 {
1156 transfer->transferSofar += (uint32_t)transferResult;
1157 if (((transfer->transferLength - transfer->transferSofar) <= 0U) ||
1158 ((uint32_t)transferResult < transfer->transferPipe->maxPacketSize))
1159 {
1160 transfer->setupStatus++;
1161 }
1162 }
1163 else
1164 {
1165 transfer->setupStatus++;
1166 }
1167 }
1168 }
1169 else
1170 {
1171 transfer->transferSofar += (uint32_t)transferResult;
1172 if (((transfer->transferLength - transfer->transferSofar) == 0U) ||
1173 ((uint32_t)transferResult < transfer->transferPipe->maxPacketSize))
1174 {
1175 usbHostPointer->trState = (uint32_t)kKhci_TrTransmitDone;
1176 }
1177 else
1178 {
1179 usbHostPointer->trState = (uint32_t)kKhci_TrStartTransmit;
1180 }
1181 }
1182 }
1183 else
1184 {
1185 if ((transferResult == USB_KHCI_ATOM_TR_NAK))
1186 {
1187 if (transfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT)
1188 {
1189 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1190 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
1191 }
1192 else
1193 {
1194 if ((_USB_HostKhciGetFrameCountSum(usbHostPointer) - transfer->union2.frame) > transfer->nakTimeout)
1195 {
1196 usbHostPointer->trState = (uint32_t)kKhci_TrTransmitDone;
1197 transfer->union1.transferResult = USB_KHCI_ATOM_TR_BUS_TIMEOUT;
1198 }
1199 else
1200 {
1201 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1202 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
1203 }
1204 }
1205 }
1206 else
1207 {
1208 usbHostPointer->trState = (uint32_t)kKhci_TrTransmitDone;
1209 }
1210 }
1211 return (khci_tr_state_t)usbHostPointer->trState;
1212 }
1213
1214 /*!
1215 * @brief host khci controller transfer clear up
1216 *
1217 * The function is used to handle controller transfer clear up.
1218 * @param handle Pointer of the host khci controller handle.
1219 *
1220 *
1221 */
_USB_HostKhciTransferClearUp(usb_host_controller_handle controllerHandle)1222 static void _USB_HostKhciTransferClearUp(usb_host_controller_handle controllerHandle)
1223 {
1224 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
1225 usb_host_transfer_t *trCancel;
1226
1227 USB_HostKhciLock();
1228 trCancel = usbHostPointer->periodicListPointer;
1229 USB_HostKhciUnlock();
1230 while (trCancel != NULL)
1231 {
1232 _USB_HostKhciUnlinkTrRequestFromList(controllerHandle, trCancel);
1233 /* callback function is different from the current condition */
1234 trCancel->callbackFn(trCancel->callbackParam, trCancel, kStatus_USB_TransferCancel);
1235 USB_HostKhciLock();
1236 trCancel = usbHostPointer->periodicListPointer;
1237 USB_HostKhciUnlock();
1238 }
1239
1240 USB_HostKhciLock();
1241 trCancel = usbHostPointer->asyncListPointer;
1242 USB_HostKhciUnlock();
1243 while (trCancel != NULL)
1244 {
1245 _USB_HostKhciUnlinkTrRequestFromList(controllerHandle, trCancel);
1246 /* callback function is different from the current condition */
1247 trCancel->callbackFn(trCancel->callbackParam, trCancel, kStatus_USB_TransferCancel);
1248 USB_HostKhciLock();
1249 trCancel = usbHostPointer->asyncListPointer;
1250 USB_HostKhciUnlock();
1251 }
1252 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1253 }
1254
1255 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1256 /*!
1257 * @brief Handle khci host controller bus resume event.
1258 *
1259 * @param usbHostPointer Pointer of the host KHCI state structure.
1260 *
1261 */
_USB_HostKhciResume(usb_khci_host_state_struct_t * usbHostPointer)1262 static void _USB_HostKhciResume(usb_khci_host_state_struct_t *usbHostPointer)
1263 {
1264 usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostPointer->hostHandle;
1265
1266 if (0 == usbHostPointer->deviceAttached)
1267 {
1268 usbHostPointer->busSuspendStatus = kBus_Idle;
1269 usbHostPointer->usbRegBase->CTL &= (uint8_t)(~USB_CTL_RESUME_MASK);
1270 usbHostPointer->usbRegBase->CTL |= USB_CTL_USBENSOFEN_MASK;
1271 }
1272 else
1273 {
1274 while ((hostPointer->hwTick - usbHostPointer->matchTick) < 21U)
1275 {
1276 __NOP();
1277 }
1278 usbHostPointer->usbRegBase->CTL &= (uint8_t)(~USB_CTL_RESUME_MASK);
1279 usbHostPointer->usbRegBase->ISTAT = USB_ISTAT_RESUME_MASK;
1280 usbHostPointer->usbRegBase->CTL |= USB_CTL_USBENSOFEN_MASK;
1281 while ((hostPointer->hwTick - usbHostPointer->matchTick) < 31U)
1282 {
1283 __NOP();
1284 }
1285 usbHostPointer->busSuspendStatus = kBus_Idle;
1286
1287 (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
1288 kUSB_HostEventResumed); /* call host callback function */
1289 hostPointer->suspendedDevice = NULL;
1290 }
1291 }
1292 #endif
1293
1294 /*!
1295 * @brief host khci controller transfer state machine
1296 *
1297 * The function is used to handle controller transfer state machine.
1298 * @param handle Pointer of the host khci controller handle.
1299 * @param transfer Pointer of transfer node struct, which will be transfer.
1300 *
1301 *
1302 */
_USB_HostKhciTransferStateMachine(usb_host_controller_handle controllerHandle,usb_host_transfer_t ** ptransfer)1303 static void _USB_HostKhciTransferStateMachine(usb_host_controller_handle controllerHandle,
1304 usb_host_transfer_t **ptransfer)
1305 {
1306 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
1307 usb_host_transfer_t *transfer = *ptransfer;
1308 usb_host_transfer_t *tempTransfer = NULL;
1309 uint32_t eventBit = 0;
1310 khci_tr_state_t trState;
1311
1312 trState = (khci_tr_state_t)usbHostPointer->trState;
1313 switch (trState)
1314 {
1315 case kKhci_TrGetMsg:
1316 transfer = NULL;
1317 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1318 if (kBus_Idle != usbHostPointer->busSuspendStatus)
1319 {
1320 if (kBus_StartSuspend == usbHostPointer->busSuspendStatus)
1321 {
1322 usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostPointer->hostHandle;
1323 usbHostPointer->usbRegBase->CTL &= (uint8_t)(~USB_CTL_USBENSOFEN_MASK);
1324 /* usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_SUSP_MASK; */
1325 usbHostPointer->matchTick = hostPointer->hwTick;
1326 while ((hostPointer->hwTick - usbHostPointer->matchTick) < 4U)
1327 {
1328 __NOP();
1329 }
1330 usbHostPointer->usbRegBase->ISTAT |= USB_INTEN_RESUMEEN_MASK;
1331 usbHostPointer->usbRegBase->INTEN |= (USB_INTEN_RESUMEEN_MASK);
1332 usbHostPointer->usbRegBase->USBTRC0 |= USB_USBTRC0_USBRESMEN_MASK;
1333 usbHostPointer->busSuspendStatus = kBus_Suspended;
1334 (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
1335 kUSB_HostEventSuspended); /* call host callback function */
1336 }
1337 else
1338 {
1339 /*no action*/
1340 }
1341 return;
1342 }
1343 #endif
1344 _USB_HostKhciGetRightTrRequest(controllerHandle, &transfer);
1345 if (transfer != NULL)
1346 {
1347 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1348 if (((usb_host_instance_t *)usbHostPointer->hostHandle)->suspendedDevice ==
1349 transfer->transferPipe->deviceHandle)
1350 {
1351 transfer->retry = RETRY_TIME;
1352 transfer->union2.frame = _USB_HostKhciGetFrameCountSum(usbHostPointer);
1353
1354 (void)_USB_HostKhciLinkTrRequestToList(controllerHandle, transfer);
1355 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
1356 }
1357 else
1358 {
1359 #endif
1360 *ptransfer = transfer;
1361 usbHostPointer->trState = (uint32_t)_USB_HostKhciStartTranfer(controllerHandle, transfer);
1362 usbHostPointer->trState = (uint32_t)kKhci_TrTransmiting;
1363 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1364 }
1365 #endif
1366 }
1367 break;
1368
1369 case kKhci_IsoTrGetMsg:
1370 *ptransfer = NULL;
1371 if (0U != usbHostPointer->periodicListAvtive)
1372 {
1373 tempTransfer = usbHostPointer->periodicListPointer;
1374 while (tempTransfer != NULL)
1375 {
1376 if ((_USB_HostKhciGetFrameCount(usbHostPointer) % tempTransfer->transferPipe->interval == 0U) &&
1377 (tempTransfer->transferPipe->pipeType == USB_ENDPOINT_ISOCHRONOUS))
1378 {
1379 *ptransfer = tempTransfer;
1380
1381 (void)_USB_HostKhciStartTranfer(controllerHandle, tempTransfer);
1382 usbHostPointer->trState = (uint32_t)kKhci_TrTransmiting;
1383 if (KOSA_StatusSuccess == OSA_EventWait(usbHostPointer->khciEventPointer,
1384 USB_KHCI_EVENT_TOK_DONE, 0U, USB_OSA_WAIT_TIMEOUT,
1385 &eventBit))
1386 {
1387 if (0U != (eventBit & USB_KHCI_EVENT_TOK_DONE))
1388 {
1389 tempTransfer->union1.transferResult = _USB_HostKhciTransactionDone(usbHostPointer, tempTransfer);
1390 if (tempTransfer->union1.transferResult > 0U)
1391 {
1392 tempTransfer->transferSofar += (uint32_t)tempTransfer->union1.transferResult;
1393 }
1394 _USB_HostKhciUnlinkTrRequestFromList(usbHostPointer, tempTransfer);
1395 _USB_HostKhciProcessTrCallback(usbHostPointer, tempTransfer,
1396 tempTransfer->union1.transferResult);
1397 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1398 }
1399 }
1400 else
1401 {
1402 usbHostPointer->trState = (uint32_t)kKhci_TrTransmiting;
1403 }
1404 break;
1405 }
1406 tempTransfer = tempTransfer->next;
1407 }
1408 }
1409 if (*ptransfer == NULL)
1410 {
1411 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1412 }
1413 break;
1414
1415 case kKhci_TrStartTransmit:
1416 if (transfer != NULL)
1417 {
1418 usbHostPointer->trState = (uint32_t)_USB_HostKhciStartTranfer(controllerHandle, transfer);
1419 }
1420 break;
1421
1422 case kKhci_TrTransmiting:
1423 if (transfer != NULL)
1424 {
1425 if ((_USB_HostKhciGetFrameCountSum(usbHostPointer) - transfer->union2.frame) > USB_TIMEOUT_OTHER)
1426 {
1427 if ((transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL) ||
1428 (transfer->transferPipe->pipeType == USB_ENDPOINT_BULK))
1429 {
1430 /* clear current bdt status */
1431 (void)_USB_HostKhciTransactionDone(usbHostPointer, transfer);
1432 usbHostPointer->trState = (uint32_t)kKhci_TrTransmitDone;
1433 transfer->union1.transferResult = USB_KHCI_ATOM_TR_BUS_TIMEOUT;
1434 return;
1435 }
1436 }
1437 }
1438 break;
1439
1440 case kKhci_TrTransmitDone:
1441 if (transfer != NULL)
1442 {
1443 _USB_HostKhciUnlinkTrRequestFromList(usbHostPointer, transfer);
1444 _USB_HostKhciProcessTrCallback(usbHostPointer, transfer, transfer->union1.transferResult);
1445 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1446 if ((usbHostPointer->asyncListAvtive == 1U) || (usbHostPointer->periodicListAvtive == 1U))
1447 {
1448 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
1449 }
1450 }
1451 break;
1452
1453 default:
1454 /*no action*/
1455 break;
1456 }
1457 }
1458
1459 /*!
1460 * @brief khci task function.
1461 *
1462 * The function is used to handle KHCI controller message.
1463 * In the BM environment, this function should be called periodically in the main function.
1464 * And in the RTOS environment, this function should be used as a function entry to create a task.
1465 *
1466 * @param hostHandle The host handle.
1467 */
USB_HostKhciTaskFunction(void * hostHandle)1468 void USB_HostKhciTaskFunction(void *hostHandle)
1469 {
1470 volatile ptr_usb_host_khci_state_struct_t usbHostPointer;
1471 uint32_t eventBit = 0;
1472 static usb_host_transfer_t *transfer;
1473
1474 if (hostHandle == NULL)
1475 {
1476 return;
1477 }
1478
1479 usbHostPointer = (usb_khci_host_state_struct_t *)(((usb_host_instance_t *)hostHandle)->controllerHandle);
1480 if (OSA_EventWait(usbHostPointer->khciEventPointer, 0xff, 0U, 1U, &eventBit) ==
1481 KOSA_StatusSuccess) /* wait all event */
1482 {
1483 if (0U != (eventBit & USB_KHCI_EVENT_ATTACH))
1484 {
1485 _USB_HostKhciAttach(usbHostPointer);
1486 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1487 }
1488 if (0U != (eventBit & USB_KHCI_EVENT_RESET))
1489 {
1490 _USB_HostKhciReset(usbHostPointer);
1491 }
1492 if (0U != (eventBit & USB_KHCI_EVENT_DETACH))
1493 {
1494 _USB_HostKhciDetach(usbHostPointer);
1495 }
1496 if (0U != (eventBit & USB_KHCI_EVENT_SOF_TOK))
1497 {
1498 if ((0 != usbHostPointer->deviceAttached))
1499 {
1500 if (((uint32_t)kKhci_TrGetMsg == usbHostPointer->trState))
1501 {
1502 usbHostPointer->trState = (uint32_t)kKhci_IsoTrGetMsg;
1503 _USB_HostKhciTransferStateMachine(usbHostPointer, &transfer);
1504 }
1505 }
1506 }
1507 if (0U != (eventBit & USB_KHCI_EVENT_TOK_DONE))
1508 {
1509 if (transfer != NULL)
1510 {
1511 usbHostPointer->trState = (uint32_t)_USB_HostKhciFinishTranfer(
1512 ((usb_host_instance_t *)hostHandle)->controllerHandle, transfer);
1513 }
1514 }
1515 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1516 if (0U != (eventBit & USB_KHCI_EVENT_RESUME))
1517 {
1518 _USB_HostKhciResume(usbHostPointer);
1519 }
1520 #endif
1521 }
1522 if (usbHostPointer->deviceAttached > 0)
1523 {
1524 _USB_HostKhciTransferStateMachine(usbHostPointer, &transfer);
1525 }
1526 else
1527 {
1528 _USB_HostKhciTransferClearUp(usbHostPointer);
1529 }
1530 }
1531
1532 /*!
1533 * @brief create the USB host khci instance.
1534 *
1535 * This function initializes the USB host khci controller driver.
1536 *
1537 * @param controllerId The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
1538 * @param hostHandle The host level handle.
1539 * @param controllerHandle Return the controller instance handle.
1540 *
1541 * @retval kStatus_USB_Success The host is initialized successfully.
1542 * @retval kStatus_USB_AllocFail allocate memory fail.
1543 * @retval kStatus_USB_Error host mutex create fail, KHCI/EHCI mutex or KHCI/EHCI event create fail.
1544 * Or, KHCI/EHCI IP initialize fail.
1545 *
1546 */
USB_HostKhciCreate(uint8_t controllerId,usb_host_handle hostHandle,usb_host_controller_handle * controllerHandle)1547 usb_status_t USB_HostKhciCreate(uint8_t controllerId,
1548 usb_host_handle hostHandle,
1549 usb_host_controller_handle *controllerHandle)
1550 {
1551 usb_khci_host_state_struct_t *usbHostPointer;
1552 usb_status_t status = kStatus_USB_Success;
1553 osa_status_t osaStatus;
1554 uint32_t usb_base_addrs[] = USB_BASE_ADDRS;
1555
1556 if (((controllerId - (uint8_t)kUSB_ControllerKhci0) >= (uint8_t)USB_HOST_CONFIG_KHCI) ||
1557 ((controllerId - (uint8_t)kUSB_ControllerKhci0) >= (sizeof(usb_base_addrs) / sizeof(uint32_t))))
1558 {
1559 return kStatus_USB_ControllerNotFound;
1560 }
1561
1562 usbHostPointer = (usb_khci_host_state_struct_t *)OSA_MemoryAllocate(sizeof(usb_khci_host_state_struct_t));
1563 if (NULL == usbHostPointer)
1564 {
1565 *controllerHandle = NULL;
1566 return kStatus_USB_AllocFail;
1567 }
1568 usbHostPointer->usbRegBase = (USB_Type *)usb_base_addrs[controllerId - (uint8_t)kUSB_ControllerKhci0];
1569
1570 /* Allocate the USB Host Pipe Descriptors */
1571 usbHostPointer->pipeDescriptorBasePointer = NULL;
1572 usbHostPointer->hostHandle = hostHandle;
1573
1574 usbHostPointer->khciSwapBufPointer = (uint8_t *)OSA_MemoryAllocate(USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER + 4U);
1575 if (NULL == usbHostPointer->khciSwapBufPointer)
1576 {
1577 #ifdef HOST_ECHO
1578 usb_echo("usbHostPointer->khciSwapBufPointer- memory allocation failed");
1579 #endif
1580 (void)USB_HostKhciDestory(usbHostPointer);
1581 return kStatus_USB_AllocFail;
1582 }
1583
1584 /* init khci mutext */
1585 usbHostPointer->khciMutex = (osa_mutex_handle_t)(&usbHostPointer->mutexBuffer[0]);
1586 osaStatus = OSA_MutexCreate(usbHostPointer->khciMutex);
1587 if (osaStatus != KOSA_StatusSuccess)
1588 {
1589 #ifdef HOST_ECHO
1590 usb_echo("khci mutex init fail\r\n");
1591 #endif
1592 (void)USB_HostKhciDestory(usbHostPointer);
1593 return kStatus_USB_Error;
1594 }
1595 usbHostPointer->khciEventPointer = (osa_event_handle_t)&usbHostPointer->taskEventHandleBuffer[0];
1596 if (KOSA_StatusSuccess != OSA_EventCreate(usbHostPointer->khciEventPointer, 1U))
1597 {
1598 usbHostPointer->khciEventPointer = NULL;
1599 #ifdef HOST_ECHO
1600 usb_echo(" memalloc failed in usb_khci_init\n");
1601 #endif
1602 (void)USB_HostKhciDestory(usbHostPointer);
1603 return kStatus_USB_AllocFail;
1604 } /* Endif */
1605
1606 usbHostPointer->asyncListAvtive = 0U;
1607 usbHostPointer->periodicListAvtive = 0U;
1608 usbHostPointer->periodicListPointer = NULL;
1609 usbHostPointer->asyncListPointer = NULL;
1610 usbHostPointer->sXferSts.isDmaAlign = 0U;
1611
1612 /* set internal register pull down */
1613 usbHostPointer->usbRegBase->CTL = USB_CTL_SE0_MASK;
1614
1615 /* Reset USB CTRL register */
1616 usbHostPointer->usbRegBase->CTL = 0U;
1617 usbHostPointer->usbRegBase->ISTAT = 0xffU;
1618 /* Enable week pull-downs, useful for detecting detach (effectively bus discharge) */
1619 usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_PDE_MASK;
1620 /* Remove suspend state */
1621 usbHostPointer->usbRegBase->USBCTRL &= (uint8_t)(~USB_USBCTRL_SUSP_MASK);
1622 usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
1623
1624 usbHostPointer->usbRegBase->BDTPAGE1 = (uint8_t)((uint32_t)USB_KHCI_BDT_BASE >> 8U);
1625 usbHostPointer->usbRegBase->BDTPAGE2 = (uint8_t)((uint32_t)USB_KHCI_BDT_BASE >> 16);
1626 usbHostPointer->usbRegBase->BDTPAGE3 = (uint8_t)((uint32_t)USB_KHCI_BDT_BASE >> 24);
1627 /* Set SOF threshold */
1628 usbHostPointer->usbRegBase->SOFTHLD = 255;
1629 usbHostPointer->usbRegBase->ERREN = 0x00U;
1630 usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
1631 /* Wait for attach interrupt */
1632 usbHostPointer->usbRegBase->INTEN |= (USB_INTEN_ATTACHEN_MASK | USB_INTEN_SOFTOKEN_MASK);
1633 #if defined(FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED) && \
1634 (FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED == 1U)
1635 usbHostPointer->usbRegBase->MISCCTRL |= USB_MISCCTRL_SOFDYNTHLD_MASK;
1636 #endif
1637 usbHostPointer->trState = (uint32_t)kKhci_TrGetMsg;
1638
1639 *controllerHandle = (usb_host_handle)usbHostPointer;
1640 return status;
1641 }
1642
1643 /*!
1644 * @brief destroy USB host khci instance.
1645 *
1646 * This function de-initialize the USB host khci controller driver.
1647 *
1648 * @param handle the controller handle.
1649 *
1650 * @retval kStatus_USB_Success The host is initialized successfully.
1651 */
USB_HostKhciDestory(usb_host_controller_handle controllerHandle)1652 usb_status_t USB_HostKhciDestory(usb_host_controller_handle controllerHandle)
1653 {
1654 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
1655
1656 usbHostPointer->usbRegBase->ISTAT = 0xFFU;
1657 usbHostPointer->usbRegBase->INTEN = 0U;
1658
1659 usbHostPointer->usbRegBase->ADDR = ((usbHostPointer->usbRegBase->ADDR & ((uint8_t)(~USB_ADDR_ADDR_MASK))) |
1660 ((((0U) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK)));
1661 usbHostPointer->usbRegBase->CTL = 0U;
1662 ;
1663 usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_PDE_MASK;
1664 usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_SUSP_MASK;
1665 usbHostPointer->usbRegBase->ADDR &= (uint8_t)(~USB_ADDR_LSEN_MASK);
1666
1667 if (NULL != usbHostPointer->khciEventPointer)
1668 {
1669 (void)OSA_EventDestroy(usbHostPointer->khciEventPointer);
1670 }
1671 if (NULL != usbHostPointer->khciMutex)
1672 {
1673 (void)OSA_MutexDestroy(usbHostPointer->khciMutex);
1674 }
1675
1676 if (NULL != usbHostPointer->khciSwapBufPointer)
1677 {
1678 OSA_MemoryFree(usbHostPointer->khciSwapBufPointer);
1679 usbHostPointer->khciSwapBufPointer = NULL;
1680 }
1681
1682 OSA_MemoryFree(usbHostPointer);
1683
1684 return kStatus_USB_Success;
1685 }
1686
1687 /*!
1688 * @brief open USB host pipe.
1689 *
1690 * This function open one pipe according to the pipeInitPointer parameter.
1691 *
1692 * @param controllerHandle the controller handle.
1693 * @param pipeHandlePointer the pipe handle pointer, it is used to return the pipe handle.
1694 * @param pipeInitPointer it is used to initialize the pipe.
1695 *
1696 * @retval kStatus_USB_Success The host is initialized successfully.
1697 * @retval kStatus_USB_Error there is no idle pipe.
1698 *
1699 */
USB_HostKhciOpenPipe(usb_host_controller_handle controllerHandle,usb_host_pipe_handle * pipeHandlePointer,usb_host_pipe_init_t * pipeInitPointer)1700 usb_status_t USB_HostKhciOpenPipe(usb_host_controller_handle controllerHandle,
1701 usb_host_pipe_handle *pipeHandlePointer,
1702 usb_host_pipe_init_t *pipeInitPointer)
1703 {
1704 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
1705 usb_host_pipe_t *pipePointer;
1706 usb_host_pipe_t *prePipePointer;
1707 usb_host_pipe_t *tempPipePointer;
1708
1709 OSA_SR_ALLOC();
1710 OSA_ENTER_CRITICAL();
1711 pipePointer = (usb_host_pipe_t *)OSA_MemoryAllocate(sizeof(usb_host_pipe_t));
1712 if (pipePointer == NULL)
1713 {
1714 OSA_MemoryFree(usbHostPointer);
1715 return kStatus_USB_AllocFail;
1716 }
1717 else
1718 {
1719 if (usbHostPointer->pipeDescriptorBasePointer == NULL)
1720 {
1721 usbHostPointer->pipeDescriptorBasePointer = pipePointer;
1722 }
1723 else
1724 {
1725 tempPipePointer = usbHostPointer->pipeDescriptorBasePointer;
1726 while (NULL != tempPipePointer)
1727 {
1728 prePipePointer = tempPipePointer;
1729 tempPipePointer = tempPipePointer->next;
1730 }
1731 prePipePointer->next = pipePointer;
1732 }
1733 pipePointer->next = NULL;
1734 }
1735 OSA_EXIT_CRITICAL();
1736
1737 pipePointer->deviceHandle = pipeInitPointer->devInstance;
1738 pipePointer->endpointAddress = pipeInitPointer->endpointAddress;
1739 pipePointer->direction = pipeInitPointer->direction;
1740 pipePointer->interval = pipeInitPointer->interval;
1741 pipePointer->maxPacketSize = pipeInitPointer->maxPacketSize;
1742 pipePointer->pipeType = pipeInitPointer->pipeType;
1743 pipePointer->numberPerUframe = pipeInitPointer->numberPerUframe;
1744 pipePointer->nakCount = pipeInitPointer->nakCount;
1745 pipePointer->nextdata01 = 0U;
1746 pipePointer->open = (uint8_t)1U;
1747 pipePointer->currentCount = 0xffffU;
1748
1749 if (pipePointer->pipeType == USB_ENDPOINT_ISOCHRONOUS)
1750 {
1751 pipePointer->interval = (uint16_t)(1UL << (pipeInitPointer->interval - 1U));
1752 }
1753 else
1754 {
1755 pipePointer->interval = (uint16_t)_USB_HostKhciGetRoundUpPow2(pipeInitPointer->interval);
1756 }
1757 *pipeHandlePointer = pipePointer;
1758
1759 return kStatus_USB_Success;
1760 }
1761
1762 /*!
1763 * @brief close USB host pipe.
1764 *
1765 * This function close one pipe and release the related resources.
1766 *
1767 * @param controllerHandle the controller handle.
1768 * @param pipeHandle the closing pipe handle.
1769 *
1770 * @retval kStatus_USB_Success The host is initialized successfully.
1771 */
USB_HostKhciClosePipe(usb_host_controller_handle controllerHandle,usb_host_pipe_handle pipeHandle)1772 usb_status_t USB_HostKhciClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle)
1773 {
1774 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
1775 usb_host_pipe_t *pipePointer = (usb_host_pipe_t *)pipeHandle;
1776 usb_host_pipe_t *prePipePointer;
1777
1778 OSA_SR_ALLOC();
1779 OSA_ENTER_CRITICAL();
1780
1781 if ((pipePointer != NULL) && (pipePointer->open == (uint8_t)1U))
1782 {
1783 if (pipeHandle == usbHostPointer->pipeDescriptorBasePointer)
1784 {
1785 usbHostPointer->pipeDescriptorBasePointer = usbHostPointer->pipeDescriptorBasePointer->next;
1786 OSA_MemoryFree(pipeHandle);
1787 }
1788 else
1789 {
1790 pipePointer = usbHostPointer->pipeDescriptorBasePointer;
1791 prePipePointer = pipePointer;
1792 while (NULL != pipePointer)
1793 {
1794 if ((0U != pipePointer->open) && (pipePointer == pipeHandle))
1795 {
1796 prePipePointer->next = pipePointer->next;
1797 OSA_MemoryFree(pipePointer);
1798 break;
1799 }
1800 prePipePointer = pipePointer;
1801 pipePointer = pipePointer->next;
1802 }
1803 }
1804 }
1805 else
1806 {
1807 #ifdef HOST_ECHO
1808 usb_echo("usb_khci_close_pipe invalid pipe \n");
1809 #endif
1810 }
1811 OSA_EXIT_CRITICAL();
1812
1813 return kStatus_USB_Success;
1814 }
1815
1816 /*!
1817 * @brief send data to pipe.
1818 *
1819 * This function request to send the transfer to the specified pipe.
1820 *
1821 * @param controllerHandle the controller handle.
1822 * @param pipeHandle the sending pipe handle.
1823 * @param transfer the transfer which will be wrote.
1824 *
1825 * @retval kStatus_USB_Success send successfully.
1826 * @retval kStatus_USB_LackSwapBuffer there is no swap buffer for KHCI.
1827 *
1828 */
USB_HostKhciWritePipe(usb_host_controller_handle controllerHandle,usb_host_pipe_handle pipeHandle,usb_host_transfer_t * transfer)1829 usb_status_t USB_HostKhciWritePipe(usb_host_controller_handle controllerHandle,
1830 usb_host_pipe_handle pipeHandle,
1831 usb_host_transfer_t *transfer)
1832 {
1833 usb_status_t status = kStatus_USB_Success;
1834 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
1835
1836 usb_host_pipe_t *pipePointer = (usb_host_pipe_t *)pipeHandle;
1837
1838 transfer->transferPipe = pipePointer;
1839 transfer->retry = RETRY_TIME;
1840
1841 if (pipePointer->endpointAddress == 0U)
1842 {
1843 if ((transfer->direction == USB_IN) && (transfer->transferBuffer != NULL) &&
1844 ((0U != (transfer->transferLength & USB_MEM4_ALIGN_MASK)) ||
1845 (0U != ((uint32_t)transfer->transferBuffer & USB_MEM4_ALIGN_MASK))))
1846 {
1847 if (usbHostPointer->khciSwapBufPointer == NULL)
1848 {
1849 return kStatus_USB_LackSwapBuffer;
1850 }
1851 if (pipePointer->maxPacketSize > USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER)
1852 {
1853 return kStatus_USB_LackSwapBuffer;
1854 }
1855 }
1856 transfer->setupStatus = (uint8_t)kTransfer_Setup0;
1857
1858 if (0U != transfer->transferLength)
1859 {
1860 if (transfer->direction == USB_IN)
1861 {
1862 transfer->nakTimeout = USB_TIMEOUT_TOHOST;
1863 }
1864 else
1865 {
1866 transfer->nakTimeout = USB_TIMEOUT_TODEVICE;
1867 }
1868 }
1869 else
1870 {
1871 transfer->nakTimeout = USB_TIMEOUT_NODATA;
1872 }
1873 }
1874 else
1875 {
1876 if (pipePointer->nakCount == 0U)
1877 {
1878 transfer->nakTimeout = USB_TIMEOUT_DEFAULT;
1879 }
1880 else
1881 {
1882 transfer->nakTimeout = pipePointer->nakCount * NAK_RETRY_TIME;
1883 }
1884 }
1885 transfer->union2.frame = _USB_HostKhciGetFrameCountSum(usbHostPointer);
1886
1887 (void)_USB_HostKhciLinkTrRequestToList(controllerHandle, transfer);
1888
1889 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
1890
1891 return status;
1892 }
1893
1894 /*!
1895 * @brief receive data from pipe.
1896 *
1897 * This function request to receive the transfer from the specified pipe.
1898 *
1899 * @param controllerHandle the controller handle.
1900 * @param pipeHandle the receiving pipe handle.
1901 * @param transfer the transfer which will be read.
1902 *
1903 * @retval kStatus_USB_Success send successfully.
1904 * @retval kStatus_USB_LackSwapBuffer there is no swap buffer for KHCI.
1905 *
1906 */
USB_HostKhciReadpipe(usb_host_controller_handle controllerHandle,usb_host_pipe_handle pipeHandle,usb_host_transfer_t * transfer)1907 usb_status_t USB_HostKhciReadpipe(usb_host_controller_handle controllerHandle,
1908 usb_host_pipe_handle pipeHandle,
1909 usb_host_transfer_t *transfer)
1910 {
1911 usb_status_t status = kStatus_USB_Success;
1912 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
1913 usb_host_pipe_t *pipePointer = (usb_host_pipe_t *)pipeHandle;
1914
1915 if ((0U != (transfer->transferLength & USB_MEM4_ALIGN_MASK)) ||
1916 (0U != ((uint32_t)transfer->transferBuffer & USB_MEM4_ALIGN_MASK)))
1917 {
1918 if (usbHostPointer->khciSwapBufPointer == NULL)
1919 {
1920 return kStatus_USB_LackSwapBuffer;
1921 }
1922 if (pipePointer->maxPacketSize > USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER)
1923 {
1924 return kStatus_USB_LackSwapBuffer;
1925 }
1926 }
1927
1928 transfer->transferPipe = pipePointer;
1929 transfer->transferSofar = 0U;
1930 if (pipePointer->nakCount == 0U)
1931 {
1932 transfer->nakTimeout = USB_TIMEOUT_DEFAULT;
1933 }
1934 else
1935 {
1936 transfer->nakTimeout = pipePointer->nakCount * NAK_RETRY_TIME;
1937 }
1938 transfer->retry = RETRY_TIME;
1939 transfer->union2.frame = _USB_HostKhciGetFrameCountSum(usbHostPointer);
1940
1941 (void)_USB_HostKhciLinkTrRequestToList(controllerHandle, transfer);
1942 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
1943
1944 return status;
1945 }
1946
1947 /*!
1948 * @brief cancel pipe's transfers.
1949 *
1950 * @param handle Pointer of the host khci controller handle.
1951 * @param pipePointer Pointer of the pipe.
1952 * @param trPointer The canceling transfer.
1953 *
1954 * @return kStatus_USB_Success or error codes.
1955 */
_USB_HostKhciCancelPipe(usb_host_controller_handle handle,usb_host_pipe_t * pipePointer,usb_host_transfer_t * trPointer)1956 static usb_status_t _USB_HostKhciCancelPipe(usb_host_controller_handle handle,
1957 usb_host_pipe_t *pipePointer,
1958 usb_host_transfer_t *trPointer)
1959 {
1960 usb_host_transfer_t *temptr = NULL;
1961 usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
1962
1963 if ((pipePointer->pipeType == USB_ENDPOINT_ISOCHRONOUS) || (pipePointer->pipeType == USB_ENDPOINT_INTERRUPT))
1964 {
1965 temptr = usbHostPointer->periodicListPointer;
1966 }
1967 else if ((pipePointer->pipeType == USB_ENDPOINT_CONTROL) || (pipePointer->pipeType == USB_ENDPOINT_BULK))
1968 {
1969 temptr = usbHostPointer->asyncListPointer;
1970 }
1971 else
1972 {
1973 /*no action*/
1974 }
1975
1976 while (temptr != NULL)
1977 {
1978 if (((usb_host_pipe_t *)(temptr->transferPipe) == pipePointer) &&
1979 ((trPointer == NULL) || (trPointer == temptr)))
1980 {
1981 _USB_HostKhciUnlinkTrRequestFromList(handle, temptr);
1982 /* callback function is different from the current condition */
1983 temptr->callbackFn(temptr->callbackParam, temptr, kStatus_USB_TransferCancel);
1984 return kStatus_USB_Success;
1985 }
1986 temptr = temptr->next;
1987 }
1988
1989 return kStatus_USB_Success;
1990 }
1991
1992 /*!
1993 * @brief khci bus control.
1994 *
1995 * @param handle Pointer of the host khci controller handle.
1996 * @param busControl Bus control code.
1997 *
1998 * @return kStatus_USB_Success
1999 */
_USB_HostKhciBusControl(usb_host_controller_handle handle,uint8_t busControl)2000 static usb_status_t _USB_HostKhciBusControl(usb_host_controller_handle handle, uint8_t busControl)
2001 {
2002 ptr_usb_host_khci_state_struct_t usbHostPointer = (usb_khci_host_state_struct_t *)handle;
2003
2004 usb_host_bus_control_t busControlCode = (usb_host_bus_control_t)busControl;
2005 if (busControlCode == kUSB_HostBusReset)
2006 {
2007 while (0U != ((usbHostPointer->usbRegBase->CTL) & USB_CTL_TXSUSPENDTOKENBUSY_MASK))
2008 {
2009 }
2010 usbHostPointer->usbRegBase->CTL |= USB_CTL_RESET_MASK;
2011 /* wait for 30 milliseconds (2.5 is minimum for reset, 10 recommended) */
2012 _USB_HostKhciDelay(usbHostPointer, 30U);
2013 usbHostPointer->usbRegBase->CTL &= (uint8_t)(~USB_CTL_RESET_MASK);
2014 usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
2015 usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
2016
2017 usbHostPointer->txBd = 0U;
2018 usbHostPointer->rxBd = 0U;
2019 }
2020 else if (busControlCode == kUSB_HostBusRestart)
2021 {
2022 usbHostPointer->deviceAttached = 0;
2023
2024 usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
2025 usbHostPointer->usbRegBase->ISTAT = 0xffU;
2026 /* Now, enable only USB interrupt attach for host mode */
2027 usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
2028 }
2029 else if (busControlCode == kUSB_HostBusEnableAttach)
2030 {
2031 if (usbHostPointer->deviceAttached <= 0)
2032 {
2033 usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
2034 }
2035 }
2036 else if (busControlCode == kUSB_HostBusDisableAttach)
2037 {
2038 usbHostPointer->usbRegBase->INTEN &= (uint8_t)(~USB_INTEN_ATTACHEN_MASK);
2039 }
2040 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
2041 else if (kUSB_HostBusSuspend == busControlCode)
2042 {
2043 if ((kBus_Idle != usbHostPointer->busSuspendStatus) || (0 == usbHostPointer->deviceAttached))
2044 {
2045 return kStatus_USB_Error;
2046 }
2047 usbHostPointer->busSuspendStatus = kBus_StartSuspend;
2048 }
2049 else if (kUSB_HostBusResume == busControlCode)
2050 {
2051 usb_host_instance_t *hostPointer = (usb_host_instance_t *)usbHostPointer->hostHandle;
2052 if ((kBus_Suspended != usbHostPointer->busSuspendStatus) || (0 == usbHostPointer->deviceAttached))
2053 {
2054 return kStatus_USB_Error;
2055 }
2056
2057 usbHostPointer->usbRegBase->INTEN &= (uint8_t)(~USB_INTEN_RESUMEEN_MASK);
2058 usbHostPointer->usbRegBase->USBTRC0 &= (uint8_t)(~USB_USBTRC0_USBRESMEN_MASK);
2059 usbHostPointer->busSuspendStatus = kBus_StartResume;
2060
2061 /* Do USB bus resume here */
2062 usbHostPointer->usbRegBase->CTL |= USB_CTL_RESUME_MASK;
2063
2064 usbHostPointer->matchTick = hostPointer->hwTick;
2065
2066 (void)OSA_EventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_RESUME);
2067 }
2068 #endif
2069 else
2070 {
2071 /*no action*/
2072 }
2073
2074 return kStatus_USB_Success;
2075 }
2076
2077 /*!
2078 * @brief io control khci.
2079 *
2080 * This function implemented khci io control khci.
2081 *
2082 * @param controllerHandle the controller handle.
2083 * @param ioctlEvent please reference to enumeration host_busControl_t.
2084 * @param ioctlParam the control parameter.
2085 *
2086 * @retval kStatus_USB_Success io control successfully.
2087 * @retval kStatus_USB_InvalidHandle The controllerHandle is a NULL pointer.
2088 */
USB_HostKciIoctl(usb_host_controller_handle controllerHandle,uint32_t ioctlEvent,void * ioctlParam)2089 usb_status_t USB_HostKciIoctl(usb_host_controller_handle controllerHandle, uint32_t ioctlEvent, void *ioctlParam)
2090 {
2091 usb_status_t status = kStatus_USB_Success;
2092 usb_host_cancel_param_t *param;
2093
2094 if (controllerHandle == NULL)
2095 {
2096 return kStatus_USB_InvalidHandle;
2097 }
2098 usb_host_controller_control_t controlCode = (usb_host_controller_control_t)ioctlEvent;
2099 switch (controlCode)
2100 {
2101 case kUSB_HostCancelTransfer:
2102 param = (usb_host_cancel_param_t *)ioctlParam;
2103 status = _USB_HostKhciCancelPipe(controllerHandle, (usb_host_pipe_t *)param->pipeHandle, param->transfer);
2104 break;
2105
2106 case kUSB_HostBusControl:
2107 status = _USB_HostKhciBusControl(controllerHandle, *((uint8_t *)ioctlParam));
2108 break;
2109
2110 case kUSB_HostGetFrameNumber:
2111 *((uint32_t *)ioctlParam) = _USB_HostKhciGetFrameCount(controllerHandle);
2112 break;
2113
2114 case kUSB_HostUpdateControlEndpointAddress:
2115 _USB_HostKhciDelay((usb_khci_host_state_struct_t *)controllerHandle, 2);
2116 break;
2117
2118 default:
2119 status = kStatus_USB_NotSupported;
2120 break;
2121 }
2122 return status;
2123 }
2124 #endif /* USB_HOST_CONFIG_KHCI */
2125