accel/amdxdna: Add basic support for AIE4 devices

Add initial support for AIE4 devices (PCI device IDs 0x17F2 and 0x1B0B),
including:
  Device initialization
  Basic mailbox communication
  SR-IOV enablement

This lays the groundwork for full AIE4 support.

Co-developed-by: Hayden Laccabue <Hayden.Laccabue@amd.com>
Signed-off-by: Hayden Laccabue <Hayden.Laccabue@amd.com>
Signed-off-by: David Zhang <yidong.zhang@amd.com>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20260330163705.3153647-3-lizhi.hou@amd.com
This commit is contained in:
David Zhang 2026-03-30 09:37:01 -07:00 committed by Lizhi Hou
parent 5a55a5da1f
commit c02697cb93
16 changed files with 666 additions and 15 deletions

View File

@ -10,6 +10,8 @@ amdxdna-y := \
aie2_psp.o \
aie2_smu.o \
aie2_solver.o \
aie4_message.o \
aie4_pci.o \
amdxdna_ctx.o \
amdxdna_gem.o \
amdxdna_iommu.o \
@ -20,7 +22,10 @@ amdxdna-y := \
amdxdna_sysfs.o \
amdxdna_ubuf.o \
npu1_regs.o \
npu3_regs.o \
npu4_regs.o \
npu5_regs.o \
npu6_regs.o
amdxdna-$(CONFIG_PCI_IOV) += aie4_sriov.o
obj-$(CONFIG_DRM_ACCEL_AMDXDNA) = amdxdna.o

View File

@ -8,6 +8,9 @@
#include "amdxdna_pci_drv.h"
#include "amdxdna_mailbox.h"
#define AIE_INTERVAL 20000 /* us */
#define AIE_TIMEOUT 1000000 /* us */
struct aie_device {
struct amdxdna_dev *xdna;
struct mailbox_channel *mgmt_chann;

View File

@ -79,7 +79,7 @@ static int aie2_get_mgmt_chann_info(struct amdxdna_dev_hdl *ndev)
* is alive.
*/
ret = readx_poll_timeout(readl, SRAM_GET_ADDR(ndev, FW_ALIVE_OFF),
addr, addr, AIE2_INTERVAL, AIE2_TIMEOUT);
addr, addr, AIE_INTERVAL, AIE_TIMEOUT);
if (ret || !addr)
return -ETIME;

View File

@ -14,9 +14,6 @@
#include "aie2_msg_priv.h"
#include "amdxdna_mailbox.h"
#define AIE2_INTERVAL 20000 /* us */
#define AIE2_TIMEOUT 1000000 /* us */
/* Firmware determines device memory base address and size */
#define AIE2_DEVM_BASE 0x4000000
#define AIE2_DEVM_SIZE SZ_64M

View File

