QcomModulePkg: Add DDR size check for choosing DTB and DTBO

DDR size check is needed for choosing DTB and DTBO, if a target
has more than one DDR variant like Bengal. Bits 8-10 of subtype
in qcom,board-id is used for storing DDR information in DT.

Change-Id: Ib62c53336e30ed448db368fbc39e849134d9d267
diff --git a/QcomModulePkg/Include/Library/Board.h b/QcomModulePkg/Include/Library/Board.h
index 1d3426d..62e30e6 100644
--- a/QcomModulePkg/Include/Library/Board.h
+++ b/QcomModulePkg/Include/Library/Board.h
@@ -56,12 +56,28 @@
   UNKNOWN,
 } MemCardType;
 
+#define DDR_SHIFT      8
+
+#define MB             (1024 * 1024UL)
+#define DDR_256MB      (256 * MB)
+#define DDR_512MB      (512 * MB)
+#define DDR_1024MB     (1024 * MB)
+#define DDR_2048MB     (2048 * MB)
+
+typedef enum {
+  DDRTYPE_256MB = 1,
+  DDRTYPE_512MB,
+  DDRTYPE_1024MB,
+  DDRTYPE_2048MB,
+} DdrType;
+
 struct BoardInfo {
   EFI_PLATFORMINFO_PLATFORM_INFO_TYPE PlatformInfo;
   UINT32 RawChipId;
   CHAR8 ChipBaseBand[EFICHIPINFO_MAX_ID_LENGTH];
   EFIChipInfoVersionType ChipVersion;
   EFIChipInfoFoundryIdType FoundryId;
+  UINT32 HlosSubType;
 };
 
 EFI_STATUS
@@ -99,4 +115,6 @@
                   UINT32 *NumPartitions);
 EFI_STATUS GetGranuleSize (UINT32 *MinPasrGranuleSize);
 VOID GetPageSize (UINT32 *PageSize);
+EFI_STATUS BoardDdrType (UINT32 *Type);
+UINT32 BoardPlatformHlosSubType (VOID);
 #endif
diff --git a/QcomModulePkg/Include/Library/LocateDeviceTree.h b/QcomModulePkg/Include/Library/LocateDeviceTree.h
index b08120a..7970d94 100644
--- a/QcomModulePkg/Include/Library/LocateDeviceTree.h
+++ b/QcomModulePkg/Include/Library/LocateDeviceTree.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-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
@@ -70,6 +70,8 @@
 #define PMIC_SHIFT_IDX (2)
 #define PLATFORM_SUBTYPE_SHIFT_ID (0x18)
 #define FOUNDRY_ID_MASK (0x00ff0000)
+#define PLATFORM_SUBTYPE_MASK (0x000000ff)
+#define DDR_MASK (0x00000700)
 
 typedef enum {
   NONE_MATCH,
@@ -99,6 +101,7 @@
   PMIC_MATCH_EXACT_MODEL_IDX3,
   SUBTYPE_DEFAULT_MATCH,
   SUBTYPE_EXACT_MATCH,
+  DDR_MATCH,
   VARIANT_MATCH,
   SOC_MATCH,
   MAX_MATCH,
diff --git a/QcomModulePkg/Library/BootLib/Board.c b/QcomModulePkg/Library/BootLib/Board.c
index 358ec61..7edc1c2 100644
--- a/QcomModulePkg/Library/BootLib/Board.c
+++ b/QcomModulePkg/Library/BootLib/Board.c
@@ -478,6 +478,7 @@
 {
   EFI_STATUS Status;
   EFIChipInfoModemType ModemType;
+  UINT32 DdrType;
 
   Status = GetChipInfo (&platform_board_info, &ModemType);
   if (EFI_ERROR (Status))
@@ -487,6 +488,12 @@
   if (EFI_ERROR (Status))
     return Status;
 
+  Status = BoardDdrType (&DdrType);
+  if (EFI_ERROR (Status))
+    return Status;
+
+  platform_board_info.HlosSubType = (DdrType << DDR_SHIFT);
+
   if (BoardPlatformFusion ()) {
     AsciiSPrint ((CHAR8 *)platform_board_info.ChipBaseBand,
                   CHIP_BASE_BAND_LEN, "%a", CHIP_BASE_BAND_MDM);
@@ -508,6 +515,8 @@
           platform_board_info.ChipBaseBand));
   DEBUG ((EFI_D_VERBOSE, "Fusion Value    : %d\n",
           platform_board_info.PlatformInfo.fusion));
+  DEBUG ((EFI_D_VERBOSE, "HLOS SubType    : 0x%x\n",
+          platform_board_info.HlosSubType));
 
   return Status;
 }
