1 /** @file
2 
3   The XHCI register operation routines.
4 
5 Copyright (c) 2011 - 2017, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "Xhci.h"
11 
12 /**
13   Read 1-byte width XHCI capability register.
14 
15   @param  Xhc          The XHCI Instance.
16   @param  Offset       The offset of the 1-byte width capability register.
17 
18   @return The register content read.
19   @retval If err, return 0xFF.
20 
21 **/
22 UINT8
XhcReadCapReg8(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset)23 XhcReadCapReg8 (
24   IN  USB_XHCI_INSTANCE   *Xhc,
25   IN  UINT32              Offset
26   )
27 {
28   UINT8                   Data;
29   EFI_STATUS              Status;
30 
31   Status = Xhc->PciIo->Mem.Read (
32                              Xhc->PciIo,
33                              EfiPciIoWidthUint8,
34                              XHC_BAR_INDEX,
35                              (UINT64) Offset,
36                              1,
37                              &Data
38                              );
39 
40   if (EFI_ERROR (Status)) {
41     DEBUG ((EFI_D_ERROR, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status, Offset));
42     Data = 0xFF;
43   }
44 
45   return Data;
46 }
47 
48 /**
49   Read 4-bytes width XHCI capability register.
50 
51   @param  Xhc          The XHCI Instance.
52   @param  Offset       The offset of the 4-bytes width capability register.
53 
54   @return The register content read.
55   @retval If err, return 0xFFFFFFFF.
56 
57 **/
58 UINT32
XhcReadCapReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset)59 XhcReadCapReg (
60   IN  USB_XHCI_INSTANCE   *Xhc,
61   IN  UINT32              Offset
62   )
63 {
64   UINT32                  Data;
65   EFI_STATUS              Status;
66 
67   Status = Xhc->PciIo->Mem.Read (
68                              Xhc->PciIo,
69                              EfiPciIoWidthUint32,
70                              XHC_BAR_INDEX,
71                              (UINT64) Offset,
72                              1,
73                              &Data
74                              );
75 
76   if (EFI_ERROR (Status)) {
77     DEBUG ((EFI_D_ERROR, "XhcReadCapReg: Pci Io read error - %r at %d\n", Status, Offset));
78     Data = 0xFFFFFFFF;
79   }
80 
81   return Data;
82 }
83 
84 /**
85   Read 4-bytes width XHCI Operational register.
86 
87   @param  Xhc          The XHCI Instance.
88   @param  Offset       The offset of the 4-bytes width operational register.
89 
90   @return The register content read.
91   @retval If err, return 0xFFFFFFFF.
92 
93 **/
94 UINT32
XhcReadOpReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset)95 XhcReadOpReg (
96   IN  USB_XHCI_INSTANCE   *Xhc,
97   IN  UINT32              Offset
98   )
99 {
100   UINT32                  Data;
101   EFI_STATUS              Status;
102 
103   ASSERT (Xhc->CapLength != 0);
104 
105   Status = Xhc->PciIo->Mem.Read (
106                              Xhc->PciIo,
107                              EfiPciIoWidthUint32,
108                              XHC_BAR_INDEX,
109                              Xhc->CapLength + Offset,
110                              1,
111                              &Data
112                              );
113 
114   if (EFI_ERROR (Status)) {
115     DEBUG ((EFI_D_ERROR, "XhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset));
116     Data = 0xFFFFFFFF;
117   }
118 
119   return Data;
120 }
121 
122 /**
123   Write the data to the 4-bytes width XHCI operational register.
124 
125   @param  Xhc      The XHCI Instance.
126   @param  Offset   The offset of the 4-bytes width operational register.
127   @param  Data     The data to write.
128 
129 **/
130 VOID
XhcWriteOpReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Data)131 XhcWriteOpReg (
132   IN USB_XHCI_INSTANCE    *Xhc,
133   IN UINT32               Offset,
134   IN UINT32               Data
135   )
136 {
137   EFI_STATUS              Status;
138 
139   ASSERT (Xhc->CapLength != 0);
140 
141   Status = Xhc->PciIo->Mem.Write (
142                              Xhc->PciIo,
143                              EfiPciIoWidthUint32,
144                              XHC_BAR_INDEX,
145                              Xhc->CapLength + Offset,
146                              1,
147                              &Data
148                              );
149 
150   if (EFI_ERROR (Status)) {
151     DEBUG ((EFI_D_ERROR, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
152   }
153 }
154 
155 
156 
157 
158 
159 /**
160   Write the data to the XHCI door bell register.
161 
162   @param  Xhc          The XHCI Instance.
163   @param  Offset       The offset of the door bell register.
164   @param  Data         The data to write.
165 
166 **/
167 VOID
XhcWriteDoorBellReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Data)168 XhcWriteDoorBellReg (
169   IN USB_XHCI_INSTANCE    *Xhc,
170   IN UINT32               Offset,
171   IN UINT32               Data
172   )
173 {
174   EFI_STATUS              Status;
175 
176   ASSERT (Xhc->DBOff != 0);
177 
178   Status = Xhc->PciIo->Mem.Write (
179                              Xhc->PciIo,
180                              EfiPciIoWidthUint32,
181                              XHC_BAR_INDEX,
182                              Xhc->DBOff + Offset,
183                              1,
184                              &Data
185                              );
186 
187   if (EFI_ERROR (Status)) {
188     DEBUG ((EFI_D_ERROR, "XhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
189   }
190 }
191 
192 /**
193   Read XHCI runtime register.
194 
195   @param  Xhc          The XHCI Instance.
196   @param  Offset       The offset of the runtime register.
197 
198   @return The register content read
199 
200 **/
201 UINT32
XhcReadRuntimeReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset)202 XhcReadRuntimeReg (
203   IN  USB_XHCI_INSTANCE   *Xhc,
204   IN  UINT32              Offset
205   )
206 {
207   UINT32                  Data;
208   EFI_STATUS              Status;
209 
210   ASSERT (Xhc->RTSOff != 0);
211 
212   Status = Xhc->PciIo->Mem.Read (
213                              Xhc->PciIo,
214                              EfiPciIoWidthUint32,
215                              XHC_BAR_INDEX,
216                              Xhc->RTSOff + Offset,
217                              1,
218                              &Data
219                              );
220 
221   if (EFI_ERROR (Status)) {
222     DEBUG ((EFI_D_ERROR, "XhcReadRuntimeReg: Pci Io Read error - %r at %d\n", Status, Offset));
223     Data = 0xFFFFFFFF;
224   }
225 
226   return Data;
227 }
228 
229 /**
230   Write the data to the XHCI runtime register.
231 
232   @param  Xhc          The XHCI Instance.
233   @param  Offset       The offset of the runtime register.
234   @param  Data         The data to write.
235 
236 **/
237 VOID
XhcWriteRuntimeReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Data)238 XhcWriteRuntimeReg (
239   IN USB_XHCI_INSTANCE    *Xhc,
240   IN UINT32               Offset,
241   IN UINT32               Data
242   )
243 {
244   EFI_STATUS              Status;
245 
246   ASSERT (Xhc->RTSOff != 0);
247 
248   Status = Xhc->PciIo->Mem.Write (
249                              Xhc->PciIo,
250                              EfiPciIoWidthUint32,
251                              XHC_BAR_INDEX,
252                              Xhc->RTSOff + Offset,
253                              1,
254                              &Data
255                              );
256 
257   if (EFI_ERROR (Status)) {
258     DEBUG ((EFI_D_ERROR, "XhcWriteRuntimeReg: Pci Io Write error: %r at %d\n", Status, Offset));
259   }
260 }
261 
262 /**
263   Read XHCI extended capability register.
264 
265   @param  Xhc          The XHCI Instance.
266   @param  Offset       The offset of the extended capability register.
267 
268   @return The register content read
269 
270 **/
271 UINT32
XhcReadExtCapReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset)272 XhcReadExtCapReg (
273   IN  USB_XHCI_INSTANCE   *Xhc,
274   IN  UINT32              Offset
275   )
276 {
277   UINT32                  Data;
278   EFI_STATUS              Status;
279 
280   ASSERT (Xhc->ExtCapRegBase != 0);
281 
282   Status = Xhc->PciIo->Mem.Read (
283                              Xhc->PciIo,
284                              EfiPciIoWidthUint32,
285                              XHC_BAR_INDEX,
286                              Xhc->ExtCapRegBase + Offset,
287                              1,
288                              &Data
289                              );
290 
291   if (EFI_ERROR (Status)) {
292     DEBUG ((EFI_D_ERROR, "XhcReadExtCapReg: Pci Io Read error - %r at %d\n", Status, Offset));
293     Data = 0xFFFFFFFF;
294   }
295 
296   return Data;
297 }
298 
299 /**
300   Write the data to the XHCI extended capability register.
301 
302   @param  Xhc          The XHCI Instance.
303   @param  Offset       The offset of the extended capability register.
304   @param  Data         The data to write.
305 
306 **/
307 VOID
XhcWriteExtCapReg(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Data)308 XhcWriteExtCapReg (
309   IN USB_XHCI_INSTANCE    *Xhc,
310   IN UINT32               Offset,
311   IN UINT32               Data
312   )
313 {
314   EFI_STATUS              Status;
315 
316   ASSERT (Xhc->ExtCapRegBase != 0);
317 
318   Status = Xhc->PciIo->Mem.Write (
319                              Xhc->PciIo,
320                              EfiPciIoWidthUint32,
321                              XHC_BAR_INDEX,
322                              Xhc->ExtCapRegBase + Offset,
323                              1,
324                              &Data
325                              );
326 
327   if (EFI_ERROR (Status)) {
328     DEBUG ((EFI_D_ERROR, "XhcWriteExtCapReg: Pci Io Write error: %r at %d\n", Status, Offset));
329   }
330 }
331 
332 
333 /**
334   Set one bit of the runtime register while keeping other bits.
335 
336   @param  Xhc          The XHCI Instance.
337   @param  Offset       The offset of the runtime register.
338   @param  Bit          The bit mask of the register to set.
339 
340 **/
341 VOID
XhcSetRuntimeRegBit(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Bit)342 XhcSetRuntimeRegBit (
343   IN USB_XHCI_INSTANCE    *Xhc,
344   IN UINT32               Offset,
345   IN UINT32               Bit
346   )
347 {
348   UINT32                  Data;
349 
350   Data  = XhcReadRuntimeReg (Xhc, Offset);
351   Data |= Bit;
352   XhcWriteRuntimeReg (Xhc, Offset, Data);
353 }
354 
355 /**
356   Clear one bit of the runtime register while keeping other bits.
357 
358   @param  Xhc          The XHCI Instance.
359   @param  Offset       The offset of the runtime register.
360   @param  Bit          The bit mask of the register to set.
361 
362 **/
363 VOID
XhcClearRuntimeRegBit(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Bit)364 XhcClearRuntimeRegBit (
365   IN USB_XHCI_INSTANCE    *Xhc,
366   IN UINT32               Offset,
367   IN UINT32               Bit
368   )
369 {
370   UINT32                  Data;
371 
372   Data  = XhcReadRuntimeReg (Xhc, Offset);
373   Data &= ~Bit;
374   XhcWriteRuntimeReg (Xhc, Offset, Data);
375 }
376 
377 /**
378   Set one bit of the operational register while keeping other bits.
379 
380   @param  Xhc          The XHCI Instance.
381   @param  Offset       The offset of the operational register.
382   @param  Bit          The bit mask of the register to set.
383 
384 **/
385 VOID
XhcSetOpRegBit(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Bit)386 XhcSetOpRegBit (
387   IN USB_XHCI_INSTANCE    *Xhc,
388   IN UINT32               Offset,
389   IN UINT32               Bit
390   )
391 {
392   UINT32                  Data;
393 
394   Data  = XhcReadOpReg (Xhc, Offset);
395   Data |= Bit;
396   XhcWriteOpReg (Xhc, Offset, Data);
397 }
398 
399 
400 /**
401   Clear one bit of the operational register while keeping other bits.
402 
403   @param  Xhc          The XHCI Instance.
404   @param  Offset       The offset of the operational register.
405   @param  Bit          The bit mask of the register to clear.
406 
407 **/
408 VOID
XhcClearOpRegBit(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Bit)409 XhcClearOpRegBit (
410   IN USB_XHCI_INSTANCE    *Xhc,
411   IN UINT32               Offset,
412   IN UINT32               Bit
413   )
414 {
415   UINT32                  Data;
416 
417   Data  = XhcReadOpReg (Xhc, Offset);
418   Data &= ~Bit;
419   XhcWriteOpReg (Xhc, Offset, Data);
420 }
421 
422 /**
423   Wait the operation register's bit as specified by Bit
424   to become set (or clear).
425 
426   @param  Xhc                    The XHCI Instance.
427   @param  Offset                 The offset of the operation register.
428   @param  Bit                    The bit of the register to wait for.
429   @param  WaitToSet              Wait the bit to set or clear.
430   @param  Timeout                The time to wait before abort (in millisecond, ms).
431 
432   @retval EFI_SUCCESS            The bit successfully changed by host controller.
433   @retval EFI_TIMEOUT            The time out occurred.
434   @retval EFI_OUT_OF_RESOURCES   Memory for the timer event could not be allocated.
435 
436 **/
437 EFI_STATUS
XhcWaitOpRegBit(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Offset,IN UINT32 Bit,IN BOOLEAN WaitToSet,IN UINT32 Timeout)438 XhcWaitOpRegBit (
439   IN USB_XHCI_INSTANCE    *Xhc,
440   IN UINT32               Offset,
441   IN UINT32               Bit,
442   IN BOOLEAN              WaitToSet,
443   IN UINT32               Timeout
444   )
445 {
446   EFI_STATUS Status;
447   EFI_EVENT  TimeoutEvent;
448 
449   TimeoutEvent = NULL;
450 
451   if (Timeout == 0) {
452     return EFI_TIMEOUT;
453   }
454 
455   Status = gBS->CreateEvent (
456                   EVT_TIMER,
457                   TPL_CALLBACK,
458                   NULL,
459                   NULL,
460                   &TimeoutEvent
461                   );
462 
463   if (EFI_ERROR(Status)) {
464     goto DONE;
465   }
466 
467   Status = gBS->SetTimer (TimeoutEvent,
468                           TimerRelative,
469                           EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
470 
471   if (EFI_ERROR(Status)) {
472     goto DONE;
473   }
474 
475   do {
476     if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
477       Status = EFI_SUCCESS;
478       goto DONE;
479     }
480 
481     gBS->Stall (XHC_1_MICROSECOND);
482   } while (EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));
483 
484   Status = EFI_TIMEOUT;
485 
486 DONE:
487   if (TimeoutEvent != NULL) {
488     gBS->CloseEvent (TimeoutEvent);
489   }
490 
491   return Status;
492 }
493 
494 /**
495   Set Bios Ownership
496 
497   @param  Xhc          The XHCI Instance.
498 
499 **/
500 VOID
XhcSetBiosOwnership(IN USB_XHCI_INSTANCE * Xhc)501 XhcSetBiosOwnership (
502   IN USB_XHCI_INSTANCE    *Xhc
503   )
504 {
505   UINT32                    Buffer;
506 
507   if (Xhc->UsbLegSupOffset == 0xFFFFFFFF) {
508     return;
509   }
510 
511   DEBUG ((EFI_D_INFO, "XhcSetBiosOwnership: called to set BIOS ownership\n"));
512 
513   Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
514   Buffer = ((Buffer & (~USBLEGSP_OS_SEMAPHORE)) | USBLEGSP_BIOS_SEMAPHORE);
515   XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
516 }
517 
518 /**
519   Clear Bios Ownership
520 
521   @param  Xhc       The XHCI Instance.
522 
523 **/
524 VOID
XhcClearBiosOwnership(IN USB_XHCI_INSTANCE * Xhc)525 XhcClearBiosOwnership (
526   IN USB_XHCI_INSTANCE    *Xhc
527   )
528 {
529   UINT32                    Buffer;
530 
531   if (Xhc->UsbLegSupOffset == 0xFFFFFFFF) {
532     return;
533   }
534 
535   DEBUG ((EFI_D_INFO, "XhcClearBiosOwnership: called to clear BIOS ownership\n"));
536 
537   Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
538   Buffer = ((Buffer & (~USBLEGSP_BIOS_SEMAPHORE)) | USBLEGSP_OS_SEMAPHORE);
539   XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
540 }
541 
542 /**
543   Calculate the offset of the XHCI capability.
544 
545   @param  Xhc     The XHCI Instance.
546   @param  CapId   The XHCI Capability ID.
547 
548   @return The offset of XHCI legacy support capability register.
549 
550 **/
551 UINT32
XhcGetCapabilityAddr(IN USB_XHCI_INSTANCE * Xhc,IN UINT8 CapId)552 XhcGetCapabilityAddr (
553   IN USB_XHCI_INSTANCE    *Xhc,
554   IN UINT8                CapId
555   )
556 {
557   UINT32 ExtCapOffset;
558   UINT8  NextExtCapReg;
559   UINT32 Data;
560 
561   ExtCapOffset = 0;
562 
563   do {
564     //
565     // Check if the extended capability register's capability id is USB Legacy Support.
566     //
567     Data = XhcReadExtCapReg (Xhc, ExtCapOffset);
568     if ((Data & 0xFF) == CapId) {
569       return ExtCapOffset;
570     }
571     //
572     // If not, then traverse all of the ext capability registers till finding out it.
573     //
574     NextExtCapReg = (UINT8)((Data >> 8) & 0xFF);
575     ExtCapOffset += (NextExtCapReg << 2);
576   } while (NextExtCapReg != 0);
577 
578   return 0xFFFFFFFF;
579 }
580 
581 /**
582   Whether the XHCI host controller is halted.
583 
584   @param  Xhc     The XHCI Instance.
585 
586   @retval TRUE    The controller is halted.
587   @retval FALSE   It isn't halted.
588 
589 **/
590 BOOLEAN
XhcIsHalt(IN USB_XHCI_INSTANCE * Xhc)591 XhcIsHalt (
592   IN USB_XHCI_INSTANCE    *Xhc
593   )
594 {
595   return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT);
596 }
597 
598 
599 /**
600   Whether system error occurred.
601 
602   @param  Xhc      The XHCI Instance.
603 
604   @retval TRUE     System error happened.
605   @retval FALSE    No system error.
606 
607 **/
608 BOOLEAN
XhcIsSysError(IN USB_XHCI_INSTANCE * Xhc)609 XhcIsSysError (
610   IN USB_XHCI_INSTANCE    *Xhc
611   )
612 {
613   return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE);
614 }
615 
616 /**
617   Set USBCMD Host System Error Enable(HSEE) Bit if PCICMD SERR# Enable Bit is set.
618 
619   The USBCMD HSEE Bit will be reset to default 0 by USBCMD Host Controller Reset(HCRST).
620   This function is to set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
621 
622   @param Xhc            The XHCI Instance.
623 
624 **/
625 VOID
XhcSetHsee(IN USB_XHCI_INSTANCE * Xhc)626 XhcSetHsee (
627   IN USB_XHCI_INSTANCE  *Xhc
628   )
629 {
630   EFI_STATUS            Status;
631   EFI_PCI_IO_PROTOCOL   *PciIo;
632   UINT16                XhciCmd;
633 
634   PciIo = Xhc->PciIo;
635   Status = PciIo->Pci.Read (
636                         PciIo,
637                         EfiPciIoWidthUint16,
638                         PCI_COMMAND_OFFSET,
639                         sizeof (XhciCmd) / sizeof (UINT16),
640                         &XhciCmd
641                         );
642   if (!EFI_ERROR (Status)) {
643     if ((XhciCmd & EFI_PCI_COMMAND_SERR) != 0) {
644       XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_HSEE);
645     }
646   }
647 }
648 
649 /**
650   Reset the XHCI host controller.
651 
652   @param  Xhc          The XHCI Instance.
653   @param  Timeout      Time to wait before abort (in millisecond, ms).
654 
655   @retval EFI_SUCCESS  The XHCI host controller is reset.
656   @return Others       Failed to reset the XHCI before Timeout.
657 
658 **/
659 EFI_STATUS
XhcResetHC(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Timeout)660 XhcResetHC (
661   IN USB_XHCI_INSTANCE    *Xhc,
662   IN UINT32               Timeout
663   )
664 {
665   EFI_STATUS              Status;
666 
667   Status = EFI_SUCCESS;
668 
669   DEBUG ((EFI_D_INFO, "XhcResetHC!\n"));
670   //
671   // Host can only be reset when it is halt. If not so, halt it
672   //
673   if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
674     Status = XhcHaltHC (Xhc, Timeout);
675 
676     if (EFI_ERROR (Status)) {
677       return Status;
678     }
679   }
680 
681   if ((Xhc->DebugCapSupOffset == 0xFFFFFFFF) || ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) != XHC_CAP_USB_DEBUG) ||
682       ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) == 0)) {
683     XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
684     //
685     // Some XHCI host controllers require to have extra 1ms delay before accessing any MMIO register during reset.
686     // Otherwise there may have the timeout case happened.
687     // The below is a workaround to solve such problem.
688     //
689     gBS->Stall (XHC_1_MILLISECOND);
690     Status = XhcWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
691 
692     if (!EFI_ERROR (Status)) {
693       //
694       // The USBCMD HSEE Bit will be reset to default 0 by USBCMD HCRST.
695       // Set USBCMD HSEE Bit if PCICMD SERR# Enable Bit is set.
696       //
697       XhcSetHsee (Xhc);
698     }
699   }
700 
701   return Status;
702 }
703 
704 
705 /**
706   Halt the XHCI host controller.
707 
708   @param  Xhc          The XHCI Instance.
709   @param  Timeout      Time to wait before abort (in millisecond, ms).
710 
711   @return EFI_SUCCESS  The XHCI host controller is halt.
712   @return EFI_TIMEOUT  Failed to halt the XHCI before Timeout.
713 
714 **/
715 EFI_STATUS
XhcHaltHC(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Timeout)716 XhcHaltHC (
717   IN USB_XHCI_INSTANCE   *Xhc,
718   IN UINT32              Timeout
719   )
720 {
721   EFI_STATUS              Status;
722 
723   XhcClearOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
724   Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, TRUE, Timeout);
725   return Status;
726 }
727 
728 
729 /**
730   Set the XHCI host controller to run.
731 
732   @param  Xhc          The XHCI Instance.
733   @param  Timeout      Time to wait before abort (in millisecond, ms).
734 
735   @return EFI_SUCCESS  The XHCI host controller is running.
736   @return EFI_TIMEOUT  Failed to set the XHCI to run before Timeout.
737 
738 **/
739 EFI_STATUS
XhcRunHC(IN USB_XHCI_INSTANCE * Xhc,IN UINT32 Timeout)740 XhcRunHC (
741   IN USB_XHCI_INSTANCE    *Xhc,
742   IN UINT32               Timeout
743   )
744 {
745   EFI_STATUS              Status;
746 
747   XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
748   Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, FALSE, Timeout);
749   return Status;
750 }
751 
752