From 09aad32189e4c7fa0fa624a4939acda4e4ef9ae7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 7 Jul 2026 22:35:39 +0200 Subject: [PATCH 1/4] PCI: dwc: Move iMSI-RX check before calling 'pp->ops->init()' The R-Car Gen4 PCIe controller integration configures MSI registers in the controller driver pp->ops->init() callback because they have to be configured while PERST# is asserted, and PERST# is asserted across the controller driver pp->ops->init() callback. A future change to the R-Car Gen4 pp->ops->init() callback will need to know whether iMSI-RX is in use. Assign pp->use_imsi_rx before calling pp->ops->init() so pp->use_imsi_rx is available. Signed-off-by: Marek Vasut Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260707203743.88299-2-marek.vasut+renesas@mailbox.org --- drivers/pci/controller/dwc/pcie-designware-host.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 06722259d2e3..f5a38e6fd8d7 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -587,6 +587,12 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) if (ret) return ret; + if (pci_msi_enabled()) { + pp->use_imsi_rx = !(pp->ops->msi_init || + of_property_present(np, "msi-parent") || + of_property_present(np, "msi-map")); + } + if (pp->ops->init) { ret = pp->ops->init(pp); if (ret) @@ -594,10 +600,6 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp) } if (pci_msi_enabled()) { - pp->use_imsi_rx = !(pp->ops->msi_init || - of_property_present(np, "msi-parent") || - of_property_present(np, "msi-map")); - /* * For the use_imsi_rx case the default assignment is handled * in the dw_pcie_msi_host_init(). From 8d6af27c0a73a49ff80555a37de3bca8f04c7849 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 7 Jul 2026 22:35:40 +0200 Subject: [PATCH 2/4] PCI: rcar-gen4: Configure AXIINTC if iMSI-RX is not used When MSI is enabled but the DWC built-in iMSI-RX is not used, MSI must be handled via the GIC ITS. Configure all controller MSI registers accordingly. Set or clear the MSICAP0 MSIE bit and the PCIEINTSTS0EN MSI_CTRL_INT bit based on the MSI enable state. Set both bits when MSI is enabled. Clear both bits when MSI is disabled. When MSI is disabled, or when MSI is enabled together with iMSI-RX, clear AXIINTCADDR and AXIINTCCONT to disable any pass through of MSI TLPs onto the AXI bus and further into the GIC ITS translation registers. When MSI is enabled and iMSI-RX is not used, program AXIINTCADDR with the target address of the GIC ITS translation register, and program AXIINTCCONT to enable MSI TLP pass through onto the AXI bus and into the GIC ITS. This configuration allows the GIC ITS to handle MSI instead of the integrated iMSI-RX. The driver includes linux/irqchip/arm-gic-v3.h which pulls in headers which are available only on ARM and ARM64, on other architectures the headers are not present and the driver fails to build. This driver is used only on ARM64 hardware, so isolate its build only to ARM64 to avoid build failures on other architectures. Co-developed-by: Yoshihiro Shimoda Signed-off-by: Yoshihiro Shimoda Signed-off-by: Marek Vasut [mani: commit log and squashed the Kconfig fix: https://patch.msgid.link/20260714131957.38067-1-marek.vasut+renesas@mailbox.org] Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Link: https://patch.msgid.link/20260707203743.88299-3-marek.vasut+renesas@mailbox.org --- drivers/pci/controller/dwc/Kconfig | 4 +- drivers/pci/controller/dwc/pcie-rcar-gen4.c | 118 +++++++++++++++++++- 2 files changed, 115 insertions(+), 7 deletions(-) diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index aa0b784c85b4..0d4bf8d4cf56 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -344,7 +344,7 @@ config PCIE_RCAR_GEN4 config PCIE_RCAR_GEN4_HOST tristate "Renesas R-Car Gen4 PCIe controller (host mode)" - depends on ARCH_RENESAS || COMPILE_TEST + depends on ARM64 && (ARCH_RENESAS || COMPILE_TEST) depends on PCI_MSI select PCIE_DW_HOST select PCIE_RCAR_GEN4 @@ -355,7 +355,7 @@ config PCIE_RCAR_GEN4_HOST config PCIE_RCAR_GEN4_EP tristate "Renesas R-Car Gen4 PCIe controller (endpoint mode)" - depends on ARCH_RENESAS || COMPILE_TEST + depends on ARM64 && (ARCH_RENESAS || COMPILE_TEST) depends on PCI_ENDPOINT select PCIE_DW_EP select PCIE_RCAR_GEN4 diff --git a/drivers/pci/controller/dwc/pcie-rcar-gen4.c b/drivers/pci/controller/dwc/pcie-rcar-gen4.c index 8b03c42f8c84..5f7211b91ee5 100644 --- a/drivers/pci/controller/dwc/pcie-rcar-gen4.c +++ b/drivers/pci/controller/dwc/pcie-rcar-gen4.c @@ -13,8 +13,11 @@ #include #include #include +#include #include #include +#include +#include #include #include #include @@ -31,6 +34,10 @@ #define DEVICE_TYPE_RC BIT(4) #define BIFUR_MOD_SET_ON BIT(0) +/* MSI Capability */ +#define MSICAP0 0x0050 +#define MSICAP0_MSIE BIT(16) + /* PCIe Interrupt Status 0 */ #define PCIEINTSTS0 0x0084 @@ -55,6 +62,14 @@ #define APP_HOLD_PHY_RST BIT(16) #define APP_LTSSM_ENABLE BIT(0) +/* INTC address */ +#define AXIINTCADDR 0x0a00 + +/* INTC control & mask */ +#define AXIINTCCONT 0x0a04 +#define INTC_EN BIT(31) +#define INTC_MASK GENMASK(11, 3) + /* PCIe Power Management Control */ #define PCIEPWRMNGCTRL 0x0070 #define APP_CLK_REQ_N BIT(11) @@ -305,13 +320,103 @@ static struct rcar_gen4_pcie *rcar_gen4_pcie_alloc(struct platform_device *pdev) return rcar; } +static int rcar_gen4_pcie_host_msi_addr(struct dw_pcie_rp *pp, u32 *msi_addr) +{ + struct dw_pcie *dw = to_dw_pcie_from_pp(pp); + struct device_node *msi_node = NULL; + struct device *dev = dw->dev; + struct resource res; + u64 addr; + int ret; + + /* + * Either the "msi-parent" or the "msi-map" phandle needs to exist + * to obtain the MSI node. + */ + of_msi_xlate(dev, &msi_node, 0); + if (!msi_node) + return -ENODEV; + + /* Check if "msi-parent" or the "msi-map" points to ARM GICv3 ITS. */ + if (!of_device_is_compatible(msi_node, "arm,gic-v3-its")) + return dev_err_probe(dev, -ENODEV, "Compatible MSI controller not found\n"); + + /* Derive GITS_TRANSLATER address from GICv3 */ + ret = of_address_to_resource(msi_node, 0, &res); + if (ret < 0) + return dev_err_probe(dev, ret, "MSI controller resources not obtained\n"); + + addr = res.start + GITS_TRANSLATER; + if (addr >= SZ_4G) + return dev_err_probe(dev, -EINVAL, "MSI controller address above 32bit range\n"); + + *msi_addr = addr; + return 0; +} + +static int rcar_gen4_pcie_host_msi_init(struct dw_pcie_rp *pp) +{ + struct dw_pcie *dw = to_dw_pcie_from_pp(pp); + struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw); + u32 val; + int ret; + + /* Make sure MSICAP0 MSIE is configured. */ + val = dw_pcie_readl_dbi(dw, MSICAP0); + if (pci_msi_enabled()) + val |= MSICAP0_MSIE; + else + val &= ~MSICAP0_MSIE; + dw_pcie_writel_dbi(dw, MSICAP0, val); + + if (!pci_msi_enabled() || pp->use_imsi_rx) { + /* Clear AXIINTC mapping. */ + writel(0, rcar->base + AXIINTCADDR); + writel(0, rcar->base + AXIINTCCONT); + } else { + ret = rcar_gen4_pcie_host_msi_addr(pp, &val); + if (ret) + goto err; + + /* Point AXIINTC to GIC ITS and enable. */ + writel(val, rcar->base + AXIINTCADDR); + writel(INTC_EN | INTC_MASK, rcar->base + AXIINTCCONT); + } + + /* Configure MSI interrupt signal */ + val = readl(rcar->base + PCIEINTSTS0EN); + if (pci_msi_enabled()) + val |= MSI_CTRL_INT; + else + val &= ~MSI_CTRL_INT; + writel(val, rcar->base + PCIEINTSTS0EN); + + return 0; + +err: + /* Deconfigure MSICAP0 MSIE. */ + val = dw_pcie_readl_dbi(dw, MSICAP0); + val &= ~MSICAP0_MSIE; + dw_pcie_writel_dbi(dw, MSICAP0, val); + + /* Clear AXIINTC mapping. */ + writel(0, rcar->base + AXIINTCADDR); + writel(0, rcar->base + AXIINTCCONT); + + /* Deconfigure MSI interrupt signal */ + val = readl(rcar->base + PCIEINTSTS0EN); + val &= ~MSI_CTRL_INT; + writel(val, rcar->base + PCIEINTSTS0EN); + + return ret; +} + /* Host mode */ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp) { struct dw_pcie *dw = to_dw_pcie_from_pp(pp); struct rcar_gen4_pcie *rcar = to_rcar_gen4_pcie(dw); int ret; - u32 val; gpiod_set_value_cansleep(dw->pe_rst, 1); @@ -328,16 +433,19 @@ static int rcar_gen4_pcie_host_init(struct dw_pcie_rp *pp) dw_pcie_writel_dbi2(dw, PCI_BASE_ADDRESS_0, 0x0); dw_pcie_writel_dbi2(dw, PCI_BASE_ADDRESS_1, 0x0); - /* Enable MSI interrupt signal */ - val = readl(rcar->base + PCIEINTSTS0EN); - val |= MSI_CTRL_INT; - writel(val, rcar->base + PCIEINTSTS0EN); + ret = rcar_gen4_pcie_host_msi_init(pp); + if (ret) + goto err; msleep(PCIE_T_PVPERL_MS); /* pe_rst requires 100msec delay */ gpiod_set_value_cansleep(dw->pe_rst, 0); return 0; + +err: + rcar_gen4_pcie_common_deinit(rcar); + return ret; } static void rcar_gen4_pcie_host_deinit(struct dw_pcie_rp *pp) From ee83126141801f5109b6ea39afe64f7c9a29015a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 7 Jul 2026 22:35:41 +0200 Subject: [PATCH 3/4] irqchip/gic-v3: Refactor GIC600 limited to 32bit PA erratum handling The GIC600 implementation is now known to be used on multiple 64-bit SoCs, where it has address width for AXI or APB interface configured to 32 bit, and it can access only the first 4GiB of physical address space. Rework the handling of the quirk to work around this limitation such that new entries can be added purely as new compatible strings, with no need to add additional functions or new its_quirk array entries. Suggested-by: Marc Zyngier Signed-off-by: Marek Vasut Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Acked-by: Marc Zyngier Link: https://patch.msgid.link/20260707203743.88299-4-marek.vasut+renesas@mailbox.org --- drivers/irqchip/irq-gic-v3-its.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index b57d81ad33a0..6409d37d7871 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -4890,10 +4890,17 @@ static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data) return true; } -static bool __maybe_unused its_enable_rk3568002(void *data) +static const char * const dma_32bit_impaired_platforms[] = { +#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002 + "rockchip,rk3566", + "rockchip,rk3568", +#endif + NULL, +}; + +static bool its_enable_dma32(void *data) { - if (!of_machine_is_compatible("rockchip,rk3566") && - !of_machine_is_compatible("rockchip,rk3568")) + if (!of_machine_compatible_match(dma_32bit_impaired_platforms)) return false; gfp_flags_quirk |= GFP_DMA32; @@ -4968,14 +4975,12 @@ static const struct gic_quirk its_quirks[] = { .property = "dma-noncoherent", .init = its_set_non_coherent, }, -#ifdef CONFIG_ROCKCHIP_ERRATUM_3568002 { - .desc = "ITS: Rockchip erratum RK3568002", + .desc = "ITS: Broken GIC600 integration limited to 32bit PA", .iidr = 0x0201743b, .mask = 0xffffffff, - .init = its_enable_rk3568002, + .init = its_enable_dma32, }, -#endif { } }; From a8818827486cd303f63be6ceadd949f64665938f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 7 Jul 2026 22:35:42 +0200 Subject: [PATCH 4/4] irqchip/gic-v3: Add Renesas R-Car Gen4 erratum workaround Renesas R-Car S4/V4H/V4M GIC600 integration has address width for AXI or APB interface configured to 32 bit, it can therefore access only the first 4 GiB of physical address space. This information comes from R-Car V4H Interface Specification sheet; there is currently no technical update number assigned to this limitation. Further input from hardware engineer indicates that this limitation also applies to R-Car S4 and V4M. Name the limitation GEN4GICITS1, and add a driver quirk to mitigate this limitation. The quirk is keyed on the combination of the GIC implementation and the platform identification in the device tree. Co-developed-by: Yoshihiro Shimoda Signed-off-by: Yoshihiro Shimoda Signed-off-by: Marek Vasut Signed-off-by: Manivannan Sadhasivam Signed-off-by: Bjorn Helgaas Acked-by: Marc Zyngier Acked-by: Thomas Gleixner Link: https://patch.msgid.link/20260707203743.88299-5-marek.vasut+renesas@mailbox.org --- Documentation/arch/arm64/silicon-errata.rst | 1 + arch/arm64/Kconfig | 9 +++++++++ drivers/irqchip/irq-gic-v3-its.c | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst index 014aa1c215a1..b0c68b64f5ac 100644 --- a/Documentation/arch/arm64/silicon-errata.rst +++ b/Documentation/arch/arm64/silicon-errata.rst @@ -352,6 +352,7 @@ stable kernels. +----------------+-----------------+-----------------+-----------------------------+ | Qualcomm Tech. | Kryo4xx Gold | N/A | ARM64_ERRATUM_1286807 | +----------------+-----------------+-----------------+-----------------------------+ +| Renesas | S4/V4H/V4M | N/A | RENESAS_ERRATUM_GEN4GICITS1 | +----------------+-----------------+-----------------+-----------------------------+ | Rockchip | RK3588 | #3588001 | ROCKCHIP_ERRATUM_3588001 | +----------------+-----------------+-----------------+-----------------------------+ diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b3afe0688919..b9e17ce475e6 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1382,6 +1382,15 @@ config NVIDIA_CARMEL_CNP_ERRATUM If unsure, say Y. +config RENESAS_ERRATUM_GEN4GICITS1 + bool "Renesas R-Car Gen4: GIC600 can not access physical addresses above 4 GiB" + default y + help + The Renesas R-Car Gen4 S4/V4H/V4M GIC600 SoC integrations have AXI + addressing limited to the first 32-bit of physical address space. + + If unsure, say Y. + config ROCKCHIP_ERRATUM_3568002 bool "Rockchip 3568002: GIC600 can not access physical addresses higher than 4GB" default y diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 6409d37d7871..fdc693602b4e 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -4891,6 +4891,11 @@ static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data) } static const char * const dma_32bit_impaired_platforms[] = { +#ifdef CONFIG_RENESAS_ERRATUM_GEN4GICITS1 + "renesas,r8a779f0", + "renesas,r8a779g0", + "renesas,r8a779h0", +#endif #ifdef CONFIG_ROCKCHIP_ERRATUM_3568002 "rockchip,rk3566", "rockchip,rk3568",