Message ID | 20170407085932.2765-1-ard.biesheuvel@linaro.org |
---|---|
State | Accepted |
Commit | 549704d61d83e4c87dbb75c4d354b215389e478b |
Headers | show |
On 7 April 2017 at 09:59, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote: > In order to be able to switch to the generic DtPlatformDxe driver, > implement the glue library that loads it and prepares it based on > the properties of the actual hardware. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > --- v2: whitespace changes mostly, and fixed the IsRevB1 test to use SOCid defines > Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c | 481 ++++++++++++++++++++ > Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf | 64 +++ > 2 files changed, 545 insertions(+) > > diff --git a/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c > new file mode 100644 > index 000000000000..b18caf19985b > --- /dev/null > +++ b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c > @@ -0,0 +1,481 @@ > +/** @file > +* > +* Copyright (c) 2017, Linaro, Ltd. 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 <PiDxe.h> > + > +#include <Guid/ArmMpCoreInfo.h> > + > +#include <libfdt.h> > +#include <Library/ArmLib.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/DxeServicesLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/PrintLib.h> > +#include <Library/UefiBootServicesTableLib.h> > + > +#include <Protocol/AmdMpCoreInfo.h> > + > +#define PMU_INT_FLAG_SPI 0 > +#define PMU_INT_TYPE_HIGH_LEVEL 4 > + > +// > +// PMU interrupts per core > +// > +#pragma pack(push, 1) > +typedef struct { > + UINT32 Flag; // 0 == SPI > + UINT32 IntId; // GSIV == IntId+32 > + UINT32 Type; // 4 == Level-Sensitive, Active-High > +} PMU_INTERRUPT; > +#pragma pack(pop) > + > +STATIC > +BOOLEAN > +ClusterInRange ( > + IN ARM_CORE_INFO *ArmCoreInfoTable, > + IN UINTN ClusterId, > + IN UINTN LowIndex, > + IN UINTN HighIndex > + ) > +{ > + do { > + if (ClusterId == ArmCoreInfoTable[LowIndex].ClusterId) > + return TRUE; > + } while (++LowIndex <= HighIndex); > + > + return FALSE; > +} > + > + > +STATIC > +UINTN > +NumberOfCoresInCluster ( > + IN ARM_CORE_INFO *ArmCoreInfoTable, > + IN UINTN NumberOfEntries, > + IN UINTN ClusterId > + ) > +{ > + UINTN Index, Cores; > + > + Cores = 0; > + for (Index = 0; Index < NumberOfEntries; ++Index) { > + if (ClusterId == ArmCoreInfoTable[Index].ClusterId) > + ++Cores; > + } > + > + return Cores; > +} > + > + > +STATIC > +UINTN > +NumberOfClustersInTable ( > + IN ARM_CORE_INFO *ArmCoreInfoTable, > + IN UINTN NumberOfEntries > + ) > +{ > + UINTN Index, Cores, Clusters, ClusterId; > + > + Index = 0; > + Clusters = 0; > + Cores = NumberOfEntries; > + while (Cores) { > + ++Clusters; > + ClusterId = ArmCoreInfoTable[Index].ClusterId; > + Cores -= NumberOfCoresInCluster (ArmCoreInfoTable, > + NumberOfEntries, > + ClusterId); > + if (Cores) { > + do { > + ++Index; > + } while (ClusterInRange (ArmCoreInfoTable, > + ArmCoreInfoTable[Index].ClusterId, > + 0, Index-1)); > + } > + } > + > + return Clusters; > +} > + > + > +STATIC > +INT32 > +fdt_alloc_phandle ( > + IN VOID *Fdt > + ) > +{ > + INT32 Offset; > + INT32 Phandle; > + > + Phandle = 0; > + > + for (Offset = fdt_next_node (Fdt, -1, NULL); Offset >= 0; > + Offset = fdt_next_node (Fdt, Offset, NULL)) { > + Phandle = MAX (Phandle, fdt_get_phandle (Fdt, Offset)); > + } > + > + return Phandle + 1; > +} > + > +STATIC > +VOID > +SetDeviceStatus ( > + IN VOID *Fdt, > + IN CONST CHAR8 *Device, > + IN BOOLEAN Enable > + ) > +{ > + INT32 Node; > + INT32 SubNode; > + INT32 Rc; > + > + Node = fdt_subnode_offset (Fdt, 0, "smb"); > + if (Node >= 0) { > + SubNode = fdt_subnode_offset (Fdt, Node, Device); > + if (SubNode >= 0) { > + Rc = fdt_setprop_string (Fdt, SubNode, "status", > + Enable ? "okay" : "disabled"); > + if (Rc) { > + DEBUG ((DEBUG_ERROR, > + "%a: Could not set 'status' property for '%a' node\n", > + __FUNCTION__, Device)); > + } > + } > + } > +} > + > +#if DO_XGBE > + > +#define MAC_ADDRESS_BYTES 6 > + > +STATIC > +VOID > +SetMacAddress ( > + IN VOID *Fdt, > + IN CONST CHAR8 *Device, > + IN UINT64 MacAddress > + ) > +{ > + INT32 Node; > + INT32 SubNode; > + INT32 Rc; > + > + Node = fdt_subnode_offset (Fdt, 0, "smb"); > + if (Node >= 0) { > + SubNode = fdt_subnode_offset (Fdt, Node, Device); > + if (SubNode >= 0) { > + Rc = fdt_setprop (Fdt, SubNode, "mac-address", (VOID *)&MacAddress, > + MAC_ADDRESS_BYTES); > + if (Rc) { > + DEBUG ((DEBUG_ERROR, > + "%a: Could not set 'mac-address' property for '%a' node\n", > + __FUNCTION__, Device)); > + } > + } > + } > +} > + > +#endif > + > +#define STYX_SOC_VERSION_MASK 0xFFF > +#define STYX_SOC_VERSION_A0 0x000 > +#define STYX_SOC_VERSION_B0 0x010 > +#define STYX_SOC_VERSION_B1 0x011 > + > +STATIC > +VOID > +SetSocIdStatus ( > + IN VOID *Fdt > + ) > +{ > + UINT32 SocId; > + BOOLEAN IsRevB1; > + > + SocId = PcdGet32 (PcdSocCpuId); > + IsRevB1 = (SocId & STYX_SOC_VERSION_MASK) >= STYX_SOC_VERSION_B1; > + > + SetDeviceStatus (Fdt, "sata@e0d00000", > + IsRevB1 && FixedPcdGet8 (PcdSata1PortCount) > 0); > + SetDeviceStatus (Fdt, "gpio@e0020000", IsRevB1); > + SetDeviceStatus (Fdt, "gpio@e0030000", IsRevB1); > + SetDeviceStatus (Fdt, "gwdt@e0bb0000", IsRevB1); > +#if DO_KCS > + SetDeviceStatus (Fdt, "kcs@e0010000", IsRevB1); > +#else > + SetDeviceStatus (Fdt, "kcs@e0010000", FALSE); > +#endif > +} > + > +STATIC > +VOID > +SetXgbeStatus ( > + IN VOID *Fdt > + ) > +{ > +#if DO_XGBE > + SetDeviceStatus (Fdt, "xgmac@e0700000", TRUE); > + SetDeviceStatus (Fdt, "phy@e1240800", TRUE); > + SetDeviceStatus (Fdt, "xgmac@e0900000", TRUE); > + SetDeviceStatus (Fdt, "phy@e1240c00", TRUE); > + > + SetMacAddress (Fdt, "xgmac@e0700000", PcdGet64 (PcdEthMacA)); > + SetMacAddress (Fdt, "xgmac@e0900000", PcdGet64 (PcdEthMacB)); > +#else > + SetDeviceStatus (Fdt, "xgmac@e0700000", FALSE); > + SetDeviceStatus (Fdt, "phy@e1240800", FALSE); > + SetDeviceStatus (Fdt, "xgmac@e0900000", FALSE); > + SetDeviceStatus (Fdt, "phy@e1240c00", FALSE); > +#endif > +} > + > + > +STATIC > +EFI_STATUS > +PrepareFdt ( > + IN OUT VOID *Fdt, > + IN UINTN FdtSize > + ) > +{ > + EFI_STATUS Status; > + INT32 Node; > + INT32 CpuNode; > + UINTN Index; > + ARM_CORE_INFO *ArmCoreInfoTable; > + UINTN ArmCoreCount; > + INT32 MapNode; > + INT32 ClusterNode; > + INT32 PmuNode; > + PMU_INTERRUPT PmuInt; > + INT32 Phandle[NUM_CORES]; > + UINT32 ClusterIndex; > + UINT32 CoreIndex; > + UINT32 ClusterCount; > + UINT32 CoresInCluster; > + UINT32 ClusterId; > + UINTN MpId; > + CHAR8 Name[10]; > + AMD_MP_CORE_INFO_PROTOCOL *AmdMpCoreInfoProtocol; > + > + // > + // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms. > + // > + // For 'cpus' and 'cpu' device tree nodes bindings, refer to this file > + // in the kernel documentation: > + // Documentation/devicetree/bindings/arm/cpus.txt > + // > + Status = gBS->LocateProtocol ( > + &gAmdMpCoreInfoProtocolGuid, > + NULL, > + (VOID **)&AmdMpCoreInfoProtocol > + ); > + ASSERT_EFI_ERROR (Status); > + > + // Get pointer to ARM core info table > + ArmCoreInfoTable = AmdMpCoreInfoProtocol->GetArmCoreInfoTable (&ArmCoreCount); > + ASSERT (ArmCoreInfoTable != NULL); > + ASSERT (ArmCoreCount <= NUM_CORES); > + > + // Get Id from primary CPU > + MpId = (UINTN)ArmReadMpidr (); > + > + // Create /pmu node > + PmuNode = fdt_add_subnode(Fdt, 0, "pmu"); > + if (PmuNode >= 0) { > + fdt_setprop_string (Fdt, PmuNode, "compatible", "arm,armv8-pmuv3"); > + > + // append PMU interrupts > + for (Index = 0; Index < ArmCoreCount; Index++) { > + MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, > + ArmCoreInfoTable[Index].CoreId); > + > + Status = AmdMpCoreInfoProtocol->GetPmuSpiFromMpId (MpId, &PmuInt.IntId); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, > + "FDT: Error getting PMU interrupt for MpId '0x%x'\n", MpId)); > + return Status; > + } > + > + PmuInt.Flag = cpu_to_fdt32 (PMU_INT_FLAG_SPI); > + PmuInt.IntId = cpu_to_fdt32 (PmuInt.IntId); > + PmuInt.Type = cpu_to_fdt32 (PMU_INT_TYPE_HIGH_LEVEL); > + fdt_appendprop (Fdt, PmuNode, "interrupts", &PmuInt, sizeof(PmuInt)); > + } > + } else { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating 'pmu' node\n")); > + return EFI_INVALID_PARAMETER; > + } > + > + // Create /cpus noide > + Node = fdt_add_subnode (Fdt, 0, "cpus"); > + if (Node >= 0) { > + // Configure the 'cpus' node > + fdt_setprop_string (Fdt, Node, "name", "cpus"); > + fdt_setprop_cell (Fdt, Node, "#address-cells", sizeof (UINTN) / 4); > + fdt_setprop_cell (Fdt, Node, "#size-cells", 0); > + } else { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating 'cpus' node\n")); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Walk the processor table in reverse order for proper listing in FDT > + // > + Index = ArmCoreCount; > + while (Index--) { > + // Create 'cpu' node > + AsciiSPrint (Name, sizeof (Name), "CPU%d", Index); > + CpuNode = fdt_add_subnode (Fdt, Node, Name); > + if (CpuNode < 0) { > + DEBUG ((DEBUG_ERROR, "FDT: Error on creating '%a' node\n", Name)); > + return EFI_INVALID_PARAMETER; > + } > + Phandle[Index] = fdt_alloc_phandle (Fdt); > + fdt_setprop_cell (Fdt, CpuNode, "phandle", Phandle[Index]); > + fdt_setprop_cell (Fdt, CpuNode, "linux,phandle", Phandle[Index]); > + > + fdt_setprop_string (Fdt, CpuNode, "enable-method", "psci"); > + > + MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, > + ArmCoreInfoTable[Index].CoreId); > + MpId = cpu_to_fdt64 (MpId); > + fdt_setprop (Fdt, CpuNode, "reg", &MpId, sizeof (MpId)); > + fdt_setprop_string (Fdt, CpuNode, "compatible", "arm,armv8"); > + fdt_setprop_string (Fdt, CpuNode, "device_type", "cpu"); > + } > + > + // Create /cpu-map node > + MapNode = fdt_add_subnode (Fdt, Node, "cpu-map"); > + if (MapNode >= 0) { > + ClusterIndex = ArmCoreCount - 1; > + ClusterCount = NumberOfClustersInTable (ArmCoreInfoTable, > + ArmCoreCount); > + while (ClusterCount--) { > + // Create 'cluster' node > + AsciiSPrint (Name, sizeof (Name), "cluster%d", ClusterCount); > + ClusterNode = fdt_add_subnode (Fdt, MapNode, Name); > + if (ClusterNode < 0) { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); > + return EFI_INVALID_PARAMETER; > + } > + > + ClusterId = ArmCoreInfoTable[ClusterIndex].ClusterId; > + CoreIndex = ClusterIndex; > + CoresInCluster = NumberOfCoresInCluster (ArmCoreInfoTable, > + ArmCoreCount, > + ClusterId); > + while (CoresInCluster--) { > + // Create 'core' node > + AsciiSPrint (Name, sizeof (Name), "core%d", CoresInCluster); > + CpuNode = fdt_add_subnode (Fdt, ClusterNode, Name); > + if (CpuNode < 0) { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); > + return EFI_INVALID_PARAMETER; > + } > + fdt_setprop_cell (Fdt, CpuNode, "cpu", Phandle[CoreIndex]); > + > + // iterate to next core in cluster > + if (CoresInCluster) { > + do { > + --CoreIndex; > + } while (ClusterId != ArmCoreInfoTable[CoreIndex].ClusterId); > + } > + } > + > + // iterate to next cluster > + if (ClusterCount) { > + do { > + --ClusterIndex; > + } while (ClusterInRange (ArmCoreInfoTable, > + ArmCoreInfoTable[ClusterIndex].ClusterId, > + ClusterIndex + 1, > + ArmCoreCount - 1)); > + } > + } > + } else { > + DEBUG ((DEBUG_ERROR,"FDT: Error creating 'cpu-map' node\n")); > + return EFI_INVALID_PARAMETER; > + } > + > + SetSocIdStatus (Fdt); > + SetXgbeStatus (Fdt); > + > + // Update the real size of the Device Tree > + fdt_pack (Fdt); > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Return a pool allocated copy of the DTB image that is appropriate for > + booting the current platform via DT. > + > + @param[out] Dtb Pointer to the DTB copy > + @param[out] DtbSize Size of the DTB copy > + > + @retval EFI_SUCCESS Operation completed successfully > + @retval EFI_NOT_FOUND No suitable DTB image could be located > + @retval EFI_OUT_OF_RESOURCES No pool memory available > + > +**/ > +EFI_STATUS > +EFIAPI > +DtPlatformLoadDtb ( > + OUT VOID **Dtb, > + OUT UINTN *DtbSize > + ) > +{ > + EFI_STATUS Status; > + VOID *OrigDtb; > + VOID *CopyDtb; > + UINTN OrigDtbSize; > + UINTN CopyDtbSize; > + INT32 Error; > + > + Status = GetSectionFromAnyFv (&gDtPlatformDefaultDtbFileGuid, > + EFI_SECTION_RAW, 0, &OrigDtb, &OrigDtbSize); > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Allocate space for the DTB: add a page of slack space to make some room > + // for our modifications. > + // > + CopyDtbSize = OrigDtbSize + EFI_PAGE_SIZE; > + CopyDtb = AllocatePool (CopyDtbSize); > + if (CopyDtb == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Error = fdt_open_into (OrigDtb, CopyDtb, CopyDtbSize); > + if (Error != 0) { > + // > + // fdt_open_into() validates the DTB header, so if it fails, the template > + // is most likely invalid. > + // > + return EFI_NOT_FOUND; > + } > + > + Status = PrepareFdt (CopyDtb, CopyDtbSize); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Dtb = CopyDtb; > + *DtbSize = CopyDtbSize; > + > + return EFI_SUCCESS; > +} > diff --git a/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf > new file mode 100644 > index 000000000000..f5ba5f1d1335 > --- /dev/null > +++ b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf > @@ -0,0 +1,64 @@ > +/** @file > +* > +* Copyright (c) 2017, Linaro, Ltd. 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 = 0x00010019 > + BASE_NAME = StyxDtbLoaderLib > + FILE_GUID = 3874890c-2917-46a6-8711-8fcaee92260a > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = DtPlatformDtbLoaderLib|DXE_DRIVER > + > +[Sources] > + StyxDtbLoaderLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + MdePkg/MdePkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + AmdModulePkg/AmdModulePkg.dec > + OpenPlatformPkg/Platforms/AMD/Styx/AmdStyx.dec > + > +[LibraryClasses] > + ArmLib > + BaseLib > + DebugLib > + DxeServicesLib > + FdtLib > + MemoryAllocationLib > + PrintLib > + UefiBootServicesTableLib > + > +[Pcd] > + gAmdStyxTokenSpaceGuid.PcdStyxFdt > + gAmdStyxTokenSpaceGuid.PcdSocCpuId > + gAmdStyxTokenSpaceGuid.PcdEthMacA > + gAmdStyxTokenSpaceGuid.PcdEthMacB > + gArmTokenSpaceGuid.PcdSystemMemoryBase > + > +[FixedPcd] > + gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset > + gArmTokenSpaceGuid.PcdArmLinuxFdtAlignment > + gAmdStyxTokenSpaceGuid.PcdPsciOsSupport > + gAmdStyxTokenSpaceGuid.PcdTrustedFWSupport > + gAmdStyxTokenSpaceGuid.PcdSata1PortCount > + > +[Guids] > + gDtPlatformDefaultDtbFileGuid > + > +[Protocols] > + gAmdMpCoreInfoProtocolGuid ## CONSUMED > + > +[Depex] > + gAmdMpCoreInfoProtocolGuid > -- > 2.9.3 >
On Fri, Apr 07, 2017 at 09:59:32AM +0100, Ard Biesheuvel wrote: > In order to be able to switch to the generic DtPlatformDxe driver, > implement the glue library that loads it and prepares it based on > the properties of the actual hardware. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> I may have left my glasses at home today, but as far as I can see, all that I asked for has been addressed, so: Revie_we_d-by: Leif Lindholm <leif.lindholm@linaro.org> (sneeks off to do some emacs scripting) > --- > Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c | 481 ++++++++++++++++++++ > Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf | 64 +++ > 2 files changed, 545 insertions(+) > > diff --git a/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c > new file mode 100644 > index 000000000000..b18caf19985b > --- /dev/null > +++ b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c > @@ -0,0 +1,481 @@ > +/** @file > +* > +* Copyright (c) 2017, Linaro, Ltd. 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 <PiDxe.h> > + > +#include <Guid/ArmMpCoreInfo.h> > + > +#include <libfdt.h> > +#include <Library/ArmLib.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/DxeServicesLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/PrintLib.h> > +#include <Library/UefiBootServicesTableLib.h> > + > +#include <Protocol/AmdMpCoreInfo.h> > + > +#define PMU_INT_FLAG_SPI 0 > +#define PMU_INT_TYPE_HIGH_LEVEL 4 > + > +// > +// PMU interrupts per core > +// > +#pragma pack(push, 1) > +typedef struct { > + UINT32 Flag; // 0 == SPI > + UINT32 IntId; // GSIV == IntId+32 > + UINT32 Type; // 4 == Level-Sensitive, Active-High > +} PMU_INTERRUPT; > +#pragma pack(pop) > + > +STATIC > +BOOLEAN > +ClusterInRange ( > + IN ARM_CORE_INFO *ArmCoreInfoTable, > + IN UINTN ClusterId, > + IN UINTN LowIndex, > + IN UINTN HighIndex > + ) > +{ > + do { > + if (ClusterId == ArmCoreInfoTable[LowIndex].ClusterId) > + return TRUE; > + } while (++LowIndex <= HighIndex); > + > + return FALSE; > +} > + > + > +STATIC > +UINTN > +NumberOfCoresInCluster ( > + IN ARM_CORE_INFO *ArmCoreInfoTable, > + IN UINTN NumberOfEntries, > + IN UINTN ClusterId > + ) > +{ > + UINTN Index, Cores; > + > + Cores = 0; > + for (Index = 0; Index < NumberOfEntries; ++Index) { > + if (ClusterId == ArmCoreInfoTable[Index].ClusterId) > + ++Cores; > + } > + > + return Cores; > +} > + > + > +STATIC > +UINTN > +NumberOfClustersInTable ( > + IN ARM_CORE_INFO *ArmCoreInfoTable, > + IN UINTN NumberOfEntries > + ) > +{ > + UINTN Index, Cores, Clusters, ClusterId; > + > + Index = 0; > + Clusters = 0; > + Cores = NumberOfEntries; > + while (Cores) { > + ++Clusters; > + ClusterId = ArmCoreInfoTable[Index].ClusterId; > + Cores -= NumberOfCoresInCluster (ArmCoreInfoTable, > + NumberOfEntries, > + ClusterId); > + if (Cores) { > + do { > + ++Index; > + } while (ClusterInRange (ArmCoreInfoTable, > + ArmCoreInfoTable[Index].ClusterId, > + 0, Index-1)); > + } > + } > + > + return Clusters; > +} > + > + > +STATIC > +INT32 > +fdt_alloc_phandle ( > + IN VOID *Fdt > + ) > +{ > + INT32 Offset; > + INT32 Phandle; > + > + Phandle = 0; > + > + for (Offset = fdt_next_node (Fdt, -1, NULL); Offset >= 0; > + Offset = fdt_next_node (Fdt, Offset, NULL)) { > + Phandle = MAX (Phandle, fdt_get_phandle (Fdt, Offset)); > + } > + > + return Phandle + 1; > +} > + > +STATIC > +VOID > +SetDeviceStatus ( > + IN VOID *Fdt, > + IN CONST CHAR8 *Device, > + IN BOOLEAN Enable > + ) > +{ > + INT32 Node; > + INT32 SubNode; > + INT32 Rc; > + > + Node = fdt_subnode_offset (Fdt, 0, "smb"); > + if (Node >= 0) { > + SubNode = fdt_subnode_offset (Fdt, Node, Device); > + if (SubNode >= 0) { > + Rc = fdt_setprop_string (Fdt, SubNode, "status", > + Enable ? "okay" : "disabled"); > + if (Rc) { > + DEBUG ((DEBUG_ERROR, > + "%a: Could not set 'status' property for '%a' node\n", > + __FUNCTION__, Device)); > + } > + } > + } > +} > + > +#if DO_XGBE > + > +#define MAC_ADDRESS_BYTES 6 > + > +STATIC > +VOID > +SetMacAddress ( > + IN VOID *Fdt, > + IN CONST CHAR8 *Device, > + IN UINT64 MacAddress > + ) > +{ > + INT32 Node; > + INT32 SubNode; > + INT32 Rc; > + > + Node = fdt_subnode_offset (Fdt, 0, "smb"); > + if (Node >= 0) { > + SubNode = fdt_subnode_offset (Fdt, Node, Device); > + if (SubNode >= 0) { > + Rc = fdt_setprop (Fdt, SubNode, "mac-address", (VOID *)&MacAddress, > + MAC_ADDRESS_BYTES); > + if (Rc) { > + DEBUG ((DEBUG_ERROR, > + "%a: Could not set 'mac-address' property for '%a' node\n", > + __FUNCTION__, Device)); > + } > + } > + } > +} > + > +#endif > + > +#define STYX_SOC_VERSION_MASK 0xFFF > +#define STYX_SOC_VERSION_A0 0x000 > +#define STYX_SOC_VERSION_B0 0x010 > +#define STYX_SOC_VERSION_B1 0x011 > + > +STATIC > +VOID > +SetSocIdStatus ( > + IN VOID *Fdt > + ) > +{ > + UINT32 SocId; > + BOOLEAN IsRevB1; > + > + SocId = PcdGet32 (PcdSocCpuId); > + IsRevB1 = (SocId & STYX_SOC_VERSION_MASK) >= STYX_SOC_VERSION_B1; > + > + SetDeviceStatus (Fdt, "sata@e0d00000", > + IsRevB1 && FixedPcdGet8 (PcdSata1PortCount) > 0); > + SetDeviceStatus (Fdt, "gpio@e0020000", IsRevB1); > + SetDeviceStatus (Fdt, "gpio@e0030000", IsRevB1); > + SetDeviceStatus (Fdt, "gwdt@e0bb0000", IsRevB1); > +#if DO_KCS > + SetDeviceStatus (Fdt, "kcs@e0010000", IsRevB1); > +#else > + SetDeviceStatus (Fdt, "kcs@e0010000", FALSE); > +#endif > +} > + > +STATIC > +VOID > +SetXgbeStatus ( > + IN VOID *Fdt > + ) > +{ > +#if DO_XGBE > + SetDeviceStatus (Fdt, "xgmac@e0700000", TRUE); > + SetDeviceStatus (Fdt, "phy@e1240800", TRUE); > + SetDeviceStatus (Fdt, "xgmac@e0900000", TRUE); > + SetDeviceStatus (Fdt, "phy@e1240c00", TRUE); > + > + SetMacAddress (Fdt, "xgmac@e0700000", PcdGet64 (PcdEthMacA)); > + SetMacAddress (Fdt, "xgmac@e0900000", PcdGet64 (PcdEthMacB)); > +#else > + SetDeviceStatus (Fdt, "xgmac@e0700000", FALSE); > + SetDeviceStatus (Fdt, "phy@e1240800", FALSE); > + SetDeviceStatus (Fdt, "xgmac@e0900000", FALSE); > + SetDeviceStatus (Fdt, "phy@e1240c00", FALSE); > +#endif > +} > + > + > +STATIC > +EFI_STATUS > +PrepareFdt ( > + IN OUT VOID *Fdt, > + IN UINTN FdtSize > + ) > +{ > + EFI_STATUS Status; > + INT32 Node; > + INT32 CpuNode; > + UINTN Index; > + ARM_CORE_INFO *ArmCoreInfoTable; > + UINTN ArmCoreCount; > + INT32 MapNode; > + INT32 ClusterNode; > + INT32 PmuNode; > + PMU_INTERRUPT PmuInt; > + INT32 Phandle[NUM_CORES]; > + UINT32 ClusterIndex; > + UINT32 CoreIndex; > + UINT32 ClusterCount; > + UINT32 CoresInCluster; > + UINT32 ClusterId; > + UINTN MpId; > + CHAR8 Name[10]; > + AMD_MP_CORE_INFO_PROTOCOL *AmdMpCoreInfoProtocol; > + > + // > + // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms. > + // > + // For 'cpus' and 'cpu' device tree nodes bindings, refer to this file > + // in the kernel documentation: > + // Documentation/devicetree/bindings/arm/cpus.txt > + // > + Status = gBS->LocateProtocol ( > + &gAmdMpCoreInfoProtocolGuid, > + NULL, > + (VOID **)&AmdMpCoreInfoProtocol > + ); > + ASSERT_EFI_ERROR (Status); > + > + // Get pointer to ARM core info table > + ArmCoreInfoTable = AmdMpCoreInfoProtocol->GetArmCoreInfoTable (&ArmCoreCount); > + ASSERT (ArmCoreInfoTable != NULL); > + ASSERT (ArmCoreCount <= NUM_CORES); > + > + // Get Id from primary CPU > + MpId = (UINTN)ArmReadMpidr (); > + > + // Create /pmu node > + PmuNode = fdt_add_subnode(Fdt, 0, "pmu"); > + if (PmuNode >= 0) { > + fdt_setprop_string (Fdt, PmuNode, "compatible", "arm,armv8-pmuv3"); > + > + // append PMU interrupts > + for (Index = 0; Index < ArmCoreCount; Index++) { > + MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, > + ArmCoreInfoTable[Index].CoreId); > + > + Status = AmdMpCoreInfoProtocol->GetPmuSpiFromMpId (MpId, &PmuInt.IntId); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, > + "FDT: Error getting PMU interrupt for MpId '0x%x'\n", MpId)); > + return Status; > + } > + > + PmuInt.Flag = cpu_to_fdt32 (PMU_INT_FLAG_SPI); > + PmuInt.IntId = cpu_to_fdt32 (PmuInt.IntId); > + PmuInt.Type = cpu_to_fdt32 (PMU_INT_TYPE_HIGH_LEVEL); > + fdt_appendprop (Fdt, PmuNode, "interrupts", &PmuInt, sizeof(PmuInt)); > + } > + } else { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating 'pmu' node\n")); > + return EFI_INVALID_PARAMETER; > + } > + > + // Create /cpus noide > + Node = fdt_add_subnode (Fdt, 0, "cpus"); > + if (Node >= 0) { > + // Configure the 'cpus' node > + fdt_setprop_string (Fdt, Node, "name", "cpus"); > + fdt_setprop_cell (Fdt, Node, "#address-cells", sizeof (UINTN) / 4); > + fdt_setprop_cell (Fdt, Node, "#size-cells", 0); > + } else { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating 'cpus' node\n")); > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Walk the processor table in reverse order for proper listing in FDT > + // > + Index = ArmCoreCount; > + while (Index--) { > + // Create 'cpu' node > + AsciiSPrint (Name, sizeof (Name), "CPU%d", Index); > + CpuNode = fdt_add_subnode (Fdt, Node, Name); > + if (CpuNode < 0) { > + DEBUG ((DEBUG_ERROR, "FDT: Error on creating '%a' node\n", Name)); > + return EFI_INVALID_PARAMETER; > + } > + Phandle[Index] = fdt_alloc_phandle (Fdt); > + fdt_setprop_cell (Fdt, CpuNode, "phandle", Phandle[Index]); > + fdt_setprop_cell (Fdt, CpuNode, "linux,phandle", Phandle[Index]); > + > + fdt_setprop_string (Fdt, CpuNode, "enable-method", "psci"); > + > + MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, > + ArmCoreInfoTable[Index].CoreId); > + MpId = cpu_to_fdt64 (MpId); > + fdt_setprop (Fdt, CpuNode, "reg", &MpId, sizeof (MpId)); > + fdt_setprop_string (Fdt, CpuNode, "compatible", "arm,armv8"); > + fdt_setprop_string (Fdt, CpuNode, "device_type", "cpu"); > + } > + > + // Create /cpu-map node > + MapNode = fdt_add_subnode (Fdt, Node, "cpu-map"); > + if (MapNode >= 0) { > + ClusterIndex = ArmCoreCount - 1; > + ClusterCount = NumberOfClustersInTable (ArmCoreInfoTable, > + ArmCoreCount); > + while (ClusterCount--) { > + // Create 'cluster' node > + AsciiSPrint (Name, sizeof (Name), "cluster%d", ClusterCount); > + ClusterNode = fdt_add_subnode (Fdt, MapNode, Name); > + if (ClusterNode < 0) { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); > + return EFI_INVALID_PARAMETER; > + } > + > + ClusterId = ArmCoreInfoTable[ClusterIndex].ClusterId; > + CoreIndex = ClusterIndex; > + CoresInCluster = NumberOfCoresInCluster (ArmCoreInfoTable, > + ArmCoreCount, > + ClusterId); > + while (CoresInCluster--) { > + // Create 'core' node > + AsciiSPrint (Name, sizeof (Name), "core%d", CoresInCluster); > + CpuNode = fdt_add_subnode (Fdt, ClusterNode, Name); > + if (CpuNode < 0) { > + DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); > + return EFI_INVALID_PARAMETER; > + } > + fdt_setprop_cell (Fdt, CpuNode, "cpu", Phandle[CoreIndex]); > + > + // iterate to next core in cluster > + if (CoresInCluster) { > + do { > + --CoreIndex; > + } while (ClusterId != ArmCoreInfoTable[CoreIndex].ClusterId); > + } > + } > + > + // iterate to next cluster > + if (ClusterCount) { > + do { > + --ClusterIndex; > + } while (ClusterInRange (ArmCoreInfoTable, > + ArmCoreInfoTable[ClusterIndex].ClusterId, > + ClusterIndex + 1, > + ArmCoreCount - 1)); > + } > + } > + } else { > + DEBUG ((DEBUG_ERROR,"FDT: Error creating 'cpu-map' node\n")); > + return EFI_INVALID_PARAMETER; > + } > + > + SetSocIdStatus (Fdt); > + SetXgbeStatus (Fdt); > + > + // Update the real size of the Device Tree > + fdt_pack (Fdt); > + > + return EFI_SUCCESS; > +} > + > + > +/** > + Return a pool allocated copy of the DTB image that is appropriate for > + booting the current platform via DT. > + > + @param[out] Dtb Pointer to the DTB copy > + @param[out] DtbSize Size of the DTB copy > + > + @retval EFI_SUCCESS Operation completed successfully > + @retval EFI_NOT_FOUND No suitable DTB image could be located > + @retval EFI_OUT_OF_RESOURCES No pool memory available > + > +**/ > +EFI_STATUS > +EFIAPI > +DtPlatformLoadDtb ( > + OUT VOID **Dtb, > + OUT UINTN *DtbSize > + ) > +{ > + EFI_STATUS Status; > + VOID *OrigDtb; > + VOID *CopyDtb; > + UINTN OrigDtbSize; > + UINTN CopyDtbSize; > + INT32 Error; > + > + Status = GetSectionFromAnyFv (&gDtPlatformDefaultDtbFileGuid, > + EFI_SECTION_RAW, 0, &OrigDtb, &OrigDtbSize); > + if (EFI_ERROR (Status)) { > + return EFI_NOT_FOUND; > + } > + > + // > + // Allocate space for the DTB: add a page of slack space to make some room > + // for our modifications. > + // > + CopyDtbSize = OrigDtbSize + EFI_PAGE_SIZE; > + CopyDtb = AllocatePool (CopyDtbSize); > + if (CopyDtb == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Error = fdt_open_into (OrigDtb, CopyDtb, CopyDtbSize); > + if (Error != 0) { > + // > + // fdt_open_into() validates the DTB header, so if it fails, the template > + // is most likely invalid. > + // > + return EFI_NOT_FOUND; > + } > + > + Status = PrepareFdt (CopyDtb, CopyDtbSize); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + *Dtb = CopyDtb; > + *DtbSize = CopyDtbSize; > + > + return EFI_SUCCESS; > +} > diff --git a/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf > new file mode 100644 > index 000000000000..f5ba5f1d1335 > --- /dev/null > +++ b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf > @@ -0,0 +1,64 @@ > +/** @file > +* > +* Copyright (c) 2017, Linaro, Ltd. 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 = 0x00010019 > + BASE_NAME = StyxDtbLoaderLib > + FILE_GUID = 3874890c-2917-46a6-8711-8fcaee92260a > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = DtPlatformDtbLoaderLib|DXE_DRIVER > + > +[Sources] > + StyxDtbLoaderLib.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + MdePkg/MdePkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + AmdModulePkg/AmdModulePkg.dec > + OpenPlatformPkg/Platforms/AMD/Styx/AmdStyx.dec > + > +[LibraryClasses] > + ArmLib > + BaseLib > + DebugLib > + DxeServicesLib > + FdtLib > + MemoryAllocationLib > + PrintLib > + UefiBootServicesTableLib > + > +[Pcd] > + gAmdStyxTokenSpaceGuid.PcdStyxFdt > + gAmdStyxTokenSpaceGuid.PcdSocCpuId > + gAmdStyxTokenSpaceGuid.PcdEthMacA > + gAmdStyxTokenSpaceGuid.PcdEthMacB > + gArmTokenSpaceGuid.PcdSystemMemoryBase > + > +[FixedPcd] > + gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset > + gArmTokenSpaceGuid.PcdArmLinuxFdtAlignment > + gAmdStyxTokenSpaceGuid.PcdPsciOsSupport > + gAmdStyxTokenSpaceGuid.PcdTrustedFWSupport > + gAmdStyxTokenSpaceGuid.PcdSata1PortCount > + > +[Guids] > + gDtPlatformDefaultDtbFileGuid > + > +[Protocols] > + gAmdMpCoreInfoProtocolGuid ## CONSUMED > + > +[Depex] > + gAmdMpCoreInfoProtocolGuid > -- > 2.9.3 >
On 7 April 2017 at 10:48, Leif Lindholm <leif.lindholm@linaro.org> wrote: > On Fri, Apr 07, 2017 at 09:59:32AM +0100, Ard Biesheuvel wrote: >> In order to be able to switch to the generic DtPlatformDxe driver, >> implement the glue library that loads it and prepares it based on >> the properties of the actual hardware. >> >> Contributed-under: TianoCore Contribution Agreement 1.0 >> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> > > I may have left my glasses at home today, but as far as I can see, all > that I asked for has been addressed, so: > > Revie_we_d-by: Leif Lindholm <leif.lindholm@linaro.org> > Thanks. I pushed this one, and the next one that moves Overdrive to it. Alan, could you let me know whether you are ok with changing Overdrive 1000 as well?
On 04/07/2017 06:26 AM, Ard Biesheuvel wrote: > On 7 April 2017 at 10:48, Leif Lindholm <leif.lindholm@linaro.org> wrote: >> On Fri, Apr 07, 2017 at 09:59:32AM +0100, Ard Biesheuvel wrote: >>> In order to be able to switch to the generic DtPlatformDxe driver, >>> implement the glue library that loads it and prepares it based on >>> the properties of the actual hardware. >>> >>> Contributed-under: TianoCore Contribution Agreement 1.0 >>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> >> I may have left my glasses at home today, but as far as I can see, all >> that I asked for has been addressed, so: >> >> Revie_we_d-by: Leif Lindholm <leif.lindholm@linaro.org> >> > > Thanks. I pushed this one, and the next one that moves Overdrive to it. > > Alan, could you let me know whether you are ok with changing Overdrive > 1000 as well? I haven't tested it here yet, but they're close enough to being the same. I can test it today. Alan.
diff --git a/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c new file mode 100644 index 000000000000..b18caf19985b --- /dev/null +++ b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c @@ -0,0 +1,481 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. 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 <PiDxe.h> + +#include <Guid/ArmMpCoreInfo.h> + +#include <libfdt.h> +#include <Library/ArmLib.h> +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/DxeServicesLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PrintLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/AmdMpCoreInfo.h> + +#define PMU_INT_FLAG_SPI 0 +#define PMU_INT_TYPE_HIGH_LEVEL 4 + +// +// PMU interrupts per core +// +#pragma pack(push, 1) +typedef struct { + UINT32 Flag; // 0 == SPI + UINT32 IntId; // GSIV == IntId+32 + UINT32 Type; // 4 == Level-Sensitive, Active-High +} PMU_INTERRUPT; +#pragma pack(pop) + +STATIC +BOOLEAN +ClusterInRange ( + IN ARM_CORE_INFO *ArmCoreInfoTable, + IN UINTN ClusterId, + IN UINTN LowIndex, + IN UINTN HighIndex + ) +{ + do { + if (ClusterId == ArmCoreInfoTable[LowIndex].ClusterId) + return TRUE; + } while (++LowIndex <= HighIndex); + + return FALSE; +} + + +STATIC +UINTN +NumberOfCoresInCluster ( + IN ARM_CORE_INFO *ArmCoreInfoTable, + IN UINTN NumberOfEntries, + IN UINTN ClusterId + ) +{ + UINTN Index, Cores; + + Cores = 0; + for (Index = 0; Index < NumberOfEntries; ++Index) { + if (ClusterId == ArmCoreInfoTable[Index].ClusterId) + ++Cores; + } + + return Cores; +} + + +STATIC +UINTN +NumberOfClustersInTable ( + IN ARM_CORE_INFO *ArmCoreInfoTable, + IN UINTN NumberOfEntries + ) +{ + UINTN Index, Cores, Clusters, ClusterId; + + Index = 0; + Clusters = 0; + Cores = NumberOfEntries; + while (Cores) { + ++Clusters; + ClusterId = ArmCoreInfoTable[Index].ClusterId; + Cores -= NumberOfCoresInCluster (ArmCoreInfoTable, + NumberOfEntries, + ClusterId); + if (Cores) { + do { + ++Index; + } while (ClusterInRange (ArmCoreInfoTable, + ArmCoreInfoTable[Index].ClusterId, + 0, Index-1)); + } + } + + return Clusters; +} + + +STATIC +INT32 +fdt_alloc_phandle ( + IN VOID *Fdt + ) +{ + INT32 Offset; + INT32 Phandle; + + Phandle = 0; + + for (Offset = fdt_next_node (Fdt, -1, NULL); Offset >= 0; + Offset = fdt_next_node (Fdt, Offset, NULL)) { + Phandle = MAX (Phandle, fdt_get_phandle (Fdt, Offset)); + } + + return Phandle + 1; +} + +STATIC +VOID +SetDeviceStatus ( + IN VOID *Fdt, + IN CONST CHAR8 *Device, + IN BOOLEAN Enable + ) +{ + INT32 Node; + INT32 SubNode; + INT32 Rc; + + Node = fdt_subnode_offset (Fdt, 0, "smb"); + if (Node >= 0) { + SubNode = fdt_subnode_offset (Fdt, Node, Device); + if (SubNode >= 0) { + Rc = fdt_setprop_string (Fdt, SubNode, "status", + Enable ? "okay" : "disabled"); + if (Rc) { + DEBUG ((DEBUG_ERROR, + "%a: Could not set 'status' property for '%a' node\n", + __FUNCTION__, Device)); + } + } + } +} + +#if DO_XGBE + +#define MAC_ADDRESS_BYTES 6 + +STATIC +VOID +SetMacAddress ( + IN VOID *Fdt, + IN CONST CHAR8 *Device, + IN UINT64 MacAddress + ) +{ + INT32 Node; + INT32 SubNode; + INT32 Rc; + + Node = fdt_subnode_offset (Fdt, 0, "smb"); + if (Node >= 0) { + SubNode = fdt_subnode_offset (Fdt, Node, Device); + if (SubNode >= 0) { + Rc = fdt_setprop (Fdt, SubNode, "mac-address", (VOID *)&MacAddress, + MAC_ADDRESS_BYTES); + if (Rc) { + DEBUG ((DEBUG_ERROR, + "%a: Could not set 'mac-address' property for '%a' node\n", + __FUNCTION__, Device)); + } + } + } +} + +#endif + +#define STYX_SOC_VERSION_MASK 0xFFF +#define STYX_SOC_VERSION_A0 0x000 +#define STYX_SOC_VERSION_B0 0x010 +#define STYX_SOC_VERSION_B1 0x011 + +STATIC +VOID +SetSocIdStatus ( + IN VOID *Fdt + ) +{ + UINT32 SocId; + BOOLEAN IsRevB1; + + SocId = PcdGet32 (PcdSocCpuId); + IsRevB1 = (SocId & STYX_SOC_VERSION_MASK) >= STYX_SOC_VERSION_B1; + + SetDeviceStatus (Fdt, "sata@e0d00000", + IsRevB1 && FixedPcdGet8 (PcdSata1PortCount) > 0); + SetDeviceStatus (Fdt, "gpio@e0020000", IsRevB1); + SetDeviceStatus (Fdt, "gpio@e0030000", IsRevB1); + SetDeviceStatus (Fdt, "gwdt@e0bb0000", IsRevB1); +#if DO_KCS + SetDeviceStatus (Fdt, "kcs@e0010000", IsRevB1); +#else + SetDeviceStatus (Fdt, "kcs@e0010000", FALSE); +#endif +} + +STATIC +VOID +SetXgbeStatus ( + IN VOID *Fdt + ) +{ +#if DO_XGBE + SetDeviceStatus (Fdt, "xgmac@e0700000", TRUE); + SetDeviceStatus (Fdt, "phy@e1240800", TRUE); + SetDeviceStatus (Fdt, "xgmac@e0900000", TRUE); + SetDeviceStatus (Fdt, "phy@e1240c00", TRUE); + + SetMacAddress (Fdt, "xgmac@e0700000", PcdGet64 (PcdEthMacA)); + SetMacAddress (Fdt, "xgmac@e0900000", PcdGet64 (PcdEthMacB)); +#else + SetDeviceStatus (Fdt, "xgmac@e0700000", FALSE); + SetDeviceStatus (Fdt, "phy@e1240800", FALSE); + SetDeviceStatus (Fdt, "xgmac@e0900000", FALSE); + SetDeviceStatus (Fdt, "phy@e1240c00", FALSE); +#endif +} + + +STATIC +EFI_STATUS +PrepareFdt ( + IN OUT VOID *Fdt, + IN UINTN FdtSize + ) +{ + EFI_STATUS Status; + INT32 Node; + INT32 CpuNode; + UINTN Index; + ARM_CORE_INFO *ArmCoreInfoTable; + UINTN ArmCoreCount; + INT32 MapNode; + INT32 ClusterNode; + INT32 PmuNode; + PMU_INTERRUPT PmuInt; + INT32 Phandle[NUM_CORES]; + UINT32 ClusterIndex; + UINT32 CoreIndex; + UINT32 ClusterCount; + UINT32 CoresInCluster; + UINT32 ClusterId; + UINTN MpId; + CHAR8 Name[10]; + AMD_MP_CORE_INFO_PROTOCOL *AmdMpCoreInfoProtocol; + + // + // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms. + // + // For 'cpus' and 'cpu' device tree nodes bindings, refer to this file + // in the kernel documentation: + // Documentation/devicetree/bindings/arm/cpus.txt + // + Status = gBS->LocateProtocol ( + &gAmdMpCoreInfoProtocolGuid, + NULL, + (VOID **)&AmdMpCoreInfoProtocol + ); + ASSERT_EFI_ERROR (Status); + + // Get pointer to ARM core info table + ArmCoreInfoTable = AmdMpCoreInfoProtocol->GetArmCoreInfoTable (&ArmCoreCount); + ASSERT (ArmCoreInfoTable != NULL); + ASSERT (ArmCoreCount <= NUM_CORES); + + // Get Id from primary CPU + MpId = (UINTN)ArmReadMpidr (); + + // Create /pmu node + PmuNode = fdt_add_subnode(Fdt, 0, "pmu"); + if (PmuNode >= 0) { + fdt_setprop_string (Fdt, PmuNode, "compatible", "arm,armv8-pmuv3"); + + // append PMU interrupts + for (Index = 0; Index < ArmCoreCount; Index++) { + MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, + ArmCoreInfoTable[Index].CoreId); + + Status = AmdMpCoreInfoProtocol->GetPmuSpiFromMpId (MpId, &PmuInt.IntId); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "FDT: Error getting PMU interrupt for MpId '0x%x'\n", MpId)); + return Status; + } + + PmuInt.Flag = cpu_to_fdt32 (PMU_INT_FLAG_SPI); + PmuInt.IntId = cpu_to_fdt32 (PmuInt.IntId); + PmuInt.Type = cpu_to_fdt32 (PMU_INT_TYPE_HIGH_LEVEL); + fdt_appendprop (Fdt, PmuNode, "interrupts", &PmuInt, sizeof(PmuInt)); + } + } else { + DEBUG ((DEBUG_ERROR, "FDT: Error creating 'pmu' node\n")); + return EFI_INVALID_PARAMETER; + } + + // Create /cpus noide + Node = fdt_add_subnode (Fdt, 0, "cpus"); + if (Node >= 0) { + // Configure the 'cpus' node + fdt_setprop_string (Fdt, Node, "name", "cpus"); + fdt_setprop_cell (Fdt, Node, "#address-cells", sizeof (UINTN) / 4); + fdt_setprop_cell (Fdt, Node, "#size-cells", 0); + } else { + DEBUG ((DEBUG_ERROR, "FDT: Error creating 'cpus' node\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Walk the processor table in reverse order for proper listing in FDT + // + Index = ArmCoreCount; + while (Index--) { + // Create 'cpu' node + AsciiSPrint (Name, sizeof (Name), "CPU%d", Index); + CpuNode = fdt_add_subnode (Fdt, Node, Name); + if (CpuNode < 0) { + DEBUG ((DEBUG_ERROR, "FDT: Error on creating '%a' node\n", Name)); + return EFI_INVALID_PARAMETER; + } + Phandle[Index] = fdt_alloc_phandle (Fdt); + fdt_setprop_cell (Fdt, CpuNode, "phandle", Phandle[Index]); + fdt_setprop_cell (Fdt, CpuNode, "linux,phandle", Phandle[Index]); + + fdt_setprop_string (Fdt, CpuNode, "enable-method", "psci"); + + MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, + ArmCoreInfoTable[Index].CoreId); + MpId = cpu_to_fdt64 (MpId); + fdt_setprop (Fdt, CpuNode, "reg", &MpId, sizeof (MpId)); + fdt_setprop_string (Fdt, CpuNode, "compatible", "arm,armv8"); + fdt_setprop_string (Fdt, CpuNode, "device_type", "cpu"); + } + + // Create /cpu-map node + MapNode = fdt_add_subnode (Fdt, Node, "cpu-map"); + if (MapNode >= 0) { + ClusterIndex = ArmCoreCount - 1; + ClusterCount = NumberOfClustersInTable (ArmCoreInfoTable, + ArmCoreCount); + while (ClusterCount--) { + // Create 'cluster' node + AsciiSPrint (Name, sizeof (Name), "cluster%d", ClusterCount); + ClusterNode = fdt_add_subnode (Fdt, MapNode, Name); + if (ClusterNode < 0) { + DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); + return EFI_INVALID_PARAMETER; + } + + ClusterId = ArmCoreInfoTable[ClusterIndex].ClusterId; + CoreIndex = ClusterIndex; + CoresInCluster = NumberOfCoresInCluster (ArmCoreInfoTable, + ArmCoreCount, + ClusterId); + while (CoresInCluster--) { + // Create 'core' node + AsciiSPrint (Name, sizeof (Name), "core%d", CoresInCluster); + CpuNode = fdt_add_subnode (Fdt, ClusterNode, Name); + if (CpuNode < 0) { + DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); + return EFI_INVALID_PARAMETER; + } + fdt_setprop_cell (Fdt, CpuNode, "cpu", Phandle[CoreIndex]); + + // iterate to next core in cluster + if (CoresInCluster) { + do { + --CoreIndex; + } while (ClusterId != ArmCoreInfoTable[CoreIndex].ClusterId); + } + } + + // iterate to next cluster + if (ClusterCount) { + do { + --ClusterIndex; + } while (ClusterInRange (ArmCoreInfoTable, + ArmCoreInfoTable[ClusterIndex].ClusterId, + ClusterIndex + 1, + ArmCoreCount - 1)); + } + } + } else { + DEBUG ((DEBUG_ERROR,"FDT: Error creating 'cpu-map' node\n")); + return EFI_INVALID_PARAMETER; + } + + SetSocIdStatus (Fdt); + SetXgbeStatus (Fdt); + + // Update the real size of the Device Tree + fdt_pack (Fdt); + + return EFI_SUCCESS; +} + + +/** + Return a pool allocated copy of the DTB image that is appropriate for + booting the current platform via DT. + + @param[out] Dtb Pointer to the DTB copy + @param[out] DtbSize Size of the DTB copy + + @retval EFI_SUCCESS Operation completed successfully + @retval EFI_NOT_FOUND No suitable DTB image could be located + @retval EFI_OUT_OF_RESOURCES No pool memory available + +**/ +EFI_STATUS +EFIAPI +DtPlatformLoadDtb ( + OUT VOID **Dtb, + OUT UINTN *DtbSize + ) +{ + EFI_STATUS Status; + VOID *OrigDtb; + VOID *CopyDtb; + UINTN OrigDtbSize; + UINTN CopyDtbSize; + INT32 Error; + + Status = GetSectionFromAnyFv (&gDtPlatformDefaultDtbFileGuid, + EFI_SECTION_RAW, 0, &OrigDtb, &OrigDtbSize); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Allocate space for the DTB: add a page of slack space to make some room + // for our modifications. + // + CopyDtbSize = OrigDtbSize + EFI_PAGE_SIZE; + CopyDtb = AllocatePool (CopyDtbSize); + if (CopyDtb == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Error = fdt_open_into (OrigDtb, CopyDtb, CopyDtbSize); + if (Error != 0) { + // + // fdt_open_into() validates the DTB header, so if it fails, the template + // is most likely invalid. + // + return EFI_NOT_FOUND; + } + + Status = PrepareFdt (CopyDtb, CopyDtbSize); + if (EFI_ERROR (Status)) { + return Status; + } + + *Dtb = CopyDtb; + *DtbSize = CopyDtbSize; + + return EFI_SUCCESS; +} diff --git a/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf new file mode 100644 index 000000000000..f5ba5f1d1335 --- /dev/null +++ b/Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf @@ -0,0 +1,64 @@ +/** @file +* +* Copyright (c) 2017, Linaro, Ltd. 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 = 0x00010019 + BASE_NAME = StyxDtbLoaderLib + FILE_GUID = 3874890c-2917-46a6-8711-8fcaee92260a + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DtPlatformDtbLoaderLib|DXE_DRIVER + +[Sources] + StyxDtbLoaderLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + AmdModulePkg/AmdModulePkg.dec + OpenPlatformPkg/Platforms/AMD/Styx/AmdStyx.dec + +[LibraryClasses] + ArmLib + BaseLib + DebugLib + DxeServicesLib + FdtLib + MemoryAllocationLib + PrintLib + UefiBootServicesTableLib + +[Pcd] + gAmdStyxTokenSpaceGuid.PcdStyxFdt + gAmdStyxTokenSpaceGuid.PcdSocCpuId + gAmdStyxTokenSpaceGuid.PcdEthMacA + gAmdStyxTokenSpaceGuid.PcdEthMacB + gArmTokenSpaceGuid.PcdSystemMemoryBase + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset + gArmTokenSpaceGuid.PcdArmLinuxFdtAlignment + gAmdStyxTokenSpaceGuid.PcdPsciOsSupport + gAmdStyxTokenSpaceGuid.PcdTrustedFWSupport + gAmdStyxTokenSpaceGuid.PcdSata1PortCount + +[Guids] + gDtPlatformDefaultDtbFileGuid + +[Protocols] + gAmdMpCoreInfoProtocolGuid ## CONSUMED + +[Depex] + gAmdMpCoreInfoProtocolGuid
In order to be able to switch to the generic DtPlatformDxe driver, implement the glue library that loads it and prepares it based on the properties of the actual hardware. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> --- Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.c | 481 ++++++++++++++++++++ Platforms/AMD/Styx/Library/StyxDtbLoaderLib/StyxDtbLoaderLib.inf | 64 +++ 2 files changed, 545 insertions(+)