@@ -695,3 +704,41 @@
   else
     StrHwPlatform[ChipIdValidLen - 1] = '\0';
 }
+
+EFI_STATUS BoardDdrType (UINT32 *Type)
+{
+  EFI_STATUS Status;
+  RamPartitionEntry *RamPartitions = NULL;
+  UINT32 i = 0;
+  UINT32 NumPartitions = 0;
+  UINT64 DdrSize = 0;
+
+  Status = ReadRamPartitions (&RamPartitions, &NumPartitions);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Error returned from GetRamPartitions %r\n", Status));
+    return Status;
+  }
+
+  for (i = 0; i < NumPartitions; i++) {
+    DdrSize += RamPartitions[i].AvailableLength;
+  }
+  DEBUG ((EFI_D_INFO, "Total DDR Size: 0x%016lx \n", DdrSize));
+
+  *Type = 0;
+  if (DdrSize <= DDR_256MB) {
+    *Type = DDRTYPE_256MB;
+  } else if (DdrSize <= DDR_512MB) {
+    *Type = DDRTYPE_512MB;
+  } else if (DdrSize <= DDR_1024MB) {
+    *Type = DDRTYPE_1024MB;
+  } else if (DdrSize <= DDR_2048MB) {
+    *Type = DDRTYPE_2048MB;
+  }
+
+  return Status;
+}
+
+UINT32 BoardPlatformHlosSubType (VOID)
+{
+  return platform_board_info.HlosSubType;
+}
diff --git a/QcomModulePkg/Library/BootLib/LocateDeviceTree.c b/QcomModulePkg/Library/BootLib/LocateDeviceTree.c
index 9b65901..d6caa31 100644
--- a/QcomModulePkg/Library/BootLib/LocateDeviceTree.c
+++ b/QcomModulePkg/Library/BootLib/LocateDeviceTree.c
@@ -742,9 +742,10 @@
 
     DEBUG ((EFI_D_VERBOSE, "BoardSubtype = %x, DtSubType = %x\n",
             BoardPlatformSubType (), CurDtbInfo->DtPlatformSubtype));
-    if (CurDtbInfo->DtPlatformSubtype == BoardPlatformSubType ()) {
+    if ((CurDtbInfo->DtPlatformSubtype & PLATFORM_SUBTYPE_MASK) ==
+        BoardPlatformSubType ()) {
       CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_EXACT_MATCH);
-    } else if (CurDtbInfo->DtPlatformSubtype == 0) {
+    } else if ((CurDtbInfo->DtPlatformSubtype & PLATFORM_SUBTYPE_MASK) == 0) {
       CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_DEFAULT_MATCH);
     } else {
       DEBUG ((EFI_D_VERBOSE, "subtype-id doesnot match\n"));
@@ -752,6 +753,13 @@
       CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
       return EFI_NOT_FOUND;
     }
+
+    if ((CurDtbInfo->DtPlatformSubtype & DDR_MASK) ==
+        (BoardPlatformHlosSubType() & DDR_MASK)) {
+      CurDtbInfo->DtMatchVal |= BIT (DDR_MATCH);
+    } else {
+      DEBUG ((EFI_D_VERBOSE, "ddr size does not match\n"));
+    }
   } else {
     DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not exist (or) (%d) "
                            "is not a multiple of (%d)\n",
@@ -1199,6 +1207,7 @@
 platform_dt_absolute_match (struct dt_entry *cur_dt_entry,
                             struct dt_entry_node *dt_list)
 {
+  UINT32 cur_dt_hlos_ddr;
   UINT32 cur_dt_hw_platform;
   UINT32 cur_dt_hw_subtype;
   UINT32 cur_dt_msm_id;
@@ -1212,6 +1221,9 @@
   cur_dt_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
   cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
 
+  /* Bits 10:8 contain ddr information */
+  cur_dt_hlos_ddr = (cur_dt_entry->board_hw_subtype & 0x700);
+
   /* 1. must match the msm_id, platform_hw_id, platform_subtype and DDR size
    *  soc, board major/minor, pmic major/minor must less than board info
    *  2. find the matched DTB then return 1
@@ -1221,6 +1233,7 @@
   if ((cur_dt_msm_id == (BoardPlatformRawChipId () & 0x0000ffff)) &&
       (cur_dt_hw_platform == BoardPlatformType ()) &&
       (cur_dt_hw_subtype == BoardPlatformSubType ()) &&
+      (cur_dt_hlos_ddr == (BoardPlatformHlosSubType() & 0x700)) &&
       (cur_dt_entry->soc_rev <= BoardPlatformChipVersion ()) &&
       ((cur_dt_entry->variant_id & 0x00ffff00) <=
        (BoardTargetId () & 0x00ffff00)) &&