3 The EHCI register operation routines.
5 Copyright (c) 2007, 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.
115 ASSERT (Ehc
->CapLen
!= 0);
117 Status
= Ehc
->PciIo
->Mem
.Write (
121 (UINT64
) (Ehc
->CapLen
+ Offset
),
126 if (EFI_ERROR (Status
)) {
127 DEBUG ((EFI_D_ERROR
, "EhcWriteOpReg: Pci Io Write error: %r at %d\n", Status
, Offset
));
133 Set one bit of the operational register while keeping other bits.
135 @param Ehc The EHCI device.
136 @param Offset The offset of the operational register.
137 @param Bit The bit mask of the register to set.
151 Data
= EhcReadOpReg (Ehc
, Offset
);
153 EhcWriteOpReg (Ehc
, Offset
, Data
);
158 Clear one bit of the operational register while keeping other bits.
160 @param Ehc The EHCI device.
161 @param Offset The offset of the operational register.
162 @param Bit The bit mask of the register to clear.
176 Data
= EhcReadOpReg (Ehc
, Offset
);
178 EhcWriteOpReg (Ehc
, Offset
, Data
);
183 Wait the operation register's bit as specified by Bit
184 to become set (or clear).
186 @param Ehc The EHCI device.
187 @param Offset The offset of the operation register.
188 @param Bit The bit of the register to wait for.
189 @param WaitToSet Wait the bit to set or clear.
190 @param Timeout The time to wait before abort (in millisecond).
192 @retval EFI_SUCCESS The bit successfully changed by host controller.
193 @retval EFI_TIMEOUT The time out occurred.
201 IN BOOLEAN WaitToSet
,
207 for (Index
= 0; Index
< Timeout
/ EHC_SYNC_POLL_INTERVAL
+ 1; Index
++) {
208 if (EHC_REG_BIT_IS_SET (Ehc
, Offset
, Bit
) == WaitToSet
) {
212 gBS
->Stall (EHC_SYNC_POLL_INTERVAL
);
220 Add support for UEFI Over Legacy (UoL) feature, stop
221 the legacy USB SMI support.
223 @param Ehc The EHCI device.
229 EhcClearLegacySupport (
234 EFI_PCI_IO_PROTOCOL
*PciIo
;
238 DEBUG ((EFI_D_INFO
, "EhcClearLegacySupport: called to clear legacy support\n"));
241 ExtendCap
= (Ehc
->HcCapParams
>> 8) & 0xFF;
243 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
244 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
246 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
247 Value
|= (0x1 << 24);
248 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
251 while (TimeOut
-- != 0) {
254 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
256 if ((Value
& 0x01010000) == 0x01000000) {
261 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
262 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
268 Set door bell and wait it to be ACKed by host controller.
269 This function is used to synchronize with the hardware.
271 @param Ehc The EHCI device.
272 @param Timeout The time to wait before abort (in millisecond, ms).
274 @retval EFI_SUCCESS Synchronized with the hardware.
275 @retval EFI_TIMEOUT Time out happened while waiting door bell to set.
279 EhcSetAndWaitDoorBell (
287 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_IAAD
);
289 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_IAA
, TRUE
, Timeout
);
292 // ACK the IAA bit in USBSTS register. Make sure other
293 // interrupt bits are not ACKed. These bits are WC (Write Clean).
295 Data
= EhcReadOpReg (Ehc
, EHC_USBSTS_OFFSET
);
296 Data
&= ~USBSTS_INTACK_MASK
;
299 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, Data
);
306 Clear all the interrutp status bits, these bits
309 @param Ehc The EHCI device.
319 EhcWriteOpReg (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_INTACK_MASK
);
324 Enable the periodic schedule then wait EHC to
327 @param Ehc The EHCI device.
328 @param Timeout The time to wait before abort (in millisecond, ms).
330 @retval EFI_SUCCESS The periodical schedule is enabled.
331 @retval EFI_TIMEOUT Time out happened while enabling periodic schedule.
335 EhcEnablePeriodSchd (
342 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
344 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, TRUE
, Timeout
);
350 Disable periodic schedule.
352 @param Ehc The EHCI device.
353 @param Timeout Time to wait before abort (in millisecond, ms).
355 @retval EFI_SUCCESS Periodic schedule is disabled.
356 @retval EFI_DEVICE_ERROR Fail to disable periodic schedule.
360 EhcDisablePeriodSchd (
367 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
369 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, FALSE
, Timeout
);
376 Enable asynchrounous schedule.
378 @param Ehc The EHCI device.
379 @param Timeout Time to wait before abort.
381 @retval EFI_SUCCESS The EHCI asynchronous schedule is enabled.
382 @return Others Failed to enable the asynchronous scheudle.
393 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
395 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, TRUE
, Timeout
);
402 Disable asynchrounous schedule.
404 @param Ehc The EHCI device.
405 @param Timeout Time to wait before abort (in millisecond, ms).
407 @retval EFI_SUCCESS The asynchronous schedule is disabled.
408 @return Others Failed to disable the asynchronous schedule.
412 EhcDisableAsyncSchd (
419 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
421 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, FALSE
, Timeout
);
428 Whether Ehc is halted.
430 @param Ehc The EHCI device.
432 @retval TRUE The controller is halted.
433 @retval FALSE It isn't halted.
441 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
);
446 Whether system error occurred.
448 @param Ehc The EHCI device.
450 @return TRUE System error happened.
451 @return FALSE No system error.
459 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
);
464 Reset the host controller.
466 @param Ehc The EHCI device.
467 @param Timeout Time to wait before abort (in millisecond, ms).
469 @retval EFI_SUCCESS The host controller is reset.
470 @return Others Failed to reset the host.
482 // Host can only be reset when it is halt. If not so, halt it
484 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
485 Status
= EhcHaltHC (Ehc
, Timeout
);
487 if (EFI_ERROR (Status
)) {
492 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
);
493 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
, FALSE
, Timeout
);
499 Halt the host controller.
501 @param Ehc The EHCI device.
502 @param Timeout Time to wait before abort.
504 @retval EFI_SUCCESS The EHCI is halt.
505 @retval EFI_TIMEOUT Failed to halt the controller before Timeout.
516 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
517 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, TRUE
, Timeout
);
525 @param Ehc The EHCI device.
526 @param Timeout Time to wait before abort.
528 @retval EFI_SUCCESS The EHCI is running.
529 @return Others Failed to set the EHCI to run.
540 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
541 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, FALSE
, Timeout
);
547 Initialize the HC hardware.
548 EHCI spec lists the five things to do to initialize the hardware:
549 1. Program CTRLDSSEGMENT
550 2. Set USBINTR to enable interrupts
551 3. Set periodic list base
552 4. Set USBCMD, interrupt threshold, frame list size etc
553 5. Write 1 to CONFIGFLAG to route all ports to EHCI
555 @param Ehc The EHCI device.
557 @return EFI_SUCCESS The EHCI has come out of halt state.
558 @return EFI_TIMEOUT Time out happened.
568 ASSERT (EhcIsHalt (Ehc
));
571 // Allocate the periodic frame and associated memeory
572 // management facilities if not already done.
574 if (Ehc
->PeriodFrame
!= NULL
) {
578 Status
= EhcInitSched (Ehc
);
580 if (EFI_ERROR (Status
)) {
584 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
586 EhcWriteOpReg (Ehc
, EHC_CTRLDSSEG_OFFSET
, Ehc
->High32bitAddr
);
589 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
591 EhcWriteOpReg (Ehc
, EHC_USBINTR_OFFSET
, 0);
594 // 3. Program periodic frame list, already done in EhcInitSched
595 // 4. Start the Host Controller
597 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
600 // 5. Set all ports routing to EHC
602 EhcSetOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
605 // Wait roothub port power stable
607 gBS
->Stall (EHC_ROOT_PORT_RECOVERY_STALL
);
609 Status
= EhcEnablePeriodSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
611 if (EFI_ERROR (Status
)) {
612 DEBUG ((EFI_D_ERROR
, "EhcInitHC: failed to enable period schedule\n"));
616 Status
= EhcEnableAsyncSchd (Ehc
, EHC_GENERIC_TIMEOUT
);
618 if (EFI_ERROR (Status
)) {
619 DEBUG ((EFI_D_ERROR
, "EhcInitHC: failed to enable async schedule\n"));