@ -44,7 +44,7 @@ static int aie2_smu_exec(struct amdxdna_dev_hdl *ndev, u32 reg_cmd,
writel(1, SMU_REG(ndev, SMU_INTR_REG));
ret = readx_poll_timeout(readl, SMU_REG(ndev, SMU_RESP_REG), resp,
resp, AIE2_INTERVAL, AIE2_TIMEOUT);
resp, AIE_INTERVAL, AIE_TIMEOUT);
if (ret) {
XDNA_ERR(ndev->aie.xdna, "smu cmd %d timed out", reg_cmd);
return ret;

View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2026, Advanced Micro Devices, Inc.
*/
#include <drm/amdxdna_accel.h>
#include <drm/drm_print.h>
#include <linux/mutex.h>
#include "aie.h"
#include "aie4_msg_priv.h"
#include "aie4_pci.h"
#include "amdxdna_mailbox.h"
#include "amdxdna_mailbox_helper.h"
#include "amdxdna_pci_drv.h"
int aie4_suspend_fw(struct amdxdna_dev_hdl *ndev)
{
DECLARE_AIE_MSG(aie4_msg_suspend, AIE4_MSG_OP_SUSPEND);
int ret;
ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
if (ret)
XDNA_ERR(ndev->aie.xdna, "Failed to suspend fw, ret %d", ret);
return ret;
}

View File

@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2026, Advanced Micro Devices, Inc.
*/
#ifndef _AIE4_MSG_PRIV_H_
#define _AIE4_MSG_PRIV_H_
#include <linux/types.h>
enum aie4_msg_opcode {
AIE4_MSG_OP_SUSPEND = 0x10003,
AIE4_MSG_OP_CREATE_VFS = 0x20001,
AIE4_MSG_OP_DESTROY_VFS = 0x20002,
};
enum aie4_msg_status {
AIE4_MSG_STATUS_SUCCESS = 0x0,
AIE4_MSG_STATUS_ERROR = 0x1,
AIE4_MSG_STATUS_NOTSUPP = 0x2,
MAX_AIE4_MSG_STATUS_CODE = 0x4,
};
struct aie4_msg_suspend_req {
__u32 rsvd;
} __packed;
struct aie4_msg_suspend_resp {
enum aie4_msg_status status;
} __packed;
struct aie4_msg_create_vfs_req {
__u32 vf_cnt;
} __packed;
struct aie4_msg_create_vfs_resp {
enum aie4_msg_status status;
} __packed;
struct aie4_msg_destroy_vfs_req {
__u32 rsvd;
} __packed;
struct aie4_msg_destroy_vfs_resp {
enum aie4_msg_status status;
} __packed;
#endif /* _AIE4_MSG_PRIV_H_ */

View File

@ -0,0 +1,364 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2026, Advanced Micro Devices, Inc.
*/
#include <drm/amdxdna_accel.h>
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include "aie4_pci.h"
#include "amdxdna_pci_drv.h"
#define NO_IOHUB 0
/*
* The management mailbox channel is allocated by firmware.
* The related register and ring buffer information is on SRAM BAR.
* This struct is the register layout.
*/
struct mailbox_info {
__u32 valid;
__u32 protocol_major;
__u32 protocol_minor;
__u32 x2i_tail_offset;
__u32 x2i_head_offset;
__u32 x2i_buffer_addr;
__u32 x2i_buffer_size;
__u32 i2x_tail_offset;
__u32 i2x_head_offset;
__u32 i2x_buffer_addr;
__u32 i2x_buffer_size;
__u32 i2x_msi_idx;
__u32 reserved[4];
};
static int aie4_fw_is_alive(struct amdxdna_dev *xdna)
{
const struct amdxdna_dev_priv *npriv = xdna->dev_info->dev_priv;
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
u32 __iomem *src;
u32 fw_is_valid;
int ret;
src = ndev->rbuf_base + npriv->mbox_info_off;
ret = readx_poll_timeout(readl, src + offsetof(struct mailbox_info, valid),
fw_is_valid, (fw_is_valid == 0x1),
AIE_INTERVAL, AIE_TIMEOUT);
if (ret)
XDNA_ERR(xdna, "fw_is_valid=%d after %d ms",
fw_is_valid, DIV_ROUND_CLOSEST(AIE_TIMEOUT, 1000000));
return ret;
}
static void aie4_read_mbox_info(struct amdxdna_dev *xdna,
struct mailbox_info *mbox_info)
{
const struct amdxdna_dev_priv *npriv = xdna->dev_info->dev_priv;
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
u32 *dst = (u32 *)mbox_info;
u32 __iomem *src;
int i;
src = ndev->rbuf_base + npriv->mbox_info_off;
for (i = 0; i < sizeof(*mbox_info) / sizeof(u32); i++)
dst[i] = readl(&src[i]);
}
static int aie4_mailbox_info(struct amdxdna_dev *xdna,
struct mailbox_info *mbox_info)
{
int ret;
ret = aie4_fw_is_alive(xdna);
if (ret)
return ret;
aie4_read_mbox_info(xdna, mbox_info);
ret = aie_check_protocol(&xdna->dev_handle->aie,
mbox_info->protocol_major,
mbox_info->protocol_minor);
if (ret)
XDNA_ERR(xdna, "mailbox major.minor %d.%d is not supported",
mbox_info->protocol_major, mbox_info->protocol_minor);
return ret;
}
static void aie4_mailbox_fini(struct amdxdna_dev_hdl *ndev)
{
struct amdxdna_dev *xdna = ndev->aie.xdna;
aie_destroy_chann(&ndev->aie, &ndev->aie.mgmt_chann);
drmm_kfree(&xdna->ddev, ndev->mbox);
ndev->mbox = NULL;
}
static int aie4_irq_init(struct amdxdna_dev *xdna)
{
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
int ret, nvec;
nvec = pci_msix_vec_count(pdev);
XDNA_DBG(xdna, "irq vectors:%d", nvec);
if (nvec <= 0) {
XDNA_ERR(xdna, "does not get number of interrupt vector");
return -EINVAL;
}
ret = pci_alloc_irq_vectors(pdev, nvec, nvec, PCI_IRQ_MSIX);
if (ret < 0) {
XDNA_ERR(xdna, "failed to alloc irq vector, ret: %d", ret);
return ret;
}
return 0;
}
static int aie4_mailbox_start(struct amdxdna_dev *xdna,
struct mailbox_info *mbi)
{
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
const struct amdxdna_dev_priv *npriv = xdna->dev_info->dev_priv;
struct xdna_mailbox_chann_res *i2x;
struct xdna_mailbox_chann_res *x2i;
int mgmt_mb_irq;
int ret;
struct xdna_mailbox_res mbox_res = {
.ringbuf_base = ndev->rbuf_base,
.ringbuf_size = pci_resource_len(pdev, npriv->mbox_rbuf_bar),
.mbox_base = ndev->mbox_base,
.mbox_size = pci_resource_len(pdev, npriv->mbox_bar),
.name = "xdna_aie4_mailbox",
};
i2x = &ndev->aie.mgmt_i2x;
x2i = &ndev->aie.mgmt_x2i;
x2i->mb_head_ptr_reg = mbi->x2i_head_offset;
x2i->mb_tail_ptr_reg = mbi->x2i_tail_offset;
x2i->rb_start_addr = mbi->x2i_buffer_addr;
x2i->rb_size = mbi->x2i_buffer_size;
i2x->rb_start_addr = mbi->i2x_buffer_addr;
i2x->rb_size = mbi->i2x_buffer_size;
i2x->mb_head_ptr_reg = mbi->i2x_head_offset;
i2x->mb_tail_ptr_reg = mbi->i2x_tail_offset;
ndev->aie.mgmt_chan_idx = mbi->i2x_msi_idx;
aie_dump_mgmt_chann_debug(&ndev->aie);
ndev->mbox = xdnam_mailbox_create(&xdna->ddev, &mbox_res);
if (!ndev->mbox) {
XDNA_ERR(xdna, "failed to create mailbox device");
return -ENODEV;
}
ndev->aie.mgmt_chann = xdna_mailbox_alloc_channel(ndev->mbox);
if (!ndev->aie.mgmt_chann) {
XDNA_ERR(xdna, "failed to alloc mailbox channel");
return -ENODEV;
}
mgmt_mb_irq = pci_irq_vector(pdev, ndev->aie.mgmt_chan_idx);
if (mgmt_mb_irq < 0) {
XDNA_ERR(xdna, "failed to alloc irq vector, return %d", mgmt_mb_irq);
ret = mgmt_mb_irq;
goto free_channel;
}
ret = xdna_mailbox_start_channel(ndev->aie.mgmt_chann,
&ndev->aie.mgmt_x2i,
&ndev->aie.mgmt_i2x,
NO_IOHUB,
mgmt_mb_irq);
if (ret) {
XDNA_ERR(xdna, "failed to start management mailbox channel");
ret = -EINVAL;
goto free_channel;
}
XDNA_DBG(xdna, "Mailbox management channel created");
return 0;
free_channel:
xdna_mailbox_free_channel(ndev->aie.mgmt_chann);
ndev->aie.mgmt_chann = NULL;
return ret;
}
static int aie4_mailbox_init(struct amdxdna_dev *xdna)
{
struct mailbox_info mbox_info;
int ret;
ret = aie4_mailbox_info(xdna, &mbox_info);
if (ret)
return ret;
return aie4_mailbox_start(xdna, &mbox_info);
}
static void aie4_fw_unload(struct amdxdna_dev_hdl *ndev)
{
/* TODO */
}
static int aie4_fw_load(struct amdxdna_dev_hdl *ndev)
{
/* TODO */
return 0;
}
static int aie4_hw_start(struct amdxdna_dev *xdna)
{
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
int ret;
ret = aie4_fw_load(ndev);
if (ret)
return ret;
ret = aie4_mailbox_init(xdna);
if (ret)
goto fw_unload;
return 0;
fw_unload:
aie4_fw_unload(ndev);
return ret;
}
static void aie4_mgmt_fw_fini(struct amdxdna_dev_hdl *ndev)
{
int ret;
/* No paired resume needed, fw is stateless */
ret = aie4_suspend_fw(ndev);
if (ret)
XDNA_ERR(ndev->aie.xdna, "suspend_fw failed, ret %d", ret);
else
XDNA_DBG(ndev->aie.xdna, "npu firmware suspended");
}
static void aie4_hw_stop(struct amdxdna_dev *xdna)
{
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
aie4_mgmt_fw_fini(ndev);
aie4_mailbox_fini(ndev);
aie4_fw_unload(ndev);
}
static int aie4_pcidev_init(struct amdxdna_dev_hdl *ndev)
{
struct amdxdna_dev *xdna = ndev->aie.xdna;
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
void __iomem *tbl[PCI_NUM_RESOURCES] = {0};
unsigned long bars = 0;
int ret, i;
/* Enable managed PCI device */
ret = pcim_enable_device(pdev);
if (ret) {
XDNA_ERR(xdna, "pcim enable device failed, ret %d", ret);
return ret;
}
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (ret) {
XDNA_ERR(xdna, "failed to set DMA mask to 64:%d", ret);
return ret;
}
set_bit(xdna->dev_info->mbox_bar, &bars);
set_bit(xdna->dev_info->sram_bar, &bars);
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
if (!test_bit(i, &bars))
continue;
tbl[i] = pcim_iomap(pdev, i, 0);
if (!tbl[i]) {
XDNA_ERR(xdna, "map bar %d failed", i);
return -ENOMEM;
}
}
ndev->mbox_base = tbl[xdna->dev_info->mbox_bar];
ndev->rbuf_base = tbl[xdna->dev_info->sram_bar];
pci_set_master(pdev);
ret = aie4_irq_init(xdna);
if (ret)
goto clear_master;
ret = aie4_hw_start(xdna);
if (ret)
goto clear_master;
return 0;
clear_master:
pci_clear_master(pdev);
return ret;
}
static void aie4_pcidev_fini(struct amdxdna_dev_hdl *ndev)
{
struct amdxdna_dev *xdna = ndev->aie.xdna;
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
aie4_hw_stop(xdna);
pci_clear_master(pdev);
}
static void aie4_fini(struct amdxdna_dev *xdna)
{
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
aie4_sriov_stop(ndev);
aie4_pcidev_fini(ndev);
}
static int aie4_init(struct amdxdna_dev *xdna)
{
struct amdxdna_dev_hdl *ndev;
int ret;
ndev = drmm_kzalloc(&xdna->ddev, sizeof(*ndev), GFP_KERNEL);
if (!ndev)
return -ENOMEM;
ndev->priv = xdna->dev_info->dev_priv;
ndev->aie.xdna = xdna;
xdna->dev_handle = ndev;
ret = aie4_pcidev_init(ndev);
if (ret) {
XDNA_ERR(xdna, "Setup PCI device failed, ret %d", ret);
return ret;
}
XDNA_DBG(xdna, "aie4 init finished");
return 0;
}
const struct amdxdna_dev_ops aie4_ops = {
.init = aie4_init,
.fini = aie4_fini,
.sriov_configure = aie4_sriov_configure,
};

