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