X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=Omap35xxPkg%2FPciEmulation%2FPciEmulation.c;h=111652366b295c335cb62338ef35f955d56154ef;hb=8a8641b5640b4eeb79a5dedfe48f81805b43c967;hp=011a6340bddbe38d55e33ec41d3ce51dc179901b;hpb=c0bd010b0bd8252574eb31a0cecc39520835391b;p=mirror_edk2.git diff --git a/Omap35xxPkg/PciEmulation/PciEmulation.c b/Omap35xxPkg/PciEmulation/PciEmulation.c index 011a6340bd..111652366b 100644 --- a/Omap35xxPkg/PciEmulation/PciEmulation.c +++ b/Omap35xxPkg/PciEmulation/PciEmulation.c @@ -1,594 +1,633 @@ -/** @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 - -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; - - // 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); - - // USB reset (GPIO 147 - Port 5 pin 19) output low - MmioAnd32 (GPIO5_BASE + GPIO_OE, ~BIT19); - MmioWrite32 (GPIO5_BASE + GPIO_CLEARDATAOUT, BIT19); - - // Turn on functional & interface clocks to the USBHOST power domain - MmioOr32 (CM_FCLKEN_USBHOST, CM_FCLKEN_USBHOST_EN_USBHOST2_ENABLE | CM_FCLKEN_USBHOST_EN_USBHOST1_ENABLE); - MmioOr32 (CM_ICLKEN_USBHOST, CM_ICLKEN_USBHOST_EN_USBHOST_ENABLE); - // Wait for clock to become active - while (0 == (MmioRead32 (CM_CLKSTST_USBHOST) & 1)); - - - - // 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_SOFTRESET - ); - while ((MmioRead32 (UHH_SYSSTATUS) & UHH_SYSSTATUS_RESETDONE) == UHH_SYSSTATUS_RESETDONE); - - MmioWrite32 (UHH_SYSCONFIG, UHH_SYSCONFIG_CLOCKACTIVITY_ON - | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY - | UHH_SYSCONFIG_ENAWAKEUP_ENABLE - ); - - - MmioWrite32 (UHH_HOSTCONFIG, UHH_HOSTCONFIG_ENA_INCR16_ENABLE - | UHH_HOSTCONFIG_ENA_INCR8_ENABLE - | UHH_HOSTCONFIG_ENA_INCR4_ENABLE - ); - - // USB reset output high - MmioWrite32 (GPIO5_BASE + GPIO_SETDATAOUT, BIT19); - -} - -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; -} - +/** @file + + Copyright (c) 2008 - 2009, Apple Inc. 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" + +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); + + // Power the USB PHY + Data = VAUX_DEV_GRP_P1; + Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VAUX2_DEV_GRP), 1, &Data); + ASSERT_EFI_ERROR(Status); + + Data = VAUX_DEDICATED_18V; + Status = gTPS65950->Write (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VAUX2_DEDICATED), 1, &Data); + ASSERT_EFI_ERROR (Status); + + // Enable power to the USB hub + Status = gTPS65950->Read (gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); + ASSERT_EFI_ERROR (Status); + + // LEDAON controls the power to the USB host, PWM is disabled + Data &= ~LEDAPWM; + Data |= LEDAON; + + 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; +} + +/** + Enable a PCI driver to read PCI controller registers in PCI configuration space. + + @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the memory operations. + @param[in] Offset The offset within the PCI configuration space for + the PCI controller. + @param[in] Count The number of PCI configuration operations to + perform. Bytes moved is Width size * Count, + starting at Offset. + + @param[in out] Buffer The destination buffer to store the results. + + @retval EFI_SUCCESS The data was read from the PCI controller. + @retval EFI_INVALID_PARAMETER "Width" is invalid. + @retval EFI_INVALID_PARAMETER "Buffer" is NULL. + +**/ +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); + EFI_STATUS Status; + + if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = PciRootBridgeIoMemRW ( + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width, + Count, + TRUE, + (PTR)(UINTN)Buffer, + TRUE, + (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) //Fix me ConfigSpace + ); + + return Status; +} + +/** + Enable a PCI driver to write PCI controller registers in PCI configuration space. + + @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param[in] Width Signifies the width of the memory operations. + @param[in] Offset The offset within the PCI configuration space for + the PCI controller. + @param[in] Count The number of PCI configuration operations to + perform. Bytes moved is Width size * Count, + starting at Offset. + + @param[in out] Buffer The source buffer to write data from. + + @retval EFI_SUCCESS The data was read from the PCI controller. + @retval EFI_INVALID_PARAMETER "Width" is invalid. + @retval EFI_INVALID_PARAMETER "Buffer" is NULL. + +**/ +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); + + if ((Width < 0) || (Width >= EfiPciIoWidthMaximum) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + 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 + ) +{ + DMA_MAP_OPERATION DmaOperation; + + if (Operation == EfiPciIoOperationBusMasterRead) { + DmaOperation = MapOperationBusMasterRead; + } else if (Operation == EfiPciIoOperationBusMasterWrite) { + DmaOperation = MapOperationBusMasterWrite; + } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) { + DmaOperation = MapOperationBusMasterCommonBuffer; + } else { + return EFI_INVALID_PARAMETER; + } + return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping); +} + +EFI_STATUS +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + return DmaUnmap (Mapping); +} + +/** + Allocate pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer + mapping. + + @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param[in] Type This parameter is not used and must be ignored. + @param[in] MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param[in] Pages The number of pages to allocate. + @param[out] HostAddress A pointer to store the base system memory address of + the allocated range. + @param[in] Attributes The requested bit mask of attributes for the allocated + range. Only the attributes, + EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE and + EFI_PCI_ATTRIBUTE_MEMORY_CACHED may be used with this + function. If any other bits are set, then EFI_UNSUPPORTED + is returned. This function ignores this bit mask. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_INVALID_PARAMETER HostAddress is NULL. + @retval EFI_INVALID_PARAMETER MemoryType is invalid. + @retval EFI_UNSUPPORTED Attributes is unsupported. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + +**/ +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_MEMORY_WRITE_COMBINE | + EFI_PCI_ATTRIBUTE_MEMORY_CACHED ))) { + return EFI_UNSUPPORTED; + } + + return DmaAllocateBuffer (MemoryType, Pages, HostAddress); +} + + +EFI_STATUS +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + return DmaFreeBuffer (Pages, HostAddress); +} + + +EFI_STATUS +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +/** + Retrieves this PCI controller's current PCI bus number, device number, and function number. + + @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param[out] SegmentNumber The PCI controller's current PCI segment number. + @param[out] BusNumber The PCI controller's current PCI bus number. + @param[out] DeviceNumber The PCI controller's current PCI device number. + @param[out] FunctionNumber The PCI controller’s current PCI function number. + + @retval EFI_SUCCESS The PCI controller location was returned. + @retval EFI_INVALID_PARAMETER At least one out of the four output parameters is + a NULL pointer. +**/ +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) || (BusNumber == NULL) || + (DeviceNumber == NULL) || (FunctionNumber == NULL) ) { + return EFI_INVALID_PARAMETER; + } + + *SegmentNumber = Private->Segment; + *BusNumber = 0xff; + *DeviceNumber = 0; + *FunctionNumber = 0; + + return EFI_SUCCESS; +} + +/** + Performs an operation on the attributes that this PCI controller supports. + + The operations include getting the set of supported attributes, retrieving + the current attributes, setting the current attributes, enabling attributes, + and disabling attributes. + + @param[in] This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param[in] Operation The operation to perform on the attributes for this + PCI controller. + @param[in] Attributes The mask of attributes that are used for Set, + Enable and Disable operations. + @param[out] Result A pointer to the result mask of attributes that are + returned for the Get and Supported operations. This + is an optional parameter that may be NULL for the + Set, Enable, and Disable operations. + + @retval EFI_SUCCESS The operation on the PCI controller's + attributes was completed. If the operation + was Get or Supported, then the attribute mask + is returned in Result. + @retval EFI_INVALID_PARAMETER Operation is greater than or equal to + EfiPciIoAttributeOperationMaximum. + @retval EFI_INVALID_PARAMETER Operation is Get and Result is NULL. + @retval EFI_INVALID_PARAMETER Operation is Supported and Result is NULL. + +**/ +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_DEVICE_ENABLE; + break; + + case EfiPciIoAttributeOperationSet: + case EfiPciIoAttributeOperationEnable: + case EfiPciIoAttributeOperationDisable: + if (Attributes & (~EFI_PCI_DEVICE_ENABLE)) { + return EFI_UNSUPPORTED; + } + // Since we are not a real PCI device no enable/set or disable operations exist. + return EFI_SUCCESS; + + default: + 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; + + + //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; +} +