View File

@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2026, Advanced Micro Devices, Inc.
*/
#ifndef _AIE4_PCI_H_
#define _AIE4_PCI_H_
#include <linux/device.h>
#include <linux/iopoll.h>
#include <linux/pci.h>
#include "aie.h"
#include "amdxdna_mailbox.h"
struct amdxdna_dev_priv {
u32 mbox_bar;
u32 mbox_rbuf_bar;
u64 mbox_info_off;
};
struct amdxdna_dev_hdl {
struct aie_device aie;
const struct amdxdna_dev_priv *priv;
void __iomem *mbox_base;
void __iomem *rbuf_base;
struct mailbox *mbox;
};
/* aie4_message.c */
int aie4_suspend_fw(struct amdxdna_dev_hdl *ndev);
/* aie4_sriov.c */
#if IS_ENABLED(CONFIG_PCI_IOV)
int aie4_sriov_configure(struct amdxdna_dev *xdna, int num_vfs);
int aie4_sriov_stop(struct amdxdna_dev_hdl *ndev);
#else
#define aie4_sriov_configure NULL
static inline int aie4_sriov_stop(struct amdxdna_dev_hdl *ndev)
{
return 0;
}
#endif
extern const struct amdxdna_dev_ops aie4_ops;
#endif /* _AIE4_PCI_H_ */

