| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 1 | #include "isdimm_vpd_parser.hpp" | 
 | 2 |  | 
 | 3 | #include <iostream> | 
 | 4 | #include <numeric> | 
 | 5 | #include <string> | 
 | 6 |  | 
 | 7 | namespace openpower | 
 | 8 | { | 
 | 9 | namespace vpd | 
 | 10 | { | 
| jinuthomas | 5700b3c | 2023-03-07 22:51:00 -0600 | [diff] [blame] | 11 | namespace isdimm | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 12 | { | 
 | 13 | namespace parser | 
 | 14 | { | 
 | 15 | static constexpr auto SPD_JEDEC_DDR4_SDRAM_CAP_MASK = 0x0F; | 
 | 16 | static constexpr auto SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MASK = 0x07; | 
 | 17 | static constexpr auto SPD_JEDEC_DDR4_SDRAM_WIDTH_MASK = 0x07; | 
 | 18 | static constexpr auto SPD_JEDEC_DDR4_NUM_RANKS_MASK = 0x38; | 
 | 19 | static constexpr auto SPD_JEDEC_DDR4_DIE_COUNT_MASK = 0x70; | 
 | 20 | static constexpr auto SPD_JEDEC_DDR4_SINGLE_LOAD_STACK = 0x02; | 
 | 21 | static constexpr auto SPD_JEDEC_DDR4_SIGNAL_LOADING_MASK = 0x03; | 
 | 22 |  | 
 | 23 | static constexpr auto SPD_JEDEC_DDR4_SDRAMCAP_MULTIPLIER = 256; | 
 | 24 | static constexpr auto SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER = 8; | 
 | 25 | static constexpr auto SPD_JEDEC_DDR4_SDRAM_WIDTH_MULTIPLIER = 4; | 
 | 26 | static constexpr auto SPD_JEDEC_DDR4_SDRAMCAP_RESERVED = 8; | 
 | 27 | static constexpr auto SPD_JEDEC_DDR4_4_RESERVED_BITS = 4; | 
 | 28 | static constexpr auto SPD_JEDEC_DDR4_3_RESERVED_BITS = 3; | 
 | 29 | static constexpr auto SPD_JEDEC_DDR4_DIE_COUNT_RIGHT_SHIFT = 4; | 
 | 30 |  | 
 | 31 | static constexpr auto SPD_JEDEC_DDR4_MFG_ID_MSB_OFFSET = 321; | 
 | 32 | static constexpr auto SPD_JEDEC_DDR4_MFG_ID_LSB_OFFSET = 320; | 
 | 33 | static constexpr auto SPD_JEDEC_DDR4_SN_BYTE0_OFFSET = 325; | 
 | 34 | static constexpr auto SPD_JEDEC_DDR4_SN_BYTE1_OFFSET = 326; | 
 | 35 | static constexpr auto SPD_JEDEC_DDR4_SN_BYTE2_OFFSET = 327; | 
 | 36 | static constexpr auto SPD_JEDEC_DDR4_SN_BYTE3_OFFSET = 328; | 
 | 37 | static constexpr auto SPD_JEDEC_DDR4_SDRAM_DENSITY_BANK_OFFSET = 4; | 
 | 38 | static constexpr auto SPD_JEDEC_DDR4_SDRAM_ADDR_OFFSET = 5; | 
 | 39 | static constexpr auto SPD_JEDEC_DDR4_DRAM_PRI_PACKAGE_OFFSET = 6; | 
 | 40 | static constexpr auto SPD_JEDEC_DDR4_DRAM_MODULE_ORG_OFFSET = 12; | 
 | 41 |  | 
 | 42 | // DDR5 JEDEC specification constants | 
 | 43 | static constexpr auto SPD_JEDEC_DDR5_SUB_CHANNELS_PER_DIMM = 235; | 
 | 44 | static constexpr auto SPD_JEDEC_DDR5_SUB_CHANNELS_PER_DIMM_MASK = 0x60; | 
 | 45 | static constexpr auto SPD_JEDEC_DDR5_PRI_BUS_WIDTH_PER_CHANNEL = 235; | 
 | 46 | static constexpr auto SPD_JEDEC_DDR5_PRI_BUS_WIDTH_PER_CHANNEL_MASK = 0x07; | 
 | 47 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_SYM_ALL = 6; | 
 | 48 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_ASYM_EVEN = 6; | 
 | 49 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_ASYM_ODD = 10; | 
 | 50 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_MASK = 0xE0; | 
 | 51 | static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_SYM_ALL = 4; | 
 | 52 | static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_ASYM_EVEN = 4; | 
 | 53 | static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_ASYM_ODD = 8; | 
 | 54 | static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_MASK = 0xE0; | 
 | 55 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_SYM_ALL = 4; | 
 | 56 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_ASYM_EVEN = 4; | 
 | 57 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_ASYM_ODD = 8; | 
 | 58 | static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_MASK = 0x1F; | 
 | 59 | static constexpr auto SPD_JEDEC_DDR5_RANK_MIX = 234; | 
 | 60 | static constexpr auto SPD_JEDEC_DDR5_RANK_MIX_SYMMETRICAL_MASK = 0x40; | 
 | 61 |  | 
 | 62 | auto isdimmVpdParser::getDDR4DimmCapacity(Binary::const_iterator& iterator) | 
 | 63 | { | 
 | 64 |     size_t tmp = 0, dimmSize = 0; | 
 | 65 |  | 
 | 66 |     size_t sdramCap = 1, priBusWid = 1, sdramWid = 1, logicalRanksPerDimm = 1; | 
 | 67 |     Byte dieCount = 1; | 
 | 68 |  | 
 | 69 |     // NOTE: This calculation is Only for DDR4 | 
 | 70 |  | 
 | 71 |     // Calculate SDRAM  capacity | 
 | 72 |     tmp = iterator[constants::SPD_BYTE_4] & SPD_JEDEC_DDR4_SDRAM_CAP_MASK; | 
 | 73 |     /* Make sure the bits are not Reserved */ | 
 | 74 |     if (tmp >= SPD_JEDEC_DDR4_SDRAMCAP_RESERVED) | 
 | 75 |     { | 
 | 76 |         std::cerr | 
 | 77 |             << "Bad data in spd byte 4. Can't calculate SDRAM capacity and so " | 
 | 78 |                "dimm size.\n "; | 
 | 79 |         return dimmSize; | 
 | 80 |     } | 
 | 81 |  | 
 | 82 |     sdramCap = (sdramCap << tmp) * SPD_JEDEC_DDR4_SDRAMCAP_MULTIPLIER; | 
 | 83 |  | 
 | 84 |     /* Calculate Primary bus width */ | 
 | 85 |     tmp = iterator[constants::SPD_BYTE_13] & SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MASK; | 
 | 86 |     if (tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS) | 
 | 87 |     { | 
 | 88 |         std::cerr | 
 | 89 |             << "Bad data in spd byte 13. Can't calculate primary bus width " | 
 | 90 |                "and so dimm size.\n "; | 
 | 91 |         return dimmSize; | 
 | 92 |     } | 
 | 93 |     priBusWid = (priBusWid << tmp) * SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER; | 
 | 94 |  | 
 | 95 |     /* Calculate SDRAM width */ | 
 | 96 |     tmp = iterator[constants::SPD_BYTE_12] & SPD_JEDEC_DDR4_SDRAM_WIDTH_MASK; | 
 | 97 |     if (tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS) | 
 | 98 |     { | 
 | 99 |         std::cerr | 
 | 100 |             << "Bad data in vpd byte 12. Can't calculate SDRAM width and so " | 
 | 101 |                "dimm size.\n "; | 
 | 102 |         return dimmSize; | 
 | 103 |     } | 
 | 104 |     sdramWid = (sdramWid << tmp) * SPD_JEDEC_DDR4_SDRAM_WIDTH_MULTIPLIER; | 
 | 105 |  | 
 | 106 |     tmp = iterator[constants::SPD_BYTE_6] & SPD_JEDEC_DDR4_SIGNAL_LOADING_MASK; | 
 | 107 |  | 
 | 108 |     if (tmp == SPD_JEDEC_DDR4_SINGLE_LOAD_STACK) | 
 | 109 |     { | 
 | 110 |         // Fetch die count | 
 | 111 |         tmp = iterator[constants::SPD_BYTE_6] & SPD_JEDEC_DDR4_DIE_COUNT_MASK; | 
 | 112 |         tmp >>= SPD_JEDEC_DDR4_DIE_COUNT_RIGHT_SHIFT; | 
 | 113 |         dieCount = tmp + 1; | 
 | 114 |     } | 
 | 115 |  | 
 | 116 |     /* Calculate Number of ranks */ | 
 | 117 |     tmp = iterator[constants::SPD_BYTE_12] & SPD_JEDEC_DDR4_NUM_RANKS_MASK; | 
 | 118 |     tmp >>= SPD_JEDEC_DDR4_3_RESERVED_BITS; | 
 | 119 |  | 
 | 120 |     if (tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS) | 
 | 121 |     { | 
 | 122 |         std::cerr << "Can't calculate number of ranks. Invalid data found.\n "; | 
 | 123 |         return dimmSize; | 
 | 124 |     } | 
 | 125 |     logicalRanksPerDimm = (tmp + 1) * dieCount; | 
 | 126 |  | 
 | 127 |     dimmSize = (sdramCap / SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER) * | 
 | 128 |                (priBusWid / sdramWid) * logicalRanksPerDimm; | 
 | 129 |  | 
 | 130 |     return dimmSize; | 
 | 131 | } | 
 | 132 |  | 
 | 133 | auto isdimmVpdParser::getDDR4PartNumber(Binary::const_iterator& iterator) | 
 | 134 | { | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 135 |     char tmpPN[constants::PART_NUM_LEN + 1] = {'\0'}; | 
 | 136 |     sprintf(tmpPN, "%02X%02X%02X%X", | 
 | 137 |             iterator[SPD_JEDEC_DDR4_SDRAM_DENSITY_BANK_OFFSET], | 
 | 138 |             iterator[SPD_JEDEC_DDR4_SDRAM_ADDR_OFFSET], | 
 | 139 |             iterator[SPD_JEDEC_DDR4_DRAM_PRI_PACKAGE_OFFSET], | 
 | 140 |             iterator[SPD_JEDEC_DDR4_DRAM_MODULE_ORG_OFFSET] & 0x0F); | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 141 |     std::string partNumber(tmpPN, sizeof(tmpPN) - 1); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 142 |     return partNumber; | 
 | 143 | } | 
 | 144 |  | 
 | 145 | auto isdimmVpdParser::getDDR4SerialNumber(Binary::const_iterator& iterator) | 
 | 146 | { | 
 | 147 |     char tmpSN[constants::SERIAL_NUM_LEN + 1] = {'\0'}; | 
 | 148 |     sprintf(tmpSN, "%02X%02X%02X%02X%02X%02X", | 
 | 149 |             iterator[SPD_JEDEC_DDR4_MFG_ID_MSB_OFFSET], | 
 | 150 |             iterator[SPD_JEDEC_DDR4_MFG_ID_LSB_OFFSET], | 
 | 151 |             iterator[SPD_JEDEC_DDR4_SN_BYTE0_OFFSET], | 
 | 152 |             iterator[SPD_JEDEC_DDR4_SN_BYTE1_OFFSET], | 
 | 153 |             iterator[SPD_JEDEC_DDR4_SN_BYTE2_OFFSET], | 
 | 154 |             iterator[SPD_JEDEC_DDR4_SN_BYTE3_OFFSET]); | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 155 |     std::string serialNumber(tmpSN, sizeof(tmpSN) - 1); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 156 |     return serialNumber; | 
 | 157 | } | 
 | 158 |  | 
 | 159 | auto isdimmVpdParser::getDDR4FruNumber(const std::string& partNumber) | 
 | 160 | { | 
 | 161 |     // check for 128GB ISRDIMM not implemented | 
 | 162 |     //(128GB 2RX4(8GX72) IS RDIMM 36*(16GBIT, 2H),1.2V 288PIN,1.2" ROHS) - NA | 
 | 163 |  | 
 | 164 |     static std::unordered_map<std::string, std::string> pnFruMap = { | 
 | 165 |         {"8421000", "78P4191"}, {"8421008", "78P4192"}, {"8529000", "78P4197"}, | 
 | 166 |         {"8529008", "78P4198"}, {"8529928", "78P4199"}, {"8529B28", "78P4200"}, | 
 | 167 |         {"8631008", "78P6815"}, {"8631928", "78P6925"}}; | 
 | 168 |  | 
 | 169 |     std::string fruNumber; | 
 | 170 |     auto itr = pnFruMap.find(partNumber); | 
 | 171 |     if (itr != pnFruMap.end()) | 
 | 172 |     { | 
 | 173 |         fruNumber = itr->second; | 
 | 174 |     } | 
 | 175 |     else | 
 | 176 |     { | 
 | 177 |         fruNumber = "FFFFFFF"; | 
 | 178 |     } | 
 | 179 |     return fruNumber; | 
 | 180 | } | 
 | 181 |  | 
 | 182 | auto isdimmVpdParser::getDDR4CCIN(const std::string& partNumber) | 
 | 183 | { | 
 | 184 |     static std::unordered_map<std::string, std::string> pnCCINMap = { | 
 | 185 |         {"8421000", "324D"}, {"8421008", "324E"}, {"8529000", "324E"}, | 
 | 186 |         {"8529008", "324F"}, {"8529928", "325A"}, {"8529B28", "324C"}, | 
 | 187 |         {"8631008", "32BB"}, {"8631928", "32BC"}}; | 
 | 188 |  | 
 | 189 |     std::string ccin; | 
 | 190 |     auto itr = pnCCINMap.find(partNumber); | 
 | 191 |     if (itr != pnCCINMap.end()) | 
 | 192 |     { | 
 | 193 |         ccin = itr->second; | 
 | 194 |     } | 
 | 195 |     else | 
 | 196 |     { | 
 | 197 |         ccin = "XXXX"; | 
 | 198 |     } | 
 | 199 |     return ccin; | 
 | 200 | } | 
 | 201 |  | 
 | 202 | auto isdimmVpdParser::getDDR5DimmCapacity(Binary::const_iterator& iterator) | 
 | 203 | { | 
 | 204 |     // dummy implementation to be updated when required | 
 | 205 |     size_t dimmSize = 0; | 
 | 206 |     (void)iterator; | 
 | 207 |     return dimmSize; | 
 | 208 | } | 
 | 209 |  | 
 | 210 | auto isdimmVpdParser::getDDR5PartNumber(Binary::const_iterator& iterator) | 
 | 211 | { | 
 | 212 |     // dummy implementation to be updated when required | 
 | 213 |     std::string partNumber; | 
 | 214 |     (void)iterator; | 
 | 215 |     partNumber = "0123456"; | 
 | 216 |     return partNumber; | 
 | 217 | } | 
 | 218 |  | 
 | 219 | auto isdimmVpdParser::getDDR5SerialNumber(Binary::const_iterator& iterator) | 
 | 220 | { | 
 | 221 |     // dummy implementation to be updated when required | 
 | 222 |     std::string serialNumber; | 
 | 223 |     (void)iterator; | 
 | 224 |     serialNumber = "444444444444"; | 
 | 225 |     return serialNumber; | 
 | 226 | } | 
 | 227 |  | 
 | 228 | auto isdimmVpdParser::getDDR5FruNumber(const std::string& partNumber) | 
 | 229 | { | 
 | 230 |     // dummy implementation to be updated when required | 
 | 231 |     static std::unordered_map<std::string, std::string> pnFruMap = { | 
 | 232 |         {"1234567", "XXXXXXX"}}; | 
 | 233 |  | 
 | 234 |     std::string fruNumber; | 
 | 235 |     auto itr = pnFruMap.find(partNumber); | 
 | 236 |     if (itr != pnFruMap.end()) | 
 | 237 |     { | 
 | 238 |         fruNumber = itr->second; | 
 | 239 |     } | 
 | 240 |     else | 
 | 241 |     { | 
 | 242 |         fruNumber = "FFFFFFF"; | 
 | 243 |     } | 
 | 244 |     return fruNumber; | 
 | 245 | } | 
 | 246 |  | 
 | 247 | auto isdimmVpdParser::getDDR5CCIN(const std::string& partNumber) | 
 | 248 | { | 
 | 249 |     // dummy implementation to be updated when required | 
 | 250 |     static std::unordered_map<std::string, std::string> pnCCINMap = { | 
 | 251 |         {"1234567", "XXXX"}}; | 
 | 252 |  | 
 | 253 |     std::string ccin; | 
 | 254 |     auto itr = pnCCINMap.find(partNumber); | 
 | 255 |     if (itr != pnCCINMap.end()) | 
 | 256 |     { | 
 | 257 |         ccin = itr->second; | 
 | 258 |     } | 
 | 259 |     else | 
 | 260 |     { | 
 | 261 |         ccin = "XXXX"; | 
 | 262 |     } | 
 | 263 |     return ccin; | 
 | 264 | } | 
 | 265 |  | 
 | 266 | kwdVpdMap isdimmVpdParser::readKeywords(Binary::const_iterator& iterator) | 
 | 267 | { | 
 | 268 |     inventory::KeywordVpdMap keywordValueMap{}; | 
 | 269 |     if ((iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) == | 
 | 270 |         constants::SPD_DRAM_TYPE_DDR5) | 
 | 271 |     { | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 272 |         size_t dimmSize = getDDR5DimmCapacity(iterator); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 273 |         if (!dimmSize) | 
 | 274 |         { | 
 | 275 |             std::cerr << "Error: Calculated dimm size is 0."; | 
 | 276 |         } | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 277 |         else | 
 | 278 |         { | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 279 |             keywordValueMap.emplace("MemorySizeInKB", dimmSize); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 280 |         } | 
 | 281 |         auto partNumber = getDDR5PartNumber(iterator); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 282 |         auto fruNumber = getDDR5FruNumber(partNumber); | 
 | 283 |         keywordValueMap.emplace("FN", move(fruNumber)); | 
 | 284 |         auto serialNumber = getDDR5SerialNumber(iterator); | 
 | 285 |         keywordValueMap.emplace("SN", move(serialNumber)); | 
 | 286 |         auto ccin = getDDR5CCIN(partNumber); | 
 | 287 |         keywordValueMap.emplace("CC", move(ccin)); | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 288 |         keywordValueMap.emplace("PN", move(partNumber)); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 289 |     } | 
 | 290 |     else if ((iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) == | 
 | 291 |              constants::SPD_DRAM_TYPE_DDR4) | 
 | 292 |     { | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 293 |         size_t dimmSize = getDDR4DimmCapacity(iterator); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 294 |         if (!dimmSize) | 
 | 295 |         { | 
 | 296 |             std::cerr << "Error: Calculated dimm size is 0."; | 
 | 297 |         } | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 298 |         else | 
 | 299 |         { | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 300 |             keywordValueMap.emplace("MemorySizeInKB", | 
 | 301 |                                     (dimmSize * constants::CONVERT_MB_TO_KB)); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 302 |         } | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 303 |  | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 304 |         auto partNumber = getDDR4PartNumber(iterator); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 305 |         auto fruNumber = getDDR4FruNumber(partNumber); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 306 |         auto serialNumber = getDDR4SerialNumber(iterator); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 307 |         auto ccin = getDDR4CCIN(partNumber); | 
| jinuthomas | d640f69 | 2023-03-28 04:13:23 -0500 | [diff] [blame] | 308 |         keywordValueMap.emplace("PN", move(partNumber)); | 
 | 309 |         keywordValueMap.emplace("FN", move(fruNumber)); | 
 | 310 |         keywordValueMap.emplace("SN", move(serialNumber)); | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 311 |         keywordValueMap.emplace("CC", move(ccin)); | 
 | 312 |     } | 
 | 313 |     return keywordValueMap; | 
 | 314 | } | 
 | 315 |  | 
 | 316 | std::variant<kwdVpdMap, Store> isdimmVpdParser::parse() | 
 | 317 | { | 
 | 318 |     // Read the data and return the map | 
 | 319 |     auto iterator = memVpd.cbegin(); | 
 | 320 |     auto vpdDataMap = readKeywords(iterator); | 
 | 321 |  | 
 | 322 |     return vpdDataMap; | 
 | 323 | } | 
 | 324 |  | 
 | 325 | } // namespace parser | 
| jinuthomas | 5700b3c | 2023-03-07 22:51:00 -0600 | [diff] [blame] | 326 | } // namespace isdimm | 
| jinuthomas | 6555e7e | 2023-02-14 21:48:00 -0600 | [diff] [blame] | 327 | } // namespace vpd | 
| jinuthomas | 5700b3c | 2023-03-07 22:51:00 -0600 | [diff] [blame] | 328 | } // namespace openpower |