3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 The EHCI register operation routines.
30 Read EHCI capability register
32 @param Ehc The Ehc device
33 @param Offset Capability register address
35 @return The register content read
47 Status
= Ehc
->PciIo
->Mem
.Read (
56 if (EFI_ERROR (Status
)) {
57 EHC_ERROR (("EhcReadCapRegister: Pci Io read error - %r at %d\n", Status
, Offset
));
66 Read Ehc Operation register
68 @param Ehc The EHCI device
69 @param Offset The operation register offset
71 @return The register content read
83 ASSERT (Ehc
->CapLen
!= 0);
85 Status
= Ehc
->PciIo
->Mem
.Read (
89 (UINT64
) (Ehc
->CapLen
+ Offset
),
94 if (EFI_ERROR (Status
)) {
95 EHC_ERROR (("EhcReadOpReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
104 Write the data to the EHCI operation register
106 @param Ehc The EHCI device
107 @param Offset EHCI operation register offset
108 @param Data The data to write
122 ASSERT (Ehc
->CapLen
!= 0);
124 Status
= Ehc
->PciIo
->Mem
.Write (
128 (UINT64
) (Ehc
->CapLen
+ Offset
),
133 if (EFI_ERROR (Status
)) {
134 EHC_ERROR (("EhcWriteOpReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
140 Set one bit of the operational register while keeping other bits
142 @param Ehc The EHCI device
143 @param Offset The offset of the operational register
144 @param Bit The bit mask of the register to set
159 Data
= EhcReadOpReg (Ehc
, Offset
);
161 EhcWriteOpReg (Ehc
, Offset
, Data
);
166 Clear one bit of the operational register while keeping other bits
168 @param Ehc The EHCI device
169 @param Offset The offset of the operational register
170 @param Bit The bit mask of the register to clear
185 Data
= EhcReadOpReg (Ehc
, Offset
);
187 EhcWriteOpReg (Ehc
, Offset
, Data
);
192 Wait the operation register's bit as specified by Bit
193 to become set (or clear)
195 @param Ehc The EHCI device
196 @param Offset The offset of the operation register
197 @param Bit The bit of the register to wait for
198 @param WaitToSet Wait the bit to set or clear
199 @param Timeout The time to wait before abort (in millisecond)
201 @retval EFI_SUCCESS The bit successfully changed by host controller
202 @retval EFI_TIMEOUT The time out occurred
211 IN BOOLEAN WaitToSet
,
217 for (Index
= 0; Index
< Timeout
/ EHC_SYNC_POLL_TIME
+ 1; Index
++) {
218 if (EHC_REG_BIT_IS_SET (Ehc
, Offset
, Bit
) == WaitToSet
) {
222 gBS
->Stall (EHC_SYNC_POLL_TIME
);
230 Add support for UEFI Over Legacy (UoL) feature, stop
231 the legacy USB SMI support
233 @param Ehc The EHCI device.
239 EhcClearLegacySupport (
244 EFI_PCI_IO_PROTOCOL
*PciIo
;
248 EHC_DEBUG (("EhcClearLegacySupport: called to clear legacy support\n"));
251 ExtendCap
= (Ehc
->HcCapParams
>> 8) & 0xFF;
253 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
254 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
256 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
257 Value
|= (0x1 << 24);
258 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
264 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
266 if ((Value
& 0x01010000) == 0x01000000) {
271 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
272 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
278 Set door bell and wait it to be ACKed by host controller.
279 This function is used to synchronize with the hardware.
281 @param Ehc The EHCI device
282 @param Timeout The time to wait before abort (in millisecond, ms)
284 @return EFI_SUCCESS : Synchronized with the hardware
285 @return EFI_TIMEOUT : Time out happened while waiting door bell to set
289 EhcSetAndWaitDoorBell (
297 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_IAAD
);
299 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_IAA
, TRUE
, Timeout
);
302 // ACK the IAA bit in USBSTS register. Make sure other
303 // interrupt bits are not ACKed. These bits are WC (Write Clean).
305 Data
= EhcReadOpReg (Ehc
, EHC_USBSTS_OFFSET
);
306 Data
&= ~USBSTS_INTACK_MASK
;
309 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, Data
);
316 Clear all the interrutp status bits, these bits
319 @param Ehc The EHCI device
329 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_INTACK_MASK
);
334 Enable the periodic schedule then wait EHC to
337 @param Ehc The EHCI device
338 @param Timeout The time to wait before abort (in millisecond, ms)
340 @return EFI_SUCCESS : The periodical schedule is enabled
341 @return EFI_TIMEOUT : Time out happened while enabling periodic schedule
346 EhcEnablePeriodSchd (
353 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
355 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, TRUE
, Timeout
);
362 Disable periodic schedule
364 @param Ehc The EHCI device
365 @param Timeout Time to wait before abort (in millisecond, ms)
367 @return EFI_SUCCESS : Periodic schedule is disabled.
368 @return EFI_DEVICE_ERROR : Fail to disable periodic schedule
372 EhcDisablePeriodSchd (
379 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
381 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, FALSE
, Timeout
);
388 Enable asynchrounous schedule
390 @param Ehc The EHCI device
391 @param Timeout Time to wait before abort
393 @return EFI_SUCCESS : The EHCI asynchronous schedule is enabled
394 @return Others : Failed to enable the asynchronous scheudle
406 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
408 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, TRUE
, Timeout
);
415 Disable asynchrounous schedule
417 @param Ehc The EHCI device
418 @param Timeout Time to wait before abort (in millisecond, ms)
420 @return EFI_SUCCESS : The asynchronous schedule is disabled
421 @return Others : Failed to disable the asynchronous schedule
425 EhcDisableAsyncSchd (
432 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
434 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, FALSE
, Timeout
);
441 Whether Ehc is halted
443 @param Ehc The EHCI device
445 @return TRUE : The controller is halted
446 @return FALSE : It isn't halted
454 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
);
459 Whether system error occurred
461 @param Ehc The EHCI device
463 @return TRUE : System error happened
464 @return FALSE : No system error
472 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
);
477 Reset the host controller
479 @param Ehc The EHCI device
480 @param Timeout Time to wait before abort (in millisecond, ms)
482 @return EFI_SUCCESS : The host controller is reset
483 @return Others : Failed to reset the host
495 // Host can only be reset when it is halt. If not so, halt it
497 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
498 Status
= EhcHaltHC (Ehc
, Timeout
);
500 if (EFI_ERROR (Status
)) {
505 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
);
506 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
, FALSE
, Timeout
);
512 Halt the host controller
514 @param Ehc The EHCI device
515 @param Timeout Time to wait before abort
517 @return EFI_SUCCESS : The EHCI is halt
518 @return EFI_TIMEOUT : Failed to halt the controller before Timeout
529 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
530 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, TRUE
, Timeout
);
538 @param Ehc The EHCI device
539 @param Timeout Time to wait before abort
541 @return EFI_SUCCESS : The EHCI is running
542 @return Others : Failed to set the EHCI to run
553 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
554 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, FALSE
, Timeout
);
560 Initialize the HC hardware.
561 EHCI spec lists the five things to do to initialize the hardware
562 1. Program CTRLDSSEGMENT
563 2. Set USBINTR to enable interrupts
564 3. Set periodic list base
565 4. Set USBCMD, interrupt threshold, frame list size etc
566 5. Write 1 to CONFIGFLAG to route all ports to EHCI
568 @param Ehc The EHCI device
570 @return EFI_SUCCESS : The EHCI has come out of halt state
571 @return EFI_TIMEOUT : Time out happened
581 ASSERT (EhcIsHalt (Ehc
));
584 // Allocate the periodic frame and associated memeory
585 // management facilities if not already done.
587 if (Ehc
->PeriodFrame
!= NULL
) {
591 Status
= EhcInitSched (Ehc
);
593 if (EFI_ERROR (Status
)) {
597 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
599 EhcWriteOpReg (Ehc
, EHC_CTRLDSSEG_OFFSET
, Ehc
->High32bitAddr
);
602 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
604 EhcWriteOpReg (Ehc
, EHC_USBINTR_OFFSET
, 0);
607 // 3. Program periodic frame list, already done in EhcInitSched
608 // 4. Start the Host Controller
610 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
613 // 5. Set all ports routing to EHC
615 EhcSetOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
617 Status
= EhcEnablePeriodSchd (Ehc
, EHC_GENERIC_TIME
);
619 if (EFI_ERROR (Status
)) {
620 EHC_ERROR (("EhcInitHC: failed to enable period schedule\n"));
624 Status
= EhcEnableAsyncSchd (Ehc
, EHC_GENERIC_TIME
);
626 if (EFI_ERROR (Status
)) {
627 EHC_ERROR (("EhcInitHC: failed to enable async schedule\n"));