diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2026-10-21 13:20:37 -0500 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-10-21 13:20:37 -0500 |
| commit | f561825595f69acbdfead2e9352c4e9efb1ec8a8 (patch) | |
| tree | aec094d7ce16e1543a02b34c46205d5df497edb7 | |
| parent | 29f5f43baa1395e07c61bb4a81504cb6e383181e (diff) | |
| parent | c56d39e0f68d49ee45e610714bcfc87e14208498 (diff) | |
| download | linux-f561825595f69acbdfead2e9352c4e9efb1ec8a8.tar.gz linux-f561825595f69acbdfead2e9352c4e9efb1ec8a8.zip | |
Merge branch 'pci/controller/rzg3s-host'
- Disable refclk on probe failure (Lad Prabhakar)
- Propagate platform_get_irq_byname() errors so probe deferral works
correctly (Lad Prabhakar)
- Tear down INTx handlers if subsequent initialization fails (Lad
Prabhakar)
- Add RZ/G3L (R9A08G046) DT and driver support (Biju Das)
* pci/controller/rzg3s-host:
PCI: rzg3s-host: Add support for RZ/G3L SoC
dt-bindings: PCI: renesas,r9a08g045s33-pcie: Document RZ/G3L SoC
PCI: rzg3s: Fix IRQ domain initialization error handling
PCI: rzg3s: Propagate platform_get_irq_byname() errors
PCI: rzg3s: Disable refclk on probe failure
| -rw-r--r-- | Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml | 33 | ||||
| -rw-r--r-- | drivers/pci/controller/pcie-rzg3s-host.c | 76 |
2 files changed, 93 insertions, 16 deletions
diff --git a/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml b/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml index 09d78bd1a577..7827d81680fe 100644 --- a/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml +++ b/Documentation/devicetree/bindings/pci/renesas,r9a08g045-pcie.yaml @@ -13,7 +13,7 @@ description: | PCIe host controller found in Renesas RZ/G3S and similar SoCs complies with PCIe Base Specification 4.0 and supports different link speeds depending on the SoC variant: - - Gen2 (5 GT/s): RZ/G3S + - Gen2 (5 GT/s): RZ/G3{L,S} - Gen3 (8 GT/s): RZ/G3E, RZ/V2H(P), RZ/V2N properties: @@ -21,6 +21,7 @@ properties: oneOf: - enum: - renesas,r9a08g045-pcie # RZ/G3S + - renesas,r9a08g046-pcie # RZ/G3L - renesas,r9a09g047-pcie # RZ/G3E - renesas,r9a09g057-pcie # RZ/V2H(P) - items: @@ -87,14 +88,18 @@ properties: interrupt-controller: true clocks: + minItems: 2 items: - description: System clock - description: PM control clock or clock for L1 substate handling + - description: PM control clock clock-names: + minItems: 2 items: - const: aclk - enum: [pm, pmu] + - const: pmu resets: minItems: 1 @@ -215,6 +220,8 @@ allOf: maxItems: 16 interrupt-names: maxItems: 16 + clocks: + maxItems: 2 clock-names: items: - const: aclk @@ -227,6 +234,28 @@ allOf: properties: compatible: contains: + const: renesas,r9a08g046-pcie + then: + properties: + interrupts: + maxItems: 16 + interrupt-names: + maxItems: 16 + clocks: + minItems: 3 + clock-names: + items: + - const: aclk + - const: pm + - const: pmu + resets: + maxItems: 1 + reset-names: + maxItems: 1 + - if: + properties: + compatible: + contains: enum: - renesas,r9a09g047-pcie - renesas,r9a09g057-pcie @@ -236,6 +265,8 @@ allOf: minItems: 23 interrupt-names: minItems: 23 + clocks: + maxItems: 2 clock-names: items: - const: aclk diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c index a1a78bdb7af1..077cfb0834b3 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -1006,22 +1006,38 @@ static const struct irq_domain_ops rzg3s_pcie_intx_domain_ops = { .xlate = irq_domain_xlate_onetwocell, }; +static void rzg3s_pcie_teardown_intx(struct rzg3s_pcie_host *host, + int count) +{ + while (--count >= 0) { + irq_set_chained_handler_and_data(host->intx_irqs[count], NULL, + NULL); + } + + if (host->intx_domain) + irq_domain_remove(host->intx_domain); +} + static int rzg3s_pcie_init_irqdomain(struct rzg3s_pcie_host *host) { struct device *dev = host->dev; struct platform_device *pdev = to_platform_device(dev); + int i, ret; - for (int i = 0; i < PCI_NUM_INTX; i++) { + for (i = 0; i < PCI_NUM_INTX; i++) { char irq_name[5] = {0}; int irq; scnprintf(irq_name, ARRAY_SIZE(irq_name), "int%c", 'a' + i); irq = platform_get_irq_byname(pdev, irq_name); - if (irq < 0) - return dev_err_probe(dev, -EINVAL, - "Failed to parse and map INT%c IRQ\n", - 'A' + i); + if (irq < 0) { + ret = irq; + dev_err_probe(dev, ret, + "Failed to parse and map INT%c IRQ\n", + 'A' + i); + goto teardown_intx; + } host->intx_irqs[i] = irq; irq_set_chained_handler_and_data(irq, @@ -1033,21 +1049,27 @@ static int rzg3s_pcie_init_irqdomain(struct rzg3s_pcie_host *host) PCI_NUM_INTX, &rzg3s_pcie_intx_domain_ops, host); - if (!host->intx_domain) - return dev_err_probe(dev, -EINVAL, - "Failed to add irq domain for INTx IRQs\n"); + if (!host->intx_domain) { + ret = -EINVAL; + dev_err_probe(dev, ret, + "Failed to add irq domain for INTx IRQs\n"); + goto teardown_intx; + } irq_domain_update_bus_token(host->intx_domain, DOMAIN_BUS_WIRED); if (IS_ENABLED(CONFIG_PCI_MSI)) { - int ret = rzg3s_pcie_init_msi(host); + ret = rzg3s_pcie_init_msi(host); - if (ret) { - irq_domain_remove(host->intx_domain); - return ret; - } + if (ret) + goto teardown_intx; } return 0; + +teardown_intx: + rzg3s_pcie_teardown_intx(host, i); + + return ret; } static void rzg3s_pcie_teardown_irqdomain(struct rzg3s_pcie_host *host) @@ -1055,7 +1077,7 @@ static void rzg3s_pcie_teardown_irqdomain(struct rzg3s_pcie_host *host) if (IS_ENABLED(CONFIG_PCI_MSI)) rzg3s_pcie_teardown_msi(host); - irq_domain_remove(host->intx_domain); + rzg3s_pcie_teardown_intx(host, PCI_NUM_INTX); } static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) @@ -1077,7 +1099,7 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) FIELD_GET(RZG3S_PCI_PCSTAT1_LTSSM_STATE, tmp) == ltssm_state_l0, PCIE_LINK_WAIT_SLEEP_MS * MILLI, PCIE_LINK_WAIT_SLEEP_MS * MILLI * - PCIE_LINK_WAIT_MAX_RETRIES); + PCIE_LINK_WAIT_MAX_RETRIES * 10); if (ret) return ret; @@ -1897,6 +1919,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev) return 0; host_probe_teardown: + clk_disable_unprepare(host->port.refclk); rzg3s_pcie_teardown_irqdomain(host); host->data->config_deinit(host); rpm_put: @@ -2074,6 +2097,25 @@ static const struct rzg3s_pcie_soc_data rzg3e_soc_data = { }, }; +static const struct rzg3s_pcie_soc_data rzg3l_soc_data = { + .power_resets = rzg3e_soc_power_resets, + .num_power_resets = ARRAY_SIZE(rzg3e_soc_power_resets), + .num_pcie_controllers = 1, + .config_pre_init = rzg3e_pcie_config_pre_init, + .config_post_init = rzg3e_pcie_config_post_init, + .config_deinit = rzg3e_pcie_config_deinit, + .sysc_info = { + [RZG3S_PCIE_CONTROLLER_ID_0] = { + .functions = { + [RZG3S_SYSC_FUNC_ID_L1_ALLOW] = { + .offset = 0x3a0, + .mask = BIT(8), + }, + }, + }, + }, +}; + static const struct rzg3s_pcie_soc_data rzv2h_soc_data = { .power_resets = rzg3e_soc_power_resets, .num_power_resets = ARRAY_SIZE(rzg3e_soc_power_resets), @@ -2124,6 +2166,10 @@ static const struct of_device_id rzg3s_pcie_of_match[] = { .data = &rzg3s_soc_data, }, { + .compatible = "renesas,r9a08g046-pcie", + .data = &rzg3l_soc_data, + }, + { .compatible = "renesas,r9a09g047-pcie", .data = &rzg3e_soc_data, }, |
