]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/EhciDxe/EhciReg.c
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
373 EhcDisablePeriodSchd (
380 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_PERIOD
);
382 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_PERIOD_ENABLED
, FALSE
, Timeout
);
389 Enable asynchrounous schedule
391 @param Ehc The EHCI device
392 @param Timeout Time to wait before abort
394 @return EFI_SUCCESS : The EHCI asynchronous schedule is enabled
395 @return Others : Failed to enable the asynchronous scheudle
407 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
409 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, TRUE
, Timeout
);
416 Disable asynchrounous schedule
418 @param Ehc The EHCI device
419 @param Timeout Time to wait before abort (in millisecond, ms)
421 @return EFI_SUCCESS : The asynchronous schedule is disabled
422 @return Others : Failed to disable the asynchronous schedule
427 EhcDisableAsyncSchd (
434 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_ENABLE_ASYNC
);
436 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_ASYNC_ENABLED
, FALSE
, Timeout
);
443 Whether Ehc is halted
445 @param Ehc The EHCI device
447 @return TRUE : The controller is halted
448 @return FALSE : It isn't halted
456 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
);
461 Whether system error occurred
463 @param Ehc The EHCI device
465 @return TRUE : System error happened
466 @return FALSE : No system error
474 return EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_SYS_ERROR
);
479 Reset the host controller
481 @param Ehc The EHCI device
482 @param Timeout Time to wait before abort (in millisecond, ms)
484 @return EFI_SUCCESS : The host controller is reset
485 @return Others : Failed to reset the host
497 // Host can only be reset when it is halt. If not so, halt it
499 if (!EHC_REG_BIT_IS_SET (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
)) {
500 Status
= EhcHaltHC (Ehc
, Timeout
);
502 if (EFI_ERROR (Status
)) {
507 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
);
508 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RESET
, FALSE
, Timeout
);
514 Halt the host controller
516 @param Ehc The EHCI device
517 @param Timeout Time to wait before abort
519 @return EFI_SUCCESS : The EHCI is halt
520 @return EFI_TIMEOUT : Failed to halt the controller before Timeout
531 EhcClearOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
532 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, TRUE
, Timeout
);
540 @param Ehc The EHCI device
541 @param Timeout Time to wait before abort
543 @return EFI_SUCCESS : The EHCI is running
544 @return Others : Failed to set the EHCI to run
555 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
556 Status
= EhcWaitOpRegBit (Ehc
, EHC_USBSTS_OFFSET
, USBSTS_HALT
, FALSE
, Timeout
);
562 Initialize the HC hardware.
563 EHCI spec lists the five things to do to initialize the hardware
564 1. Program CTRLDSSEGMENT
565 2. Set USBINTR to enable interrupts
566 3. Set periodic list base
567 4. Set USBCMD, interrupt threshold, frame list size etc
568 5. Write 1 to CONFIGFLAG to route all ports to EHCI
570 @param Ehc The EHCI device
572 @return EFI_SUCCESS : The EHCI has come out of halt state
573 @return EFI_TIMEOUT : Time out happened
583 ASSERT (EhcIsHalt (Ehc
));
586 // Allocate the periodic frame and associated memeory
587 // management facilities if not already done.
589 if (Ehc
->PeriodFrame
!= NULL
) {
593 Status
= EhcInitSched (Ehc
);
595 if (EFI_ERROR (Status
)) {
599 // 1. Program the CTRLDSSEGMENT register with the high 32 bit addr
601 EhcWriteOpReg (Ehc
, EHC_CTRLDSSEG_OFFSET
, Ehc
->High32bitAddr
);
604 // 2. Clear USBINTR to disable all the interrupt. UEFI works by polling
606 EhcWriteOpReg (Ehc
, EHC_USBINTR_OFFSET
, 0);
609 // 3. Program periodic frame list, already done in EhcInitSched
610 // 4. Start the Host Controller
612 EhcSetOpRegBit (Ehc
, EHC_USBCMD_OFFSET
, USBCMD_RUN
);
615 // 5. Set all ports routing to EHC
617 EhcSetOpRegBit (Ehc
, EHC_CONFIG_FLAG_OFFSET
, CONFIGFLAG_ROUTE_EHC
);
619 Status
= EhcEnablePeriodSchd (Ehc
, EHC_GENERIC_TIME
);
621 if (EFI_ERROR (Status
)) {
622 EHC_ERROR (("EhcInitHC: failed to enable period schedule\n"));
626 Status
= EhcEnableAsyncSchd (Ehc
, EHC_GENERIC_TIME
);
628 if (EFI_ERROR (Status
)) {
629 EHC_ERROR (("EhcInitHC: failed to enable async schedule\n"));