From: Gangliang Xie <[email protected]>

add uniras support for umc v13

Signed-off-by: Gangliang Xie <[email protected]>
Reviewed-by: Hawking Zhang <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/ras/core/Makefile        |   1 +
 drivers/gpu/drm/amd/ras/core/ras_umc.c       |   4 +
 drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.c | 221 +++++++++++++++++++
 drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.h |  70 ++++++
 4 files changed, 296 insertions(+)
 create mode 100644 drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.c
 create mode 100644 drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.h

diff --git a/drivers/gpu/drm/amd/ras/core/Makefile 
b/drivers/gpu/drm/amd/ras/core/Makefile
index fb16bacaef2fd..2c73d0405a489 100644
--- a/drivers/gpu/drm/amd/ras/core/Makefile
+++ b/drivers/gpu/drm/amd/ras/core/Makefile
@@ -30,6 +30,7 @@ RAS_CORE_FILES = core.o \
                        eeprom.o \
                        ras_umc.o \
                        ras_umc_v12_0.o \
+                       ras_umc_v13_0.o \
                        ras_umc_v15_0.o \
                        cmd.o \
                        ras_gfx.o \
diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc.c 
b/drivers/gpu/drm/amd/ras/core/ras_umc.c
index b3f30da19a78f..aaf98cbee619b 100644
--- a/drivers/gpu/drm/amd/ras/core/ras_umc.c
+++ b/drivers/gpu/drm/amd/ras/core/ras_umc.c
@@ -24,6 +24,7 @@
 #include "ras.h"
 #include "ras_umc.h"
 #include "ras_umc_v12_0.h"
+#include "ras_umc_v13_0.h"
 #include "ras_umc_v15_0.h"
 
 #define MAX_ECC_NUM_PER_RETIREMENT  16
