]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c
ArmPlatformPkg/ArmJunoPkg: Added Juno development board support
[mirror_edk2.git] / ArmPlatformPkg / ArmJunoPkg / Drivers / ArmJunoDxe / PciEmulation.c
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/PciEmulation.c
new file mode 100644 (file)
index 0000000..7c2d756
--- /dev/null
@@ -0,0 +1,486 @@
+/** @file\r
+\r
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+  Copyright (c) 2013 - 2014, ARM Ltd. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "PciEmulation.h"\r
+\r
+#define HOST_CONTROLLER_OPERATION_REG_SIZE  0x44\r
+\r
+typedef struct {\r
+  ACPI_HID_DEVICE_PATH      AcpiDevicePath;\r
+  PCI_DEVICE_PATH           PciDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  EndDevicePath;\r
+} EFI_PCI_IO_DEVICE_PATH;\r
+\r
+typedef struct {\r
+  UINT32                  Signature;\r
+  EFI_PCI_IO_DEVICE_PATH  DevicePath;\r
+  EFI_PCI_IO_PROTOCOL     PciIoProtocol;\r
+  PCI_TYPE00              *ConfigSpace;\r
+  PCI_ROOT_BRIDGE         RootBridge;\r
+  UINTN                   Segment;\r
+} EFI_PCI_IO_PRIVATE_DATA;\r
+\r
+#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE     SIGNATURE_32('p', 'c', 'i', 'o')\r
+#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a)  CR (a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE)\r
+\r
+EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate =\r
+{\r
+  {\r
+    { ACPI_DEVICE_PATH, ACPI_DP, { sizeof (ACPI_HID_DEVICE_PATH), 0 } },\r
+    EISA_PNP_ID(0x0A03),  // HID\r
+    0                     // UID\r
+  },\r
+  {\r
+    { HARDWARE_DEVICE_PATH, HW_PCI_DP, { sizeof (PCI_DEVICE_PATH), 0 } },\r
+    0,\r
+    0\r
+  },\r
+  { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }\r
+};\r
+\r
+STATIC\r
+VOID\r
+ConfigureUSBHost (\r
+  VOID\r
+  )\r
+{\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PciIoPollMem (\r
+  IN EFI_PCI_IO_PROTOCOL           *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN  UINT8                        BarIndex,\r
+  IN  UINT64                       Offset,\r
+  IN  UINT64                       Mask,\r
+  IN  UINT64                       Value,\r
+  IN  UINT64                       Delay,\r
+  OUT UINT64                       *Result\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoPollIo (\r
+  IN EFI_PCI_IO_PROTOCOL           *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN  UINT8                        BarIndex,\r
+  IN  UINT64                       Offset,\r
+  IN  UINT64                       Mask,\r
+  IN  UINT64                       Value,\r
+  IN  UINT64                       Delay,\r
+  OUT UINT64                       *Result\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoMemRead (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        BarIndex,\r
+  IN     UINT64                       Offset,\r
+  IN     UINTN                        Count,\r
+  IN OUT VOID                         *Buffer\r
+  )\r
+{\r
+  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  return PciRootBridgeIoMemRead (&Private->RootBridge.Io,\r
+                                (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                Private->ConfigSpace->Device.Bar[BarIndex] + Offset, //Fix me ConfigSpace\r
+                                Count,\r
+                                Buffer\r
+                                );\r
+}\r
+\r
+EFI_STATUS\r
+PciIoMemWrite (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        BarIndex,\r
+  IN     UINT64                       Offset,\r
+  IN     UINTN                        Count,\r
+  IN OUT VOID                         *Buffer\r
+  )\r
+{\r
+  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  return PciRootBridgeIoMemWrite (&Private->RootBridge.Io,\r
+                                 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                 Private->ConfigSpace->Device.Bar[BarIndex] + Offset,  //Fix me ConfigSpace\r
+                                 Count,\r
+                                 Buffer\r
+                                 );\r
+}\r
+\r
+EFI_STATUS\r
+PciIoIoRead (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        BarIndex,\r
+  IN     UINT64                       Offset,\r
+  IN     UINTN                        Count,\r
+  IN OUT VOID                         *Buffer\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoIoWrite (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        BarIndex,\r
+  IN     UINT64                       Offset,\r
+  IN     UINTN                        Count,\r
+  IN OUT VOID                         *Buffer\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoPciRead (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT32                       Offset,\r
+  IN     UINTN                        Count,\r
+  IN OUT VOID                         *Buffer\r
+  )\r
+{\r
+  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);\r
+  EFI_STATUS Status;\r
+\r
+  Status = PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width,\r
+                               Count,\r
+                               TRUE,\r
+                               (PTR)(UINTN)Buffer,\r
+                               TRUE,\r
+                               (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset)  //Fix me ConfigSpace\r
+                              );\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoPciWrite (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT32                       Offset,\r
+  IN     UINTN                        Count,\r
+  IN OUT VOID                         *Buffer\r
+  )\r
+{\r
+  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                               Count,\r
+                               TRUE,\r
+                               (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset),  //Fix me ConfigSpace\r
+                               TRUE,\r
+                               (PTR)(UINTN)Buffer\r
+                               );\r
+}\r
+\r
+EFI_STATUS\r
+PciIoCopyMem (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        DestBarIndex,\r
+  IN     UINT64                       DestOffset,\r
+  IN     UINT8                        SrcBarIndex,\r
+  IN     UINT64                       SrcOffset,\r
+  IN     UINTN                        Count\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoMap (\r
+  IN EFI_PCI_IO_PROTOCOL                *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,\r
+  IN     VOID                           *HostAddress,\r
+  IN OUT UINTN                          *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,\r
+  OUT    VOID                           **Mapping\r
+  )\r
+{\r
+  DMA_MAP_OPERATION   DmaOperation;\r
+\r
+  if (Operation == EfiPciIoOperationBusMasterRead) {\r
+    DmaOperation = MapOperationBusMasterRead;\r
+  } else if (Operation == EfiPciIoOperationBusMasterWrite) {\r
+    DmaOperation = MapOperationBusMasterWrite;\r
+  } else if (Operation == EfiPciIoOperationBusMasterCommonBuffer) {\r
+    DmaOperation = MapOperationBusMasterCommonBuffer;\r
+  } else {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  return DmaMap (DmaOperation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);\r
+}\r
+\r
+EFI_STATUS\r
+PciIoUnmap (\r
+  IN EFI_PCI_IO_PROTOCOL           *This,\r
+  IN  VOID                         *Mapping\r
+  )\r
+{\r
+  return DmaUnmap (Mapping);\r
+}\r
+\r
+EFI_STATUS\r
+PciIoAllocateBuffer (\r
+  IN EFI_PCI_IO_PROTOCOL           *This,\r
+  IN  EFI_ALLOCATE_TYPE            Type,\r
+  IN  EFI_MEMORY_TYPE              MemoryType,\r
+  IN  UINTN                        Pages,\r
+  OUT VOID                         **HostAddress,\r
+  IN  UINT64                       Attributes\r
+  )\r
+{\r
+  if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) {\r
+    // Check this\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return DmaAllocateBuffer (MemoryType, Pages, HostAddress);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PciIoFreeBuffer (\r
+  IN EFI_PCI_IO_PROTOCOL           *This,\r
+  IN  UINTN                        Pages,\r
+  IN  VOID                         *HostAddress\r
+  )\r
+{\r
+  return DmaFreeBuffer (Pages, HostAddress);\r
+}\r
+\r
+\r
+EFI_STATUS\r
+PciIoFlush (\r
+  IN EFI_PCI_IO_PROTOCOL  *This\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoGetLocation (\r
+  IN EFI_PCI_IO_PROTOCOL          *This,\r
+  OUT UINTN                       *SegmentNumber,\r
+  OUT UINTN                       *BusNumber,\r
+  OUT UINTN                       *DeviceNumber,\r
+  OUT UINTN                       *FunctionNumber\r
+  )\r
+{\r
+  EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (SegmentNumber != NULL) {\r
+    *SegmentNumber = Private->Segment;\r
+  }\r
+\r
+  if (BusNumber != NULL) {\r
+    *BusNumber = 0xff;\r
+  }\r
+\r
+  if (DeviceNumber != NULL) {\r
+    *DeviceNumber = 0;\r
+  }\r
+\r
+  if (FunctionNumber != NULL) {\r
+    *FunctionNumber = 0;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL                       *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes,\r
+  OUT UINT64                                   *Result OPTIONAL\r
+  )\r
+{\r
+  switch (Operation) {\r
+  case EfiPciIoAttributeOperationGet:\r
+  case EfiPciIoAttributeOperationSupported:\r
+    if (Result == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    // We are not a real PCI device so just say things we kind of do\r
+    *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE;\r
+    break;\r
+\r
+  case EfiPciIoAttributeOperationSet:\r
+  case EfiPciIoAttributeOperationEnable:\r
+  case EfiPciIoAttributeOperationDisable:\r
+    // Since we are not a real PCI device no enable/set or disable operations exist.\r
+    return EFI_SUCCESS;\r
+\r
+  default:\r
+  ASSERT (FALSE);\r
+    return EFI_INVALID_PARAMETER;\r
+  };\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoGetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL             *This,\r
+  IN  UINT8                          BarIndex,\r
+  OUT UINT64                         *Supports, OPTIONAL\r
+  OUT VOID                           **Resources OPTIONAL\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoSetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     UINT64                       Attributes,\r
+  IN     UINT8                        BarIndex,\r
+  IN OUT UINT64                       *Offset,\r
+  IN OUT UINT64                       *Length\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+EFI_PCI_IO_PROTOCOL PciIoTemplate =\r
+{\r
+  PciIoPollMem,\r
+  PciIoPollIo,\r
+  { PciIoMemRead, PciIoMemWrite },\r
+  { PciIoIoRead,  PciIoIoWrite },\r
+  { PciIoPciRead, PciIoPciWrite },\r
+  PciIoCopyMem,\r
+  PciIoMap,\r
+  PciIoUnmap,\r
+  PciIoAllocateBuffer,\r
+  PciIoFreeBuffer,\r
+  PciIoFlush,\r
+  PciIoGetLocation,\r
+  PciIoAttributes,\r
+  PciIoGetBarAttributes,\r
+  PciIoSetBarAttributes,\r
+  0,\r
+  0\r
+};\r
+\r
+EFI_STATUS\r
+PciInstallDevice (\r
+  IN UINTN            DeviceId,\r
+  IN PHYSICAL_ADDRESS MemoryStart,\r
+  IN UINT64           MemorySize,\r
+  IN UINTN            ClassCode1,\r
+  IN UINTN            ClassCode2,\r
+  IN UINTN            ClassCode3\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_HANDLE              Handle;\r
+  EFI_PCI_IO_PRIVATE_DATA *Private;\r
+\r
+  // Configure USB host\r
+  ConfigureUSBHost ();\r
+\r
+  // Create a private structure\r
+  Private = AllocatePool (sizeof (EFI_PCI_IO_PRIVATE_DATA));\r
+  if (Private == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    return Status;\r
+  }\r
+\r
+  Private->Signature              = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE;  // Fill in signature\r
+  Private->RootBridge.Signature   = PCI_ROOT_BRIDGE_SIGNATURE;          // Fake Root Bridge structure needs a signature too\r
+  Private->RootBridge.MemoryStart = MemoryStart; // Get the USB capability register base\r
+  Private->Segment                = 0;                                  // Default to segment zero\r
+\r
+  // Calculate the total size of the USB controller (OHCI + EHCI).\r
+  Private->RootBridge.MemorySize = MemorySize; //CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1));\r
+\r
+  // Create fake PCI config space: OHCI + EHCI\r
+  Private->ConfigSpace = AllocateZeroPool (sizeof (PCI_TYPE00));\r
+  if (Private->ConfigSpace == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    FreePool (Private);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Configure PCI config space: OHCI + EHCI\r
+  //\r
+  Private->ConfigSpace->Hdr.VendorId = 0x3530; //TODO: Define one\r
+  Private->ConfigSpace->Hdr.DeviceId = 0x3530; //TODO: Define one\r
+  Private->ConfigSpace->Hdr.ClassCode[0] = ClassCode1;\r
+  Private->ConfigSpace->Hdr.ClassCode[1] = ClassCode2;\r
+  Private->ConfigSpace->Hdr.ClassCode[2] = ClassCode3;\r
+  Private->ConfigSpace->Device.Bar[0] = MemoryStart;\r
+\r
+  Handle = NULL;\r
+\r
+  // Unique device path.\r
+  CopyMem (&Private->DevicePath, &PciIoDevicePathTemplate, sizeof (PciIoDevicePathTemplate));\r
+  Private->DevicePath.AcpiDevicePath.UID = 0;\r
+  Private->DevicePath.PciDevicePath.Device = DeviceId;\r
+\r
+  // Copy protocol structure\r
+  CopyMem (&Private->PciIoProtocol, &PciIoTemplate, sizeof (PciIoTemplate));\r
+\r
+  Status = gBS->InstallMultipleProtocolInterfaces (&Handle,\r
+                                                  &gEfiPciIoProtocolGuid,       &Private->PciIoProtocol,\r
+                                                  &gEfiDevicePathProtocolGuid,  &Private->DevicePath,\r
+                                                  NULL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces () failed.\n"));\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+PciEmulationEntryPoint (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  Status = PciInstallDevice (0, FixedPcdGet32 (PcdSynopsysUsbOhciBaseAddress), SIZE_64KB, PCI_IF_OHCI, PCI_CLASS_SERIAL_USB, PCI_CLASS_SERIAL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "PciEmulation: failed to install OHCI device.\n"));\r
+  }\r
+\r
+  Status = PciInstallDevice (1, FixedPcdGet32 (PcdSynopsysUsbEhciBaseAddress), SIZE_64KB, PCI_IF_EHCI, PCI_CLASS_SERIAL_USB, PCI_CLASS_SERIAL);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "PciEmulation: failed to install EHCI device.\n"));\r
+  }\r
+\r
+  return Status;\r
+}\r