[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250905101659.95700-2-devendra.verma@amd.com>
Date: Fri, 5 Sep 2025 15:46:58 +0530
From: Devendra K Verma <devendra.verma@....com>
To: <bhelgaas@...gle.com>, <mani@...nel.org>, <vkoul@...nel.org>
CC: <dmaengine@...r.kernel.org>, <linux-pci@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <michal.simek@....com>
Subject: [PATCH 1/2] dmaengine: dw-edma: Add AMD MDB Endpoint Support
AMD MDB PCIe endpoint support. For AMD specific support
added the following
- AMD supported PCIe Device IDs and Vendor ID (Xilinx).
- AMD MDB specific driver data
- AMD MDB specific VSEC capability to retrieve the device DDR
base address.
Signed-off-by: Devendra K Verma <devendra.verma@....com>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 83 +++++++++++++++++++++++++++++++++++++-
include/linux/pci_ids.h | 1 +
2 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 3371e0a7..749067b 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -18,10 +18,12 @@
#include "dw-edma-core.h"
#define DW_PCIE_VSEC_DMA_ID 0x6
+#define DW_PCIE_AMD_MDB_VSEC_ID 0x20
#define DW_PCIE_VSEC_DMA_BAR GENMASK(10, 8)
#define DW_PCIE_VSEC_DMA_MAP GENMASK(2, 0)
#define DW_PCIE_VSEC_DMA_WR_CH GENMASK(9, 0)
#define DW_PCIE_VSEC_DMA_RD_CH GENMASK(25, 16)
+#define DW_PCIE_AMD_MDB_INVALID_ADDR (~0ULL)
#define DW_BLOCK(a, b, c) \
{ \
@@ -50,6 +52,7 @@ struct dw_edma_pcie_data {
u8 irqs;
u16 wr_ch_cnt;
u16 rd_ch_cnt;
+ u64 phys_addr;
};
static const struct dw_edma_pcie_data snps_edda_data = {
@@ -90,6 +93,44 @@ struct dw_edma_pcie_data {
.rd_ch_cnt = 2,
};
+static const struct dw_edma_pcie_data amd_mdb_data = {
+ /* MDB registers location */
+ .rg.bar = BAR_0,
+ .rg.off = 0x00001000, /* 4 Kbytes */
+ .rg.sz = 0x00002000, /* 8 Kbytes */
+ /* MDB memory linked list location */
+ .ll_wr = {
+ /* Channel 0 - BAR 2, offset 0 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00000000, 0x00000800)
+ /* Channel 1 - BAR 2, offset 2 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00200000, 0x00000800)
+ },
+ .ll_rd = {
+ /* Channel 0 - BAR 2, offset 4 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00400000, 0x00000800)
+ /* Channel 1 - BAR 2, offset 6 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00600000, 0x00000800)
+ },
+ /* MDB memory data location */
+ .dt_wr = {
+ /* Channel 0 - BAR 2, offset 8 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00800000, 0x00000800)
+ /* Channel 1 - BAR 2, offset 9 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00900000, 0x00000800)
+ },
+ .dt_rd = {
+ /* Channel 0 - BAR 2, offset 10 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00a00000, 0x00000800)
+ /* Channel 1 - BAR 2, offset 11 Mbytes, size 2 Kbytes */
+ DW_BLOCK(BAR_2, 0x00b00000, 0x00000800)
+ },
+ /* Other */
+ .mf = EDMA_MF_HDMA_NATIVE,
+ .irqs = 1,
+ .wr_ch_cnt = 2,
+ .rd_ch_cnt = 2,
+};
+
static int dw_edma_pcie_irq_vector(struct device *dev, unsigned int nr)
{
return pci_irq_vector(to_pci_dev(dev), nr);
@@ -120,9 +161,14 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev,
u32 val, map;
u16 vsec;
u64 off;
+ u16 vendor;
- vsec = pci_find_vsec_capability(pdev, PCI_VENDOR_ID_SYNOPSYS,
- DW_PCIE_VSEC_DMA_ID);
+ vendor = pdev->vendor;
+ if (vendor != PCI_VENDOR_ID_SYNOPSYS &&
+ vendor != PCI_VENDOR_ID_XILINX)
+ return;
+
+ vsec = pci_find_vsec_capability(pdev, vendor, DW_PCIE_VSEC_DMA_ID);
if (!vsec)
return;
@@ -155,6 +201,27 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev,
off <<= 32;
off |= val;
pdata->rg.off = off;
+
+ /* AMD specific VSEC capability */
+ if (vendor != PCI_VENDOR_ID_XILINX)
+ return;
+
+ vsec = pci_find_vsec_capability(pdev, vendor,
+ DW_PCIE_AMD_MDB_VSEC_ID);
+ if (!vsec)
+ return;
+
+ pci_read_config_dword(pdev, vsec + PCI_VNDR_HEADER, &val);
+ if (PCI_VNDR_HEADER_ID(val) != 0x20 ||
+ PCI_VNDR_HEADER_REV(val) != 0x1)
+ return;
+
+ pci_read_config_dword(pdev, vsec + 0xc, &val);
+ off = val;
+ pci_read_config_dword(pdev, vsec + 0x8, &val);
+ off <<= 32;
+ off |= val;
+ pdata->phys_addr = off;
}
static int dw_edma_pcie_probe(struct pci_dev *pdev,
@@ -179,6 +246,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
}
memcpy(vsec_data, pdata, sizeof(struct dw_edma_pcie_data));
+ vsec_data->phys_addr = DW_PCIE_AMD_MDB_INVALID_ADDR;
/*
* Tries to find if exists a PCIe Vendor-Specific Extended Capability
@@ -186,6 +254,15 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
*/
dw_edma_pcie_get_vsec_dma_data(pdev, vsec_data);
+ if (pdev->vendor == PCI_VENDOR_ID_XILINX) {
+ /*
+ * There is no valid address found for the LL memory
+ * space on the device side.
+ */
+ if (vsec_data->phys_addr == DW_PCIE_AMD_MDB_INVALID_ADDR)
+ return -EINVAL;
+ }
+
/* Mapping PCI BAR regions */
mask = BIT(vsec_data->rg.bar);
for (i = 0; i < vsec_data->wr_ch_cnt; i++) {
@@ -367,6 +444,8 @@ static void dw_edma_pcie_remove(struct pci_dev *pdev)
static const struct pci_device_id dw_edma_pcie_id_table[] = {
{ PCI_DEVICE_DATA(SYNOPSYS, EDDA, &snps_edda_data) },
+ { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_AMD_MDB_B054),
+ (kernel_ulong_t)&amd_mdb_data },
{ }
};
MODULE_DEVICE_TABLE(pci, dw_edma_pcie_id_table);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 92ffc43..c15607d 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -636,6 +636,7 @@
#define PCI_DEVICE_ID_AMD_HUDSON2_SMBUS 0x780b
#define PCI_DEVICE_ID_AMD_HUDSON2_IDE 0x780c
#define PCI_DEVICE_ID_AMD_KERNCZ_SMBUS 0x790b
+#define PCI_DEVICE_ID_AMD_MDB_B054 0xb054
#define PCI_VENDOR_ID_TRIDENT 0x1023
#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000
--
1.8.3.1
Powered by blists - more mailing lists