@@ -80,6 +81,9 @@ static const struct ras_umc_ip_func *ras_umc_get_ip_func(
        case IP_VERSION(15, 0, 0):
                ras_umc->max_pages_per_row = 128;
                return &ras_umc_func_v15_0;
+       case IP_VERSION(13, 1, 0):
+               ras_umc->max_pages_per_row = 128;
+               return &ras_umc_func_v13_0;
        default:
                RAS_DEV_ERR(ras_core->dev,
                        "UMC ip version(0x%x) is not supported!\n", ip_version);
diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.c 
b/drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.c
new file mode 100644
index 0000000000000..7cb127c6cafdc
--- /dev/null
+++ b/drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include "ras.h"
+#include "ras_umc.h"
+#include "core_status.h"
+#include "ras_umc_v13_0.h"
+
+static void __get_nps_pa_flip_bits(struct ras_core_context *ras_core,
+                       enum umc_memory_partition_mode nps,
+                       struct umc_flip_bits *flip_bits)
+{
+
+}
+
+static uint64_t  __get_nps_pa_flip_mask(struct ras_core_context *ras_core,
+               enum umc_memory_partition_mode nps)
+{
+       struct umc_flip_bits flip_bits = {0};
+       uint64_t flip_mask = 0;
+       int i;
+
+       __get_nps_pa_flip_bits(ras_core, nps, &flip_bits);
+
+       for (i = 0; i < flip_bits.bit_num; i++)
+               flip_mask |= BIT_ULL(flip_bits.flip_bits_in_pa[i]);
+
+       return flip_mask;
+}
+
+static int lookup_bad_pages_in_a_row(struct ras_core_context *ras_core,
+               struct eeprom_umc_record *record, uint32_t nps,
+               uint64_t *pfns, uint32_t num,
+               uint64_t seq_no, bool dump)
+{
+       return 0;
+}
+
+static int umc_v13_convert_ma_to_pa(struct ras_core_context *ras_core,
+                       struct umc_mca_addr *addr_in, struct umc_phy_addr 
*addr_out,
+                       uint32_t nps)
+{
+
+       return 0;
+}
+
+static int convert_ma_to_pa(struct ras_core_context *ras_core,
+                       struct umc_mca_addr *addr_in, struct umc_phy_addr 
*addr_out,
+                       uint32_t nps)
+{
+       int ret;
+
+       ret = ras_umc_psp_translate_addr(ras_core,
+                               addr_in, addr_out, nps);
+       if (ret != -EOPNOTSUPP)
+               return ret;
+
+       if (ras_psp_check_supported_cmd(ras_core, RAS_TA_CMD_ID__QUERY_ADDRESS))
+               ret = ras_umc_ras_ta_translate_addr(ras_core,
+                               addr_in, addr_out, nps);
+       else
+               ret = umc_v13_convert_ma_to_pa(ras_core,
+                               addr_in, addr_out, nps);
+
+       return ret;
+}
+
+static int convert_bank_to_nps_addr(struct ras_core_context *ras_core,
+                       struct ras_bank_ecc *bank, struct umc_phy_addr 
*pa_addr, uint32_t nps)
+{
+       struct umc_mca_addr addr_in;
+       struct umc_phy_addr addr_out;
+       int ret;
+
+       memset(&addr_in, 0, sizeof(addr_in));
+       memset(&addr_out, 0, sizeof(addr_out));
+
+       addr_in.err_addr = ACA_ADDR_2_ERR_ADDR(bank->addr);
+       addr_in.ch_inst = ACA_IPID_2_UMC_CH(bank->ipid);
+       addr_in.umc_inst = ACA_IPID_2_UMC_INST(bank->ipid);
+       addr_in.node_inst = ACA_IPID_2_DIE_ID(bank->ipid);
+       addr_in.socket_id = ACA_IPID_2_SOCKET_ID(bank->ipid);
+       addr_in.mca_addr = bank->addr;
+       addr_in.ipid = bank->ipid;
+
+       ret = convert_ma_to_pa(ras_core, &addr_in, &addr_out, nps);
+       if (!ret) {
+               pa_addr->pa_flip_mask = addr_out.pa_flip_mask;
+               pa_addr->pa = addr_out.pa | pa_addr->pa_flip_mask;
+               pa_addr->channel_idx = addr_out.channel_idx;
+               pa_addr->bank = addr_out.bank;
+       }
+
+       return ret;
+}
+
+static int umc_v13_0_bank_to_eeprom_record(struct ras_core_context *ras_core,
+               struct ras_bank_ecc *bank, struct eeprom_umc_record *record)
+{
+       struct umc_phy_addr nps_addr;
+       int ret;
+
+       memset(&nps_addr, 0, sizeof(nps_addr));
+
+       ret = convert_bank_to_nps_addr(ras_core, bank,
+                       &nps_addr, bank->nps);
+       if (ret)
+               return ret;
+
+       ras_umc_fill_eeprom_record(ras_core,
+               ACA_ADDR_2_ERR_ADDR(bank->addr), 
ACA_IPID_2_UMC_INST(bank->ipid),
+               &nps_addr, bank->nps, record);
+
+       /* If the bank being converted already has a timestamp,
+        * then use the bank's timestamp.
+        */
+       if (bank->timestamp)
+               record->ts = bank->timestamp;
+
+       lookup_bad_pages_in_a_row(ras_core, record,
+               bank->nps, NULL, 0, bank->seq_no, true);
+
+       return 0;
+}
+
+static int convert_eeprom_record_to_nps_addr(struct ras_core_context *ras_core,
+       struct eeprom_umc_record *record, uint64_t *pa, uint64_t *pa_flip_mask, 
uint32_t nps)
+{
+       struct device_system_info dev_info = {0};
+       struct umc_mca_addr addr_in;
+       struct umc_phy_addr addr_out;
+       int ret;
+
+       memset(&addr_in, 0, sizeof(addr_in));
+       memset(&addr_out, 0, sizeof(addr_out));
+
+       ras_core_get_device_system_info(ras_core, &dev_info);
+
+       addr_in.err_addr = record->address;
+       addr_in.ch_inst = record->mem_channel;
+       addr_in.umc_inst = record->mcumc_id;
+       addr_in.node_inst = UMC_INV_AID_NODE;
+       addr_in.socket_id = dev_info.socket_id;
+
+       ret = convert_ma_to_pa(ras_core, &addr_in, &addr_out, nps);
+       if (ret)
+               return ret;
+
+       *pa_flip_mask = addr_out.pa_flip_mask;
+       *pa = addr_out.pa | addr_out.pa_flip_mask;
+
+       return 0;
+}
+
+static int umc_v13_0_eeprom_record_to_nps_record(struct ras_core_context 
*ras_core,
+                               struct eeprom_umc_record *record, uint32_t nps)
+{
+       uint64_t pa = 0, flip_mask = 0;
+       uint64_t row_pfn;
+       int ret = 0;
+
+       if (nps == EEPROM_RECORD_UMC_NPS_MODE(record)) {
+               record->cur_nps_pa_flip_mask = __get_nps_pa_flip_mask(ras_core, 
nps);
+               row_pfn = EEPROM_RECORD_UMC_ADDR_PFN(record);
+               record->cur_nps_retired_row_pfn =
+                       RAS_ADDR_TO_PFN(RAS_PFN_TO_ADDR(row_pfn) | 
record->cur_nps_pa_flip_mask);
+       } else {
+               ret = convert_eeprom_record_to_nps_addr(ras_core,
+                               record, &pa, &flip_mask, nps);
+               if (!ret) {
+                       record->cur_nps_retired_row_pfn = RAS_ADDR_TO_PFN(pa);
+                       record->cur_nps_pa_flip_mask = flip_mask;
+               }
+       }
+
+       record->cur_nps = nps;
+
+       return ret;
+}
+
+static int umc_v13_0_soc_pa_to_bank(struct ras_core_context *ras_core,
+                       uint64_t soc_pa,
+                       struct umc_bank_addr *bank_addr)
+{
+       return 0;
+}
+
+static int umc_v13_0_bank_to_soc_pa(struct ras_core_context *ras_core,
+                       struct umc_bank_addr bank_addr,
+                       uint64_t *soc_pa)
+{
+       return 0;
+}
+
+const struct ras_umc_ip_func ras_umc_func_v13_0 = {
+       .bank_to_eeprom_record = umc_v13_0_bank_to_eeprom_record,
+       .eeprom_record_to_nps_record = umc_v13_0_eeprom_record_to_nps_record,
+       .bank_to_soc_pa = umc_v13_0_bank_to_soc_pa,
+       .soc_pa_to_bank = umc_v13_0_soc_pa_to_bank,
+};
+
diff --git a/drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.h 
b/drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.h
new file mode 100644
index 0000000000000..35b2080473747
--- /dev/null
+++ b/drivers/gpu/drm/amd/ras/core/ras_umc_v13_0.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __RAS_UMC_V13_0_H__
+#define __RAS_UMC_V13_0_H__
+#include "ras.h"
+
+/* MCA_UMC_UMC0_MCUMC_ADDRT0 */
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr__SHIFT                0x0
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved__SHIFT                 0x38
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__ErrorAddr_MASK                  
0x00FFFFFFFFFFFFFFL
+#define MCA_UMC_UMC0_MCUMC_ADDRT0__Reserved_MASK                   
0xFF00000000000000L
+
+/* MCMP1_IPIDT0 */
+#define MCMP1_IPIDT0__InstanceIdLo__SHIFT                          0x0
+#define MCMP1_IPIDT0__HardwareID__SHIFT                            0x20
+#define MCMP1_IPIDT0__InstanceIdHi__SHIFT                          0x2c
+#define MCMP1_IPIDT0__McaType__SHIFT                               0x30
+
+#define MCMP1_IPIDT0__InstanceIdLo_MASK                            
0x00000000FFFFFFFFL
+#define MCMP1_IPIDT0__HardwareID_MASK                              
0x00000FFF00000000L
+#define MCMP1_IPIDT0__InstanceIdHi_MASK                            
0x0000F00000000000L
+#define MCMP1_IPIDT0__McaType_MASK                                 
0xFFFF000000000000L
+
+#define ACA_IPID_HI_2_UMC_AID(_ipid_hi) (((_ipid_hi) >> 2) & 0x3)
+#define ACA_IPID_LO_2_UMC_CH(_ipid_lo)  \
+       (((((_ipid_lo) >> 20) & 0x1) * 4) + (((_ipid_lo) >> 12) & 0xF))
+#define ACA_IPID_LO_2_UMC_INST(_ipid_lo) (((_ipid_lo) >> 21) & 0x7)
+
+#define ACA_IPID_2_DIE_ID(ipid)  ((REG_GET_FIELD(ipid, MCMP1_IPIDT0, 
InstanceIdHi) >> 2) & 0x03)
+#define ACA_IPID_2_UMC_CH(ipid) \
+       (ACA_IPID_LO_2_UMC_CH(REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdLo)))
+
+#define ACA_IPID_2_UMC_INST(ipid) \
+       (ACA_IPID_LO_2_UMC_INST(REG_GET_FIELD(ipid, MCMP1_IPIDT0, 
InstanceIdLo)))
+
+#define ACA_IPID_2_SOCKET_ID(ipid) \
+       (((REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdLo) & 0x1) << 2) | \
+        (REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdHi) & 0x03))
+
+#define ACA_ADDR_2_ERR_ADDR(addr) \
+       REG_GET_FIELD(addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr)
+
+/* invalid node instance value */
+#define UMC_INV_AID_NODE 0xffff
+
+extern const struct ras_umc_ip_func ras_umc_func_v13_0;
+
+#endif
+
-- 
2.55.0

Reply via email to