3 The EHCI register operation routines.
5 Copyright (c) 2007 - 2009, Intel Corporation
6 All rights reserved. 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
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.
21 Read EHCI capability register.
23 @param Ehc The EHCI device.
24 @param Offset Capability register address.
26 @return The register content read.
27 @retval If err, return 0xffff.
39 Status
= Ehc
->PciIo
->Mem
.Read (
48 if (EFI_ERROR (Status
)) {
49 DEBUG ((EFI_D_ERROR
, "EhcReadCapRegister: Pci Io read error - %r at %d\n", Status
, Offset
));
58 Read EHCI Operation register.
60 @param Ehc The EHCI device.
61 @param Offset The operation register offset.
63 @return The register content read.
64 @retval If err, return 0xffff.
76 ASSERT (Ehc
->CapLen
!= 0);
78 Status
= Ehc
->PciIo
->Mem
.Read (
82 (UINT64
) (Ehc
->CapLen
+ Offset
),
87 if (EFI_ERROR (Status
)) {
88 DEBUG ((EFI_D_ERROR
, "EhcReadOpReg: Pci Io Read error - %r at %d\n", Status
, Offset
));
97 Write the data to the EHCI operation register.
99 @param Ehc The EHCI device.
100 @param Offset EHCI operation register offset.
101 @param Data The data to write.
113 ASSERT (Ehc
->CapLen
!= 0);
115 Status
= Ehc
->PciIo
->Mem
.Write (
119 (UINT64
) (Ehc
->CapLen
+ Offset
),
124 if (EFI_ERROR (Status
)) {
125 DEBUG ((EFI_D_ERROR
, "EhcWriteOpReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
131 Set one bit of the operational register while keeping other bits.
133 @param Ehc The EHCI device.
134 @param Offset The offset of the operational register.
135 @param Bit The bit mask of the register to set.
147 Data
= EhcReadOpReg (Ehc
, Offset
);
149 EhcWriteOpReg (Ehc
, Offset
, Data
);
154 Clear one bit of the operational register while keeping other bits.
156 @param Ehc The EHCI device.
157 @param Offset The offset of the operational register.
158 @param Bit The bit mask of the register to clear.
170 Data
= EhcReadOpReg (Ehc
, Offset
);
172 EhcWriteOpReg (Ehc
, Offset
, Data
);
177 Wait the operation register's bit as specified by Bit
178 to become set (or clear).
180 @param Ehc The EHCI device.
181 @param Offset The offset of the operation register.
182 @param Bit The bit of the register to wait for.
183 @param WaitToSet Wait the bit to set or clear.
184 @param Timeout The time to wait before abort (in millisecond).
186 @retval EFI_SUCCESS The bit successfully changed by host controller.
187 @retval EFI_TIMEOUT The time out occurred.
195 IN BOOLEAN WaitToSet
,
201 for (Index
= 0; Index
< Timeout
/ EHC_SYNC_POLL_INTERVAL
+ 1; Index
++) {
202 if (EHC_REG_BIT_IS_SET (Ehc
, Offset
, Bit
) == WaitToSet
) {
206 gBS
->Stall (EHC_SYNC_POLL_INTERVAL
);
214 Add support for UEFI Over Legacy (UoL) feature, stop
215 the legacy USB SMI support.
217 @param Ehc The EHCI device.
221 EhcClearLegacySupport (
226 EFI_PCI_IO_PROTOCOL
*PciIo
;
230 DEBUG ((EFI_D_INFO
, "EhcClearLegacySupport: called to clear legacy support\n"));
233 ExtendCap
= (Ehc
->HcCapParams
>> 8) & 0xFF;
235 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
236 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
238 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
239 Value
|= (0x1 << 24);
240 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
243 while (TimeOut
-- != 0) {
246 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
248 if ((Value
& 0x01010000) == 0x01000000) {
253 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
254 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
260 Set door bell and wait it to be ACKed by host controller.
261 This function is used to synchronize with the hardware.
263 @param Ehc The EHCI device.
264 @param Timeout The time to wait before abort (in millisecond, ms).
266 @retval EFI_SUCCESS Synchronized with the hardware.
267 @retval EFI_TIMEOUT Time out happened while waiting door bell to set.
271 EhcSetAndWaitDoorBell (
279 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_IAAD
);
281 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_IAA
, TRUE
, Timeout
);
284 // ACK the IAA bit in USBSTS register. Make sure other
285 // interrupt bits are not ACKed. These bits are WC (Write Clean).
287 Data
= EhcReadOpReg (Ehc
, EHC_USBSTS_OFFSET
);
288 Data
&= ~USBSTS_INTACK_MASK
;
291 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, Data
);
298 Clear all the interrutp status bits, these bits
301 @param Ehc The EHCI device.
309 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_INTACK_MASK
);
314 Enable the periodic schedule then wait EHC to
317 @param Ehc The EHCI device.
318 @param Timeout The time to wait before abort (in millisecond, ms).
320 @retval EFI_SUCCESS The periodical schedule is enabled.
321 @retval EFI_TIMEOUT Time out happened while enabling periodic schedule.
325 EhcEnablePeriodSchd (
332 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
334 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, TRUE
, Timeout
);
340 Disable periodic schedule.
342 @param Ehc The EHCI device.
343 @param Timeout Time to wait before abort (in millisecond, ms).
345 @retval EFI_SUCCESS Periodic schedule is disabled.
346 @retval EFI_DEVICE_ERROR Fail to disable periodic schedule.
350 EhcDisablePeriodSchd (
357 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
359 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, FALSE
, Timeout
);
366 Enable asynchrounous schedule.
368 @param Ehc The EHCI device.
369 @param Timeout Time to wait before abort.
371 @retval EFI_SUCCESS The EHCI asynchronous schedule is enabled.
372 @return Others Failed to enable the asynchronous scheudle.
383 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
385 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, TRUE
, Timeout
);
392 Disable asynchrounous schedule.
394 @param Ehc The EHCI device.
395 @param Timeout Time to wait before abort (in millisecond, ms).
397 @retval EFI_SUCCESS The asynchronous schedule is disabled.
398 @return Others Failed to disable the asynchronous schedule.
402 EhcDisableAsyncSchd (
409 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
411 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, FALSE
, Timeout
);
418 Whether Ehc is halted.
420 @param Ehc The EHCI device.
422 @retval TRUE The controller is halted.
423 @retval FALSE It isn't halted.
431 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
);
436 Whether system error occurred.
438 @param Ehc The EHCI device.
440 @return TRUE System error happened.
441 @return FALSE No system error.
449 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
);
454 Reset the host controller.
456 @param Ehc The EHCI device.
457 @param Timeout Time to wait before abort (in millisecond, ms).
459 @retval EFI_SUCCESS The host controller is reset.
460 @return Others Failed to reset the host.
472 // Host can only be reset when it is halt. If not so, halt it
474 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
475 Status
= EhcHaltHC (Ehc
, Timeout
);
477 if (EFI_ERROR (Status
)) {
482 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
);
483 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
, FALSE
, Timeout
);
489 Halt the host controller.
491 @param Ehc The EHCI device.
492 @param Timeout Time to wait before abort.
494 @retval EFI_SUCCESS The EHCI is halt.
495 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.
506 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
507 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, TRUE
, Timeout
);
515 @param Ehc The EHCI device.
516 @param Timeout Time to wait before abort.
518 @retval EFI_SUCCESS The EHCI is running.
519 @return Others Failed to set the EHCI to run.
530 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
531 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, FALSE
, Timeout
);
537 Initialize the HC hardware.
538 EHCI spec lists the five things to do to initialize the hardware:
539 1. Program CTRLDSSEGMENT
540 2. Set USBINTR to enable interrupts
541 3. Set periodic list base
542 4. Set USBCMD, interrupt threshold, frame list size etc
543 5. Write 1 to CONFIGFLAG to route all ports to EHCI
545 @param Ehc The EHCI device.
547 @return EFI_SUCCESS The EHCI has come out of halt state.
548 @return EFI_TIMEOUT Time out happened.
558 ASSERT (EhcIsHalt (Ehc
));
561 // Allocate the periodic frame and associated memeory
562 // management facilities if not already done.
564 if (Ehc
->PeriodFrameHost
!= NULL
) {
568 Status
= EhcInitSched (Ehc
);
570 if (EFI_ERROR (Status
)) {
574 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
576 EhcWriteOpReg (Ehc
, EHC_CTRLDSSEG_OFFSET
, Ehc
->High32bitAddr
);
579 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
581 EhcWriteOpReg (Ehc
, EHC_USBINTR_OFFSET
, 0);
584 // 3. Program periodic frame list, already done in EhcInitSched
585 // 4. Start the Host Controller
587 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
590 // 5. Set all ports routing to EHC
592 EhcSetOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
595 // Wait roothub port power stable
597 gBS
->Stall (EHC_ROOT_PORT_RECOVERY_STALL
);
599 Status
= EhcEnablePeriodSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
601 if (EFI_ERROR (Status
)) {
602 DEBUG ((EFI_D_ERROR
, "EhcInitHC: failed to enable period schedule\n"));
606 Status
= EhcEnableAsyncSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
608 if (EFI_ERROR (Status
)) {
609 DEBUG ((EFI_D_ERROR
, "EhcInitHC: failed to enable async schedule\n"));