From 75479bed53b11f81e37fb38c0608a2af4ddc9b1e Mon Sep 17 00:00:00 2001 From: Florian Eckert Date: Fri, 17 Apr 2026 10:35:46 +0200 Subject: [PATCH 1/6] PCI: intel-gw: Remove unused PCIE_APP_INTX_OFST definition The C preprocessor define 'PCIE_APP_INTX_OFST' is not used in the sources. Delete it. Signed-off-by: Florian Eckert Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260417-pcie-intel-gw-v5-2-0a2b933fe04f@dev.tdt.de --- drivers/pci/controller/dwc/pcie-intel-gw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index c21906eced61..80d1607c46cb 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -47,7 +47,6 @@ #define PCIE_APP_IRN_INTD BIT(16) #define PCIE_APP_IRN_MSG_LTR BIT(18) #define PCIE_APP_IRN_SYS_ERR_RC BIT(29) -#define PCIE_APP_INTX_OFST 12 #define PCIE_APP_IRN_INT \ (PCIE_APP_IRN_AER_REPORT | PCIE_APP_IRN_PME | \ From abddc0539e5931f4ad2f589a03cbba5a6a64485f Mon Sep 17 00:00:00 2001 From: Florian Eckert Date: Fri, 17 Apr 2026 10:35:47 +0200 Subject: [PATCH 2/6] PCI: intel-gw: Move interrupt enable to own function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To improve the readability of the code, move the interrupt enable instructions to a separate function. That is already done for the disable interrupt instruction. In addition, clear and disable all pending interrupts, as is done in intel_pcie_core_irq_disable(). After that, enable all relevant interrupts again. The 'PCIE_APP_IRNEN' definition contains all the relevant interrupts that are of interest. This change is also done in the MaxLinear SDK [1]. As I unfortunately don’t have any documentation for this IP core, I suspect that the intention is to set the IP core for interrupt handling to a specific state. Perhaps the problem is that the IP core did not reinitialize the interrupt register properly after a power cycle. In my view, it can’t do any harm to switch the interrupt off and then on again to set them to a specific state. The reason why the MaxLinear SDK is used as a reference here is, that this PCIe DWC IP is used in the URX851 and URX850 SoC. This SoC was originally developed by Intel when they acquired Lantiq’s home networking division in 2015 [2]. In 2020 the home network division was sold to MaxLinear [3]. Since then, this SoC belongs to MaxLinear. They use their own SDK, which runs on kernel version '5.15.x'. [1] https://github.com/maxlinear/linux/blob/updk_9.1.90/drivers/pci/controller/dwc/pcie-intel-gw.c#L431 [2] https://www.intc.com/news-events/press-releases/detail/364/intel-to-acquire-lantiq-advancing-the-connected-home [3] https://investors.maxlinear.com/press-releases/detail/395/maxlinear-to-acquire-intels-home-gateway-platform Signed-off-by: Florian Eckert Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260417-pcie-intel-gw-v5-3-0a2b933fe04f@dev.tdt.de --- drivers/pci/controller/dwc/pcie-intel-gw.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index 80d1607c46cb..e88b8243cc41 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -195,6 +195,13 @@ static void intel_pcie_device_rst_deassert(struct intel_pcie *pcie) gpiod_set_value_cansleep(pcie->reset_gpio, 0); } +static void intel_pcie_core_irq_enable(struct intel_pcie *pcie) +{ + pcie_app_wr(pcie, PCIE_APP_IRNEN, 0); + pcie_app_wr(pcie, PCIE_APP_IRNCR, PCIE_APP_IRN_INT); + pcie_app_wr(pcie, PCIE_APP_IRNEN, PCIE_APP_IRN_INT); +} + static void intel_pcie_core_irq_disable(struct intel_pcie *pcie) { pcie_app_wr(pcie, PCIE_APP_IRNEN, 0); @@ -316,9 +323,7 @@ static int intel_pcie_host_setup(struct intel_pcie *pcie) if (ret) goto app_init_err; - /* Enable integrated interrupts */ - pcie_app_wr_mask(pcie, PCIE_APP_IRNEN, PCIE_APP_IRN_INT, - PCIE_APP_IRN_INT); + intel_pcie_core_irq_enable(pcie); return 0; From febf9ed3c35e5eec7ea384ebbd55a5296e3ca5e9 Mon Sep 17 00:00:00 2001 From: Florian Eckert Date: Fri, 17 Apr 2026 10:35:48 +0200 Subject: [PATCH 3/6] PCI: intel-gw: Enable clock before PHY init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To ensure that the boot sequence is correct, the DWC PCIe core clock must be switched on before PHY init call [1]. This changes are based on patched kernel sources of the MaxLinear SDK. The reason why the MaxLinear SDK is used as a reference here is, that this PCIe DWC IP is used in the URX851 and URX850 SoC. This SoC was originally developed by Intel when they acquired Lantiq’s home networking division in 2015 [2]. In 2020 the home network division was sold to MaxLinear [3]. Since then, this SoC belongs to MaxLinear. They use their own SDK, which runs on kernel version '5.15.x'. [1] https://github.com/maxlinear/linux/blob/updk_9.1.90/drivers/pci/controller/dwc/pcie-intel-gw.c#L544 [2] https://www.intc.com/news-events/press-releases/detail/364/intel-to-acquire-lantiq-advancing-the-connected-home [3] https://investors.maxlinear.com/press-releases/detail/395/maxlinear-to-acquire-intels-home-gateway-platform Signed-off-by: Florian Eckert Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260417-pcie-intel-gw-v5-4-0a2b933fe04f@dev.tdt.de --- drivers/pci/controller/dwc/pcie-intel-gw.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index e88b8243cc41..6d9499d95467 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -291,13 +291,9 @@ static int intel_pcie_host_setup(struct intel_pcie *pcie) intel_pcie_core_rst_assert(pcie); intel_pcie_device_rst_assert(pcie); - - ret = phy_init(pcie->phy); - if (ret) - return ret; - intel_pcie_core_rst_deassert(pcie); + /* Controller clock must be provided earlier than PHY */ ret = clk_prepare_enable(pcie->core_clk); if (ret) { dev_err(pcie->pci.dev, "Core clock enable failed: %d\n", ret); @@ -306,13 +302,17 @@ static int intel_pcie_host_setup(struct intel_pcie *pcie) pci->atu_base = pci->dbi_base + 0xC0000; + ret = phy_init(pcie->phy); + if (ret) + goto phy_err; + intel_pcie_ltssm_disable(pcie); intel_pcie_link_setup(pcie); intel_pcie_init_n_fts(pci); ret = dw_pcie_setup_rc(&pci->pp); if (ret) - goto app_init_err; + goto err; dw_pcie_upconfig_setup(pci); @@ -321,17 +321,18 @@ static int intel_pcie_host_setup(struct intel_pcie *pcie) ret = dw_pcie_wait_for_link(pci); if (ret) - goto app_init_err; + goto err; intel_pcie_core_irq_enable(pcie); return 0; -app_init_err: +err: + phy_exit(pcie->phy); +phy_err: clk_disable_unprepare(pcie->core_clk); clk_err: intel_pcie_core_rst_assert(pcie); - phy_exit(pcie->phy); return ret; } From 1eedabe7c6170b5c73c7d801f427c127be74916e Mon Sep 17 00:00:00 2001 From: Florian Eckert Date: Fri, 17 Apr 2026 10:35:49 +0200 Subject: [PATCH 4/6] PCI: intel-gw: Add .start_link() callback The pcie-intel-gw driver had no .start_link() callback. Add one so the driver works again and does not abort with the following error messages during probing: intel-gw-pcie d1000000.pcie: host bridge /soc/pcie@d1000000 ranges: intel-gw-pcie d1000000.pcie: MEM 0x00dc000000..0x00ddffffff -> 0x00dc000000 intel-combo-phy d0c00000.combo-phy: Set combo mode: combophy[1]: mode: PCIe single lane mode intel-gw-pcie d1000000.pcie: No outbound iATU found intel-gw-pcie d1000000.pcie: Cannot initialize host intel-gw-pcie d1000000.pcie: probe with driver intel-gw-pcie failed with error -22 intel-gw-pcie c1100000.pcie: host bridge /soc/pcie@c1100000 ranges: intel-gw-pcie c1100000.pcie: MEM 0x00ce000000..0x00cfffffff -> 0x00ce000000 intel-combo-phy c0c00000.combo-phy: Set combo mode: combophy[3]: mode: PCIe single lane mode intel-gw-pcie c1100000.pcie: No outbound iATU found intel-gw-pcie c1100000.pcie: Cannot initialize host intel-gw-pcie c1100000.pcie: probe with driver intel-gw-pcie failed with error -22 Fixes: c5097b9869a1 ("Revert "PCI: dwc: Wait for link up only if link is started"") Fixes: da56a1bfbab5 ("PCI: dwc: Wait for link up only if link is started") Signed-off-by: Florian Eckert Signed-off-by: Manivannan Sadhasivam [bhelgaas: remove timestamps] Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260417-pcie-intel-gw-v5-5-0a2b933fe04f@dev.tdt.de --- drivers/pci/controller/dwc/pcie-intel-gw.c | 24 ++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index 6d9499d95467..afd933050c92 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -284,6 +284,16 @@ static void intel_pcie_turn_off(struct intel_pcie *pcie) pcie_rc_cfg_wr_mask(pcie, PCI_COMMAND, PCI_COMMAND_MEMORY, 0); } +static int intel_pcie_start_link(struct dw_pcie *pci) +{ + struct intel_pcie *pcie = dev_get_drvdata(pci->dev); + + intel_pcie_device_rst_deassert(pcie); + intel_pcie_ltssm_enable(pcie); + + return 0; +} + static int intel_pcie_host_setup(struct intel_pcie *pcie) { int ret; @@ -310,25 +320,12 @@ static int intel_pcie_host_setup(struct intel_pcie *pcie) intel_pcie_link_setup(pcie); intel_pcie_init_n_fts(pci); - ret = dw_pcie_setup_rc(&pci->pp); - if (ret) - goto err; - dw_pcie_upconfig_setup(pci); - intel_pcie_device_rst_deassert(pcie); - intel_pcie_ltssm_enable(pcie); - - ret = dw_pcie_wait_for_link(pci); - if (ret) - goto err; - intel_pcie_core_irq_enable(pcie); return 0; -err: - phy_exit(pcie->phy); phy_err: clk_disable_unprepare(pcie->core_clk); clk_err: @@ -386,6 +383,7 @@ static int intel_pcie_rc_init(struct dw_pcie_rp *pp) } static const struct dw_pcie_ops intel_pcie_ops = { + .start_link = intel_pcie_start_link, }; static const struct dw_pcie_host_ops intel_pcie_dw_ops = { From 19f90be49c117db2d70c49f5d73ec428c84dbb1e Mon Sep 17 00:00:00 2001 From: Florian Eckert Date: Fri, 17 Apr 2026 10:35:50 +0200 Subject: [PATCH 5/6] PCI: intel-gw: Fix ATU base address setup and add optional DT 'atu' region The ATU base address was set in intel_pcie_host_setup(), which is called via pp->ops->init(). However, dw_pcie_get_resources() runs before this callback and sets a default atu_base of 0x300000, which then gets overwritten by the driver's value of 0xC0000. But this ordering is broken because atu_base must be set before dw_pcie_get_resources() runs, not after. So move the atu_base assignment from intel_pcie_host_setup() to intel_pcie_probe() to fix the initialization order. The call stack is: intel_pcie_probe dw_pcie_host_init dw_pcie_host_get_resources dw_pcie_get_resources <- sets atu_base = 0x300000 pp->ops->init intel_pcie_rc_init intel_pcie_host_setup <- was overwriting atu_base here Additionally, add support for parsing the ATU region from the device tree. If an 'atu' region is present in DT, the DWC core parses it via dw_pcie_get_resources() and the driver does not set atu_base explicitly. If 'atu' is absent, the driver falls back to the hardcoded offset (0xC0000 from DBI base) for backwards compatibility, with a warning to the user. Signed-off-by: Florian Eckert [mani: commit log] Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260417-pcie-intel-gw-v5-6-0a2b933fe04f@dev.tdt.de --- drivers/pci/controller/dwc/pcie-intel-gw.c | 29 ++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index afd933050c92..2674cd376f49 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -310,8 +310,6 @@ static int intel_pcie_host_setup(struct intel_pcie *pcie) goto clk_err; } - pci->atu_base = pci->dbi_base + 0xC0000; - ret = phy_init(pcie->phy); if (ret) goto phy_err; @@ -395,6 +393,7 @@ static int intel_pcie_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct intel_pcie *pcie; struct dw_pcie_rp *pp; + struct resource *res; struct dw_pcie *pci; int ret; @@ -419,6 +418,32 @@ static int intel_pcie_probe(struct platform_device *pdev) pci->ops = &intel_pcie_ops; pp->ops = &intel_pcie_dw_ops; + /* + * If the 'atu' region is not available in the devicetree, use the + * default offset from DBI region for backwards compatibility. The + * 'atu' region should always be specified in the devicetree, as + * this is a hardware-specific address that should not be defined + * in the driver. + */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu"); + if (!res) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); + pci->dbi_base = devm_pci_remap_cfg_resource(pci->dev, res); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); + + pci->dbi_phys_addr = res->start; + pci->atu_base = devm_ioremap(dev, res->start + 0xC0000, SZ_4K); + if (!pci->atu_base) { + dev_err(dev, "failed to remap ATU space\n"); + return -ENOMEM; + } + + pci->atu_size = SZ_4K; + pci->atu_phys_addr = res->start + 0xC0000; + dev_warn(dev, "ATU region not specified in DT. Using default offset\n"); + } + ret = dw_pcie_host_init(pp); if (ret) { dev_err(dev, "Cannot initialize host\n"); From e220b668b17f329476d0fcea6783bb06cceeca6d Mon Sep 17 00:00:00 2001 From: Florian Eckert Date: Fri, 17 Apr 2026 10:35:51 +0200 Subject: [PATCH 6/6] dt-bindings: PCI: intel,lgm-pcie: Add 'atu' resource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'atu' information is already set in the dwc core, if it is specified in the devicetree. The driver uses its own default, if not set in the devicetree. This information is hardware-specific and should therefore be maintained in the devicetree rather than in the source. To be backward compatible, this field is not mandatory. If 'atu' resource is not specified in the devicetree, the driver’s default value is used. Signed-off-by: Florian Eckert Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Reviewed-by: Rob Herring (Arm) Link: https://patch.msgid.link/20260417-pcie-intel-gw-v5-7-0a2b933fe04f@dev.tdt.de --- Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml b/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml index 54e2890ae631..394bb46b38e6 100644 --- a/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml +++ b/Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml @@ -27,16 +27,20 @@ properties: - const: snps,dw-pcie reg: + minItems: 3 items: - description: Controller control and status registers. - description: PCIe configuration registers. - description: Controller application registers. + - description: Internal Address Translation Unit (iATU) registers. reg-names: + minItems: 3 items: - const: dbi - const: config - const: app + - const: atu ranges: maxItems: 1 @@ -95,8 +99,9 @@ examples: #size-cells = <2>; reg = <0xd0e00000 0x1000>, <0xd2000000 0x800000>, - <0xd0a41000 0x1000>; - reg-names = "dbi", "config", "app"; + <0xd0a41000 0x1000>, + <0xd0ec0000 0x1000>; + reg-names = "dbi", "config", "app", "atu"; linux,pci-domain = <0>; max-link-speed = <4>; bus-range = <0x00 0x08>;