]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
9d50ef824261acc357812e33a911eec017bea09b
[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 XHCI legacy support capability register offset.
575
576 @param Xhc The XHCI Instance.
577
578 @return The offset of XHCI legacy support capability register.
579
580 **/
581 UINT32
582 XhcGetLegSupCapAddr (
583 IN USB_XHCI_INSTANCE *Xhc
584 )
585 {
586 UINT32 ExtCapOffset;
587 UINT8 NextExtCapReg;
588 UINT32 Data;
589
590 ExtCapOffset = 0;
591
592 do {
593 //
594 // Check if the extended capability register's capability id is USB Legacy Support.
595 //
596 Data = XhcReadExtCapReg (Xhc, ExtCapOffset);
597 if ((Data & 0xFF) == 0x1) {
598 return ExtCapOffset;
599 }
600 //
601 // If not, then traverse all of the ext capability registers till finding out it.
602 //
603 NextExtCapReg = (UINT8)((Data >> 8) & 0xFF);
604 ExtCapOffset += (NextExtCapReg << 2);
605 } while (NextExtCapReg != 0);
606
607 return 0;
608 }
609
610 /**
611 Whether the XHCI host controller is halted.
612
613 @param Xhc The XHCI Instance.
614
615 @retval TRUE The controller is halted.
616 @retval FALSE It isn't halted.
617
618 **/
619 BOOLEAN
620 XhcIsHalt (
621 IN USB_XHCI_INSTANCE *Xhc
622 )
623 {
624 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT);
625 }
626
627
628 /**
629 Whether system error occurred.
630
631 @param Xhc The XHCI Instance.
632
633 @retval TRUE System error happened.
634 @retval FALSE No system error.
635
636 **/
637 BOOLEAN
638 XhcIsSysError (
639 IN USB_XHCI_INSTANCE *Xhc
640 )
641 {
642 return XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HSE);
643 }
644
645 /**
646 Reset the XHCI host controller.
647
648 @param Xhc The XHCI Instance.
649 @param Timeout Time to wait before abort (in millisecond, ms).
650
651 @retval EFI_SUCCESS The XHCI host controller is reset.
652 @return Others Failed to reset the XHCI before Timeout.
653
654 **/
655 EFI_STATUS
656 XhcResetHC (
657 IN USB_XHCI_INSTANCE *Xhc,
658 IN UINT32 Timeout
659 )
660 {
661 EFI_STATUS Status;
662
663 DEBUG ((EFI_D_INFO, "XhcResetHC!\n"));
664 //
665 // Host can only be reset when it is halt. If not so, halt it
666 //
667 if (!XHC_REG_BIT_IS_SET (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT)) {
668 Status = XhcHaltHC (Xhc, Timeout);
669
670 if (EFI_ERROR (Status)) {
671 return Status;
672 }
673 }
674
675 XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET);
676 Status = XhcWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
677 return Status;
678 }
679
680
681 /**
682 Halt the XHCI host controller.
683
684 @param Xhc The XHCI Instance.
685 @param Timeout Time to wait before abort (in millisecond, ms).
686
687 @return EFI_SUCCESS The XHCI host controller is halt.
688 @return EFI_TIMEOUT Failed to halt the XHCI before Timeout.
689
690 **/
691 EFI_STATUS
692 XhcHaltHC (
693 IN USB_XHCI_INSTANCE *Xhc,
694 IN UINT32 Timeout
695 )
696 {
697 EFI_STATUS Status;
698
699 XhcClearOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
700 Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, TRUE, Timeout);
701 return Status;
702 }
703
704
705 /**
706 Set the XHCI host controller to run.
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 running.
712 @return EFI_TIMEOUT Failed to set the XHCI to run before Timeout.
713
714 **/
715 EFI_STATUS
716 XhcRunHC (
717 IN USB_XHCI_INSTANCE *Xhc,
718 IN UINT32 Timeout
719 )
720 {
721 EFI_STATUS Status;
722
723 XhcSetOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RUN);
724 Status = XhcWaitOpRegBit (Xhc, XHC_USBSTS_OFFSET, XHC_USBSTS_HALT, FALSE, Timeout);
725 return Status;
726 }
727