From: Jan Dąbroś jsd@semihalf.com
Improve PciEmulation driver in order to support SATA controllers. This patch also add workaround for Cp110 chip, where SATA controller isn't fully compatible with AHCI standard.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jan Dabros jsd@semihalf.com Signed-off-by: Marcin Wojtas mw@semihalf.com --- Documentation/Marvell/PortingGuide/Sata.txt | 16 ++++++++ Documentation/Marvell/UserGuide.txt | 1 + Platforms/Marvell/Marvell.dec | 4 ++ Platforms/Marvell/PciEmulation/PciEmulation.c | 54 ++++++++++++++++++++++++- Platforms/Marvell/PciEmulation/PciEmulation.h | 6 +++ Platforms/Marvell/PciEmulation/PciEmulation.inf | 2 + 6 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 Documentation/Marvell/PortingGuide/Sata.txt
diff --git a/Documentation/Marvell/PortingGuide/Sata.txt b/Documentation/Marvell/PortingGuide/Sata.txt new file mode 100644 index 0000000..f76923d --- /dev/null +++ b/Documentation/Marvell/PortingGuide/Sata.txt @@ -0,0 +1,16 @@ +SATA configuration +------------------ +In order to add new SATA device, please refer to document describing +PciEmulation - /path/to/opp/Documenation/Marvell/PortingGuide/PciEmulation.txt + +There are also two additional PCDs: + + gMarvellTokenSpaceGuid.PcdSataBaseAddress + +Base address of SATA controller register space - used in SATA ComPhy init +sequence. + + gMarvellTokenSpaceGuid.PcdSataMapPortAddress + +Boolean indicating if controller on platform needs specific address mapping for +SATA ports. diff --git a/Documentation/Marvell/UserGuide.txt b/Documentation/Marvell/UserGuide.txt index 27a23f3..5d3612e 100644 --- a/Documentation/Marvell/UserGuide.txt +++ b/Documentation/Marvell/UserGuide.txt @@ -12,6 +12,7 @@ Table of contents: mpp - PortingGuide/Mpp.txt ramdisk - PortingGuide/Ramdisk.txt reset library - PortingGuide/Reset.txt + sata - PortingGuide/Sata.txt spi - PortingGuide/Spi.txt spi flash - PortingGuide/SpiFlash.txt usb - PortingGuide/PciEmulation.txt diff --git a/Platforms/Marvell/Marvell.dec b/Platforms/Marvell/Marvell.dec index 30275f5..6df6268 100644 --- a/Platforms/Marvell/Marvell.dec +++ b/Platforms/Marvell/Marvell.dec @@ -145,6 +145,10 @@ gMarvellTokenSpaceGuid.PcdPciEDevClassCode2|{ 0 }|VOID*|0x30000062 gMarvellTokenSpaceGuid.PcdPciEDevClassCode3|{ 0 }|VOID*|0x30000063
+#SATA + gMarvellTokenSpaceGuid.PcdSataBaseAddress|0|UINT32|0x4000052 + gMarvellTokenSpaceGuid.PcdSataMapPortAddress|FALSE|BOOLEAN|0x4000053 + [Protocols] gEfiEepromProtocolGuid = { 0xcd728a1f, 0x45b5, 0x4feb, { 0x98, 0xc8, 0x31, 0x3d, 0xa8, 0x11, 0x74, 0x62 }} gEfiSpiMasterProtocolGuid = { 0x23de66a3, 0xf666, 0x4b3e, { 0xaa, 0xa2, 0x68, 0x9b, 0x18, 0xae, 0x2e, 0x19 }} diff --git a/Platforms/Marvell/PciEmulation/PciEmulation.c b/Platforms/Marvell/PciEmulation/PciEmulation.c index 586bb86..236838a 100644 --- a/Platforms/Marvell/PciEmulation/PciEmulation.c +++ b/Platforms/Marvell/PciEmulation/PciEmulation.c @@ -69,6 +69,30 @@ EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate = } };
+STATIC +UINT64 +MapSataPortAddress ( + IN UINT64 Offset + ) +{ + + // + // Since AHCI controller in CP110 isn't compatible with AHCI specification, + // below workaround is necessary. It maps PORT address' offsets. + // + // PORT | AHCI port offset | CP110 port offset + // -------------------------------------------------------- + // 1 | 100h - 180h | 10000h - 1080h + // 2 | 180h - 260h | 20000h - 2080h + // + if ((Offset > 0x100) && (Offset < 0x180)) + Offset = (Offset - 0x100) + 0x10000; + if ((Offset > 0x180) && (Offset < 0x260)) + Offset = (Offset - 0x180) + 0x20000; + + return Offset; +} + EFI_STATUS PciIoPollMem ( IN EFI_PCI_IO_PROTOCOL *This, @@ -113,6 +137,10 @@ PciIoMemRead ( { EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
+ if (BarIndex == EFI_AHCI_BAR_INDEX && PcdGetBool (PcdSataMapPortAddress)) { + Offset = MapSataPortAddress (Offset); + } + return PciRootBridgeIoMemRead (&Private->RootBridge.Io, (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, Private->ConfigSpace->Device.Bar[BarIndex] + Offset, @@ -132,6 +160,10 @@ PciIoMemWrite ( { EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This);
+ if (BarIndex == EFI_AHCI_BAR_INDEX && PcdGetBool (PcdSataMapPortAddress)) { + Offset = MapSataPortAddress (Offset); + } + return PciRootBridgeIoMemWrite (&Private->RootBridge.Io, (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, Private->ConfigSpace->Device.Bar[BarIndex] + Offset, @@ -526,6 +558,7 @@ InstallDevices ( EFI_STATUS Status; EFI_HANDLE Handle; EFI_PCI_IO_PRIVATE_DATA *Private; + UINT32 ClassCodes;
// Create a private structure Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA)); @@ -556,7 +589,26 @@ InstallDevices ( Private->ConfigSpace->Hdr.ClassCode[0] = ClassCode1; Private->ConfigSpace->Hdr.ClassCode[1] = ClassCode2; Private->ConfigSpace->Hdr.ClassCode[2] = ClassCode3; - Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart; + + // + // Concatenate ClassCodes into single number, which will be next used to + // recognize device add fill proper BAR + // + ClassCodes = (ClassCode1 << 16) + (ClassCode2 << 8) + ClassCode3; + + switch (ClassCodes) { + case XHCI_PCI_CLASS_CODE_NR: + Private->ConfigSpace->Device.Bar[EFI_XHCI_BAR_INDEX] = + Private->RootBridge.MemoryStart; + break; + case AHCI_PCI_CLASS_CODE_NR: + Private->ConfigSpace->Device.Bar[EFI_AHCI_BAR_INDEX] = + Private->RootBridge.MemoryStart; + break; + default: + DEBUG((EFI_D_ERROR, "PciEmulation: Unknown PCI device. Abort.\n")); + return EFI_D_ERROR; + }
Handle = NULL;
diff --git a/Platforms/Marvell/PciEmulation/PciEmulation.h b/Platforms/Marvell/PciEmulation/PciEmulation.h index 536b236..9dcd7e3 100644 --- a/Platforms/Marvell/PciEmulation/PciEmulation.h +++ b/Platforms/Marvell/PciEmulation/PciEmulation.h @@ -45,6 +45,12 @@ #define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL #define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
+#define XHCI_PCI_CLASS_CODE_NR 0x30030C +#define AHCI_PCI_CLASS_CODE_NR 0x010601 + +#define EFI_XHCI_BAR_INDEX 0x0 +#define EFI_AHCI_BAR_INDEX 0x5 + typedef struct { ACPI_HID_DEVICE_PATH AcpiDevicePath; EFI_DEVICE_PATH_PROTOCOL EndDevicePath; diff --git a/Platforms/Marvell/PciEmulation/PciEmulation.inf b/Platforms/Marvell/PciEmulation/PciEmulation.inf index 59a0650..0df9eb1 100644 --- a/Platforms/Marvell/PciEmulation/PciEmulation.inf +++ b/Platforms/Marvell/PciEmulation/PciEmulation.inf @@ -61,5 +61,7 @@ gMarvellTokenSpaceGuid.PcdPciEDevClassCode2 gMarvellTokenSpaceGuid.PcdPciEDevClassCode3
+ gMarvellTokenSpaceGuid.PcdSataMapPortAddress + [Depex] TRUE