]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
Just like EhciDxe, do not reset host controller when debug capability is enabled...
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / XhciDxe / XhciReg.c
1 /** @file
2
3 The XHCI register operation routines.
4
5 Copyright (c) 2011, 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 UINTN Loop;
519
520 Loop = (Timeout * XHC_1_MILLISECOND / XHC_POLL_DELAY) + 1;
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_POLL_DELAY);
528 }
529
530 return EFI_TIMEOUT;
531 }
532
533 /**
534 Set Bios Ownership
535
536 @param Xhc The XHCI Instance.
537
538 **/
539 VOID
540 XhcSetBiosOwnership (
541 IN USB_XHCI_INSTANCE *Xhc
542 )
543 {
544 UINT32 Buffer;
545
546 DEBUG ((EFI_D_INFO, "XhcSetBiosOwnership: called to set BIOS ownership\n"));
547
548 Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
549 Buffer = ((Buffer & (~USBLEGSP_OS_SEMAPHORE)) | USBLEGSP_BIOS_SEMAPHORE);
550 XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
551 }
552
553 /**
554 Clear Bios Ownership
555
556 @param Xhc The XHCI Instance.
557
558 **/
559 VOID
560 XhcClearBiosOwnership (
561 IN USB_XHCI_INSTANCE *Xhc
562 )
563 {
564 UINT32 Buffer;
565
566 DEBUG ((EFI_D_INFO, "XhcClearBiosOwnership: called to clear BIOS ownership\n"));
567
568 Buffer = XhcReadExtCapReg (Xhc, Xhc->UsbLegSupOffset);
569 Buffer = ((Buffer & (~USBLEGSP_BIOS_SEMAPHORE)) | USBLEGSP_OS_SEMAPHORE);
570 XhcWriteExtCapReg (Xhc, Xhc->UsbLegSupOffset, Buffer);
571 }
572
573 /**
574 Calculate the offset of the XHCI capability.
575
576 @param Xhc The XHCI Instance.
577 @param CapId The XHCI Capability ID.
578
579 @return The offset of XHCI legacy support capability register.
580
581 **/
582 UINT32
583 XhcGetCapabilityAddr (
584 IN USB_XHCI_INSTANCE *Xhc,
585 IN UINT8 CapId
586 )
587 {
588 UINT32 ExtCapOffset;
589 UINT8 NextExtCapReg;
590 UINT32 Data;
591
592 ExtCapOffset = 0;
593
594 do {
595 //
596 // Check if the extended capability register's capability id is USB Legacy Support.
597 //
598 Data = XhcReadExtCapReg (Xhc, ExtCapOffset);
599 if ((Data & 0xFF) == CapId) {
600 return ExtCapOffset;
601 }
602 //
603 // If not, then traverse all of the ext capability registers till finding out it.
604 //
605 NextExtCapReg = (UINT8)((Data >> 8) & 0xFF);
606 ExtCapOffset += (NextExtCapReg << 2);
607 } while (NextExtCapReg != 0);
608
609 return 0;
610 }
611
612 /**
613 Whether the XHCI host controller is halted.
614
615 @param Xhc The XHCI Instance.
616
617 @retval TRUE The controller is halted.
618 @retval FALSE It isn't halted.
619
620 **/
621 BOOLEAN
622 XhcIsHalt (
623 IN USB_XHCI_INSTANCE *Xhc
624 )
625 {
626 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT);
627 }
628
629
630 /**
631 Whether system error occurred.
632
633 @param Xhc The XHCI Instance.
634
635 @retval TRUE System error happened.
636 @retval FALSE No system error.
637
638 **/
639 BOOLEAN
640 XhcIsSysError (
641 IN USB_XHCI_INSTANCE *Xhc
642 )
643 {
644 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE);
645 }
646
647 /**
648 Reset the XHCI host controller.
649
650 @param Xhc The XHCI Instance.
651 @param Timeout Time to wait before abort (in millisecond, ms).
652
653 @retval EFI_SUCCESS The XHCI host controller is reset.
654 @return Others Failed to reset the XHCI before Timeout.
655
656 **/
657 EFI_STATUS
658 XhcResetHC (
659 IN USB_XHCI_INSTANCE *Xhc,
660 IN UINT32 Timeout
661 )
662 {
663 EFI_STATUS Status;
664
665 Status = EFI_SUCCESS;
666
667 DEBUG ((EFI_D_INFO, "XhcResetHC!\n"));
668 //
669 // Host can only be reset when it is halt. If not so, halt it
670 //
671 if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
672 Status = XhcHaltHC (Xhc, Timeout);
673
674 if (EFI_ERROR (Status)) {
675 return Status;
676 }
677 }
678
679 if (((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset) & 0xFF) != XHC_CAP_USB_DEBUG) ||
680 ((XhcReadExtCapReg (Xhc, Xhc->DebugCapSupOffset + XHC_DC_DCCTRL) & BIT0) == 0)) {
681 XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
682 Status = XhcWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
683 }
684
685 return Status;
686 }
687
688
689 /**
690 Halt the XHCI host controller.
691
692 @param Xhc The XHCI Instance.
693 @param Timeout Time to wait before abort (in millisecond, ms).
694
695 @return EFI_SUCCESS The XHCI host controller is halt.
696 @return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
697
698 **/
699 EFI_STATUS
700 XhcHaltHC (
701 IN USB_XHCI_INSTANCE *Xhc,
702 IN UINT32 Timeout
703 )
704 {
705 EFI_STATUS Status;
706
707 XhcClearOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
708 Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, TRUE, Timeout);
709 return Status;
710 }
711
712
713 /**
714 Set the XHCI host controller to run.
715
716 @param Xhc The XHCI Instance.
717 @param Timeout Time to wait before abort (in millisecond, ms).
718
719 @return EFI_SUCCESS The XHCI host controller is running.
720 @return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
721
722 **/
723 EFI_STATUS
724 XhcRunHC (
725 IN USB_XHCI_INSTANCE *Xhc,
726 IN UINT32 Timeout
727 )
728 {
729 EFI_STATUS Status;
730
731 XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
732 Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, FALSE, Timeout);
733 return Status;
734 }
735