3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PciEmulation.h"
17 EMBEDDED_EXTERNAL_DEVICE
*gTPS65950
;
19 #define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44
22 ACPI_HID_DEVICE_PATH AcpiDevicePath
;
23 PCI_DEVICE_PATH PciDevicePath
;
24 EFI_DEVICE_PATH_PROTOCOL EndDevicePath
;
25 } EFI_PCI_IO_DEVICE_PATH
;
29 EFI_PCI_IO_DEVICE_PATH DevicePath
;
30 EFI_PCI_IO_PROTOCOL PciIoProtocol
;
31 PCI_TYPE00
*ConfigSpace
;
32 PCI_ROOT_BRIDGE RootBridge
;
34 } EFI_PCI_IO_PRIVATE_DATA
;
36 #define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o')
37 #define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)
39 EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate
=
42 { ACPI_DEVICE_PATH
, ACPI_DP
, sizeof (ACPI_HID_DEVICE_PATH
), 0},
43 EISA_PNP_ID(0x0A03), // HID
47 { HARDWARE_DEVICE_PATH
, HW_PCI_DP
, sizeof (PCI_DEVICE_PATH
), 0},
51 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0}
63 // Take USB host out of force-standby mode
64 MmioWrite32 (UHH_SYSCONFIG
, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY
65 | UHH_SYSCONFIG_CLOCKACTIVITY_ON
66 | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY
67 | UHH_SYSCONFIG_ENAWAKEUP_ENABLE
68 | UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN
);
69 MmioWrite32 (UHH_HOSTCONFIG
, UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT
70 | UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT
71 | UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT
72 | UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE
73 | UHH_HOSTCONFIG_ENA_INCR16_ENABLE
74 | UHH_HOSTCONFIG_ENA_INCR8_ENABLE
75 | UHH_HOSTCONFIG_ENA_INCR4_ENABLE
76 | UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON
77 | UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE
);
79 // USB reset (GPIO 147 - Port 5 pin 19) output high
80 MmioAnd32 (GPIO5_BASE
+ GPIO_OE
, ~BIT19
);
81 MmioWrite32 (GPIO5_BASE
+ GPIO_SETDATAOUT
, BIT19
);
83 // Get the Power IC protocol
84 Status
= gBS
->LocateProtocol (&gEmbeddedExternalDeviceProtocolGuid
, NULL
, (VOID
**)&gTPS65950
);
85 ASSERT_EFI_ERROR (Status
);
88 Data
= VAUX_DEV_GRP_P1
;
89 Status
= gTPS65950
->Write (gTPS65950
, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4
, VAUX2_DEV_GRP
), 1, &Data
);
90 ASSERT_EFI_ERROR(Status
);
92 Data
= VAUX_DEDICATED_18V
;
93 Status
= gTPS65950
->Write (gTPS65950
, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4
, VAUX2_DEDICATED
), 1, &Data
);
94 ASSERT_EFI_ERROR (Status
);
96 // Enable power to the USB hub
97 Status
= gTPS65950
->Read (gTPS65950
, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3
, LEDEN
), 1, &Data
);
98 ASSERT_EFI_ERROR (Status
);
100 // LEDAON controls the power to the USB host, PWM is disabled
104 Status
= gTPS65950
->Write (gTPS65950
, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3
, LEDEN
), 1, &Data
);
105 ASSERT_EFI_ERROR (Status
);
111 IN EFI_PCI_IO_PROTOCOL
*This
,
112 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
122 return EFI_UNSUPPORTED
;
127 IN EFI_PCI_IO_PROTOCOL
*This
,
128 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
138 return EFI_UNSUPPORTED
;
143 IN EFI_PCI_IO_PROTOCOL
*This
,
144 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
151 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
153 return PciRootBridgeIoMemRead (&Private
->RootBridge
.Io
,
154 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
155 Private
->ConfigSpace
->Device
.Bar
[BarIndex
] + Offset
,
163 IN EFI_PCI_IO_PROTOCOL
*This
,
164 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
171 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
173 return PciRootBridgeIoMemWrite (&Private
->RootBridge
.Io
,
174 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
175 Private
->ConfigSpace
->Device
.Bar
[BarIndex
] + Offset
,
183 IN EFI_PCI_IO_PROTOCOL
*This
,
184 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
192 return EFI_UNSUPPORTED
;
197 IN EFI_PCI_IO_PROTOCOL
*This
,
198 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
206 return EFI_UNSUPPORTED
;
211 IN EFI_PCI_IO_PROTOCOL
*This
,
212 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
218 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
220 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)Width
,
225 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
)
231 IN EFI_PCI_IO_PROTOCOL
*This
,
232 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
238 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
240 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
243 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
),
251 IN EFI_PCI_IO_PROTOCOL
*This
,
252 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
253 IN UINT8 DestBarIndex
,
254 IN UINT64 DestOffset
,
255 IN UINT8 SrcBarIndex
,
261 return EFI_UNSUPPORTED
;
266 IN EFI_PCI_IO_PROTOCOL
*This
,
267 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
268 IN VOID
*HostAddress
,
269 IN OUT UINTN
*NumberOfBytes
,
270 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
274 DMA_MAP_OPERATION DmaOperation
;
276 if (Operation
== EfiPciIoOperationBusMasterRead
) {
277 DmaOperation
= MapOperationBusMasterRead
;
278 } else if (Operation
== EfiPciIoOperationBusMasterWrite
) {
279 DmaOperation
= MapOperationBusMasterWrite
;
280 } else if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
281 DmaOperation
= MapOperationBusMasterCommonBuffer
;
283 return EFI_INVALID_PARAMETER
;
285 return DmaMap (DmaOperation
, HostAddress
, NumberOfBytes
, DeviceAddress
, Mapping
);
290 IN EFI_PCI_IO_PROTOCOL
*This
,
294 return DmaUnmap (Mapping
);
298 PciIoAllocateBuffer (
299 IN EFI_PCI_IO_PROTOCOL
*This
,
300 IN EFI_ALLOCATE_TYPE Type
,
301 IN EFI_MEMORY_TYPE MemoryType
,
303 OUT VOID
**HostAddress
,
307 if (Attributes
& EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER
) {
309 return EFI_UNSUPPORTED
;
312 return DmaAllocateBuffer (MemoryType
, Pages
, HostAddress
);
318 IN EFI_PCI_IO_PROTOCOL
*This
,
323 return DmaFreeBuffer (Pages
, HostAddress
);
329 IN EFI_PCI_IO_PROTOCOL
*This
337 IN EFI_PCI_IO_PROTOCOL
*This
,
338 OUT UINTN
*SegmentNumber
,
339 OUT UINTN
*BusNumber
,
340 OUT UINTN
*DeviceNumber
,
341 OUT UINTN
*FunctionNumber
344 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
346 if (SegmentNumber
!= NULL
) {
347 *SegmentNumber
= Private
->Segment
;
350 if (BusNumber
!= NULL
) {
354 if (DeviceNumber
!= NULL
) {
358 if (FunctionNumber
!= NULL
) {
367 IN EFI_PCI_IO_PROTOCOL
*This
,
368 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
369 IN UINT64 Attributes
,
370 OUT UINT64
*Result OPTIONAL
374 case EfiPciIoAttributeOperationGet
:
375 case EfiPciIoAttributeOperationSupported
:
376 if (Result
== NULL
) {
377 return EFI_INVALID_PARAMETER
;
379 // We are not a real PCI device so just say things we kind of do
380 *Result
= EFI_PCI_IO_ATTRIBUTE_MEMORY
| EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
| EFI_PCI_DEVICE_ENABLE
;
383 case EfiPciIoAttributeOperationSet
:
384 case EfiPciIoAttributeOperationEnable
:
385 case EfiPciIoAttributeOperationDisable
:
386 // Since we are not a real PCI device no enable/set or disable operations exist.
391 return EFI_INVALID_PARAMETER
;
397 PciIoGetBarAttributes (
398 IN EFI_PCI_IO_PROTOCOL
*This
,
400 OUT UINT64
*Supports
, OPTIONAL
401 OUT VOID
**Resources OPTIONAL
405 return EFI_UNSUPPORTED
;
409 PciIoSetBarAttributes (
410 IN EFI_PCI_IO_PROTOCOL
*This
,
411 IN UINT64 Attributes
,
413 IN OUT UINT64
*Offset
,
414 IN OUT UINT64
*Length
418 return EFI_UNSUPPORTED
;
421 EFI_PCI_IO_PROTOCOL PciIoTemplate
=
439 PciIoGetBarAttributes
,
440 PciIoSetBarAttributes
,
447 PciEmulationEntryPoint (
448 IN EFI_HANDLE ImageHandle
,
449 IN EFI_SYSTEM_TABLE
*SystemTable
454 EFI_PCI_IO_PRIVATE_DATA
*Private
;
455 UINT8 CapabilityLength
;
460 //Configure USB host for OMAP3530.
463 // Create a private structure
464 Private
= AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA
));
465 if (Private
== NULL
) {
466 Status
= EFI_OUT_OF_RESOURCES
;
470 Private
->Signature
= EFI_PCI_IO_PRIVATE_DATA_SIGNATURE
; // Fill in signature
471 Private
->RootBridge
.Signature
= PCI_ROOT_BRIDGE_SIGNATURE
; // Fake Root Bridge structure needs a signature too
472 Private
->RootBridge
.MemoryStart
= USB_EHCI_HCCAPBASE
; // Get the USB capability register base
473 Private
->Segment
= 0; // Default to segment zero
475 // Find out the capability register length and number of physical ports.
476 CapabilityLength
= MmioRead8(Private
->RootBridge
.MemoryStart
);
477 PhysicalPorts
= (MmioRead32 (Private
->RootBridge
.MemoryStart
+ 0x4)) & 0x0000000F;
479 // Calculate the total size of the USB registers.
480 Private
->RootBridge
.MemorySize
= CapabilityLength
+ (HOST_CONTROLLER_OPERATION_REG_SIZE
+ ((4 * PhysicalPorts
) - 1));
482 // Enable Port Power bit in Port status and control registers in EHCI register space.
483 // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
484 // host controller implementation includes port power control.
485 for (Count
= 0; Count
< PhysicalPorts
; Count
++) {
486 MmioOr32 ((Private
->RootBridge
.MemoryStart
+ CapabilityLength
+ HOST_CONTROLLER_OPERATION_REG_SIZE
+ 4*Count
), 0x00001000);
489 // Create fake PCI config space.
490 Private
->ConfigSpace
= AllocateZeroPool(sizeof(PCI_TYPE00
));
491 if (Private
->ConfigSpace
== NULL
) {
492 Status
= EFI_OUT_OF_RESOURCES
;
497 // Configure PCI config space
498 Private
->ConfigSpace
->Hdr
.VendorId
= 0x3530;
499 Private
->ConfigSpace
->Hdr
.DeviceId
= 0x3530;
500 Private
->ConfigSpace
->Hdr
.ClassCode
[0] = 0x20;
501 Private
->ConfigSpace
->Hdr
.ClassCode
[1] = 0x03;
502 Private
->ConfigSpace
->Hdr
.ClassCode
[2] = 0x0C;
503 Private
->ConfigSpace
->Device
.Bar
[0] = Private
->RootBridge
.MemoryStart
;
507 // Unique device path.
508 CopyMem(&Private
->DevicePath
, &PciIoDevicePathTemplate
, sizeof(PciIoDevicePathTemplate
));
509 Private
->DevicePath
.AcpiDevicePath
.UID
= 0;
511 // Copy protocol structure
512 CopyMem(&Private
->PciIoProtocol
, &PciIoTemplate
, sizeof(PciIoTemplate
));
514 Status
= gBS
->InstallMultipleProtocolInterfaces(&Handle
,
515 &gEfiPciIoProtocolGuid
, &Private
->PciIoProtocol
,
516 &gEfiDevicePathProtocolGuid
, &Private
->DevicePath
,
518 if (EFI_ERROR(Status
)) {
519 DEBUG((EFI_D_ERROR
, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));