diff options
Diffstat (limited to 'Omap35xxPkg/PciEmulation')
-rw-r--r-- | Omap35xxPkg/PciEmulation/PciEmulation.c | 578 | ||||
-rw-r--r-- | Omap35xxPkg/PciEmulation/PciEmulation.h | 305 | ||||
-rw-r--r-- | Omap35xxPkg/PciEmulation/PciEmulation.inf | 58 | ||||
-rw-r--r-- | Omap35xxPkg/PciEmulation/PciRootBridgeIo.c | 306 |
4 files changed, 1247 insertions, 0 deletions
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.c b/Omap35xxPkg/PciEmulation/PciEmulation.c new file mode 100644 index 0000000000..fa44570b4c --- /dev/null +++ b/Omap35xxPkg/PciEmulation/PciEmulation.c @@ -0,0 +1,578 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "PciEmulation.h" +#include <Omap3530/Omap3530.h> + +EFI_CPU_ARCH_PROTOCOL *gCpu; +EMBEDDED_EXTERNAL_DEVICE *gTPS65950; + +#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44 + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + PCI_DEVICE_PATH PciDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_IO_DEVICE_PATH; + +typedef struct { + UINT32 Signature; + EFI_PCI_IO_DEVICE_PATH DevicePath; + EFI_PCI_IO_PROTOCOL PciIoProtocol; + PCI_TYPE00 *ConfigSpace; + PCI_ROOT_BRIDGE RootBridge; + UINTN Segment; +} EFI_PCI_IO_PRIVATE_DATA; + +#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o') +#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE) + +EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate = +{ + { + { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0}, + EISA_PNP_ID(0x0A03), // HID + 0 // UID + }, + { + { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0}, + 0, + 0 + }, + { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} +}; + +STATIC +VOID +ConfigureUSBHost ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 Data = 0; + + // Take USB host out of force-standby mode + MmioWrite32(UHH_SYSCONFIG, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY + | UHH_SYSCONFIG_CLOCKACTIVITY_ON + | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY + | UHH_SYSCONFIG_ENAWAKEUP_ENABLE + | UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN); + MmioWrite32(UHH_HOSTCONFIG, UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE + | UHH_HOSTCONFIG_ENA_INCR16_ENABLE + | UHH_HOSTCONFIG_ENA_INCR8_ENABLE + | UHH_HOSTCONFIG_ENA_INCR4_ENABLE + | UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON + | UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE); + + // USB reset (GPIO 147 - Port 5 pin 19) output high + MmioAnd32(GPIO5_BASE + GPIO_OE, ~BIT19); + MmioWrite32(GPIO5_BASE + GPIO_SETDATAOUT, BIT19); + + // Get the Power IC protocol. + Status = gBS->LocateProtocol(&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950); + ASSERT_EFI_ERROR(Status); + + //Enable power to the USB host. + Status = gTPS65950->Read(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); + ASSERT_EFI_ERROR(Status); + + //LEDAON & LEDAPWM control the power to the USB host so enable those bits. + Data |= (LEDAON | LEDAPWM); + + Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); + ASSERT_EFI_ERROR(Status); +} + +EFI_STATUS +PciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRead (&Private->RootBridge.Io, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Private->ConfigSpace->Device.Bar[BarIndex] + Offset, + Count, + Buffer + ); +} + +EFI_STATUS +PciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemWrite (&Private->RootBridge.Io, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Private->ConfigSpace->Device.Bar[BarIndex] + Offset, + Count, + Buffer + ); +} + +EFI_STATUS +PciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoPciRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width, + Count, + TRUE, + (PTR)(UINTN)Buffer, + TRUE, + (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) + ); +} + +EFI_STATUS +PciIoPciWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Count, + TRUE, + (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset), + TRUE, + (PTR)(UINTN)Buffer + ); +} + +EFI_STATUS +PciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + MAP_INFO_INSTANCE *Map; + EFI_STATUS Status; + + if ( HostAddress == NULL || NumberOfBytes == NULL || + DeviceAddress == NULL || Mapping == NULL ) { + + return EFI_INVALID_PARAMETER; + } + + + if (Operation >= EfiPciOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + *DeviceAddress = ConvertToPhysicalAddress (HostAddress); + + // Data cache flush (HostAddress, NumberOfBytes); + + // Remember range so we can flush on the other side + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (PCI_DMA_MAP), (VOID **) &Map); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } + + *Mapping = Map; + + Map->HostAddress = (UINTN)HostAddress; + Map->DeviceAddress = *DeviceAddress; + Map->NumberOfBytes = *NumberOfBytes; + Map->Operation = Operation; + + // EfiCpuFlushTypeWriteBack, EfiCpuFlushTypeInvalidate + gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + PCI_DMA_MAP *Map; + + if (Mapping == NULL) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Map = (PCI_DMA_MAP *)Mapping; + if (Map->Operation == EfiPciOperationBusMasterWrite) { + // + // Make sure we read buffer from uncached memory and not the cache + // + gCpu->FlushDataCache (gCpu, Map->HostAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate); + } + + FreePool (Map); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + // We used uncached memory to keep coherency + // + if (MemoryType == EfiBootServicesData) { + *HostAddress = UncachedAllocatePages (Pages); + } else if (MemoryType != EfiRuntimeServicesData) { + *HostAddress = UncachedAllocateRuntimePages (Pages); + } else { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UncachedFreePages (HostAddress, Pages); + return EFI_SUCCESS; +} + + +EFI_STATUS +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + if (SegmentNumber != NULL) { + *SegmentNumber = Private->Segment; + } + + if (BusNumber != NULL) { + *BusNumber = 0xff; + } + + if (DeviceNumber != NULL) { + *DeviceNumber = 0; + } + + if (FunctionNumber != NULL) { + *FunctionNumber = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ) +{ + switch (Operation) { + case EfiPciIoAttributeOperationGet: + case EfiPciIoAttributeOperationSupported: + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + // We are not a real PCI device so just say things we kind of do + *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE; + break; + + case EfiPciIoAttributeOperationSet: + case EfiPciIoAttributeOperationEnable: + case EfiPciIoAttributeOperationDisable: + // Since we are not a real PCI device no enable/set or disable operations exist. + return EFI_SUCCESS; + + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + }; + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoGetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoSetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_PCI_IO_PROTOCOL PciIoTemplate = +{ + PciIoPollMem, + PciIoPollIo, + PciIoMemRead, + PciIoMemWrite, + PciIoIoRead, + PciIoIoWrite, + PciIoPciRead, + PciIoPciWrite, + PciIoCopyMem, + PciIoMap, + PciIoUnmap, + PciIoAllocateBuffer, + PciIoFreeBuffer, + PciIoFlush, + PciIoGetLocation, + PciIoAttributes, + PciIoGetBarAttributes, + PciIoSetBarAttributes, + 0, + 0 +}; + +EFI_STATUS +EFIAPI +PciEmulationEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_PCI_IO_PRIVATE_DATA *Private; + UINT8 CapabilityLength; + UINT8 PhysicalPorts; + UINTN Count; + + // Get the Cpu protocol for later use + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); + ASSERT_EFI_ERROR(Status); + + //Configure USB host for OMAP3530. + ConfigureUSBHost(); + + // Create a private structure + Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA)); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } + + Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature + Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too + Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base + Private->Segment = 0; // Default to segment zero + + // Find out the capability register length and number of physical ports. + CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart); + PhysicalPorts = (MmioRead32(Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F; + + // Calculate the total size of the USB registers. + Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1)); + + // Enable Port Power bit in Port status and control registers in EHCI register space. + // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates + // host controller implementation includes port power control. + for (Count = 0; Count < PhysicalPorts; Count++) { + MmioOr32((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000); + } + + // Create fake PCI config space. + Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00)); + if (Private->ConfigSpace == NULL) { + Status = EFI_OUT_OF_RESOURCES; + FreePool(Private); + return Status; + } + + // Configure PCI config space + Private->ConfigSpace->Hdr.VendorId = 0x3530; + Private->ConfigSpace->Hdr.DeviceId = 0x3530; + Private->ConfigSpace->Hdr.ClassCode[0] = 0x20; + Private->ConfigSpace->Hdr.ClassCode[1] = 0x03; + Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C; + Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart; + + Handle = NULL; + + // Unique device path. + CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate)); + Private->DevicePath.AcpiDevicePath.UID = 0; + + // Copy protocol structure + CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate)); + + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, + &gEfiPciIoProtocolGuid, &Private->PciIoProtocol, + &gEfiDevicePathProtocolGuid, &Private->DevicePath, + NULL); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n")); + } + + return Status; +} + diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.h b/Omap35xxPkg/PciEmulation/PciEmulation.h new file mode 100644 index 0000000000..c19cd8c551 --- /dev/null +++ b/Omap35xxPkg/PciEmulation/PciEmulation.h @@ -0,0 +1,305 @@ +/** @file
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCI_ROOT_BRIDGE_H_
+#define _PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <TPS65950.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/Cpu.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+
+#include <IndustryStandard/Pci22.h>
+#include <IndustryStandard/Acpi.h>
+
+extern EFI_CPU_ARCH_PROTOCOL *gCpu;
+
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
+
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+
+#define ACPI_CONFIG_IO 0
+#define ACPI_CONFIG_MMIO 1
+#define ACPI_CONFIG_BUS 2
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
+} ACPI_CONFIG_INFO;
+
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
+
+ UINT8 StartBus;
+ UINT8 EndBus;
+ UINT16 Type;
+ UINT32 MemoryStart;
+ UINT32 MemorySize;
+ UINTN IoOffset;
+ UINT32 IoStart;
+ UINT32 IoSize;
+ UINT64 PciAttributes;
+
+ ACPI_CONFIG_INFO *Config;
+
+} PCI_ROOT_BRIDGE;
+
+
+#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+
+typedef union {
+ UINT8 volatile *buf;
+ UINT8 volatile *ui8;
+ UINT16 volatile *ui16;
+ UINT32 volatile *ui32;
+ UINT64 volatile *ui64;
+ UINTN volatile ui;
+} PTR;
+
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINTN NumberOfBytes;
+ EFI_PCI_IO_PROTOCOL_OPERATION Operation;
+
+} MAP_INFO_INSTANCE;
+
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINTN NumberOfBytes;
+ EFI_PCI_IO_PROTOCOL_OPERATION Operation;
+} PCI_DMA_MAP;
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Private Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ );
+
+BOOLEAN
+PciIoMemAddressValid (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Address
+ );
+
+EFI_STATUS
+EmulatePciIoForEhci (
+ INTN MvPciIfMaxIf
+ );
+
+#endif
+
diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.inf b/Omap35xxPkg/PciEmulation/PciEmulation.inf new file mode 100644 index 0000000000..8b179ae63c --- /dev/null +++ b/Omap35xxPkg/PciEmulation/PciEmulation.inf @@ -0,0 +1,58 @@ +/** @file
+
+ Copyright (c) 2009 Apple, Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BeagleBoardPciEmulation
+ FILE_GUID = feaa2e2b-53ac-4d5e-ae10-1efd5da4a2ba
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PciEmulationEntryPoint
+
+[Sources.common]
+ PciRootBridgeIo.c
+ PciEmulation.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ Omap35xxPkg/Omap35xxPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DxeServicesTableLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ UncachedMemoryAllocationLib
+ IoLib
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiPciHostBridgeResourceAllocationProtocolGuid
+ gEfiCpuArchProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEmbeddedExternalDeviceProtocolGuid
+
+[Depex]
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid AND
+ gEmbeddedExternalDeviceProtocolGuid
+
\ No newline at end of file diff --git a/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c b/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c new file mode 100644 index 0000000000..d06a56ce57 --- /dev/null +++ b/Omap35xxPkg/PciEmulation/PciRootBridgeIo.c @@ -0,0 +1,306 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PciEmulation.h"
+
+BOOLEAN
+PciRootBridgeMemAddressValid (
+ IN PCI_ROOT_BRIDGE *Private,
+ IN UINT64 Address
+ )
+{
+ if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ )
+{
+ UINTN Stride;
+ UINTN InStride;
+ UINTN OutStride;
+
+
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ Stride = (UINTN)1 << Width;
+ InStride = InStrideFlag ? Stride : 0;
+ OutStride = OutStrideFlag ? Stride : 0;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui8 = *Out.ui8;
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui16 = *Out.ui16;
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui32 = *Out.ui32;
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.buf = Buffer;
+ Out.buf = (VOID *)(UINTN) Address;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.buf = (VOID *)(UINTN) Address;
+ Out.buf = Buffer;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+
|