[RFC PATCH v2 06/11] ras/amd/atl: Add Hygon UMC MCA to system address conversion support

From: Aichun Shi

Date: Wed May 27 2026 - 23:54:01 EST


Prepare hygon_convert_umc_mca_addr_to_sys_addr() to be registered by
amd_atl_register_decoder() in amd_atl_init() later.

- Add hygon/umc.c for Hygon-specific implementation similar to umc.c for
AMD.
- Add hygon_convert_umc_mca_addr_to_sys_addr() to call
hygon_norm_to_sys_addr() to do the address translation process.
- Use hygon_cpu_to_df_node() to map the CPU to a contiguous DF node
index; propagate -errno on failure.
- Build hygon/umc.c from the Makefile as an amd_atl object.

Signed-off-by: Aichun Shi <shiaichun@xxxxxxxxxxxxxx>
---
drivers/ras/amd/atl/Makefile | 1 +
drivers/ras/amd/atl/hygon/umc.c | 44 +++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 drivers/ras/amd/atl/hygon/umc.c

diff --git a/drivers/ras/amd/atl/Makefile b/drivers/ras/amd/atl/Makefile
index 0a42f2cbabc4..9d65e215b87a 100644
--- a/drivers/ras/amd/atl/Makefile
+++ b/drivers/ras/amd/atl/Makefile
@@ -20,6 +20,7 @@ amd_atl-y += hygon/dehash.o
amd_atl-y += hygon/denormalize.o
amd_atl-y += hygon/map.o
amd_atl-y += hygon/system.o
+amd_atl-y += hygon/umc.o

amd_atl-$(CONFIG_AMD_ATL_PRM) += prm.o

diff --git a/drivers/ras/amd/atl/hygon/umc.c b/drivers/ras/amd/atl/hygon/umc.c
new file mode 100644
index 000000000000..0f064dd22bcc
--- /dev/null
+++ b/drivers/ras/amd/atl/hygon/umc.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD Address Translation Library (for hygon)
+ *
+ * umc.c : Unified Memory Controller (UMC) topology helpers for Hygon
+ *
+ * Author: Aichun Shi <shiaichun@xxxxxxxxxxxxxx>
+ */
+
+#include "../internal.h"
+
+static int hygon_get_die_id(struct atl_err *err)
+{
+ return hygon_cpu_to_df_node(err->cpu);
+}
+
+#define HYGON_IPID_SUB_CHANNEL_MASK BIT(13)
+static u8 hygon_get_ipid_sub_channel(struct atl_err *err)
+{
+ return FIELD_GET(HYGON_IPID_SUB_CHANNEL_MASK, err->ipid);
+}
+
+#define HYGON_UMC_CHANNEL_NUM GENMASK(23, 20)
+static u8 hygon_get_coh_st_inst_id(struct atl_err *err)
+{
+ return FIELD_GET(HYGON_UMC_CHANNEL_NUM, err->ipid);
+}
+
+unsigned long hygon_convert_umc_mca_addr_to_sys_addr(struct atl_err *err)
+{
+ u8 socket_id = topology_physical_package_id(err->cpu);
+ u8 coh_st_inst_id = hygon_get_coh_st_inst_id(err);
+ int die_id = hygon_get_die_id(err);
+ u8 sub_channel = hygon_get_ipid_sub_channel(err);
+
+ if (die_id < 0)
+ return die_id;
+
+ pr_debug("socket_id=0x%x die_id=0x%x coh_st_inst_id=0x%x addr=0x%016llx",
+ socket_id, die_id, coh_st_inst_id, err->addr);
+
+ return hygon_norm_to_sys_addr(socket_id, die_id, coh_st_inst_id,
+ sub_channel, err->addr);
+}
--
2.47.3