TianoCore EDK2 master
Loading...
Searching...
No Matches
EhciReg.c
Go to the documentation of this file.
1
10#include "Ehci.h"
11
22UINT32
24 IN USB2_HC_DEV *Ehc,
25 IN UINT32 Offset
26 )
27{
28 UINT32 Data;
29 EFI_STATUS Status;
30
31 Status = Ehc->PciIo->Mem.Read (
32 Ehc->PciIo,
33 EfiPciIoWidthUint32,
34 EHC_BAR_INDEX,
35 (UINT64)Offset,
36 1,
37 &Data
38 );
39
40 if (EFI_ERROR (Status)) {
41 DEBUG ((DEBUG_ERROR, "EhcReadCapRegister: Pci Io read error - %r at %d\n", Status, Offset));
42 Data = 0xFFFF;
43 }
44
45 return Data;
46}
47
58UINT32
60 IN CONST USB2_HC_DEV *Ehc,
61 IN UINT32 Offset
62 )
63{
64 UINT32 Data;
65 EFI_STATUS Status;
66
67 Status = Ehc->PciIo->Mem.Read (
68 Ehc->PciIo,
69 EfiPciIoWidthUint32,
70 Ehc->DebugPortBarNum,
71 Ehc->DebugPortOffset + Offset,
72 1,
73 &Data
74 );
75
76 if (EFI_ERROR (Status)) {
77 DEBUG ((DEBUG_ERROR, "EhcReadDbgRegister: Pci Io read error - %r at %d\n", Status, Offset));
78 Data = 0xFFFF;
79 }
80
81 return Data;
82}
83
103BOOLEAN
105 IN CONST USB2_HC_DEV *Ehc,
106 IN CONST UINT8 *PortNumber OPTIONAL
107 )
108{
109 UINT32 State;
110
111 if (Ehc->DebugPortNum == 0) {
112 //
113 // The host controller has no debug port.
114 //
115 return FALSE;
116 }
117
118 //
119 // The Debug Port Number field in HCSPARAMS is one-based.
120 //
121 if ((PortNumber != NULL) && (*PortNumber != Ehc->DebugPortNum - 1)) {
122 //
123 // The caller specified a port, but it's not the debug port of the host
124 // controller.
125 //
126 return FALSE;
127 }
128
129 //
130 // Deduce usage from the Control Register.
131 //
132 State = EhcReadDbgRegister (Ehc, 0);
133 return (State & USB_DEBUG_PORT_IN_USE_MASK) == USB_DEBUG_PORT_IN_USE_MASK;
134}
135
146UINT32
148 IN USB2_HC_DEV *Ehc,
149 IN UINT32 Offset
150 )
151{
152 UINT32 Data;
153 EFI_STATUS Status;
154
155 ASSERT (Ehc->CapLen != 0);
156
157 Status = Ehc->PciIo->Mem.Read (
158 Ehc->PciIo,
159 EfiPciIoWidthUint32,
160 EHC_BAR_INDEX,
161 Ehc->CapLen + Offset,
162 1,
163 &Data
164 );
165
166 if (EFI_ERROR (Status)) {
167 DEBUG ((DEBUG_ERROR, "EhcReadOpReg: Pci Io Read error - %r at %d\n", Status, Offset));
168 Data = 0xFFFF;
169 }
170
171 return Data;
172}
173
182VOID
184 IN USB2_HC_DEV *Ehc,
185 IN UINT32 Offset,
186 IN UINT32 Data
187 )
188{
189 EFI_STATUS Status;
190
191 ASSERT (Ehc->CapLen != 0);
192
193 Status = Ehc->PciIo->Mem.Write (
194 Ehc->PciIo,
195 EfiPciIoWidthUint32,
196 EHC_BAR_INDEX,
197 Ehc->CapLen + Offset,
198 1,
199 &Data
200 );
201
202 if (EFI_ERROR (Status)) {
203 DEBUG ((DEBUG_ERROR, "EhcWriteOpReg: Pci Io Write error: %r at %d\n", Status, Offset));
204 }
205}
206
215VOID
217 IN USB2_HC_DEV *Ehc,
218 IN UINT32 Offset,
219 IN UINT32 Bit
220 )
221{
222 UINT32 Data;
223
224 Data = EhcReadOpReg (Ehc, Offset);
225 Data |= Bit;
226 EhcWriteOpReg (Ehc, Offset, Data);
227}
228
237VOID
239 IN USB2_HC_DEV *Ehc,
240 IN UINT32 Offset,
241 IN UINT32 Bit
242 )
243{
244 UINT32 Data;
245
246 Data = EhcReadOpReg (Ehc, Offset);
247 Data &= ~Bit;
248 EhcWriteOpReg (Ehc, Offset, Data);
249}
250
267 IN USB2_HC_DEV *Ehc,
268 IN UINT32 Offset,
269 IN UINT32 Bit,
270 IN BOOLEAN WaitToSet,
271 IN UINT32 Timeout
272 )
273{
274 UINT32 Index;
275
276 for (Index = 0; Index < Timeout / EHC_SYNC_POLL_INTERVAL + 1; Index++) {
277 if (EHC_REG_BIT_IS_SET (Ehc, Offset, Bit) == WaitToSet) {
278 return EFI_SUCCESS;
279 }
280
281 gBS->Stall (EHC_SYNC_POLL_INTERVAL);
282 }
283
284 return EFI_TIMEOUT;
285}
286
294VOID
296 IN USB2_HC_DEV *Ehc
297 )
298{
299 UINT32 ExtendCap;
300 EFI_PCI_IO_PROTOCOL *PciIo;
301 UINT32 Value;
302 UINT32 TimeOut;
303
304 DEBUG ((DEBUG_INFO, "EhcClearLegacySupport: called to clear legacy support\n"));
305
306 PciIo = Ehc->PciIo;
307 ExtendCap = (Ehc->HcCapParams >> 8) & 0xFF;
308
309 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
310 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
311
312 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
313 Value |= (0x1 << 24);
314 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
315
316 TimeOut = 40;
317 while (TimeOut-- != 0) {
318 gBS->Stall (500);
319
320 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
321
322 if ((Value & 0x01010000) == 0x01000000) {
323 break;
324 }
325 }
326
327 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
328 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
329}
330
344 IN USB2_HC_DEV *Ehc,
345 IN UINT32 Timeout
346 )
347{
348 EFI_STATUS Status;
349 UINT32 Data;
350
351 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_IAAD);
352
353 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_IAA, TRUE, Timeout);
354
355 //
356 // ACK the IAA bit in USBSTS register. Make sure other
357 // interrupt bits are not ACKed. These bits are WC (Write Clean).
358 //
359 Data = EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET);
360 Data &= ~USBSTS_INTACK_MASK;
361 Data |= USBSTS_IAA;
362
363 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, Data);
364
365 return Status;
366}
367
375VOID
377 IN USB2_HC_DEV *Ehc
378 )
379{
380 EhcWriteOpReg (Ehc, EHC_USBSTS_OFFSET, USBSTS_INTACK_MASK);
381}
382
396 IN USB2_HC_DEV *Ehc,
397 IN UINT32 Timeout
398 )
399{
400 EFI_STATUS Status;
401
402 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_PERIOD);
403
404 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_PERIOD_ENABLED, TRUE, Timeout);
405 return Status;
406}
407
420 IN USB2_HC_DEV *Ehc,
421 IN UINT32 Timeout
422 )
423{
424 EFI_STATUS Status;
425
426 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_ENABLE_ASYNC);
427
428 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_ASYNC_ENABLED, TRUE, Timeout);
429 return Status;
430}
431
441BOOLEAN
443 IN USB2_HC_DEV *Ehc
444 )
445{
446 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT);
447}
448
458BOOLEAN
460 IN USB2_HC_DEV *Ehc
461 )
462{
463 return EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_SYS_ERROR);
464}
465
478 IN USB2_HC_DEV *Ehc,
479 IN UINT32 Timeout
480 )
481{
482 EFI_STATUS Status;
483
484 //
485 // Host can only be reset when it is halt. If not so, halt it
486 //
487 if (!EHC_REG_BIT_IS_SET (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT)) {
488 Status = EhcHaltHC (Ehc, Timeout);
489
490 if (EFI_ERROR (Status)) {
491 return Status;
492 }
493 }
494
495 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET);
496 Status = EhcWaitOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RESET, FALSE, Timeout);
497 return Status;
498}
499
512 IN USB2_HC_DEV *Ehc,
513 IN UINT32 Timeout
514 )
515{
516 EFI_STATUS Status;
517
518 EhcClearOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
519 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, TRUE, Timeout);
520 return Status;
521}
522
535 IN USB2_HC_DEV *Ehc,
536 IN UINT32 Timeout
537 )
538{
539 EFI_STATUS Status;
540
541 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
542 Status = EhcWaitOpRegBit (Ehc, EHC_USBSTS_OFFSET, USBSTS_HALT, FALSE, Timeout);
543 return Status;
544}
545
563 IN USB2_HC_DEV *Ehc
564 )
565{
566 EFI_STATUS Status;
567 UINT32 Index;
568 UINT32 RegVal;
569
570 // This ASSERT crashes the BeagleBoard. There is some issue in the USB stack.
571 // This ASSERT needs to be removed so the BeagleBoard will boot. When we fix
572 // the USB stack we can put this ASSERT back in
573 // ASSERT (EhcIsHalt (Ehc));
574
575 //
576 // Allocate the periodic frame and associated memeory
577 // management facilities if not already done.
578 //
579 if (Ehc->PeriodFrame != NULL) {
580 EhcFreeSched (Ehc);
581 }
582
583 Status = EhcInitSched (Ehc);
584
585 if (EFI_ERROR (Status)) {
586 return Status;
587 }
588
589 //
590 // 1. Clear USBINTR to disable all the interrupt. UEFI works by polling
591 //
592 EhcWriteOpReg (Ehc, EHC_USBINTR_OFFSET, 0);
593
594 //
595 // 2. Start the Host Controller
596 //
597 EhcSetOpRegBit (Ehc, EHC_USBCMD_OFFSET, USBCMD_RUN);
598
599 //
600 // 3. Power up all ports if EHCI has Port Power Control (PPC) support
601 //
602 if (Ehc->HcStructParams & HCSP_PPC) {
603 for (Index = 0; Index < (UINT8)(Ehc->HcStructParams & HCSP_NPORTS); Index++) {
604 //
605 // Do not clear port status bits on initialization. Otherwise devices will
606 // not enumerate properly at startup.
607 //
608 RegVal = EhcReadOpReg (Ehc, (UINT32)(EHC_PORT_STAT_OFFSET + (4 * Index)));
609 RegVal &= ~PORTSC_CHANGE_MASK;
610 RegVal |= PORTSC_POWER;
611 EhcWriteOpReg (Ehc, (UINT32)(EHC_PORT_STAT_OFFSET + (4 * Index)), RegVal);
612 }
613 }
614
615 //
616 // Wait roothub port power stable
617 //
618 gBS->Stall (EHC_ROOT_PORT_RECOVERY_STALL);
619
620 //
621 // 4. Set all ports routing to EHC
622 //
623 EhcSetOpRegBit (Ehc, EHC_CONFIG_FLAG_OFFSET, CONFIGFLAG_ROUTE_EHC);
624
625 Status = EhcEnablePeriodSchd (Ehc, EHC_GENERIC_TIMEOUT);
626
627 if (EFI_ERROR (Status)) {
628 DEBUG ((DEBUG_ERROR, "EhcInitHC: failed to enable period schedule\n"));
629 return Status;
630 }
631
632 Status = EhcEnableAsyncSchd (Ehc, EHC_GENERIC_TIMEOUT);
633
634 if (EFI_ERROR (Status)) {
635 DEBUG ((DEBUG_ERROR, "EhcInitHC: failed to enable async schedule\n"));
636 return Status;
637 }
638
639 return EFI_SUCCESS;
640}
EFI_STATUS EhcInitSched(IN USB2_HC_DEV *Ehc)
Definition: EhciSched.c:102
VOID EhcFreeSched(IN USB2_HC_DEV *Ehc)
Definition: EhciSched.c:250
VOID EhcClearOpRegBit(IN USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Bit)
Definition: EhciReg.c:238
EFI_STATUS EhcResetHC(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:477
UINT32 EhcReadDbgRegister(IN CONST USB2_HC_DEV *Ehc, IN UINT32 Offset)
Definition: EhciReg.c:59
EFI_STATUS EhcEnablePeriodSchd(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:395
VOID EhcWriteOpReg(IN USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Data)
Definition: EhciReg.c:183
EFI_STATUS EhcInitHC(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:562
EFI_STATUS EhcSetAndWaitDoorBell(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:343
EFI_STATUS EhcEnableAsyncSchd(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:419
VOID EhcSetOpRegBit(IN USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Bit)
Definition: EhciReg.c:216
BOOLEAN EhcIsHalt(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:442
EFI_STATUS EhcHaltHC(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:511
VOID EhcClearLegacySupport(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:295
UINT32 EhcReadCapRegister(IN USB2_HC_DEV *Ehc, IN UINT32 Offset)
Definition: EhciReg.c:23
BOOLEAN EhcIsSysError(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:459
EFI_STATUS EhcRunHC(IN USB2_HC_DEV *Ehc, IN UINT32 Timeout)
Definition: EhciReg.c:534
EFI_STATUS EhcWaitOpRegBit(IN USB2_HC_DEV *Ehc, IN UINT32 Offset, IN UINT32 Bit, IN BOOLEAN WaitToSet, IN UINT32 Timeout)
Definition: EhciReg.c:266
UINT32 EhcReadOpReg(IN USB2_HC_DEV *Ehc, IN UINT32 Offset)
Definition: EhciReg.c:147
VOID EhcAckAllInterrupt(IN USB2_HC_DEV *Ehc)
Definition: EhciReg.c:376
BOOLEAN EhcIsDebugPortInUse(IN CONST USB2_HC_DEV *Ehc, IN CONST UINT8 *PortNumber OPTIONAL)
Definition: EhciReg.c:104
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define DEBUG(Expression)
Definition: DebugLib.h:434
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_PCI_IO_PROTOCOL_CONFIG Read
Definition: PciIo.h:232
EFI_PCI_IO_PROTOCOL_CONFIG Write
Definition: PciIo.h:236