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