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
;
210 Enable a PCI driver to read PCI controller registers in PCI configuration space.
212 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
213 @param[in] Width Signifies the width of the memory operations.
214 @param[in] Offset The offset within the PCI configuration space for
216 @param[in] Count The number of PCI configuration operations to
217 perform. Bytes moved is Width size * Count,
220 @param[in out] Buffer The destination buffer to store the results.
222 @retval EFI_SUCCESS The data was read from the PCI controller.
223 @retval EFI_INVALID_PARAMETER "Width" is invalid.
224 @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
229 IN EFI_PCI_IO_PROTOCOL
*This
,
230 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
236 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
239 if ((Width
< 0) || (Width
>= EfiPciIoWidthMaximum
) || (Buffer
== NULL
)) {
240 return EFI_INVALID_PARAMETER
;
243 Status
= PciRootBridgeIoMemRW (
244 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
)Width
,
249 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
) //Fix me ConfigSpace
256 Enable a PCI driver to write PCI controller registers in PCI configuration space.
258 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
259 @param[in] Width Signifies the width of the memory operations.
260 @param[in] Offset The offset within the PCI configuration space for
262 @param[in] Count The number of PCI configuration operations to
263 perform. Bytes moved is Width size * Count,
266 @param[in out] Buffer The source buffer to write data from.
268 @retval EFI_SUCCESS The data was read from the PCI controller.
269 @retval EFI_INVALID_PARAMETER "Width" is invalid.
270 @retval EFI_INVALID_PARAMETER "Buffer" is NULL.
275 IN EFI_PCI_IO_PROTOCOL
*This
,
276 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
282 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
284 if ((Width
< 0) || (Width
>= EfiPciIoWidthMaximum
) || (Buffer
== NULL
)) {
285 return EFI_INVALID_PARAMETER
;
288 return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
291 (PTR
)(UINTN
)(((UINT8
*)Private
->ConfigSpace
) + Offset
),
299 IN EFI_PCI_IO_PROTOCOL
*This
,
300 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
301 IN UINT8 DestBarIndex
,
302 IN UINT64 DestOffset
,
303 IN UINT8 SrcBarIndex
,
309 return EFI_UNSUPPORTED
;
314 IN EFI_PCI_IO_PROTOCOL
*This
,
315 IN EFI_PCI_IO_PROTOCOL_OPERATION Operation
,
316 IN VOID
*HostAddress
,
317 IN OUT UINTN
*NumberOfBytes
,
318 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
322 DMA_MAP_OPERATION DmaOperation
;
324 if (Operation
== EfiPciIoOperationBusMasterRead
) {
325 DmaOperation
= MapOperationBusMasterRead
;
326 } else if (Operation
== EfiPciIoOperationBusMasterWrite
) {
327 DmaOperation
= MapOperationBusMasterWrite
;
328 } else if (Operation
== EfiPciIoOperationBusMasterCommonBuffer
) {
329 DmaOperation
= MapOperationBusMasterCommonBuffer
;
331 return EFI_INVALID_PARAMETER
;
333 return DmaMap (DmaOperation
, HostAddress
, NumberOfBytes
, DeviceAddress
, Mapping
);
338 IN EFI_PCI_IO_PROTOCOL
*This
,
342 return DmaUnmap (Mapping
);
346 Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer
349 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
350 @param[in] Type This parameter is not used and must be ignored.
351 @param[in] MemoryType The type of memory to allocate, EfiBootServicesData or
352 EfiRuntimeServicesData.
353 @param[in] Pages The number of pages to allocate.
354 @param[out] HostAddress A pointer to store the base system memory address of
356 @param[in] Attributes The requested bit mask of attributes for the allocated
357 range. Only the attributes,
358 EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and
359 EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with this
360 function. If any other bits are set, then EFI_UNSUPPORTED
361 is returned. This function ignores this bit mask.
363 @retval EFI_SUCCESS The requested memory pages were allocated.
364 @retval EFI_INVALID_PARAMETER HostAddress is NULL.
365 @retval EFI_INVALID_PARAMETER MemoryType is invalid.
366 @retval EFI_UNSUPPORTED Attributes is unsupported.
367 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
371 PciIoAllocateBuffer (
372 IN EFI_PCI_IO_PROTOCOL
*This
,
373 IN EFI_ALLOCATE_TYPE Type
,
374 IN EFI_MEMORY_TYPE MemoryType
,
376 OUT VOID
**HostAddress
,
381 (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
382 EFI_PCI_ATTRIBUTE_MEMORY_CACHED
))) {
383 return EFI_UNSUPPORTED
;
386 return DmaAllocateBuffer (MemoryType
, Pages
, HostAddress
);
392 IN EFI_PCI_IO_PROTOCOL
*This
,
397 return DmaFreeBuffer (Pages
, HostAddress
);
403 IN EFI_PCI_IO_PROTOCOL
*This
410 Retrieves this PCI controller's current PCI bus number, device number, and function number.
412 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
413 @param[out] SegmentNumber The PCI controller's current PCI segment number.
414 @param[out] BusNumber The PCI controller's current PCI bus number.
415 @param[out] DeviceNumber The PCI controller's current PCI device number.
416 @param[out] FunctionNumber The PCI controller’s current PCI function number.
418 @retval EFI_SUCCESS The PCI controller location was returned.
419 @retval EFI_INVALID_PARAMETER At least one out of the four output parameters is
424 IN EFI_PCI_IO_PROTOCOL
*This
,
425 OUT UINTN
*SegmentNumber
,
426 OUT UINTN
*BusNumber
,
427 OUT UINTN
*DeviceNumber
,
428 OUT UINTN
*FunctionNumber
431 EFI_PCI_IO_PRIVATE_DATA
*Private
= EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This
);
433 if ((SegmentNumber
== NULL
) || (BusNumber
== NULL
) ||
434 (DeviceNumber
== NULL
) || (FunctionNumber
== NULL
) ) {
435 return EFI_INVALID_PARAMETER
;
438 *SegmentNumber
= Private
->Segment
;
447 Performs an operation on the attributes that this PCI controller supports.
449 The operations include getting the set of supported attributes, retrieving
450 the current attributes, setting the current attributes, enabling attributes,
451 and disabling attributes.
453 @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance.
454 @param[in] Operation The operation to perform on the attributes for this
456 @param[in] Attributes The mask of attributes that are used for Set,
457 Enable and Disable operations.
458 @param[out] Result A pointer to the result mask of attributes that are
459 returned for the Get and Supported operations. This
460 is an optional parameter that may be NULL for the
461 Set, Enable, and Disable operations.
463 @retval EFI_SUCCESS The operation on the PCI controller's
464 attributes was completed. If the operation
465 was Get or Supported, then the attribute mask
466 is returned in Result.
467 @retval EFI_INVALID_PARAMETER Operation is greater than or equal to
468 EfiPciIoAttributeOperationMaximum.
469 @retval EFI_INVALID_PARAMETER Operation is Get and Result is NULL.
470 @retval EFI_INVALID_PARAMETER Operation is Supported and Result is NULL.
475 IN EFI_PCI_IO_PROTOCOL
*This
,
476 IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
,
477 IN UINT64 Attributes
,
478 OUT UINT64
*Result OPTIONAL
482 case EfiPciIoAttributeOperationGet
:
483 case EfiPciIoAttributeOperationSupported
:
484 if (Result
== NULL
) {
485 return EFI_INVALID_PARAMETER
;
488 // We are not a real PCI device so just say things we kind of do
490 *Result
= EFI_PCI_DEVICE_ENABLE
;
493 case EfiPciIoAttributeOperationSet
:
494 case EfiPciIoAttributeOperationEnable
:
495 case EfiPciIoAttributeOperationDisable
:
496 if (Attributes
& (~EFI_PCI_DEVICE_ENABLE
)) {
497 return EFI_UNSUPPORTED
;
499 // Since we are not a real PCI device no enable/set or disable operations exist.
503 return EFI_INVALID_PARAMETER
;
509 PciIoGetBarAttributes (
510 IN EFI_PCI_IO_PROTOCOL
*This
,
512 OUT UINT64
*Supports
, OPTIONAL
513 OUT VOID
**Resources OPTIONAL
517 return EFI_UNSUPPORTED
;
521 PciIoSetBarAttributes (
522 IN EFI_PCI_IO_PROTOCOL
*This
,
523 IN UINT64 Attributes
,
525 IN OUT UINT64
*Offset
,
526 IN OUT UINT64
*Length
530 return EFI_UNSUPPORTED
;
533 EFI_PCI_IO_PROTOCOL PciIoTemplate
=
537 { PciIoMemRead
, PciIoMemWrite
},
538 { PciIoIoRead
, PciIoIoWrite
},
539 { PciIoPciRead
, PciIoPciWrite
},
548 PciIoGetBarAttributes
,
549 PciIoSetBarAttributes
,
556 PciEmulationEntryPoint (
557 IN EFI_HANDLE ImageHandle
,
558 IN EFI_SYSTEM_TABLE
*SystemTable
563 EFI_PCI_IO_PRIVATE_DATA
*Private
;
564 UINT8 CapabilityLength
;
569 //Configure USB host for OMAP3530.
572 // Create a private structure
573 Private
= AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA
));
574 if (Private
== NULL
) {
575 Status
= EFI_OUT_OF_RESOURCES
;
579 Private
->Signature
= EFI_PCI_IO_PRIVATE_DATA_SIGNATURE
; // Fill in signature
580 Private
->RootBridge
.Signature
= PCI_ROOT_BRIDGE_SIGNATURE
; // Fake Root Bridge structure needs a signature too
581 Private
->RootBridge
.MemoryStart
= USB_EHCI_HCCAPBASE
; // Get the USB capability register base
582 Private
->Segment
= 0; // Default to segment zero
584 // Find out the capability register length and number of physical ports.
585 CapabilityLength
= MmioRead8(Private
->RootBridge
.MemoryStart
);
586 PhysicalPorts
= (MmioRead32 (Private
->RootBridge
.MemoryStart
+ 0x4)) & 0x0000000F;
588 // Calculate the total size of the USB registers.
589 Private
->RootBridge
.MemorySize
= CapabilityLength
+ (HOST_CONTROLLER_OPERATION_REG_SIZE
+ ((4 * PhysicalPorts
) - 1));
591 // Enable Port Power bit in Port status and control registers in EHCI register space.
592 // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates
593 // host controller implementation includes port power control.
594 for (Count
= 0; Count
< PhysicalPorts
; Count
++) {
595 MmioOr32 ((Private
->RootBridge
.MemoryStart
+ CapabilityLength
+ HOST_CONTROLLER_OPERATION_REG_SIZE
+ 4*Count
), 0x00001000);
598 // Create fake PCI config space.
599 Private
->ConfigSpace
= AllocateZeroPool(sizeof(PCI_TYPE00
));
600 if (Private
->ConfigSpace
== NULL
) {
601 Status
= EFI_OUT_OF_RESOURCES
;
606 // Configure PCI config space
607 Private
->ConfigSpace
->Hdr
.VendorId
= 0xFFFF; // Invalid vendor Id as it is not an actual device.
608 Private
->ConfigSpace
->Hdr
.DeviceId
= 0x0000; // Not relevant as the vendor id is not valid.
609 Private
->ConfigSpace
->Hdr
.ClassCode
[0] = 0x20;
610 Private
->ConfigSpace
->Hdr
.ClassCode
[1] = 0x03;
611 Private
->ConfigSpace
->Hdr
.ClassCode
[2] = 0x0C;
612 Private
->ConfigSpace
->Device
.Bar
[0] = Private
->RootBridge
.MemoryStart
;
616 // Unique device path.
617 CopyMem(&Private
->DevicePath
, &PciIoDevicePathTemplate
, sizeof(PciIoDevicePathTemplate
));
618 Private
->DevicePath
.AcpiDevicePath
.UID
= 0;
620 // Copy protocol structure
621 CopyMem(&Private
->PciIoProtocol
, &PciIoTemplate
, sizeof(PciIoTemplate
));
623 Status
= gBS
->InstallMultipleProtocolInterfaces(&Handle
,
624 &gEfiPciIoProtocolGuid
, &Private
->PciIoProtocol
,
625 &gEfiDevicePathProtocolGuid
, &Private
->DevicePath
,
627 if (EFI_ERROR(Status
)) {
628 DEBUG((EFI_D_ERROR
, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n"));