]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
EDAC/igen6: Fix memory topology parsing for Panther Lake-H SoCs
authorQiuxu Zhuo <qiuxu.zhuo@intel.com>
Fri, 3 Apr 2026 05:40:28 +0000 (13:40 +0800)
committerTony Luck <tony.luck@intel.com>
Fri, 29 May 2026 15:34:12 +0000 (08:34 -0700)
Panther Lake-H SoC memory controller registers for memory topology have
been updated, but the current igen6_edac driver still uses old generation
ones to incorrectly parse memory topology.

Fix the issue by adding memory topology parsing function pointers to the
'struct res_config' and creating a new configuration structure for Panther
Lake-H SoCs to enable igen6_edac to parse memory correctly.

Fixes: 0be9f1af3902 ("EDAC/igen6: Add Intel Panther Lake-H SoCs support")
Fixes: 4c36e6106997 ("EDAC/igen6: Add more Intel Panther Lake-H SoCs support")
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Link: https://patch.msgid.link/20260403054029.3950383-3-qiuxu.zhuo@intel.com
drivers/edac/igen6_edac.c
include/linux/edac.h

index 0bf9cf349d0b4e41a0df77ce84897931810c834b..f849e3299593f70c067ea742db6d5ee7c024ac52 100644 (file)
 #define MEM_SLICE_HASH_MASK(v)         (GET_BITFIELD(v, 6, 19) << 6)
 #define MEM_SLICE_HASH_LSB_MASK_BIT(v) GET_BITFIELD(v, 24, 26)
 
