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
);
87 //Enable power to the USB host.
88 Status
= gTPS65950
->Read(gTPS65950
, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3
, LEDEN
), 1, &Data
);
89 ASSERT_EFI_ERROR(Status
);
91 //LEDAON & LEDAPWM control the power to the USB host so enable those bits.
92 Data
|= (LEDAON
| LEDAPWM
);
94 Status
= gTPS65950
->Write(gTPS65950
, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3
, LEDEN
), 1, &Data
);
95 ASSERT_EFI_ERROR(Status
);
101 IN EFI_PCI_IO_PROTOCOL
*This
,
102 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
112 return EFI_UNSUPPORTED
;
117 IN EFI_PCI_IO_PROTOCOL
*This
,
118 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
128 return EFI_UNSUPPORTED
;
133 IN EFI_PCI_IO_PROTOCOL
*This
,
134 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
141 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
143 return PciRootBridgeIoMemRead (&Private
->RootBridge
.Io
,
144 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
145 Private
->ConfigSpace
->Device
.Bar
[BarIndex
] + Offset
,
153 IN EFI_PCI_IO_PROTOCOL
*This
,
154 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
161 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
163 return PciRootBridgeIoMemWrite (&Private
->RootBridge
.Io
,
164 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
165 Private
->ConfigSpace
->Device
.Bar
[BarIndex
] + Offset
,
173 IN EFI_PCI_IO_PROTOCOL
*This
,
174 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
182 return EFI_UNSUPPORTED
;
187 IN EFI_PCI_IO_PROTOCOL
*This
,
188 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
196 return EFI_UNSUPPORTED
;
201 IN EFI_PCI_IO_PROTOCOL
*This
,
202 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
208 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
210 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)Width
,
215 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
)
221 IN EFI_PCI_IO_PROTOCOL
*This
,
222 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
228 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
230 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
233 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
),
241 IN EFI_PCI_IO_PROTOCOL
*This
,
242 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
243 IN UINT8 DestBarIndex
,
244 IN UINT64 DestOffset
,
245 IN UINT8 SrcBarIndex
,
251 return EFI_UNSUPPORTED
;
256 IN EFI_PCI_IO_PROTOCOL
*This
,
257 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
258 IN VOID
*HostAddress
,
259 IN OUT UINTN
*NumberOfBytes
,
260 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
264 DMA_MAP_OPERATION DmaOperation
;
266 if (Operation
== EfiPciIoOperationBusMasterRead
) {
267 DmaOperation
= MapOperationBusMasterRead
;
268 } else if (Operation
== EfiPciIoOperationBusMasterWrite
) {
269 DmaOperation
= MapOperationBusMasterWrite
;
270 } else if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
271 DmaOperation
= MapOperationBusMasterCommonBuffer
;
273 return EFI_INVALID_PARAMETER
;
275 return DmaMap (DmaOperation
, HostAddress
, NumberOfBytes
, DeviceAddress
, Mapping
);
280 IN EFI_PCI_IO_PROTOCOL
*This
,
284 return DmaUnmap (Mapping
);
288 PciIoAllocateBuffer (
289 IN EFI_PCI_IO_PROTOCOL
*This
,
290 IN EFI_ALLOCATE_TYPE Type
,
291 IN EFI_MEMORY_TYPE MemoryType
,
293 OUT VOID
**HostAddress
,
297 if (Attributes
& EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER
) {
299 return EFI_UNSUPPORTED
;
302 return DmaAllocateBuffer (MemoryType
, Pages
, HostAddress
);
308 IN EFI_PCI_IO_PROTOCOL
*This
,
313 return DmaFreeBuffer (Pages
, HostAddress
);
319 IN EFI_PCI_IO_PROTOCOL
*This
327 IN EFI_PCI_IO_PROTOCOL
*This
,
328 OUT UINTN
*SegmentNumber
,
329 OUT UINTN
*BusNumber
,
330 OUT UINTN
*DeviceNumber
,
331 OUT UINTN
*FunctionNumber
334 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This
);
336 if (SegmentNumber
!= NULL
) {
337 *SegmentNumber
= Private
->Segment
;
340 if (BusNumber
!= NULL
) {
344 if (DeviceNumber
!= NULL
) {
348 if (FunctionNumber
!= NULL
) {
357 IN EFI_PCI_IO_PROTOCOL
*This
,
358 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
359 IN UINT64 Attributes
,
360 OUT UINT64
*Result OPTIONAL
364 case EfiPciIoAttributeOperationGet
:
365 case EfiPciIoAttributeOperationSupported
:
366 if (Result
== NULL
) {
367 return EFI_INVALID_PARAMETER
;
369 // We are not a real PCI device so just say things we kind of do
370 *Result
= EFI_PCI_IO_ATTRIBUTE_MEMORY
| EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
| EFI_PCI_DEVICE_ENABLE
;
373 case EfiPciIoAttributeOperationSet
:
374 case EfiPciIoAttributeOperationEnable
:
375 case EfiPciIoAttributeOperationDisable
:
376 // Since we are not a real PCI device no enable/set or disable operations exist.
381 return EFI_INVALID_PARAMETER
;
387 PciIoGetBarAttributes (
388 IN EFI_PCI_IO_PROTOCOL
*This
,
390 OUT UINT64
*Supports
, OPTIONAL
391 OUT VOID
**Resources OPTIONAL
395 return EFI_UNSUPPORTED
;
399 PciIoSetBarAttributes (
400 IN EFI_PCI_IO_PROTOCOL
*This
,
401 IN UINT64 Attributes
,
403 IN OUT UINT64
*Offset
,
404 IN OUT UINT64
*Length
408 return EFI_UNSUPPORTED
;
411 EFI_PCI_IO_PROTOCOL PciIoTemplate
=
429 PciIoGetBarAttributes
,
430 PciIoSetBarAttributes
,
437 PciEmulationEntryPoint (
438 IN EFI_HANDLE ImageHandle
,
439 IN EFI_SYSTEM_TABLE
*SystemTable
444 EFI_PCI_IO_PRIVATE_DATA
*Private
;
445 UINT8 CapabilityLength
;
450 //Configure USB host for OMAP3530.
453 // Create a private structure
454 Private
= AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA
));
455 if (Private
== NULL
) {
456 Status
= EFI_OUT_OF_RESOURCES
;
460 Private
->Signature
= EFI_PCI_IO_PRIVATE_DATA_SIGNATURE
; // Fill in signature
461 Private
->RootBridge
.Signature
= PCI_ROOT_BRIDGE_SIGNATURE
; // Fake Root Bridge structure needs a signature too
462 Private
->RootBridge
.MemoryStart
= USB_EHCI_HCCAPBASE
; // Get the USB capability register base
463 Private
->Segment
= 0; // Default to segment zero
465 // Find out the capability register length and number of physical ports.
466 CapabilityLength
= MmioRead8(Private
->RootBridge
.MemoryStart
);
467 PhysicalPorts
= (MmioRead32 (Private
->RootBridge
.MemoryStart
+ 0x4)) & 0x0000000F;
469 // Calculate the total size of the USB registers.
470 Private
->RootBridge
.MemorySize
= CapabilityLength
+ (HOST_CONTROLLER_OPERATION_REG_SIZE
+ ((4 * PhysicalPorts
) - 1));
472 // Enable Port Power bit in Port status and control registers in EHCI register space.
473 // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
474 // host controller implementation includes port power control.
475 for (Count
= 0; Count
< PhysicalPorts
; Count
++) {
476 MmioOr32 ((Private
->RootBridge
.MemoryStart
+ CapabilityLength
+ HOST_CONTROLLER_OPERATION_REG_SIZE
+ 4*Count
), 0x00001000);
479 // Create fake PCI config space.
480 Private
->ConfigSpace
= AllocateZeroPool(sizeof(PCI_TYPE00
));
481 if (Private
->ConfigSpace
== NULL
) {
482 Status
= EFI_OUT_OF_RESOURCES
;
487 // Configure PCI config space
488 Private
->ConfigSpace
->Hdr
.VendorId
= 0x3530;
489 Private
->ConfigSpace
->Hdr
.DeviceId
= 0x3530;
490 Private
->ConfigSpace
->Hdr
.ClassCode
[0] = 0x20;
491 Private
->ConfigSpace
->Hdr
.ClassCode
[1] = 0x03;
492 Private
->ConfigSpace
->Hdr
.ClassCode
[2] = 0x0C;
493 Private
->ConfigSpace
->Device
.Bar
[0] = Private
->RootBridge
.MemoryStart
;
497 // Unique device path.
498 CopyMem(&Private
->DevicePath
, &PciIoDevicePathTemplate
, sizeof(PciIoDevicePathTemplate
));
499 Private
->DevicePath
.AcpiDevicePath
.UID
= 0;
501 // Copy protocol structure
502 CopyMem(&Private
->PciIoProtocol
, &PciIoTemplate
, sizeof(PciIoTemplate
));
504 Status
= gBS
->InstallMultipleProtocolInterfaces(&Handle
,
505 &gEfiPciIoProtocolGuid
, &Private
->PciIoProtocol
,
506 &gEfiDevicePathProtocolGuid
, &Private
->DevicePath
,
508 if (EFI_ERROR(Status
)) {
509 DEBUG((EFI_D_ERROR
, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));