View File

@ -0,0 +1,88 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2026, Advanced Micro Devices, Inc.
*/
#include <drm/amdxdna_accel.h>
#include <drm/drm_print.h>
#include <linux/pci.h>
#include "aie.h"
#include "aie4_msg_priv.h"
#include "aie4_pci.h"
#include "amdxdna_mailbox.h"
#include "amdxdna_mailbox_helper.h"
#include "amdxdna_pci_drv.h"
static int aie4_destroy_vfs(struct amdxdna_dev_hdl *ndev)
{
DECLARE_AIE_MSG(aie4_msg_destroy_vfs, AIE4_MSG_OP_DESTROY_VFS);
int ret;
ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
if (ret)
XDNA_ERR(ndev->aie.xdna, "destroy vfs op failed: %d", ret);
return ret;
}
static int aie4_create_vfs(struct amdxdna_dev_hdl *ndev, int num_vfs)
{
DECLARE_AIE_MSG(aie4_msg_create_vfs, AIE4_MSG_OP_CREATE_VFS);
int ret;
req.vf_cnt = num_vfs;
ret = aie_send_mgmt_msg_wait(&ndev->aie, &msg);
if (ret)
XDNA_ERR(ndev->aie.xdna, "create vfs op failed: %d", ret);
return ret;
}
int aie4_sriov_stop(struct amdxdna_dev_hdl *ndev)
{
struct amdxdna_dev *xdna = ndev->aie.xdna;
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
int ret;
if (!pci_num_vf(pdev))
return 0;
ret = pci_vfs_assigned(pdev);
if (ret) {
XDNA_ERR(xdna, "VFs are still assigned to VMs");
return -EPERM;
}
pci_disable_sriov(pdev);
return aie4_destroy_vfs(ndev);
}
static int aie4_sriov_start(struct amdxdna_dev_hdl *ndev, int num_vfs)
{
struct amdxdna_dev *xdna = ndev->aie.xdna;
struct pci_dev *pdev = to_pci_dev(xdna->ddev.dev);
int ret;
ret = aie4_create_vfs(ndev, num_vfs);
if (ret)
return ret;
ret = pci_enable_sriov(pdev, num_vfs);
if (ret) {
XDNA_ERR(xdna, "configure VFs failed, ret: %d", ret);
aie4_destroy_vfs(ndev);
return ret;
}
return num_vfs;
}
int aie4_sriov_configure(struct amdxdna_dev *xdna, int num_vfs)
{
struct amdxdna_dev_hdl *ndev = xdna->dev_handle;
drm_WARN_ON(&xdna->ddev, !mutex_is_locked(&xdna->dev_lock));
return (num_vfs) ? aie4_sriov_start(ndev, num_vfs) : aie4_sriov_stop(ndev);
}

