Re: [PATCH v9 4/4] PCI: dwc: Support ECAM mechanism by enabling iATU 'CFG Shift Feature'
From: Krishna Chaitanya Chundru
Date: Fri Nov 28 2025 - 08:45:09 EST
On 11/28/2025 2:07 PM, Maciej W. Rozycki wrote:
On Fri, 28 Nov 2025, Krishna Chaitanya Chundru wrote:Hi Maciej, Can you try attached patch and let me know if that is helping you or not. - Krishna Chaitanya.
I'm not sure what you mean as to the parport driver; it's standard stuff:Hi Maciej, can you share us lspci -vvv o/p with working & non working case andDesignware databook r5.20a, sec 3.10.10.3 documents the 'CFG ShiftSo this broke a parallel port on my HiFive Unmatched machine (a SiFive
Feature'
of the internal Address Translation Unit (iATU). When this feature is
enabled, it shifts/maps the BDF contained in the bits [27:12] of the
target
address in MEM TLP to become BDF of the CFG TLP. This essentially
implements the Enhanced Configuration Address Mapping (ECAM) mechanism as
defined in PCIe r6.0, sec 7.2.2.
FU740-C000 based system), the driver no longer registers the device, no
/dev/parport0 anymore.
also can you point us parport driver. - Krishna Chaitanya.
$ zgrep PARPORT /proc/config.gz
CONFIG_PARPORT=y
CONFIG_PARPORT_PC=y
# CONFIG_PARPORT_SERIAL is not set
CONFIG_PARPORT_PC_FIFO=y
CONFIG_PARPORT_1284=y
# CONFIG_PATA_PARPORT is not set
# CONFIG_I2C_PARPORT is not set
# CONFIG_USB_SERIAL_MOS7715_PARPORT is not set
$
I've attached output from `lspci -xxxx' so that you can decode it yourself
however you need, though I fail to see anything standing out there.
If you can't figure out what's going on here, then I'll try to poke at
the driver to see what exactly it is that causes it to fail there, but I'm
a little constrained on the resources and completely unfamiliar with the
ECAM feature (and the lack of documentation for the DW IP does not help).
I have no slightest idea why it should cause a regression such as this,
it seems totally unrelated. Yet it's 100% reproducible. Could this be
because it's the only device in the system that actually uses PCI/e port
I/O?
# cat /proc/ioportsFrom ad002661c2e559ee3ec523b00e23948407968cd7 Mon Sep 17 00:00:00 2001
00000000-0000ffff : pcie@e00000000
00001000-00002fff : PCI Bus 0000:01
00001000-00002fff : PCI Bus 0000:02
00001000-00002fff : PCI Bus 0000:05
00001000-00002fff : PCI Bus 0000:06
00001000-00001fff : PCI Bus 0000:07
00001000-00001007 : 0000:07:00.0
00001000-00001002 : parport0
00001003-00001007 : parport0
00001008-0000100b : 0000:07:00.0
00001008-0000100a : parport0
00002000-00002fff : PCI Bus 0000:08
00002000-00002fff : PCI Bus 0000:09
00002000-000020ff : 0000:09:01.0
00002100-0000217f : 0000:09:02.0
#
(Hmm, indentation does not appear correct to me for buses below 0000:07.)
Maciej
From: Krishna Chaitanya Chundru <krishna.chundru@xxxxxxxxxxxxxxxx>
Date: Fri, 28 Nov 2025 16:44:17 +0530
Subject: [PATCH] PCI: qcom: Enable iATU mapping for memory & IO regions
Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@xxxxxxxxxxxxxxxx>
---
.../pci/controller/dwc/pcie-designware-host.c | 24 ++++++++++++++-----
drivers/pci/controller/dwc/pcie-designware.c | 3 +++
drivers/pci/controller/dwc/pcie-designware.h | 2 +-
3 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index e92513c5bda5..a60f1539fadc 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -36,6 +36,7 @@ static struct pci_ops dw_child_pcie_ops;
#define IS_256MB_ALIGNED(x) IS_ALIGNED(x, SZ_256M)
+static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp);
static const struct msi_parent_ops dw_pcie_msi_parent_ops = {
.required_flags = DW_PCIE_MSI_FLAGS_REQUIRED,
.supported_flags = DW_PCIE_MSI_FLAGS_SUPPORTED,
@@ -427,13 +428,17 @@ static int dw_pcie_config_ecam_iatu(struct dw_pcie_rp *pp)
bus = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS);
+ ret = dw_pcie_iatu_setup(pp);
+ if (ret)
+ return ret;
+
/*
* Root bus under the host bridge doesn't require any iATU configuration
* as DBI region will be used to access root bus config space.
* Immediate bus under Root Bus, needs type 0 iATU configuration and
* remaining buses need type 1 iATU configuration.
*/
- atu.index = 0;
+ atu.index = pp->ob_atu_index;
atu.type = PCIE_ATU_TYPE_CFG0;
atu.parent_bus_addr = pp->cfg0_base + SZ_1M;
/* 1MiB is to cover 1 (bus) * 32 (devices) * 8 (functions) */
@@ -443,19 +448,26 @@ static int dw_pcie_config_ecam_iatu(struct dw_pcie_rp *pp)
if (ret)
return ret;
+
bus_range_max = resource_size(bus->res);
if (bus_range_max < 2)
return 0;
+ pp->ob_atu_index++;
+
/* Configure remaining buses in type 1 iATU configuration */
- atu.index = 1;
+ atu.index = pp->ob_atu_index;
atu.type = PCIE_ATU_TYPE_CFG1;
atu.parent_bus_addr = pp->cfg0_base + SZ_2M;
atu.size = (SZ_1M * bus_range_max) - SZ_2M;
atu.ctrl2 = PCIE_ATU_CFG_SHIFT_MODE_ENABLE;
- return dw_pcie_prog_outbound_atu(pci, &atu);
+ ret = dw_pcie_prog_outbound_atu(pci, &atu);
+ if (!ret)
+ pp->ob_atu_index++;
+
+ return ret;
}
static int dw_pcie_create_ecam_window(struct dw_pcie_rp *pp, struct resource *res)
@@ -942,7 +954,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp)
dev_warn(pci->dev, "Ranges exceed outbound iATU size (%d)\n",
pci->num_ob_windows);
- pp->msg_atu_index = i;
+ pp->ob_atu_index = i;
i = 0;
resource_list_for_each_entry(entry, &pp->bridge->dma_ranges) {
@@ -1113,7 +1125,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
void __iomem *mem;
int ret;
- if (pci->num_ob_windows <= pci->pp.msg_atu_index)
+ if (pci->num_ob_windows <= pci->pp.ob_atu_index)
return -ENOSPC;
if (!pci->pp.msg_res)
@@ -1123,7 +1135,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci)
atu.routing = PCIE_MSG_TYPE_R_BC;
atu.type = PCIE_ATU_TYPE_MSG;
atu.size = resource_size(pci->pp.msg_res);
- atu.index = pci->pp.msg_atu_index;
+ atu.index = pci->pp.ob_atu_index;
atu.parent_bus_addr = pci->pp.msg_res->start - pci->parent_bus_offset;
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index c644216995f6..d27b469b417b 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -478,6 +478,9 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci,
limit_addr = parent_bus_addr + atu->size - 1;
+ if (atu->index > pci->num_ob_windows)
+ return -ENOSPC;
+
if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) ||
!IS_ALIGNED(parent_bus_addr, pci->region_align) ||
!IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) {
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index e995f692a1ec..69d0bd8b3c57 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -423,8 +423,8 @@ struct dw_pcie_rp {
struct pci_host_bridge *bridge;
raw_spinlock_t lock;
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
+ int ob_atu_index;
bool use_atu_msg;
- int msg_atu_index;
struct resource *msg_res;
bool use_linkup_irq;
struct pci_eq_presets presets;
--
2.34.1