summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2026-10-21 13:20:37 -0500
committerBjorn Helgaas <bhelgaas@google.com>2026-10-21 13:20:37 -0500
commitf561825595f69acbdfead2e9352c4e9efb1ec8a8 (patch)
treeaec094d7ce16e1543a02b34c46205d5df497edb7
parent29f5f43baa1395e07c61bb4a81504cb6e383181e (diff)
parentc56d39e0f68d49ee45e610714bcfc87e14208498 (diff)
downloadlinux-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.yaml33
-rw-r--r--drivers/pci/controller/pcie-rzg3s-host.c76
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,
},