[PATCH V2] accel/amdxdna: Get device revision to derive VBNV string
From: Lizhi Hou
Date: Thu Apr 16 2026 - 15:02:04 EST
From: Max Zhen <max.zhen@xxxxxxx>
Add support for querying the device revision from firmware.
Use the returned revision to look up the VBNV string during device
initialization, and fall back to the default VBNV when the revision
query is not supported or no mapping is found.
This allows the driver to report the accurate VBNV for devices that
share the same vendor/device ID but differ by hardware revision.
Signed-off-by: Max Zhen <max.zhen@xxxxxxx>
[Lizhi: Revise amdxdna_vbnv_init()]
Signed-off-by: Lizhi Hou <lizhi.hou@xxxxxxx>
---
drivers/accel/amdxdna/aie.c | 30 +++++++++++++++++++++++++
drivers/accel/amdxdna/aie.h | 7 ++++++
drivers/accel/amdxdna/aie2_message.c | 25 +++++++++++++++++++++
drivers/accel/amdxdna/aie2_msg_priv.h | 23 +++++++++++++++++++
drivers/accel/amdxdna/aie2_pci.c | 17 ++++++++++++++
drivers/accel/amdxdna/aie2_pci.h | 3 +++
drivers/accel/amdxdna/aie4_pci.c | 1 +
drivers/accel/amdxdna/amdxdna_pci_drv.h | 6 ++++-
drivers/accel/amdxdna/amdxdna_sysfs.c | 5 ++++-
drivers/accel/amdxdna/npu1_regs.c | 2 +-
drivers/accel/amdxdna/npu3_regs.c | 2 +-
drivers/accel/amdxdna/npu4_regs.c | 16 ++++++++++++-
drivers/accel/amdxdna/npu5_regs.c | 3 ++-
drivers/accel/amdxdna/npu6_regs.c | 3 ++-
14 files changed, 136 insertions(+), 7 deletions(-)
diff --git a/drivers/accel/amdxdna/aie.c b/drivers/accel/amdxdna/aie.c
index 4b3d4493128e..66849ba9026a 100644
--- a/drivers/accel/amdxdna/aie.c
+++ b/drivers/accel/amdxdna/aie.c
@@ -87,3 +87,33 @@ int aie_check_protocol(struct aie_device *aie, u32 fw_major, u32 fw_minor)
return found ? 0 : -EOPNOTSUPP;
}
+
+static void amdxdna_update_vbnv(struct amdxdna_dev *xdna,
+ const struct amdxdna_rev_vbnv *tbl,
+ u32 rev)
+{
+ int i;
+
+ for (i = 0; tbl[i].vbnv; i++) {
+ if (tbl[i].revision == rev) {
+ xdna->vbnv = tbl[i].vbnv;
+ break;
+ }
+ }
+}
+
+void amdxdna_vbnv_init(struct amdxdna_dev *xdna)
+{
+ const struct amdxdna_dev_info *info = xdna->dev_info;
+ u32 rev;
+
+ xdna->vbnv = info->default_vbnv;
+
+ if (!info->ops->get_dev_revision || !info->rev_vbnv_tbl)
+ return;
+
+ if (info->ops->get_dev_revision(xdna, &rev))
+ return;
+
+ amdxdna_update_vbnv(xdna, info->rev_vbnv_tbl, rev);
+}
diff --git a/drivers/accel/amdxdna/aie.h b/drivers/accel/amdxdna/aie.h
index ba4c9ee21823..7a68b114f235 100644
--- a/drivers/accel/amdxdna/aie.h
+++ b/drivers/accel/amdxdna/aie.h
@@ -82,11 +82,18 @@ struct psp_config {
u32 notify_val;
};
+/* Device revision to VBNV string mapping table entry */
+struct amdxdna_rev_vbnv {
+ u32 revision;
+ const char *vbnv;
+};
+
/* aie.c */
void aie_dump_mgmt_chann_debug(struct aie_device *aie);
void aie_destroy_chann(struct aie_device *aie, struct mailbox_channel **chann);
int aie_send_mgmt_msg_wait(struct aie_device *aie, struct xdna_mailbox_msg *msg);
int aie_check_protocol(struct aie_device *aie, u32 fw_major, u32 fw_minor);
+void amdxdna_vbnv_init(struct amdxdna_dev *xdna);
/* aie_psp.c */
struct psp_device *aiem_psp_create(struct drm_device *ddev, struct psp_config *conf);
diff --git a/drivers/accel/amdxdna/aie2_message.c b/drivers/accel/amdxdna/aie2_message.c
index 976ad6281078..6e98af7b74db 100644
--- a/drivers/accel/amdxdna/aie2_message.c
+++ b/drivers/accel/amdxdna/aie2_message.c
@@ -1244,3 +1244,28 @@ int aie2_update_prop_time_quota(struct amdxdna_dev_hdl *ndev, u32 us)
}
return ret;
}
+
+int aie2_get_dev_revision(struct amdxdna_dev_hdl *ndev, enum aie2_dev_revision *rev)
+{
+ DECLARE_AIE_MSG(get_dev_revision, MSG_OP_GET_DEV_REVISION);
+ struct amdxdna_dev *xdna = ndev->aie.xdna;
+ int ret;
+
+ if (!AIE_FEATURE_ON(&ndev->aie, AIE2_GET_DEV_REVISION))
+ return -EOPNOTSUPP;
+
+ ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
+ if (ret)
+ return ret;
+
+ *rev = resp.rev;
+
+ if (*rev < AIE2_DEV_REVISION_STXA || *rev >= AIE2_DEV_REVISION_UNKN) {
+ XDNA_ERR(xdna, "Unknown device revision: %d (raw fuse: 0x%x)",
+ *rev, resp.raw_fuse_data);
+ return -EINVAL;
+ }
+
+ XDNA_DBG(xdna, "Device revision: %d (raw fuse: 0x%x)", *rev, resp.raw_fuse_data);
+ return 0;
+}
diff --git a/drivers/accel/amdxdna/aie2_msg_priv.h b/drivers/accel/amdxdna/aie2_msg_priv.h
index b10552c627ee..a41c9797e265 100644
--- a/drivers/accel/amdxdna/aie2_msg_priv.h
+++ b/drivers/accel/amdxdna/aie2_msg_priv.h
@@ -33,6 +33,7 @@ enum aie2_msg_opcode {
MSG_OP_REGISTER_ASYNC_EVENT_MSG = 0x10C,
MSG_OP_UPDATE_PROPERTY = 0x113,
MSG_OP_GET_APP_HEALTH = 0x114,
+ MSG_OP_GET_DEV_REVISION = 0x117,
MSG_OP_MAX_DRV_OPCODE,
MSG_OP_GET_PROTOCOL_VERSION = 0x301,
MSG_OP_MAX_OPCODE
@@ -519,4 +520,26 @@ struct update_property_resp {
enum aie2_msg_status status;
} __packed;
+enum aie2_dev_revision {
+ AIE2_DEV_REVISION_STXA = 1,
+ AIE2_DEV_REVISION_STXB,
+ AIE2_DEV_REVISION_KRK1,
+ AIE2_DEV_REVISION_KRK2,
+ AIE2_DEV_REVISION_HALO,
+ AIE2_DEV_REVISION_GPT1,
+ AIE2_DEV_REVISION_GPT2,
+ AIE2_DEV_REVISION_GPT3,
+ AIE2_DEV_REVISION_UNKN,
+};
+
+struct get_dev_revision_req {
+ __u32 place_holder;
+} __packed;
+
+struct get_dev_revision_resp {
+ enum aie2_msg_status status;
+ enum aie2_dev_revision rev;
+ __u32 raw_fuse_data;
+} __packed;
+
#endif /* _AIE2_MSG_PRIV_H_ */
diff --git a/drivers/accel/amdxdna/aie2_pci.c b/drivers/accel/amdxdna/aie2_pci.c
index afbe3f8f67ce..1d1fb012294a 100644
--- a/drivers/accel/amdxdna/aie2_pci.c
+++ b/drivers/accel/amdxdna/aie2_pci.c
@@ -608,6 +608,7 @@ static int aie2_init(struct amdxdna_dev *xdna)
release_firmware(fw);
aie2_msg_init(ndev);
+ amdxdna_vbnv_init(xdna);
amdxdna_pm_init(xdna);
return 0;
@@ -1255,6 +1256,21 @@ static int aie2_set_state(struct amdxdna_client *client,
return ret;
}
+static int aie2_get_dev_rev(struct amdxdna_dev *xdna, u32 *rev)
+{
+ struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
+ enum aie2_dev_revision aie2_rev;
+ int ret;
+
+ drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
+ ret = aie2_get_dev_revision(ndev, &aie2_rev);
+
+ if (!ret)
+ *rev = (u32)aie2_rev;
+
+ return ret;
+}
+
const struct amdxdna_dev_ops aie2_ops = {
.init = aie2_init,
.fini = aie2_fini,
@@ -1269,4 +1285,5 @@ const struct amdxdna_dev_ops aie2_ops = {
.cmd_submit = aie2_cmd_submit,
.hmm_invalidate = aie2_hmm_invalidate,
.get_array = aie2_get_array,
+ .get_dev_revision = aie2_get_dev_rev,
};
diff --git a/drivers/accel/amdxdna/aie2_pci.h b/drivers/accel/amdxdna/aie2_pci.h
index 69b53c7bcb86..c44616065058 100644
--- a/drivers/accel/amdxdna/aie2_pci.h
+++ b/drivers/accel/amdxdna/aie2_pci.h
@@ -223,6 +223,7 @@ enum aie2_fw_feature {
AIE2_TEMPORAL_ONLY,
AIE2_APP_HEALTH,
AIE2_UPDATE_PROPERTY,
+ AIE2_GET_DEV_REVISION,
AIE2_FEATURE_MAX
};
@@ -258,6 +259,7 @@ extern const struct dpm_clk_freq npu4_dpm_clk_table[];
extern const struct rt_config npu1_default_rt_cfg[];
extern const struct rt_config npu4_default_rt_cfg[];
extern const struct amdxdna_fw_feature_tbl npu4_fw_feature_table[];
+extern const struct amdxdna_rev_vbnv npu4_rev_vbnv_tbl[];
extern const struct aie2_hw_ops npu4_hw_ops;
/* aie2_pm.c */
@@ -286,6 +288,7 @@ int aie2_query_firmware_version(struct amdxdna_dev_hdl *ndev,
struct amdxdna_fw_ver *fw_ver);
int aie2_query_app_health(struct amdxdna_dev_hdl *ndev, u32 context_id,
struct app_health_report *report);
+int aie2_get_dev_revision(struct amdxdna_dev_hdl *ndev, enum aie2_dev_revision *rev);
int aie2_create_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx);
int aie2_destroy_context(struct amdxdna_dev_hdl *ndev, struct amdxdna_hwctx *hwctx);
int aie2_map_host_buf(struct amdxdna_dev_hdl *ndev, u32 context_id, u64 addr, u64 size);
diff --git a/drivers/accel/amdxdna/aie4_pci.c b/drivers/accel/amdxdna/aie4_pci.c
index f50e0bc566e4..87f80f804f91 100644
--- a/drivers/accel/amdxdna/aie4_pci.c
+++ b/drivers/accel/amdxdna/aie4_pci.c
@@ -471,6 +471,7 @@ static int aie4_init(struct amdxdna_dev *xdna)
return ret;
}
+ amdxdna_vbnv_init(xdna);
XDNA_DBG(xdna, "aie4 init finished");
return 0;
}
diff --git a/drivers/accel/amdxdna/amdxdna_pci_drv.h b/drivers/accel/amdxdna/amdxdna_pci_drv.h
index eabbf57f2b38..bdd0dc83f92e 100644
--- a/drivers/accel/amdxdna/amdxdna_pci_drv.h
+++ b/drivers/accel/amdxdna/amdxdna_pci_drv.h
@@ -65,6 +65,7 @@ struct amdxdna_dev_ops {
int (*get_aie_info)(struct amdxdna_client *client, struct amdxdna_drm_get_info *args);
int (*set_aie_state)(struct amdxdna_client *client, struct amdxdna_drm_set_state *args);
int (*get_array)(struct amdxdna_client *client, struct amdxdna_drm_get_array *args);
+ int (*get_dev_revision)(struct amdxdna_dev *xdna, u32 *rev);
};
struct amdxdna_fw_feature_tbl {
@@ -89,7 +90,8 @@ struct amdxdna_dev_info {
u32 dev_mem_buf_shift;
u64 dev_mem_base;
size_t dev_mem_size;
- char *vbnv;
+ const char *default_vbnv;
+ const struct amdxdna_rev_vbnv *rev_vbnv_tbl;
const struct amdxdna_dev_priv *dev_priv;
const struct amdxdna_fw_feature_tbl *fw_feature_tbl;
const struct amdxdna_dev_ops *ops;
@@ -117,6 +119,8 @@ struct amdxdna_dev {
struct iommu_group *group;
struct iommu_domain *domain;
struct iova_domain iovad;
+ /* Accurate board name queried from firmware, or default_vbnv as fallback */
+ const char *vbnv;
};
/*
diff --git a/drivers/accel/amdxdna/amdxdna_sysfs.c b/drivers/accel/amdxdna/amdxdna_sysfs.c
index f27e4ee960a0..d9e359ee8182 100644
--- a/drivers/accel/amdxdna/amdxdna_sysfs.c
+++ b/drivers/accel/amdxdna/amdxdna_sysfs.c
@@ -17,7 +17,10 @@ static ssize_t vbnv_show(struct device *dev, struct device_attribute *attr, char
{
struct amdxdna_dev *xdna = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", xdna->dev_info->vbnv);
+ if (!xdna->vbnv)
+ return sprintf(buf, "\n");
+
+ return sprintf(buf, "%s\n", xdna->vbnv);
}
static DEVICE_ATTR_RO(vbnv);
diff --git a/drivers/accel/amdxdna/npu1_regs.c b/drivers/accel/amdxdna/npu1_regs.c
index f1141a65e64d..d7e50c6b06ef 100644
--- a/drivers/accel/amdxdna/npu1_regs.c
+++ b/drivers/accel/amdxdna/npu1_regs.c
@@ -137,7 +137,7 @@ const struct amdxdna_dev_info dev_npu1_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
- .vbnv = "RyzenAI-npu1",
+ .default_vbnv = "RyzenAI-npu1",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
.dev_priv = &npu1_dev_priv,
.fw_feature_tbl = npu1_fw_feature_table,
diff --git a/drivers/accel/amdxdna/npu3_regs.c b/drivers/accel/amdxdna/npu3_regs.c
index 5a0bbc916094..acece0faddf2 100644
--- a/drivers/accel/amdxdna/npu3_regs.c
+++ b/drivers/accel/amdxdna/npu3_regs.c
@@ -69,7 +69,7 @@ const struct amdxdna_dev_info dev_npu3_pf_info = {
.sram_bar = NPU3_MBOX_BUFFER_BAR,
.psp_bar = NPU3_PSP_BAR_INDEX,
.smu_bar = NPU3_SMU_BAR_INDEX,
- .vbnv = "RyzenAI-npu3-pf",
+ .default_vbnv = "RyzenAI-npu3-pf",
.device_type = AMDXDNA_DEV_TYPE_PF,
.dev_priv = &npu3_dev_priv,
.fw_feature_tbl = npu3_fw_feature_table,
diff --git a/drivers/accel/amdxdna/npu4_regs.c b/drivers/accel/amdxdna/npu4_regs.c
index 6ebf75ad5fb4..935999ced70f 100644
--- a/drivers/accel/amdxdna/npu4_regs.c
+++ b/drivers/accel/amdxdna/npu4_regs.c
@@ -98,6 +98,7 @@ const struct amdxdna_fw_feature_tbl npu4_fw_feature_table[] = {
{ .features = BIT_U64(AIE2_NPU_COMMAND), .major = 6, .min_minor = 15 },
{ .features = BIT_U64(AIE2_UPDATE_PROPERTY), .major = 6, .min_minor = 15 },
{ .features = BIT_U64(AIE2_APP_HEALTH), .major = 6, .min_minor = 18 },
+ { .features = BIT_U64(AIE2_GET_DEV_REVISION), .major = 6, .min_minor = 24 },
{ .features = AIE2_ALL_FEATURES, .major = 7 },
{ 0 }
};
@@ -142,6 +143,18 @@ const struct aie2_hw_ops npu4_hw_ops = {
.update_counters = npu4_update_counters,
};
+const struct amdxdna_rev_vbnv npu4_rev_vbnv_tbl[] = {
+ { AIE2_DEV_REVISION_STXA, "NPU Strix" },
+ { AIE2_DEV_REVISION_STXB, "NPU Strix" },
+ { AIE2_DEV_REVISION_KRK1, "NPU Krackan 1" },
+ { AIE2_DEV_REVISION_KRK2, "NPU Krackan 2" },
+ { AIE2_DEV_REVISION_HALO, "NPU Strix Halo" },
+ { AIE2_DEV_REVISION_GPT1, "NPU Gorgon Point 1" },
+ { AIE2_DEV_REVISION_GPT2, "NPU Gorgon Point 2" },
+ { AIE2_DEV_REVISION_GPT3, "NPU Gorgon Point 3" },
+ { 0 }
+};
+
static const struct amdxdna_dev_priv npu4_dev_priv = {
.fw_path = "amdnpu/17f0_10/",
.rt_config = npu4_default_rt_cfg,
@@ -185,8 +198,9 @@ const struct amdxdna_dev_info dev_npu4_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
- .vbnv = "RyzenAI-npu4",
+ .default_vbnv = "RyzenAI-npu4",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
+ .rev_vbnv_tbl = npu4_rev_vbnv_tbl,
.dev_priv = &npu4_dev_priv,
.fw_feature_tbl = npu4_fw_feature_table,
.ops = &aie2_ops, /* NPU4 can share NPU1's callback */
diff --git a/drivers/accel/amdxdna/npu5_regs.c b/drivers/accel/amdxdna/npu5_regs.c
index 6d4596b9e61e..795bd1996845 100644
--- a/drivers/accel/amdxdna/npu5_regs.c
+++ b/drivers/accel/amdxdna/npu5_regs.c
@@ -105,8 +105,9 @@ const struct amdxdna_dev_info dev_npu5_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
- .vbnv = "RyzenAI-npu5",
+ .default_vbnv = "RyzenAI-npu5",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
+ .rev_vbnv_tbl = npu4_rev_vbnv_tbl,
.dev_priv = &npu5_dev_priv,
.fw_feature_tbl = npu4_fw_feature_table,
.ops = &aie2_ops,
diff --git a/drivers/accel/amdxdna/npu6_regs.c b/drivers/accel/amdxdna/npu6_regs.c
index 76181345b6d1..3125d1ce45ab 100644
--- a/drivers/accel/amdxdna/npu6_regs.c
+++ b/drivers/accel/amdxdna/npu6_regs.c
@@ -106,8 +106,9 @@ const struct amdxdna_dev_info dev_npu6_info = {
.dev_mem_buf_shift = 15, /* 32 KiB aligned */
.dev_mem_base = AIE2_DEVM_BASE,
.dev_mem_size = AIE2_DEVM_SIZE,
- .vbnv = "RyzenAI-npu6",
+ .default_vbnv = "RyzenAI-npu6",
.device_type = AMDXDNA_DEV_TYPE_KMQ,
+ .rev_vbnv_tbl = npu4_rev_vbnv_tbl,
.dev_priv = &npu6_dev_priv,
.fw_feature_tbl = npu4_fw_feature_table,
.ops = &aie2_ops,
--
2.34.1