View File

@ -112,6 +112,18 @@ static u32 mailbox_reg_read(struct mailbox_channel *mb_chann, u32 mbox_reg)
return readl(ringbuf_addr);
}
static inline void mailbox_irq_acknowledge(struct mailbox_channel *mb_chann)
{
if (mb_chann->iohub_int_addr)
mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0);
}
static inline u32 mailbox_irq_status(struct mailbox_channel *mb_chann)
{
return (mb_chann->iohub_int_addr) ?
mailbox_reg_read(mb_chann, mb_chann->iohub_int_addr) : 0;
}
static inline void
mailbox_set_headptr(struct mailbox_channel *mb_chann, u32 headptr_val)
{
@ -199,7 +211,6 @@ mailbox_send_msg(struct mailbox_channel *mb_chann, struct mailbox_msg *mb_msg)
start_addr = mb_chann->res[CHAN_RES_X2I].rb_start_addr;
tmp_tail = tail + mb_msg->pkg_size;
check_again:
if (tail >= head && tmp_tail > ringbuf_size) {
write_addr = mb_chann->mb->res.ringbuf_base + start_addr + tail;
@ -357,7 +368,7 @@ static void mailbox_rx_worker(struct work_struct *rx_work)
}
again:
mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0);
mailbox_irq_acknowledge(mb_chann);
while (1) {
/*
@ -382,7 +393,7 @@ static void mailbox_rx_worker(struct work_struct *rx_work)
* the interrupt register to make sure there is not any new response
* before exiting.
*/
if (mailbox_reg_read(mb_chann, mb_chann->iohub_int_addr))
if (mailbox_irq_status(mb_chann))
goto again;
}
@ -520,7 +531,7 @@ xdna_mailbox_start_channel(struct mailbox_channel *mb_chann,
}
mb_chann->bad_state = false;
mailbox_reg_write(mb_chann, mb_chann->iohub_int_addr, 0);
mailbox_irq_acknowledge(mb_chann);
MB_DBG(mb_chann, "Mailbox channel started (irq: %d)", mb_chann->msix_irq);
return 0;

