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