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(+)
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
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.