View File

@ -1,10 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2022-2024, Advanced Micro Devices, Inc.
* Copyright (C) 2022-2026, Advanced Micro Devices, Inc.
*/
#ifndef _AIE2_MAILBOX_H_
#define _AIE2_MAILBOX_H_
#ifndef _AIE_MAILBOX_H_
#define _AIE_MAILBOX_H_
struct mailbox;
struct mailbox_channel;
@ -124,4 +124,4 @@ void xdna_mailbox_stop_channel(struct mailbox_channel *mailbox_chann);
int xdna_mailbox_send_msg(struct mailbox_channel *mailbox_chann,
const struct xdna_mailbox_msg *msg, u64 tx_timeout);
#endif /* _AIE2_MAILBOX_ */
#endif /* _AIE_MAILBOX_ */

View File

@ -37,9 +37,10 @@ MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
* 0.6: Support preemption
* 0.7: Support getting power and utilization data
* 0.8: Support BO usage query
* 0.9: Add new device type AMDXDNA_DEV_TYPE_PF
*/
#define AMDXDNA_DRIVER_MAJOR 0
#define AMDXDNA_DRIVER_MINOR 8
#define AMDXDNA_DRIVER_MINOR 9
/*
* Bind the driver base on (vendor_id, device_id) pair and later use the
@ -49,6 +50,8 @@ MODULE_FIRMWARE("amdnpu/17f0_11/npu_7.sbin");
static const struct pci_device_id pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1502) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f0) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x17f2) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1B0B) },
{0}
};
@ -59,6 +62,8 @@ static const struct amdxdna_device_id amdxdna_ids[] = {
{ 0x17f0, 0x10, &dev_npu4_info },
{ 0x17f0, 0x11, &dev_npu5_info },
{ 0x17f0, 0x20, &dev_npu6_info },
{ 0x17f2, 0x10, &dev_npu3_pf_info },
{ 0x1B0B, 0x10, &dev_npu3_pf_info },
{0}
};
@ -365,12 +370,24 @@ static const struct dev_pm_ops amdxdna_pm_ops = {
RUNTIME_PM_OPS(amdxdna_pm_suspend, amdxdna_pm_resume, NULL)
};
static int amdxdna_sriov_configure(struct pci_dev *pdev, int num_vfs)
{
struct amdxdna_dev *xdna = pci_get_drvdata(pdev);
guard(mutex)(&xdna->dev_lock);
if (xdna->dev_info->ops->sriov_configure)
return xdna->dev_info->ops->sriov_configure(xdna, num_vfs);
return -ENOENT;
}
static struct pci_driver amdxdna_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = pci_ids,
.probe = amdxdna_probe,
.remove = amdxdna_remove,
.driver.pm = &amdxdna_pm_ops,
.sriov_configure = amdxdna_sriov_configure,
};
module_pci_driver(amdxdna_pci_driver);

View File

@ -55,6 +55,7 @@ struct amdxdna_dev_ops {
void (*fini)(struct amdxdna_dev *xdna);
int (*resume)(struct amdxdna_dev *xdna);
int (*suspend)(struct amdxdna_dev *xdna);
int (*sriov_configure)(struct amdxdna_dev *xdna, int num_vfs);
int (*hwctx_init)(struct amdxdna_hwctx *hwctx);
void (*hwctx_fini)(struct amdxdna_hwctx *hwctx);
int (*hwctx_config)(struct amdxdna_hwctx *hwctx, u32 type, u64 value, void *buf, u32 size);
@ -157,6 +158,7 @@ struct amdxdna_client {
/* Add device info below */
extern const struct amdxdna_dev_info dev_npu1_info;
extern const struct amdxdna_dev_info dev_npu3_pf_info;
extern const struct amdxdna_dev_info dev_npu4_info;
extern const struct amdxdna_dev_info dev_npu5_info;
extern const struct amdxdna_dev_info dev_npu6_info;