+struct igen6_imc {
+       int mc;
+       struct mem_ctl_info *mci;
+       struct pci_dev *pdev;
+       struct device dev;
+       void __iomem *window;
+       u64 size;
+       u64 ch_s_size;
+       int ch_l_map;
+       u64 dimm_s_size[NUM_CHANNELS];
+       u64 dimm_l_size[NUM_CHANNELS];
+       int dimm_l_map[NUM_CHANNELS];
+};
+
 static struct res_config {
        bool machine_check;
        /* The number of present memory controllers. */
@@ -134,12 +148,29 @@ static struct res_config {
        u64 reg_touud_mask;
        /* IBECC error log */
        u64 reg_eccerrlog_addr_mask;
+       /* MEMSS_PMA_CR registers. */
+       u32 reg_mem_config_offset;
+       u32 reg_mem_config_ddr_type_mask;
+       /* Memory controller registers. */
+       u32 reg_mad_inter_size_mask[NUM_CHANNELS];
+       u64 reg_mad_inter_size_granularity;
+       u32 reg_mad_intra_rank_mask[NUM_DIMMS];
+       u32 reg_mad_intra_width_mask[NUM_DIMMS];
+       u32 reg_mad_intra_density_mask[NUM_DIMMS];
        u32 imc_base;
        u32 cmf_base;
        u32 cmf_size;
        u32 ms_hash_offset;
        u32 ibecc_base;
        u32 ibecc_error_log_offset;
+       /* Get memory type. */
+       enum mem_type (*get_mem_type)(struct igen6_imc *imc);
+       /* Get DRAM chip type. */
+       enum dev_type (*get_dev_type)(struct igen6_imc *imc, int chan, int dimm_l);
+       /* Set imc->ch_{s_size,l_map}. */
+       void (*set_chan_params)(struct igen6_imc *imc);
+       /* Set imc->dimm_{l_size,s_size,l_map}[chan]. */
+       void (*set_dimm_params)(struct igen6_imc *imc, int chan);
        bool (*ibecc_available)(struct pci_dev *pdev);
        /* Extract error address logged in IBECC */
        u64 (*err_addr)(u64 ecclog);
@@ -149,22 +180,9 @@ static struct res_config {
        u64 (*err_addr_to_imc_addr)(u64 eaddr, int mc);
 } *res_cfg;
 
-struct igen6_imc {
-       int mc;
-       struct mem_ctl_info *mci;
-       struct pci_dev *pdev;
-       struct device dev;
-       void __iomem *window;
-       u64 size;
-       u64 ch_s_size;
-       int ch_l_map;
-       u64 dimm_s_size[NUM_CHANNELS];
-       u64 dimm_l_size[NUM_CHANNELS];
-       int dimm_l_map[NUM_CHANNELS];
-};
-
 static struct igen6_pvt {
        struct igen6_imc imc[NUM_IMC];
+       void __iomem *memss_pma_cr;
        u64 ms_hash;
        u64 ms_s_size;
        int ms_l_map;
@@ -500,6 +518,119 @@ static u64 rpl_p_err_addr(u64 ecclog)
        return field_get(res_cfg->reg_eccerrlog_addr_mask, ecclog);
 }
 
+static enum mem_type ptl_h_get_mem_type(struct igen6_imc *imc)
+{
+       u32 mtype, val;
+
+       val = readl(igen6_pvt->memss_pma_cr + res_cfg->reg_mem_config_offset);
+       mtype = field_get(res_cfg->reg_mem_config_ddr_type_mask, val);
+
+       edac_dbg(2, "mtype %u (reg 0x%x)\n", mtype, val);
+
+       switch (mtype) {
+       case 1:
+               return MEM_DDR5;
+       case 2:
+               return MEM_LPDDR5;
+       case 3:
+               return MEM_LPDDR4;
+       default:
+               return MEM_UNKNOWN;
+       }
+}
+
+static enum dev_type ptl_h_get_dev_type(struct igen6_imc *imc, int chan, int dimm)
+{
+       u32 width, val;
+
+       val = readl(imc->window + MAD_INTRA_CH0_OFFSET + chan * 4);
+       width = field_get(res_cfg->reg_mad_intra_width_mask[dimm], val);
+
+       switch (width) {
+       case 1:
+               return DEV_X8;
+       default:
+               return DEV_X16;
+       }
+}
+
+static u64 ptl_h_get_chan_size(struct igen6_imc *imc, int chan)
+{
+       u32 val = readl(imc->window + MAD_INTER_CHANNEL_OFFSET);
+
+       return field_get(res_cfg->reg_mad_inter_size_mask[chan], val) *
+              res_cfg->reg_mad_inter_size_granularity;
+}
+
+static u64 ptl_h_get_dimm_size(struct igen6_imc *imc, int chan, int dimm)
+{
+       u32 val = readl(imc->window + MAD_INTRA_CH0_OFFSET + chan * 4);
+       u32 ranks = 1 << field_get(res_cfg->reg_mad_intra_rank_mask[dimm], val);
+       /* DRAM device density in Gb */
+       u64 density = field_get(res_cfg->reg_mad_intra_density_mask[dimm], val) * 4;
+
+       enum mem_type mtype = ptl_h_get_mem_type(imc);
+       enum dev_type dtype = ptl_h_get_dev_type(imc, chan, dimm);
+       u64 sub_ch_width, dev_num;
+
+       switch (mtype) {
+       case MEM_DDR5:
+               sub_ch_width = 32;
+               break;
+       case MEM_LPDDR5:
+       case MEM_LPDDR4:
+               sub_ch_width = 16;
+               break;
+       default:
+               sub_ch_width = 0;
+       }
+
+       switch (dtype) {
+       case DEV_X8:
+               dev_num = sub_ch_width / 8;
+               break;
+       case DEV_X16:
+               dev_num = sub_ch_width / 16;
+               break;
+       default:
+               dev_num = 0;
+       }
+
+       edac_dbg(2, "ranks %d, density %lluGb, sub_ch_width %llu, dev_num %llu (reg 0x%x)\n", ranks, density, sub_ch_width, dev_num, val);
+
+       return ((dev_num * density / 8) * ranks) << 30;
+}
+
+static void ptl_h_set_chan_params(struct igen6_imc *imc)
+{
+       u64 ch0_size = ptl_h_get_chan_size(imc, 0);
+       u64 ch1_size = ptl_h_get_chan_size(imc, 1);
+
+       if (ch0_size <= ch1_size) {
+               imc->ch_s_size = ch0_size;
+               imc->ch_l_map = 1;
+       } else {
+               imc->ch_s_size = ch1_size;
+               imc->ch_l_map = 0;
+       }
+}
+
+static void ptl_h_set_dimm_params(struct igen6_imc *imc, int chan)
+{
+       u64 dimm0_size = ptl_h_get_dimm_size(imc, chan, 0);
+       u64 dimm1_size = ptl_h_get_dimm_size(imc, chan, 1);
+
+       if (dimm0_size <= dimm1_size) {
+               imc->dimm_s_size[chan] = dimm0_size;
+               imc->dimm_l_size[chan] = dimm1_size;
+               imc->dimm_l_map[chan]  = 1;
+       } else {
+               imc->dimm_s_size[chan] = dimm1_size;
+               imc->dimm_l_size[chan] = dimm0_size;
+               imc->dimm_l_map[chan]  = 0;
+       }
+}
+
 static struct res_config ehl_cfg = {
        .num_imc                = 1,
        .reg_mchbar_mask        = GENMASK_ULL(38, 16),
@@ -622,6 +753,36 @@ static struct res_config mtl_p_cfg = {
        .err_addr_to_imc_addr   = adl_err_addr_to_imc_addr,
 };
 
+static struct res_config ptl_h_cfg = {
+       .machine_check                  = true,
+       .num_imc                        = 2,
+       .reg_mchbar_mask                = GENMASK_ULL(41, 17),
+       .reg_tom_mask                   = GENMASK_ULL(41, 20),
+       .reg_touud_mask                 = GENMASK_ULL(41, 20),
+       .reg_eccerrlog_addr_mask        = GENMASK_ULL(38, 5),
+       .reg_mem_config_offset          = 0x13d04,
+       .reg_mem_config_ddr_type_mask   = GENMASK(8, 6),
+       .reg_mad_inter_size_mask[0]     = GENMASK(15, 8),
+       .reg_mad_inter_size_mask[1]     = GENMASK(23, 16),
+       .reg_mad_inter_size_granularity = BIT_ULL(29),
+       .reg_mad_intra_rank_mask[0]     = BIT(7),
+       .reg_mad_intra_rank_mask[1]     = BIT(15),
+       .reg_mad_intra_width_mask[0]    = BIT(6),
+       .reg_mad_intra_width_mask[1]    = BIT(14),
+       .reg_mad_intra_density_mask[0]  = GENMASK(3, 0),
+       .reg_mad_intra_density_mask[1]  = GENMASK(11, 8),
+       .imc_base                       = 0xd800,
+       .ibecc_base                     = 0xd400,
+       .ibecc_error_log_offset         = 0x170,
+       .get_mem_type                   = ptl_h_get_mem_type,
+       .get_dev_type                   = ptl_h_get_dev_type,
+       .set_chan_params                = ptl_h_set_chan_params,
+       .set_dimm_params                = ptl_h_set_dimm_params,
+       .ibecc_available                = mtl_p_ibecc_available,
+       .err_addr_to_sys_addr           = adl_err_addr_to_sys_addr,
+       .err_addr_to_imc_addr           = adl_err_addr_to_imc_addr,
+};
+
 static struct res_config wcl_cfg = {
        .machine_check          = true,
        .num_imc                = 1,
@@ -689,46 +850,34 @@ static struct pci_device_id igen6_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, DID_ARL_UH_SKU1), (kernel_ulong_t)&mtl_p_cfg },
        { PCI_VDEVICE(INTEL, DID_ARL_UH_SKU2), (kernel_ulong_t)&mtl_p_cfg },
        { PCI_VDEVICE(INTEL, DID_ARL_UH_SKU3), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU1), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU2), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU3), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU4), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU5), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU6), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU7), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU8), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU9), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU10), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU11), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU12), (kernel_ulong_t)&mtl_p_cfg },
