From nobody Thu Oct 2 03:30:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA0532DCF44; Tue, 23 Sep 2025 11:27:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626826; cv=none; b=ZwgUnIflUvVEZRlsaiIk330KExrNYgy/5gZP2lffzJa8h+AG1R2qFEh99W3IeqZC2z3MfBlNIRMQrfQ3nlwEfdvUmJ0jSN8VLb51CGMDrUQug60BynUL68QykvfI/he8eQNnE+rMwfVEC90GZKjOpo9JXGzRGkLtq5RjWOCCtsA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626826; c=relaxed/simple; bh=QK89HfzaIRfYko6DvW1egCZ032E8BKz9tQqphqpwaUI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dLjrXePIWz8Lcpo3U5vKcC1FtVyiQlS5aFwrf0vhsP2d1enzh3buu5vAFVw9Niz98HbI56og0YTdKV6KaInkIlfxhrvq5bhuOFZys80QX2Qi5VfDxi1YefvDdGdkVm/XEkSfvovHVAlhdAzuvMlgngS3GwsCh5k7wQT1p8n6VEU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=a/Q8EXrA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="a/Q8EXrA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ECC9DC4CEF5; Tue, 23 Sep 2025 11:26:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758626825; bh=QK89HfzaIRfYko6DvW1egCZ032E8BKz9tQqphqpwaUI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=a/Q8EXrAEidQspdMqpGC8PqYv/m5aea0jlJN6rx1o5k5g+TP+5bSX/gkJ/3qQCz7U icoXWuPsIe4/cTL9z5vn7x9Y8wFZRjaLvI5wkEaK/IO5/iuzpiWHSLTOst+ph6hH0y nOsWXb/FkYXwai+5oF4Q2zywDJhoIDCNSq8MA7Hm5hi5ZD7UF2OOkFdBKBAueDhQe6 22/3dCHLv10zX9rlShxUPwWW21pVtyLiwGVpJQKjcgKURZlESxCe5ox5awjYw967mC buHRFFJpMc/KXkEtXd80VHgXnWdcL3GSULzZmGDhIEk2FSaBoHWLbsqdcmAhU8V6e6 m+WLmeR8Y41JQ== From: Manivannan Sadhasivam Date: Tue, 23 Sep 2025 16:56:51 +0530 Subject: [PATCH v10 1/4] PCI: dwc: Add support for ELBI resource mapping Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250923-controller-dwc-ecam-v10-1-e84390ba75fa@kernel.org> References: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> In-Reply-To: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> To: Jingoo Han , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Rob Herring , Bjorn Helgaas , Krzysztof Kozlowski , Alim Akhtar , Jonathan Chocron Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Krishna Chaitanya Chundru , Manivannan Sadhasivam , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=12565; i=mani@kernel.org; h=from:subject:message-id; bh=DKhRz+a4KIXGMj2kY1iE857MbisCPu8GCsn4LJxBkdg=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBo0oP+5tpKs3wwbzXBA8VwzTE25IfQPF/iFCtoz wTUZIxePF+JATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaNKD/gAKCRBVnxHm/pHO 9bNUB/4vLdWiyCS28E0FrCmaSzsDtiSMPpdlNmdrGGis3/vNZEnv5cXH7m+2cywa4Zcv32uCArY sytJFwa+YdtlRt8w+nUcn64OIHilRHkLFeH8KJDnBnZY1qQ3HUuAns46dTUbDeYwhuIomiwWl/d F6n8LRvXzKmbWIH5U0ayAv8NpsCXQbJvA0sxAmw6giWLuapDGoh9Bva5oLQZAMimq0omqrnUNIy Kn7Ehj+KYCDoPowwH/JsqwnJKU43wK2aci3WrETTkSeuJAq9JFsde2JnUATT9UV0MsCYBkfFmYN QX6TD/XAxDsWNkG1zEvZ/5yiU+Dy6TN3FG5w67oKOBrWdv/q X-Developer-Key: i=mani@kernel.org; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 From: Krishna Chaitanya Chundru External Local Bus Interface (ELBI) is an optional register space for all DWC IPs containing the vendor specific registers. There is no need for the vendor glue drivers to fetch and map the ELBI region separately. Hence, optionally fetch and map the resource from DT in the DWC core. This also warrants dropping the corresponding code from glue drivers. Hence, drop the ELBI resource fetch and map logic from glue drivers and convert them to use 'dw_pci::elbi_base'. Note that the pcie-qcom-ep driver used devm_pci_remap_cfg_resource() to map the ELBI resource previously. But it was a mistake since devm_pci_remap_cfg_resource() should only be used for mapping the PCIe config space region as it maps the region as Non-Posted. As ELBI is used to hold vendor specific registers, there is no need to map the region as Non-Posted. With this conversion, the region will get mapped as normal MMIO memory. Suggested-by: Manivannan Sadhasivam Signed-off-by: Krishna Chaitanya Chundru [mani: removed elbi override, converted glue drivers and reworded descripti= on] Signed-off-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pci-exynos.c | 62 ++++++++++++++----------= ---- drivers/pci/controller/dwc/pcie-designware.c | 8 ++++ drivers/pci/controller/dwc/pcie-designware.h | 1 + drivers/pci/controller/dwc/pcie-qcom-ep.c | 15 ++----- drivers/pci/controller/dwc/pcie-qcom.c | 16 ++++--- 5 files changed, 50 insertions(+), 52 deletions(-) diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controll= er/dwc/pci-exynos.c index 1f0e98d07109353e7321667e98ead2695151184c..0bb7d4f5d7840eaed75b2ba0884= f045e4d1c6d2f 100644 --- a/drivers/pci/controller/dwc/pci-exynos.c +++ b/drivers/pci/controller/dwc/pci-exynos.c @@ -53,7 +53,6 @@ =20 struct exynos_pcie { struct dw_pcie pci; - void __iomem *elbi_base; struct clk_bulk_data *clks; struct phy *phy; struct regulator_bulk_data supplies[2]; @@ -71,73 +70,78 @@ static u32 exynos_pcie_readl(void __iomem *base, u32 re= g) =20 static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *ep, bool o= n) { + struct dw_pcie *pci =3D &ep->pci; u32 val; =20 - val =3D exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_AWMISC); + val =3D exynos_pcie_readl(pci->elbi_base, PCIE_ELBI_SLV_AWMISC); if (on) val |=3D PCIE_ELBI_SLV_DBI_ENABLE; else val &=3D ~PCIE_ELBI_SLV_DBI_ENABLE; - exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_AWMISC); + exynos_pcie_writel(pci->elbi_base, val, PCIE_ELBI_SLV_AWMISC); } =20 static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *ep, bool o= n) { + struct dw_pcie *pci =3D &ep->pci; u32 val; =20 - val =3D exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_SLV_ARMISC); + val =3D exynos_pcie_readl(pci->elbi_base, PCIE_ELBI_SLV_ARMISC); if (on) val |=3D PCIE_ELBI_SLV_DBI_ENABLE; else val &=3D ~PCIE_ELBI_SLV_DBI_ENABLE; - exynos_pcie_writel(ep->elbi_base, val, PCIE_ELBI_SLV_ARMISC); + exynos_pcie_writel(pci->elbi_base, val, PCIE_ELBI_SLV_ARMISC); } =20 static void exynos_pcie_assert_core_reset(struct exynos_pcie *ep) { + struct dw_pcie *pci =3D &ep->pci; u32 val; =20 - val =3D exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET); + val =3D exynos_pcie_readl(pci->elbi_base, PCIE_CORE_RESET); val &=3D ~PCIE_CORE_RESET_ENABLE; - exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET); - exynos_pcie_writel(ep->elbi_base, 0, PCIE_STICKY_RESET); - exynos_pcie_writel(ep->elbi_base, 0, PCIE_NONSTICKY_RESET); + exynos_pcie_writel(pci->elbi_base, val, PCIE_CORE_RESET); + exynos_pcie_writel(pci->elbi_base, 0, PCIE_STICKY_RESET); + exynos_pcie_writel(pci->elbi_base, 0, PCIE_NONSTICKY_RESET); } =20 static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep) { + struct dw_pcie *pci =3D &ep->pci; u32 val; =20 - val =3D exynos_pcie_readl(ep->elbi_base, PCIE_CORE_RESET); + val =3D exynos_pcie_readl(pci->elbi_base, PCIE_CORE_RESET); val |=3D PCIE_CORE_RESET_ENABLE; =20 - exynos_pcie_writel(ep->elbi_base, val, PCIE_CORE_RESET); - exynos_pcie_writel(ep->elbi_base, 1, PCIE_STICKY_RESET); - exynos_pcie_writel(ep->elbi_base, 1, PCIE_NONSTICKY_RESET); - exynos_pcie_writel(ep->elbi_base, 1, PCIE_APP_INIT_RESET); - exynos_pcie_writel(ep->elbi_base, 0, PCIE_APP_INIT_RESET); + exynos_pcie_writel(pci->elbi_base, val, PCIE_CORE_RESET); + exynos_pcie_writel(pci->elbi_base, 1, PCIE_STICKY_RESET); + exynos_pcie_writel(pci->elbi_base, 1, PCIE_NONSTICKY_RESET); + exynos_pcie_writel(pci->elbi_base, 1, PCIE_APP_INIT_RESET); + exynos_pcie_writel(pci->elbi_base, 0, PCIE_APP_INIT_RESET); } =20 static int exynos_pcie_start_link(struct dw_pcie *pci) { - struct exynos_pcie *ep =3D to_exynos_pcie(pci); u32 val; =20 - val =3D exynos_pcie_readl(ep->elbi_base, PCIE_SW_WAKE); + val =3D exynos_pcie_readl(pci->elbi_base, PCIE_SW_WAKE); val &=3D ~PCIE_BUS_EN; - exynos_pcie_writel(ep->elbi_base, val, PCIE_SW_WAKE); + exynos_pcie_writel(pci->elbi_base, val, PCIE_SW_WAKE); =20 /* assert LTSSM enable */ - exynos_pcie_writel(ep->elbi_base, PCIE_ELBI_LTSSM_ENABLE, + exynos_pcie_writel(pci->elbi_base, PCIE_ELBI_LTSSM_ENABLE, PCIE_APP_LTSSM_ENABLE); return 0; } =20 static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *ep) { - u32 val =3D exynos_pcie_readl(ep->elbi_base, PCIE_IRQ_PULSE); + struct dw_pcie *pci =3D &ep->pci; =20 - exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_PULSE); + u32 val =3D exynos_pcie_readl(pci->elbi_base, PCIE_IRQ_PULSE); + + exynos_pcie_writel(pci->elbi_base, val, PCIE_IRQ_PULSE); } =20 static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) @@ -150,12 +154,14 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, v= oid *arg) =20 static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *ep) { + struct dw_pcie *pci =3D &ep->pci; + u32 val =3D IRQ_INTA_ASSERT | IRQ_INTB_ASSERT | IRQ_INTC_ASSERT | IRQ_INTD_ASSERT; =20 - exynos_pcie_writel(ep->elbi_base, val, PCIE_IRQ_EN_PULSE); - exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_LEVEL); - exynos_pcie_writel(ep->elbi_base, 0, PCIE_IRQ_EN_SPECIAL); + exynos_pcie_writel(pci->elbi_base, val, PCIE_IRQ_EN_PULSE); + exynos_pcie_writel(pci->elbi_base, 0, PCIE_IRQ_EN_LEVEL); + exynos_pcie_writel(pci->elbi_base, 0, PCIE_IRQ_EN_SPECIAL); } =20 static u32 exynos_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, @@ -211,8 +217,7 @@ static struct pci_ops exynos_pci_ops =3D { =20 static bool exynos_pcie_link_up(struct dw_pcie *pci) { - struct exynos_pcie *ep =3D to_exynos_pcie(pci); - u32 val =3D exynos_pcie_readl(ep->elbi_base, PCIE_ELBI_RDLH_LINKUP); + u32 val =3D exynos_pcie_readl(pci->elbi_base, PCIE_ELBI_RDLH_LINKUP); =20 return val & PCIE_ELBI_XMLH_LINKUP; } @@ -295,11 +300,6 @@ static int exynos_pcie_probe(struct platform_device *p= dev) if (IS_ERR(ep->phy)) return PTR_ERR(ep->phy); =20 - /* External Local Bus interface (ELBI) registers */ - ep->elbi_base =3D devm_platform_ioremap_resource_byname(pdev, "elbi"); - if (IS_ERR(ep->elbi_base)) - return PTR_ERR(ep->elbi_base); - ret =3D devm_clk_bulk_get_all_enabled(dev, &ep->clks); if (ret < 0) return ret; diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/con= troller/dwc/pcie-designware.c index 89aad5a08928cc29870ab258d33bee9ff8f83143..93da8a26c9313dfdd6b269a90bb= fb017aab2abe7 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -167,6 +167,14 @@ int dw_pcie_get_resources(struct dw_pcie *pci) } } =20 + /* ELBI is an optional resource */ + res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); + if (res) { + pci->elbi_base =3D devm_ioremap_resource(pci->dev, res); + if (IS_ERR(pci->elbi_base)) + return PTR_ERR(pci->elbi_base); + } + /* LLDD is supposed to manually switch the clocks and resets state */ if (dw_pcie_cap_is(pci, REQ_RES)) { ret =3D dw_pcie_get_clocks(pci); diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/con= troller/dwc/pcie-designware.h index 2418214730e4a2d065651f177bb64530b5d4f88b..9eb3c4c762ddca7d6faff3a98a5= 4b37d7cd9f11b 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -491,6 +491,7 @@ struct dw_pcie { resource_size_t dbi_phys_addr; void __iomem *dbi_base2; void __iomem *atu_base; + void __iomem *elbi_base; resource_size_t atu_phys_addr; size_t atu_size; resource_size_t parent_bus_offset; diff --git a/drivers/pci/controller/dwc/pcie-qcom-ep.c b/drivers/pci/contro= ller/dwc/pcie-qcom-ep.c index aaf060bf39d40b6927e190b0aba5a86dcd320d0d..d7a7e278f6821dc7976f9698260= 7564fb2f42169 100644 --- a/drivers/pci/controller/dwc/pcie-qcom-ep.c +++ b/drivers/pci/controller/dwc/pcie-qcom-ep.c @@ -179,7 +179,6 @@ struct qcom_pcie_ep_cfg { * struct qcom_pcie_ep - Qualcomm PCIe Endpoint Controller * @pci: Designware PCIe controller struct * @parf: Qualcomm PCIe specific PARF register base - * @elbi: Designware PCIe specific ELBI register base * @mmio: MMIO register base * @perst_map: PERST regmap * @mmio_res: MMIO region resource @@ -202,7 +201,6 @@ struct qcom_pcie_ep { struct dw_pcie pci; =20 void __iomem *parf; - void __iomem *elbi; void __iomem *mmio; struct regmap *perst_map; struct resource *mmio_res; @@ -267,10 +265,9 @@ static void qcom_pcie_ep_configure_tcsr(struct qcom_pc= ie_ep *pcie_ep) =20 static bool qcom_pcie_dw_link_up(struct dw_pcie *pci) { - struct qcom_pcie_ep *pcie_ep =3D to_pcie_ep(pci); u32 reg; =20 - reg =3D readl_relaxed(pcie_ep->elbi + ELBI_SYS_STTS); + reg =3D readl_relaxed(pci->elbi_base + ELBI_SYS_STTS); =20 return reg & XMLH_LINK_UP; } @@ -294,16 +291,15 @@ static void qcom_pcie_dw_stop_link(struct dw_pcie *pc= i) static void qcom_pcie_dw_write_dbi2(struct dw_pcie *pci, void __iomem *bas= e, u32 reg, size_t size, u32 val) { - struct qcom_pcie_ep *pcie_ep =3D to_pcie_ep(pci); int ret; =20 - writel(1, pcie_ep->elbi + ELBI_CS2_ENABLE); + writel(1, pci->elbi_base + ELBI_CS2_ENABLE); =20 ret =3D dw_pcie_write(pci->dbi_base2 + reg, size, val); if (ret) dev_err(pci->dev, "Failed to write DBI2 register (0x%x): %d\n", reg, ret= ); =20 - writel(0, pcie_ep->elbi + ELBI_CS2_ENABLE); + writel(0, pci->elbi_base + ELBI_CS2_ENABLE); } =20 static void qcom_pcie_ep_icc_update(struct qcom_pcie_ep *pcie_ep) @@ -583,11 +579,6 @@ static int qcom_pcie_ep_get_io_resources(struct platfo= rm_device *pdev, return PTR_ERR(pci->dbi_base); pci->dbi_base2 =3D pci->dbi_base; =20 - res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); - pcie_ep->elbi =3D devm_pci_remap_cfg_resource(dev, res); - if (IS_ERR(pcie_ep->elbi)) - return PTR_ERR(pcie_ep->elbi); - pcie_ep->mmio_res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "mmio"); if (!pcie_ep->mmio_res) { diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controlle= r/dwc/pcie-qcom.c index 15d71109a2f7d45ea2184728360d1f3db8e8f3c6..c48a20602d7fa4c50056ccf6502= d3b5bf0a8287f 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -276,7 +276,6 @@ struct qcom_pcie_port { struct qcom_pcie { struct dw_pcie *pci; void __iomem *parf; /* DT parf */ - void __iomem *elbi; /* DT elbi */ void __iomem *mhi; union qcom_pcie_resources res; struct icc_path *icc_mem; @@ -409,12 +408,17 @@ static void qcom_pcie_configure_dbi_atu_base(struct q= com_pcie *pcie) =20 static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie) { + struct dw_pcie *pci =3D pcie->pci; u32 val; =20 + if (!pci->elbi_base) { + dev_err(pci->dev, "ELBI is not present\n"); + return; + } /* enable link training */ - val =3D readl(pcie->elbi + ELBI_SYS_CTRL); + val =3D readl(pci->elbi_base + ELBI_SYS_CTRL); val |=3D ELBI_SYS_CTRL_LT_ENABLE; - writel(val, pcie->elbi + ELBI_SYS_CTRL); + writel(val, pci->elbi_base + ELBI_SYS_CTRL); } =20 static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) @@ -1847,12 +1851,6 @@ static int qcom_pcie_probe(struct platform_device *p= dev) goto err_pm_runtime_put; } =20 - pcie->elbi =3D devm_platform_ioremap_resource_byname(pdev, "elbi"); - if (IS_ERR(pcie->elbi)) { - ret =3D PTR_ERR(pcie->elbi); - goto err_pm_runtime_put; - } - /* MHI region is optional */ res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "mhi"); if (res) { --=20 2.48.1 From nobody Thu Oct 2 03:30:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C1CFE322549; Tue, 23 Sep 2025 11:27:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626830; cv=none; b=qcqDUzUV6IYunTCtoSHwBqOBXDxnlNOQ+DblcjKxBBSrl6eEeEgVyEkeOFTHkGVB7TflxXdR6hIHhv6iHojJjAG3a0MryhVTAVH1J4izYKS0CvPymJ7ovIvH2HxxbIpiCt8tnP4MyoFZf3bkIk+6BLN0eo61wFoTndUo7SxS+9U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626830; c=relaxed/simple; bh=q5sDj6WfjMML3tGdURLJIkj+dHzcfgO40GeaR5j+mSU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KUw2cZqKskHWaXJG1EsV9oQiOm/9pX8cba0W3UDeyqkqkwFBegwPqvuq2WZprnAV5rzxraP8Y8fg2LuR0ilGPQ365yomHOx5YhArUaFalwq3jaxF4HHvTyD2lbTB+UTg7MkpG5wVkL4F+SgjDGUjFrso7dzRxlJWIfaTBflZ3GU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FBbiI+Ct; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FBbiI+Ct" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4D33FC4CEF5; Tue, 23 Sep 2025 11:27:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758626830; bh=q5sDj6WfjMML3tGdURLJIkj+dHzcfgO40GeaR5j+mSU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FBbiI+Ct5JJcQuFbaHDEKGQGySIHJw8k6cv3UtchPDiQUEXRn3ZKcuiRO7Kibfuu1 m8x4EJRA9qAgVfphQb1liLKnuK8saVg43RlHwCyHgTv/tsY7T13XJNPv4ZwicSoake GdUDVWNzJZcGroLIMcQalKaosBHQEkLRiG/hfnfrUroVVGPK+BcdXNQZwDTDox+Oke H/bMj6+UVfDJSHUJTosI4lFeuLK7zC42W863RnNLkiGlDX0nvGQq2pL9kuUKa6QJ1Z fQDEqqqSAC47h2nkaK333XyYB95Fj8avWLni5X1VwUQFPj87VUWME2ELGg6TtW+qHD +rAIqA9YnmitQ== From: Manivannan Sadhasivam Date: Tue, 23 Sep 2025 16:56:52 +0530 Subject: [PATCH v10 2/4] PCI: dwc: Prepare the driver for enabling ECAM mechanism using iATU 'CFG Shift Feature' Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250923-controller-dwc-ecam-v10-2-e84390ba75fa@kernel.org> References: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> In-Reply-To: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> To: Jingoo Han , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Rob Herring , Bjorn Helgaas , Krzysztof Kozlowski , Alim Akhtar , Jonathan Chocron Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Krishna Chaitanya Chundru , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8333; i=mani@kernel.org; h=from:subject:message-id; bh=okr8gH/4lMmav3d4HKOkzUWJuRe10mFhDVwkfrYA40s=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBo0oP+mQjj8XB1+vYD+iJrcFGa+iNQTaNQTFwYD 9qmoyo2/rKJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaNKD/gAKCRBVnxHm/pHO 9f0tB/sH3wXbYpE9zXGGxUB77IKW2lCIZF2v+l1xFG2gEBJSy588mSpigP9vu9VveiwM7W3vABY zp2PkL0lKGM8vz6U6l7P+NSrflrDyTtweqWRu5Hcf08S8OajP4NHjEeoRwrUOIi8X8i329nNQ6e DhB7zax77VYCm0VrG3eudrYXdDQbuWUMxusMh5P1sYa/Hc6wdmxKSA5TT4rYXCNwSd8tTAC3TFw YAZ7crt7QIp5YgZ63fYd0hHLX2nu42+QnnsBPc1pKfsV85J1z3NmwH5f+fm8pO1XcMsVnzNAEsZ sn7K3h4mSREOddWSQJqTaQmkbwZIuc1Em5KAea9CrP1YFMKv X-Developer-Key: i=mani@kernel.org; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 From: Krishna Chaitanya Chundru In order to enable PCIe ECAM mechanism in DWC driver as per the 'CFG Shift Feature' documented in Designware databook r5.20a, sec 3.10.10.3, prepare the driver to handle the one time iATU setup and creating ECAM window. Signed-off-by: Krishna Chaitanya Chundru [mani: splitted the preparatory code into a separate commit for bisectabili= ty] Signed-off-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/Kconfig | 1 + drivers/pci/controller/dwc/pcie-designware-host.c | 116 ++++++++++++++++++= +--- drivers/pci/controller/dwc/pcie-designware.c | 2 +- drivers/pci/controller/dwc/pcie-designware.h | 5 + 4 files changed, 109 insertions(+), 15 deletions(-) diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dw= c/Kconfig index deafc512b07928e30e93b814ad325a6be7dbcf75..dc0271203909fbcfa2b47733693= d99b7a069426b 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -20,6 +20,7 @@ config PCIE_DW_HOST bool select PCIE_DW select IRQ_MSI_LIB + select PCI_HOST_COMMON =20 config PCIE_DW_EP bool diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pc= i/controller/dwc/pcie-designware-host.c index 952f8594b501254d2b2de5d5e056e16d2aa8d4b7..94e0fe11a0b062d0f14e09fe586= e20bde46a4266 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -413,6 +413,67 @@ static void dw_pcie_host_request_msg_tlp_res(struct dw= _pcie_rp *pp) } } =20 +static int dw_pcie_config_ecam_iatu(struct dw_pcie_rp *pp) +{ + struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); + struct dw_pcie_ob_atu_cfg atu =3D {0}; + resource_size_t bus_range_max; + struct resource_entry *bus; + int ret; + + bus =3D resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS); + + /* + * 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 =3D 0; + atu.type =3D PCIE_ATU_TYPE_CFG0; + atu.parent_bus_addr =3D pp->cfg0_base + SZ_1M; + /* 1MiB is to cover 1 (bus) * 32 (devices) * 8 (functions) */ + atu.size =3D SZ_1M; + atu.ctrl2 =3D PCIE_ATU_CFG_SHIFT_MODE_ENABLE; + ret =3D dw_pcie_prog_outbound_atu(pci, &atu); + if (ret) + return ret; + + bus_range_max =3D resource_size(bus->res); + + if (bus_range_max < 2) + return 0; + + /* Configure remaining buses in type 1 iATU configuration */ + atu.index =3D 1; + atu.type =3D PCIE_ATU_TYPE_CFG1; + atu.parent_bus_addr =3D pp->cfg0_base + SZ_2M; + atu.size =3D (SZ_1M * bus_range_max) - SZ_2M; + atu.ctrl2 =3D PCIE_ATU_CFG_SHIFT_MODE_ENABLE; + + return dw_pcie_prog_outbound_atu(pci, &atu); +} + +static int dw_pcie_create_ecam_window(struct dw_pcie_rp *pp, struct resour= ce *res) +{ + struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); + struct device *dev =3D pci->dev; + struct resource_entry *bus; + + bus =3D resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS); + if (!bus) + return -ENODEV; + + pp->cfg =3D pci_ecam_create(dev, res, bus->res, &pci_generic_ecam_ops); + if (IS_ERR(pp->cfg)) + return PTR_ERR(pp->cfg); + + pci->dbi_base =3D pp->cfg->win; + pci->dbi_phys_addr =3D res->start; + + return 0; +} + static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp) { struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); @@ -422,10 +483,6 @@ static int dw_pcie_host_get_resources(struct dw_pcie_r= p *pp) struct resource *res; int ret; =20 - ret =3D dw_pcie_get_resources(pci); - if (ret) - return ret; - res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); if (!res) { dev_err(dev, "Missing \"config\" reg space\n"); @@ -435,9 +492,31 @@ static int dw_pcie_host_get_resources(struct dw_pcie_r= p *pp) pp->cfg0_size =3D resource_size(res); pp->cfg0_base =3D res->start; =20 - pp->va_cfg0_base =3D devm_pci_remap_cfg_resource(dev, res); - if (IS_ERR(pp->va_cfg0_base)) - return PTR_ERR(pp->va_cfg0_base); + if (pp->ecam_enabled) { + ret =3D dw_pcie_create_ecam_window(pp, res); + if (ret) + return ret; + + pp->bridge->ops =3D (struct pci_ops *)&pci_generic_ecam_ops.pci_ops; + pp->bridge->sysdata =3D pp->cfg; + pp->cfg->priv =3D pp; + } else { + pp->va_cfg0_base =3D devm_pci_remap_cfg_resource(dev, res); + if (IS_ERR(pp->va_cfg0_base)) + return PTR_ERR(pp->va_cfg0_base); + + /* Set default bus ops */ + pp->bridge->ops =3D &dw_pcie_ops; + pp->bridge->child_ops =3D &dw_child_pcie_ops; + pp->bridge->sysdata =3D pp; + } + + ret =3D dw_pcie_get_resources(pci); + if (ret) { + if (pp->cfg) + pci_ecam_free(pp->cfg); + return ret; + } =20 /* Get the I/O range from DT */ win =3D resource_list_first_type(&pp->bridge->windows, IORESOURCE_IO); @@ -476,14 +555,10 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) if (ret) return ret; =20 - /* Set default bus ops */ - bridge->ops =3D &dw_pcie_ops; - bridge->child_ops =3D &dw_child_pcie_ops; - if (pp->ops->init) { ret =3D pp->ops->init(pp); if (ret) - return ret; + goto err_free_ecam; } =20 if (pci_msi_enabled()) { @@ -525,6 +600,14 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) if (ret) goto err_free_msi; =20 + if (pp->ecam_enabled) { + ret =3D dw_pcie_config_ecam_iatu(pp); + if (ret) { + dev_err(dev, "Failed to configure iATU in ECAM mode\n"); + goto err_free_msi; + } + } + /* * Allocate the resource for MSG TLP before programming the iATU * outbound window in dw_pcie_setup_rc(). Since the allocation depends @@ -560,8 +643,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) /* Ignore errors, the link may come up later */ dw_pcie_wait_for_link(pci); =20 - bridge->sysdata =3D pp; - ret =3D pci_host_probe(bridge); if (ret) goto err_stop_link; @@ -587,6 +668,10 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) if (pp->ops->deinit) pp->ops->deinit(pp); =20 +err_free_ecam: + if (pp->cfg) + pci_ecam_free(pp->cfg); + return ret; } EXPORT_SYMBOL_GPL(dw_pcie_host_init); @@ -609,6 +694,9 @@ void dw_pcie_host_deinit(struct dw_pcie_rp *pp) =20 if (pp->ops->deinit) pp->ops->deinit(pp); + + if (pp->cfg) + pci_ecam_free(pp->cfg); } EXPORT_SYMBOL_GPL(dw_pcie_host_deinit); =20 diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/con= troller/dwc/pcie-designware.c index 93da8a26c9313dfdd6b269a90bbfb017aab2abe7..ee8caae1edbd44c10e6986430a6= 932c10f20a9eb 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -575,7 +575,7 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, val =3D dw_pcie_enable_ecrc(val); dw_pcie_writel_atu_ob(pci, atu->index, PCIE_ATU_REGION_CTRL1, val); =20 - val =3D PCIE_ATU_ENABLE; + val =3D PCIE_ATU_ENABLE | atu->ctrl2; if (atu->type =3D=3D PCIE_ATU_TYPE_MSG) { /* The data-less messages only for now */ val |=3D PCIE_ATU_INHIBIT_PAYLOAD | atu->code; diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/con= troller/dwc/pcie-designware.h index 9eb3c4c762ddca7d6faff3a98a54b37d7cd9f11b..779868e8fa8fd78e5f35cd0fa25= 75f52cc07c335 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -20,6 +20,7 @@ #include #include #include +#include #include =20 #include @@ -168,6 +169,7 @@ #define PCIE_ATU_REGION_CTRL2 0x004 #define PCIE_ATU_ENABLE BIT(31) #define PCIE_ATU_BAR_MODE_ENABLE BIT(30) +#define PCIE_ATU_CFG_SHIFT_MODE_ENABLE BIT(28) #define PCIE_ATU_INHIBIT_PAYLOAD BIT(22) #define PCIE_ATU_FUNC_NUM_MATCH_EN BIT(19) #define PCIE_ATU_LOWER_BASE 0x008 @@ -386,6 +388,7 @@ struct dw_pcie_ob_atu_cfg { u8 func_no; u8 code; u8 routing; + u32 ctrl2; u64 parent_bus_addr; u64 pci_addr; u64 size; @@ -424,6 +427,8 @@ struct dw_pcie_rp { struct resource *msg_res; bool use_linkup_irq; struct pci_eq_presets presets; + struct pci_config_window *cfg; + bool ecam_enabled; }; =20 struct dw_pcie_ep_ops { --=20 2.48.1 From nobody Thu Oct 2 03:30:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B41FF3218DB; Tue, 23 Sep 2025 11:27:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626837; cv=none; b=sExbbX0YxNBcdhfWAkfMkoR/Po319c2IkQKDF1h5sj92jkJystrsa4w5sxT80D+n/PySQTok+mHSUaFZpC5wPP1XWwjmGuGlVlrIb2y+koA8rALjRwbHu3YWBlubTTr31N4UdUtiK9KzaxoRxv8glNl9oQ+DD64eSL9XID2lWTE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626837; c=relaxed/simple; bh=Q2ZPEdzb2gnORGVGeGO0IjeJe1l44gLt8XXnAyUuDs8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=S27+JcBDweGWrdOAJC2la6EBWvLZv0+mBy5KI6tVAugcIJmEv+MSM9S4LFjfqcYIVpavarKv8lhF4PsMgCyb+hA53GCQNtPf33Z57IltB1rLIb6YKLwlvpEkDT11ZZmDREbumN1Alc8i/xT2YQFEgXibrhShs2vq4CsBmBkMGH0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UxRtRGp0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UxRtRGp0" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0099FC4CEF5; Tue, 23 Sep 2025 11:27:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758626835; bh=Q2ZPEdzb2gnORGVGeGO0IjeJe1l44gLt8XXnAyUuDs8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UxRtRGp0z2xiTUUUBesIglAe4niKZKHngVBoyIw1OLjXZASD0/gfb/9uUh3qYLF+f I+OSFxsO0MM/oKN2Y0M0bJ4CL/duS1RDbQpITlg+xF+IqPDWqAzJ87l7nIcYq9zU4N L6LBN0l5aQ/JGBf22gIflpZsEOat4+1e/YoJdR9v8mUTd4wu02nu4jCOovCQZyjwyO BfnrGSyxliKgtCyfHqCRx7c44rCN1hRg6utdmQMAq7CfL3KeHjQOdnOEono7sG1M1i LhKDYe4SM0SbPg87LBVmfHGn+6k+1RP61sq+giwLdc1SF5LpjUgDrwxkAERN1kbVJ5 oDNT6UT7kYyoA== From: Manivannan Sadhasivam Date: Tue, 23 Sep 2025 16:56:53 +0530 Subject: [PATCH v10 3/4] PCI: qcom: Prepare for the DWC ECAM enablement Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250923-controller-dwc-ecam-v10-3-e84390ba75fa@kernel.org> References: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> In-Reply-To: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> To: Jingoo Han , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Rob Herring , Bjorn Helgaas , Krzysztof Kozlowski , Alim Akhtar , Jonathan Chocron Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Krishna Chaitanya Chundru , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5560; i=mani@kernel.org; h=from:subject:message-id; bh=ollTmHdc+LRKjxsyHOHDxETPk2GcR9fbJFLU7EjwZyE=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBo0oP+ERpPcf1S7vPHdvG9W21uHfJMNRjASUUzA ipFx2XcwvOJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaNKD/gAKCRBVnxHm/pHO 9WY5B/9wApen9liIm5MjwGfbgjrWAUdg6N4ans9uzmaEz7ZJDErDwNWt2pzQKs5uIj4REIOoJLV K0nmecB67wCHl92/nL2A8Kbdufyj/9sY9C2njmqAAXsiUgLapYZIBYvBuA4tMF/mksJYlnLiDrB RpRyZSBHoN04M8YM9k4r3l03XOABh1r+ZnJTt6h7tIox1Flvt80Cq3upYYae94M2OQN/R84xuVX ybbU2jFc7D1q5PAIIoANGUXGXQS9k7B0Nr08Q0W2UaErot8KP8cXEDleAPkxWRHATHlYq19J7di +8iHLaf5WgBTjiQaoYse59r0XpcJLXuNHzBXvnc7woEDmMDR X-Developer-Key: i=mani@kernel.org; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 From: Krishna Chaitanya Chundru To support the DWC ECAM mechanism, prepare the driver by performing below configurations: 1. Since the ELBI region will be covered by the ECAM 'config' space, override the 'elbi_base' with the address derived from 'dbi_base' and the offset from PARF_SLV_DBI_ELBI register. 2. Block the transactions from the host bridge to devices other than Root Port on the root bus to return all F's. This is required when the 'CFG Shift Feature' of iATU is enabled. Signed-off-by: Krishna Chaitanya Chundru [mani: code split, reworded subject/description and comments] Signed-off-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-qcom.c | 68 ++++++++++++++++++++++++++++++= ++++ 1 file changed, 68 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controlle= r/dwc/pcie-qcom.c index c48a20602d7fa4c50056ccf6502d3b5bf0a8287f..e6d2a6b0c087151781ddaf6bf76= 12f87e2445d17 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -55,6 +55,7 @@ #define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 #define PARF_Q2A_FLUSH 0x1ac #define PARF_LTSSM 0x1b0 +#define PARF_SLV_DBI_ELBI 0x1b4 #define PARF_INT_ALL_STATUS 0x224 #define PARF_INT_ALL_CLEAR 0x228 #define PARF_INT_ALL_MASK 0x22c @@ -64,6 +65,16 @@ #define PARF_DBI_BASE_ADDR_V2_HI 0x354 #define PARF_SLV_ADDR_SPACE_SIZE_V2 0x358 #define PARF_SLV_ADDR_SPACE_SIZE_V2_HI 0x35c +#define PARF_BLOCK_SLV_AXI_WR_BASE 0x360 +#define PARF_BLOCK_SLV_AXI_WR_BASE_HI 0x364 +#define PARF_BLOCK_SLV_AXI_WR_LIMIT 0x368 +#define PARF_BLOCK_SLV_AXI_WR_LIMIT_HI 0x36c +#define PARF_BLOCK_SLV_AXI_RD_BASE 0x370 +#define PARF_BLOCK_SLV_AXI_RD_BASE_HI 0x374 +#define PARF_BLOCK_SLV_AXI_RD_LIMIT 0x378 +#define PARF_BLOCK_SLV_AXI_RD_LIMIT_HI 0x37c +#define PARF_ECAM_BASE 0x380 +#define PARF_ECAM_BASE_HI 0x384 #define PARF_NO_SNOOP_OVERRIDE 0x3d4 #define PARF_ATU_BASE_ADDR 0x634 #define PARF_ATU_BASE_ADDR_HI 0x638 @@ -87,6 +98,7 @@ =20 /* PARF_SYS_CTRL register fields */ #define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN BIT(29) +#define PCIE_ECAM_BLOCKER_EN BIT(26) #define MST_WAKEUP_EN BIT(13) #define SLV_WAKEUP_EN BIT(12) #define MSTR_ACLK_CGC_DIS BIT(10) @@ -134,6 +146,9 @@ /* PARF_LTSSM register fields */ #define LTSSM_EN BIT(8) =20 +/* PARF_SLV_DBI_ELBI */ +#define SLV_DBI_ELBI_ADDR_BASE GENMASK(11, 0) + /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */ #define PARF_INT_ALL_LINK_UP BIT(13) #define PARF_INT_MSI_DEV_0_7 GENMASK(30, 23) @@ -312,6 +327,47 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *p= cie) qcom_perst_assert(pcie, false); } =20 +static void qcom_pci_config_ecam(struct dw_pcie_rp *pp) +{ + struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); + struct qcom_pcie *pcie =3D to_qcom_pcie(pci); + u64 addr, addr_end; + u32 val; + + writel_relaxed(lower_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_= BASE); + writel_relaxed(upper_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_= BASE_HI); + + /* + * The only device on the root bus is a single Root Port. If we try to + * access any devices other than Device/Function 00.0 on Bus 0, the TLP + * will go outside of the controller to the PCI bus. But with CFG Shift + * Feature (ECAM) enabled in iATU, there is no guarantee that the + * response is going to be all F's. Hence, to make sure that the + * requester gets all F's response for accesses other than the Root + * Port, configure iATU to block the transactions starting from + * function 1 of the root bus to the end of the root bus (i.e., from + * dbi_base + 4KB to dbi_base + 1MB). + */ + addr =3D pci->dbi_phys_addr + SZ_4K; + writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BA= SE); + writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BA= SE_HI); + + writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BA= SE); + writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BA= SE_HI); + + addr_end =3D pci->dbi_phys_addr + SZ_1M - 1; + + writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_W= R_LIMIT); + writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_W= R_LIMIT_HI); + + writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_R= D_LIMIT); + writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_R= D_LIMIT_HI); + + val =3D readl_relaxed(pcie->parf + PARF_SYS_CTRL); + val |=3D PCIE_ECAM_BLOCKER_EN; + writel_relaxed(val, pcie->parf + PARF_SYS_CTRL); +} + static int qcom_pcie_start_link(struct dw_pcie *pci) { struct qcom_pcie *pcie =3D to_qcom_pcie(pci); @@ -1284,6 +1340,7 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) { struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); struct qcom_pcie *pcie =3D to_qcom_pcie(pci); + u16 offset; int ret; =20 qcom_ep_reset_assert(pcie); @@ -1292,6 +1349,17 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) if (ret) return ret; =20 + if (pp->ecam_enabled) { + /* + * Override ELBI when ECAM is enabled, as when ECAM is enabled, + * ELBI moves under the 'config' space. + */ + offset =3D FIELD_GET(SLV_DBI_ELBI_ADDR_BASE, readl(pcie->parf + PARF_SLV= _DBI_ELBI)); + pci->elbi_base =3D pci->dbi_base + offset; + + qcom_pci_config_ecam(pp); + } + ret =3D qcom_pcie_phy_power_on(pcie); if (ret) goto err_deinit; --=20 2.48.1 From nobody Thu Oct 2 03:30:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4FFEE322A04; Tue, 23 Sep 2025 11:27:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626840; cv=none; b=SxCjDDcm7kHGuBDOtSmNrnA5cgZI4EtnEkLbQjbK3UmtITvsfVB+8v76SqinV1O58R71uLbYhUQWnLKC9ClF5767mxWgXJyNprxdDZzTjzEQ5kFeGmv5ilrVhBdaI2+98Yu+DIiem7Eg6AbULHf3Al8XLICm73PlmVfoz4w6zLg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758626840; c=relaxed/simple; bh=Y6Ks5wTiGs+ByHpP/pFcc1umqPWY5L5vAWv9OUX9xY4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NL41A1zmQxDgX7YDivuTsPgTa7lUswkZJLXlMbtDpHSrF+T951tV/PHeorq8ImKlmh7AHfN5qob7WokZzBMJtoi3DDgOuQWpVPgdL5NEtGtRcF+6HSHi5fPPxYEf3dKdqT2TLqlPl7LS0YX0u42bQtAFhoPSIs70FGpsciMn8Nc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lSGF6VcZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lSGF6VcZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C285CC113D0; Tue, 23 Sep 2025 11:27:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758626839; bh=Y6Ks5wTiGs+ByHpP/pFcc1umqPWY5L5vAWv9OUX9xY4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lSGF6VcZInmak+B2nWzBYISkHvSHzLyb6KqUZmybeHjCUvZ2zSZiSshpUWaFIC/+/ KIPPH90NuiZ4PJdQZKOuFQ7eEIgQM0euVR+UDpHvINhha8BkeinZ3AYrz0xE5yAo8D dMqGfU0SipM0Q+y9ea1s1z3c5Ta1eRaYNWgs8SdQw0BVKSbOs4ii/e14hImcGW1Smq jcUa9swNvFFk0vqERZNOlCdftDtXcughtKx7esxyNbeNVrv5kBQYp33YyoDd5mIzOm w0Z8xUuYHY+V0/ZTe4p/GP6OhH5OUVT5TR1xBXD/8jSrX+0htFJEKvOmj6EgPCnyJF AAl/AeT1DgpWQ== From: Manivannan Sadhasivam Date: Tue, 23 Sep 2025 16:56:54 +0530 Subject: [PATCH v10 4/4] PCI: dwc: Support ECAM mechanism by enabling iATU 'CFG Shift Feature' Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250923-controller-dwc-ecam-v10-4-e84390ba75fa@kernel.org> References: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> In-Reply-To: <20250923-controller-dwc-ecam-v10-0-e84390ba75fa@kernel.org> To: Jingoo Han , Lorenzo Pieralisi , =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= , Rob Herring , Bjorn Helgaas , Krzysztof Kozlowski , Alim Akhtar , Jonathan Chocron Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Krishna Chaitanya Chundru , Manivannan Sadhasivam X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5632; i=mani@kernel.org; h=from:subject:message-id; bh=lqpEGDikWMpJGoh9O49BHabw0FX3kIuCt8c+nBt0Fho=; b=owEBbQGS/pANAwAKAVWfEeb+kc71AcsmYgBo0oP+nT1B3irIDsL2tBTAYHWeInJiZBrMnFQ05 AMvJOLqXayJATMEAAEKAB0WIQRnpUMqgUjL2KRYJ5dVnxHm/pHO9QUCaNKD/gAKCRBVnxHm/pHO 9cUGB/9mDuyKuvKq+CVaMM99wK7fYEnjT595IwhOdIKIy2KvO0vicoCYdJhIcC7gnv+JM/ndKqe ZZonzGWZ5UnI7h1e7FRGc8jXLsRoc5ho3EP6I3R8dpXV634QumVCUglmAiiy9AQh8yun3XEnH0p XAZQhQ7gIUR38caj7YWj1PkqHikqkT4zBlaH+NybnNkTOYfOFxKxQMm5E+3rqHEOQ7huyyBXtYR E03eue8AmKHIHFfTEZ9rLA2Oxnwtoh2W7rSKqBksRdmQI+jVnlVNAXdiEeKCKV3A9yTeDT/S0sX zvWMVWZ/ThtygcydYXhWiOQX7Rv23g7d5Mu8EqVjT/F2LGI6 X-Developer-Key: i=mani@kernel.org; a=openpgp; fpr=C668AEC3C3188E4C611465E7488550E901166008 From: Krishna Chaitanya Chundru Designware databook r5.20a, sec 3.10.10.3 documents the 'CFG Shift 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. Currently, the driver is not making use of this CFG shift feature, thereby creating the iATU outbound map for each config access to the devices, causing latency and wasting CPU cycles. So to avoid this, configure the controller to enable CFG shift feature by enabling the 'CFG Shift' bit of the 'iATU Control 2 Register'. As a result of enabling CFG shift (ECAM), there is longer a need to map the DBI register space separately as the DBI region falls under the 'config' space used for ECAM (as DBI is used to access the Root Port). For enabling ECAM using CFG shift, the platform has to satisfy following requirements: 1. Size of the 'config' memory space to be used as ECAM memory should be able to accommodate the number of buses defined in the 'bus-range' property of the host bridge DT node. 2. The 'config' memory space should be 256 MiB aligned. This requirement comes from PCIe r6.0, sec 7.2.2, which says the base address of ECAM memory should be aligned to a 2^(n+20) byte address boundary. For the DWC cores, n is 8, so this results in 2^28 byte alignment requirement. It should be noted that some DWC vendor glue drivers like pcie-al may use their own ECAM mechanism. For those controllers, set 'dw_pcie_rp::native_ecam' flag and skip enabling the CFG Shift feature in the DWC core. Signed-off-by: Krishna Chaitanya Chundru [mani: code split, reworded subject/description, comment, native_ecam flag] Signed-off-by: Manivannan Sadhasivam --- drivers/pci/controller/dwc/pcie-al.c | 1 + drivers/pci/controller/dwc/pcie-designware-host.c | 32 +++++++++++++++++++= ++++ drivers/pci/controller/dwc/pcie-designware.h | 1 + 3 files changed, 34 insertions(+) diff --git a/drivers/pci/controller/dwc/pcie-al.c b/drivers/pci/controller/= dwc/pcie-al.c index 643115f74092d1c9319e9738db6e94b2752d30c4..345c281c74fefd2113233ef5461= f96834b3765de 100644 --- a/drivers/pci/controller/dwc/pcie-al.c +++ b/drivers/pci/controller/dwc/pcie-al.c @@ -352,6 +352,7 @@ static int al_pcie_probe(struct platform_device *pdev) return -ENOENT; } al_pcie->ecam_size =3D resource_size(ecam_res); + pci->pp.native_ecam =3D true; =20 controller_res =3D platform_get_resource_byname(pdev, IORESOURCE_MEM, "controller"); diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pc= i/controller/dwc/pcie-designware-host.c index 94e0fe11a0b062d0f14e09fe586e20bde46a4266..20c9333bcb1c4812e2fd96047a4= 9944574df1e6f 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -8,6 +8,7 @@ * Author: Jingoo Han */ =20 +#include #include #include #include @@ -32,6 +33,8 @@ static struct pci_ops dw_child_pcie_ops; MSI_FLAG_PCI_MSIX | \ MSI_GENERIC_FLAGS_MASK) =20 +#define IS_256MB_ALIGNED(x) IS_ALIGNED(x, SZ_256M) + static const struct msi_parent_ops dw_pcie_msi_parent_ops =3D { .required_flags =3D DW_PCIE_MSI_FLAGS_REQUIRED, .supported_flags =3D DW_PCIE_MSI_FLAGS_SUPPORTED, @@ -474,6 +477,34 @@ static int dw_pcie_create_ecam_window(struct dw_pcie_r= p *pp, struct resource *re return 0; } =20 +static bool dw_pcie_ecam_enabled(struct dw_pcie_rp *pp, struct resource *c= onfig_res) +{ + struct resource *bus_range; + u64 nr_buses; + + /* Vendor glue drivers may implement their own ECAM mechanism */ + if (pp->native_ecam) + return false; + + /* + * PCIe spec r6.0, sec 7.2.2 mandates the base address used for ECAM to + * be aligned on a 2^(n+20) byte boundary, where n is the number of bits + * used for representing 'bus' in BDF. Since the DWC cores always use 8 + * bits for representing 'bus', the base address has to be aligned to + * 2^28 byte boundary, which is 256 MiB. + */ + if (!IS_256MB_ALIGNED(config_res->start)) + return false; + + bus_range =3D resource_list_first_type(&pp->bridge->windows, IORESOURCE_B= US)->res; + if (!bus_range) + return false; + + nr_buses =3D resource_size(config_res) >> PCIE_ECAM_BUS_SHIFT; + + return nr_buses >=3D resource_size(bus_range); +} + static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp) { struct dw_pcie *pci =3D to_dw_pcie_from_pp(pp); @@ -492,6 +523,7 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp= *pp) pp->cfg0_size =3D resource_size(res); pp->cfg0_base =3D res->start; =20 + pp->ecam_enabled =3D dw_pcie_ecam_enabled(pp, res); if (pp->ecam_enabled) { ret =3D dw_pcie_create_ecam_window(pp, res); if (ret) diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/con= troller/dwc/pcie-designware.h index 779868e8fa8fd78e5f35cd0fa2575f52cc07c335..625320565360c0134ee9345bcc2= e54a6ce83326a 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -429,6 +429,7 @@ struct dw_pcie_rp { struct pci_eq_presets presets; struct pci_config_window *cfg; bool ecam_enabled; + bool native_ecam; }; =20 struct dw_pcie_ep_ops { --=20 2.48.1