summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaushal Kumar <kaushalk@codeaurora.org>2019-11-19 18:52:38 +0530
committerAmit Pundir <amit.pundir@linaro.org>2022-12-20 23:39:29 +0530
commit9fe7be243c58fa1bc3d5ff535fa63dce5aa33bb9 (patch)
treebc3c40d6868cc68325ed38933955df22daa85fd4
parent5a9b0bc7cca48d3163643853c4440df37e28f0c5 (diff)
QcomModulePkg: Add support to update DDR rank & HBB in device tree
Add support to update device tree with the DDR device rank information per channel and Highest Bank Bit information per rank for each of the DDR channels. Change-Id: Ia00d582e4ef03838c7bdf33d46880519824410e7
-rw-r--r--QcomModulePkg/Include/Protocol/DDRDetails.h8
-rw-r--r--QcomModulePkg/Include/Protocol/EFIDDRGetConfig.h4
-rw-r--r--QcomModulePkg/Library/BootLib/UpdateDeviceTree.c77
3 files changed, 75 insertions, 14 deletions
diff --git a/QcomModulePkg/Include/Protocol/DDRDetails.h b/QcomModulePkg/Include/Protocol/DDRDetails.h
index 6532de6983..5fd1b47033 100644
--- a/QcomModulePkg/Include/Protocol/DDRDetails.h
+++ b/QcomModulePkg/Include/Protocol/DDRDetails.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,7 +32,9 @@
#define MAX_IDX 8
#define MAX_NUM_CLOCK_PLAN 14
-#define DDR_DETAILS_STRUCT_VERSION 0x0000000000030000
+#define DDR_DETAILS_STRUCT_VERSION 0x0000000000040000
+#define MAX_CHANNELS 2
+#define MAX_RANKS 2
struct ddr_freq_table {
UINT32 freq_khz;
@@ -59,6 +61,8 @@ typedef struct ddr_details_entry_info {
struct ddr_part_details ddr_params[MAX_IDX];
ddr_freq_plan_entry ddr_freq_tbl;
UINT8 num_channels;
+ UINT8 num_ranks[MAX_CHANNELS];/* Number of ranks per channel */
+ UINT8 hbb[MAX_CHANNELS][MAX_RANKS];/* Highest Bank Bit per rank per channel */
} ddr_details_entry;
#endif /* DDRDETAILS_H */
diff --git a/QcomModulePkg/Include/Protocol/EFIDDRGetConfig.h b/QcomModulePkg/Include/Protocol/EFIDDRGetConfig.h
index 1609e87ad8..969a0aa8f0 100644
--- a/QcomModulePkg/Include/Protocol/EFIDDRGetConfig.h
+++ b/QcomModulePkg/Include/Protocol/EFIDDRGetConfig.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -40,7 +40,7 @@ typedef struct _EFI_DDRGETINFO_PROTOCOL EFI_DDRGETINFO_PROTOCOL;
/**
Protocol version.
*/
-#define EFI_DDRGETINFO_PROTOCOL_REVISION 0x0000000000030000
+#define EFI_DDRGETINFO_PROTOCOL_REVISION 0x0000000000040000
/*Both the protocl version and the structure version should be same */
#if (EFI_DDRGETINFO_PROTOCOL_REVISION != DDR_DETAILS_STRUCT_VERSION)
diff --git a/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c b/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
index b7bed3b6d8..87f6143440 100644
--- a/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
+++ b/QcomModulePkg/Library/BootLib/UpdateDeviceTree.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -69,29 +69,28 @@ PrintSplashMemInfo (CONST CHAR8 *data, INT32 datalen)
}
STATIC EFI_STATUS
-GetDDRInfo (UINT8 *DdrDeviceType)
+GetDDRInfo (struct ddr_details_entry_info *DdrInfo,
+ UINT64 *Revision)
{
EFI_DDRGETINFO_PROTOCOL *DdrInfoIf;
- struct ddr_details_entry_info DdrInfo;
EFI_STATUS Status;
Status = gBS->LocateProtocol (&gEfiDDRGetInfoProtocolGuid, NULL,
(VOID **)&DdrInfoIf);
if (Status != EFI_SUCCESS) {
DEBUG ((EFI_D_VERBOSE,
- "INFO: Unable to get DDR Info protocol. DDR type not updated:%r\n",
+ "INFO: Unable to get DDR Info protocol:%r\n",
Status));
return Status;
}
- Status = DdrInfoIf->GetDDRDetails (DdrInfoIf, &DdrInfo);
+ Status = DdrInfoIf->GetDDRDetails (DdrInfoIf, DdrInfo);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "INFO: GetDDR details failed\n"));
return Status;
}
-
- *DdrDeviceType = DdrInfo.device_type;
- DEBUG ((EFI_D_VERBOSE, "DDR deviceType:%d", *DdrDeviceType));
+ *Revision = DdrInfoIf->Revision;
+ DEBUG ((EFI_D_VERBOSE, "DDR Header Revision =0x%x\n", *Revision));
return Status;
}
@@ -480,6 +479,12 @@ UpdateDeviceTree (VOID *fdt,
UINT32 PaddSize = 0;
UINT64 KaslrSeed = 0;
UINT8 DdrDeviceType;
+ /* Single space reserved for chan(0-9) */
+ CHAR8 FdtRankProp[] = "ddr_device_rank_ch ";
+ /* Single spaces reserved for chan(0-9), rank(0-9) */
+ CHAR8 FdtHbbProp[] = "ddr_device_hbb_ch _rank ";
+ struct ddr_details_entry_info *DdrInfo;
+ UINT64 Revision;
EFI_STATUS Status;
UINT64 UpdateDTStartTime = GetTimerCountms ();
@@ -518,17 +523,69 @@ UpdateDeviceTree (VOID *fdt,
return Status;
}
- Status = GetDDRInfo (&DdrDeviceType);
+ DdrInfo = AllocateZeroPool (sizeof (struct ddr_details_entry_info));
+ if (DdrInfo == NULL) {
+ DEBUG ((EFI_D_ERROR, "DDR Info Buffer: Out of resources\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = GetDDRInfo (DdrInfo, &Revision);
if (Status == EFI_SUCCESS) {
+ DdrDeviceType = DdrInfo->device_type;
+ DEBUG ((EFI_D_VERBOSE, "DDR deviceType:%d\n", DdrDeviceType));
+
ret = fdt_appendprop_u32 (fdt, offset, (CONST char *)"ddr_device_type",
(UINT32)DdrDeviceType);
if (ret) {
DEBUG ((EFI_D_ERROR,
- "ERROR: Cannot update memory node [ddr_device_type] - 0x%x\n",
+ "ERROR: Cannot update memory node [ddr_device_type]:0x%x\n",
ret));
} else {
DEBUG ((EFI_D_VERBOSE, "ddr_device_type is added to memory node\n"));
}
+
+ if (Revision < EFI_DDRGETINFO_PROTOCOL_REVISION) {
+ DEBUG ((EFI_D_VERBOSE,
+ "ddr_device_rank, HBB not supported in Revision=0x%x\n",
+ Revision));
+ } else {
+ DEBUG ((EFI_D_VERBOSE, "DdrInfo->num_channels:%d\n",
+ DdrInfo->num_channels));
+ for (UINT8 Chan = 0; Chan < DdrInfo->num_channels; Chan++) {
+ DEBUG ((EFI_D_VERBOSE, "ddr_device_rank_ch%d:%d\n",
+ Chan, DdrInfo->num_ranks[Chan]));
+ AsciiSPrint (FdtRankProp, sizeof (FdtRankProp),
+ "ddr_device_rank_ch%d", Chan);
+ ret = fdt_appendprop_u32 (fdt, offset,
+ (CONST char *)FdtRankProp,
+ (UINT32)DdrInfo->num_ranks[Chan]);
+ if (ret) {
+ DEBUG ((EFI_D_ERROR,
+ "ERROR: Cannot update memory node ddr_device_rank_ch%d:0x%x\n",
+ Chan, ret));
+ } else {
+ DEBUG ((EFI_D_VERBOSE, "ddr_device_rank_ch%d added to memory node\n",
+ Chan));
+ }
+ for (UINT8 Rank = 0; Rank < DdrInfo->num_ranks[Chan]; Rank++) {
+ DEBUG ((EFI_D_VERBOSE, "ddr_device_hbb_ch%d_rank%d:%d\n",
+ Chan, Rank, DdrInfo->hbb[Chan][Rank]));
+ AsciiSPrint (FdtHbbProp, sizeof (FdtHbbProp),
+ "ddr_device_hbb_ch%d_rank%d", Chan, Rank);
+ ret = fdt_appendprop_u32 (fdt, offset,
+ (CONST char *)FdtHbbProp,
+ (UINT32)DdrInfo->hbb[Chan][Rank]);
+ if (ret) {
+ DEBUG ((EFI_D_ERROR,
+ "ERROR: Cannot update memory node ddr_device_hbb_ch%d_rank%d:0x%x\n",
+ Chan, Rank, ret));
+ } else {
+ DEBUG ((EFI_D_VERBOSE,
+ "ddr_device_hbb_ch%d_rank%d added to memory node\n",
+ Chan, Rank));
+ }
+ }
+ }
+ }
}
UpdateSplashMemInfo (fdt);