View File

@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2026, Advanced Micro Devices, Inc.
*/
#include <drm/amdxdna_accel.h>
#include <drm/drm_device.h>
#include "aie4_pci.h"
#include "amdxdna_pci_drv.h"
#define NPU3_MBOX_BAR 0
#define NPU3_MBOX_BUFFER_BAR 2
#define NPU3_MBOX_INFO_OFF 0x0
/* PCIe BAR Index for NPU3 */
#define NPU3_REG_BAR_INDEX 0
static const struct amdxdna_fw_feature_tbl npu3_fw_feature_table[] = {
{ .major = 5, .min_minor = 10 },
{ 0 }
};
static const struct amdxdna_dev_priv npu3_dev_priv = {
.mbox_bar = NPU3_MBOX_BAR,
.mbox_rbuf_bar = NPU3_MBOX_BUFFER_BAR,
.mbox_info_off = NPU3_MBOX_INFO_OFF,
};
const struct amdxdna_dev_info dev_npu3_pf_info = {
.mbox_bar = NPU3_MBOX_BAR,
.sram_bar = NPU3_MBOX_BUFFER_BAR,
.vbnv = "RyzenAI-npu3-pf",
.device_type = AMDXDNA_DEV_TYPE_PF,
.dev_priv = &npu3_dev_priv,
.fw_feature_tbl = npu3_fw_feature_table,
.ops = &aie4_ops,
};

View File

@ -29,7 +29,8 @@ extern "C" {
enum amdxdna_device_type {
AMDXDNA_DEV_TYPE_UNKNOWN = -1,
AMDXDNA_DEV_TYPE_KMQ,
AMDXDNA_DEV_TYPE_KMQ = 0,
AMDXDNA_DEV_TYPE_PF = 2,
};
enum amdxdna_drm_ioctl_id {