-       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU13), (kernel_ulong_t)&mtl_p_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU1), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU2), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU3), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU4), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU5), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU6), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU7), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU8), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU9), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU10), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU11), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU12), (kernel_ulong_t)&ptl_h_cfg },
+       { PCI_VDEVICE(INTEL, DID_PTL_H_SKU13), (kernel_ulong_t)&ptl_h_cfg },
        { PCI_VDEVICE(INTEL, DID_WCL_SKU1), (kernel_ulong_t)&wcl_cfg },
        { },
 };
 MODULE_DEVICE_TABLE(pci, igen6_pci_tbl);
 
-static enum dev_type get_width(int dimm_l, u32 mad_dimm)
+static enum mem_type get_mem_type(struct igen6_imc *imc)
 {
-       u32 w = dimm_l ? MAD_DIMM_CH_DLW(mad_dimm) :
-                        MAD_DIMM_CH_DSW(mad_dimm);
+       u32 val;
 
-       switch (w) {
-       case 0:
-               return DEV_X8;
-       case 1:
-               return DEV_X16;
-       case 2:
-               return DEV_X32;
-       default:
-               return DEV_UNKNOWN;
-       }
-}
+       if (res_cfg->get_mem_type)
+               return res_cfg->get_mem_type(imc);
 
-static enum mem_type get_memory_type(u32 mad_inter)
-{
-       u32 t = MAD_INTER_CHANNEL_DDR_TYPE(mad_inter);
+       val = readl(imc->window + MAD_INTER_CHANNEL_OFFSET);
 
-       switch (t) {
+       switch (MAD_INTER_CHANNEL_DDR_TYPE(val)) {
        case 0:
                return MEM_DDR4;
        case 1:
@@ -744,6 +893,73 @@ static enum mem_type get_memory_type(u32 mad_inter)
        }
 }
 
+static bool large_dimm(struct igen6_imc *imc, int chan, int dimm)
+{
+       return dimm == imc->dimm_l_map[chan];
+}
+
+static enum dev_type get_dev_type(struct igen6_imc *imc, int chan, int dimm)
+{
+       u32 width, val;
+
+       if (res_cfg->get_dev_type)
+               return res_cfg->get_dev_type(imc, chan, dimm);
+
+       val = readl(imc->window + MAD_DIMM_CH0_OFFSET + chan * 4);
+       width = large_dimm(imc, chan, dimm) ? MAD_DIMM_CH_DLW(val) :
+                                         MAD_DIMM_CH_DSW(val);
+
+       switch (width) {
+       case 0:
+               return DEV_X8;
+       case 1:
+               return DEV_X16;
+       case 2:
+               return DEV_X32;
+       default:
+               return DEV_UNKNOWN;
+       }
+}
+
+static u64 get_dimm_size(struct igen6_imc *imc, int chan, int dimm)
+{
+       if (large_dimm(imc, chan, dimm))
+               return imc->dimm_l_size[chan];
+
+       return imc->dimm_s_size[chan];
+}
+
+static void set_chan_params(struct igen6_imc *imc)
+{
+       u32 val;
+
+       if (res_cfg->set_chan_params) {
+               res_cfg->set_chan_params(imc);
+               return;
+       }
+
+       val = readl(imc->window + MAD_INTER_CHANNEL_OFFSET);
+       imc->ch_s_size = MAD_INTER_CHANNEL_CH_S_SIZE(val);
+       imc->ch_l_map = MAD_INTER_CHANNEL_CH_L_MAP(val);
+}
+
+static void set_dimm_params(struct igen6_imc *imc, int chan)
+{
+       u32 val;
+
+       if (res_cfg->set_dimm_params) {
+               res_cfg->set_dimm_params(imc, chan);
+               return;
+       }
+
+       val = readl(imc->window + MAD_INTRA_CH0_OFFSET + chan * 4);
+       imc->dimm_l_map[chan]  = MAD_INTRA_CH_DIMM_L_MAP(val);
+
+       val = readl(imc->window + MAD_DIMM_CH0_OFFSET + chan * 4);
+       imc->dimm_l_size[chan] = MAD_DIMM_CH_DIMM_L_SIZE(val);
+       imc->dimm_s_size[chan] = MAD_DIMM_CH_DIMM_S_SIZE(val);
+}
+
 static int decode_chan_idx(u64 addr, u64 mask, int intlv_bit)
 {
        u64 hash_addr = addr & mask, hash = 0;
@@ -1084,7 +1300,6 @@ static bool igen6_check_ecc(struct igen6_imc *imc)
 static int igen6_get_dimm_config(struct mem_ctl_info *mci)
 {
        struct igen6_imc *imc = mci->pvt_info;
-       u32 mad_inter, mad_intra, mad_dimm;
        int i, j, ndimms, mc = imc->mc;
        struct dimm_info *dimm;
        enum mem_type mtype;
@@ -1094,33 +1309,20 @@ static int igen6_get_dimm_config(struct mem_ctl_info *mci)
 
        edac_dbg(2, "\n");
 
-       mad_inter = readl(imc->window + MAD_INTER_CHANNEL_OFFSET);
-       mtype = get_memory_type(mad_inter);
+       mtype = get_mem_type(imc);
        ecc = igen6_check_ecc(imc);
-       imc->ch_s_size = MAD_INTER_CHANNEL_CH_S_SIZE(mad_inter);
-       imc->ch_l_map  = MAD_INTER_CHANNEL_CH_L_MAP(mad_inter);
+       set_chan_params(imc);
 
        for (i = 0; i < NUM_CHANNELS; i++) {
-               mad_intra = readl(imc->window + MAD_INTRA_CH0_OFFSET + i * 4);
-               mad_dimm  = readl(imc->window + MAD_DIMM_CH0_OFFSET + i * 4);
-
-               imc->dimm_l_size[i] = MAD_DIMM_CH_DIMM_L_SIZE(mad_dimm);
-               imc->dimm_s_size[i] = MAD_DIMM_CH_DIMM_S_SIZE(mad_dimm);
-               imc->dimm_l_map[i]  = MAD_INTRA_CH_DIMM_L_MAP(mad_intra);
+               set_dimm_params(imc, i);
                imc->size += imc->dimm_s_size[i];
                imc->size += imc->dimm_l_size[i];
                ndimms = 0;
 
                for (j = 0; j < NUM_DIMMS; j++) {
                        dimm = edac_get_dimm(mci, i, j, 0);
-
-                       if (j ^ imc->dimm_l_map[i]) {
-                               dtype = get_width(0, mad_dimm);
-                               dsize = imc->dimm_s_size[i];
-                       } else {
-                               dtype = get_width(1, mad_dimm);
-                               dsize = imc->dimm_l_size[i];
-                       }
+                       dtype = get_dev_type(imc, i, j);
+                       dsize = get_dimm_size(imc, i, j);
 
                        if (!dsize)
                                continue;
@@ -1223,6 +1425,39 @@ static void igen6_debug_setup(void) {}
 static void igen6_debug_teardown(void) {}
 #endif
 
+static struct igen6_pvt *igen6_pvt_setup(struct pci_dev *pdev)
+{
+       void __iomem *memss_pma_cr;
+       struct igen6_pvt *pvt;
+       u64 mchbar;
+       int rc;
+
+       pvt = kzalloc_obj(*igen6_pvt);
+       if (!pvt)
+               return NULL;
+
+       rc = get_mchbar(pdev, &mchbar);
+       if (rc) {
+               kfree(pvt);
+               return NULL;
+       }
+
+       memss_pma_cr = ioremap(mchbar, MCHBAR_SIZE * 2);
+       if (!memss_pma_cr) {
+               kfree(pvt);
+               return NULL;
+       }
+       pvt->memss_pma_cr = memss_pma_cr;
+
+       return pvt;
+}
+
+static void igen6_pvt_release(struct igen6_pvt *pvt)
+{
+       iounmap(pvt->memss_pma_cr);
+       kfree(pvt);
+}
+
 static int igen6_pci_setup(struct pci_dev *pdev, u64 *mchbar)
 {
        union  {
@@ -1555,12 +1790,12 @@ static int igen6_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        edac_dbg(2, "\n");
 
-       igen6_pvt = kzalloc_obj(*igen6_pvt);
+       res_cfg = (struct res_config *)ent->driver_data;
+
+       igen6_pvt = igen6_pvt_setup(pdev);
        if (!igen6_pvt)
                return -ENOMEM;
 
-       res_cfg = (struct res_config *)ent->driver_data;
-
        rc = igen6_pci_setup(pdev, &mchbar);
        if (rc)
                goto fail;
@@ -1609,7 +1844,7 @@ fail3:
 fail2:
        igen6_unregister_mcis();
 fail:
-       kfree(igen6_pvt);
+       igen6_pvt_release(igen6_pvt);
        return rc;
 }
 
@@ -1624,7 +1859,7 @@ static void igen6_remove(struct pci_dev *pdev)
        flush_work(&ecclog_work);
        gen_pool_destroy(ecclog_pool);
        igen6_unregister_mcis();
-       kfree(igen6_pvt);
+       igen6_pvt_release(igen6_pvt);
 }
 
 static struct pci_driver igen6_driver = {
index deba46b3ee25d9ef226dde53c21635b41f1da972..e6b4e51130e5ff3612f89f19a3dda29a451e7963 100644 (file)
@@ -184,6 +184,7 @@ static inline char *mc_event_error_type(const unsigned int err_type)
  * @MEM_DDR5:          Unbuffered DDR5 RAM
  * @MEM_RDDR5:         Registered DDR5 RAM
  * @MEM_LRDDR5:                Load-Reduced DDR5 memory.
+ * @MEM_LPDDR5:                Low-Power DDR5 memory.
  * @MEM_NVDIMM:                Non-volatile RAM
  * @MEM_WIO2:          Wide I/O 2.
  * @MEM_HBM2:          High bandwidth Memory Gen 2.
@@ -216,6 +217,7 @@ enum mem_type {
        MEM_DDR5,
        MEM_RDDR5,
        MEM_LRDDR5,
+       MEM_LPDDR5,
        MEM_NVDIMM,
        MEM_WIO2,
        MEM_HBM2,
@@ -247,6 +249,7 @@ enum mem_type {
 #define MEM_FLAG_DDR5          BIT(MEM_DDR5)
 #define MEM_FLAG_RDDR5         BIT(MEM_RDDR5)
 #define MEM_FLAG_LRDDR5                BIT(MEM_LRDDR5)
+#define MEM_FLAG_LPDDR5                BIT(MEM_LPDDR5)
 #define MEM_FLAG_NVDIMM                BIT(MEM_NVDIMM)
 #define MEM_FLAG_WIO2          BIT(MEM_WIO2)
 #define MEM_FLAG_HBM2          BIT(MEM_HBM2)