]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: rzg3s-host: Add SoC-specific configuration and initialization callbacks
authorJohn Madieu <john.madieu.xa@bp.renesas.com>
Fri, 6 Mar 2026 14:34:16 +0000 (15:34 +0100)
committerManivannan Sadhasivam <mani@kernel.org>
Sun, 15 Mar 2026 15:38:41 +0000 (21:08 +0530)
Add optional cfg_pre_init, cfg_post_init, and cfg_deinit callbacks
to handle SoC-specific configuration methods. While RZ/G3S uses the Linux
reset framework with dedicated reset lines, other SoC variants like RZ/G3E
control configuration resets through PCIe AXI registers.

As Linux reset bulk API gracefully handles optional NULL reset lines
(num_cfg_resets = 0 for RZ/G3E), the driver continues to use the standard
reset framework when reset lines are available, while custom callbacks
are only invoked when provided.

This provides a balanced pattern where:
- RZ/G3S: Uses callbacks that fall back to the reset framework
- RZ/G3E: Sets num_cfg_resets=0, provides
  cfg_pre_init/cfg_post_init/cfg_deinit

Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
Signed-off-by: Manivannan Sadhasivam <mani@kernel.org>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> # RZ/V2N EVK
Tested-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Reviewed-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Link: https://patch.msgid.link/20260306143423.19562-10-john.madieu.xa@bp.renesas.com
drivers/pci/controller/pcie-rzg3s-host.c

index c818651c0b750ec6ec155d4e5d3e3788f4c8e4db..be6b7fa1a053f38526c75d4b2774ac34885832b2 100644 (file)
@@ -233,6 +233,9 @@ struct rzg3s_pcie_host;
 /**
  * struct rzg3s_pcie_soc_data - SoC specific data
  * @init_phy: PHY initialization function
+ * @config_pre_init: Optional callback for SoC-specific pre-configuration
+ * @config_post_init: Callback for SoC-specific post-configuration
+ * @config_deinit: Callback for SoC-specific de-initialization
  * @power_resets: array with the resets that need to be de-asserted after
  *                power-on
  * @cfg_resets: array with the resets that need to be de-asserted after
@@ -243,6 +246,9 @@ struct rzg3s_pcie_host;
  */
 struct rzg3s_pcie_soc_data {
        int (*init_phy)(struct rzg3s_pcie_host *host);
+       void (*config_pre_init)(struct rzg3s_pcie_host *host);
+       int (*config_post_init)(struct rzg3s_pcie_host *host);
+       int (*config_deinit)(struct rzg3s_pcie_host *host);
        const char * const *power_resets;
        const char * const *cfg_resets;
        struct rzg3s_sysc_info sysc_info;
@@ -1109,6 +1115,18 @@ static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host)
        return 0;
 }
 
+static int rzg3s_pcie_config_post_init(struct rzg3s_pcie_host *host)
+{
+       return reset_control_bulk_deassert(host->data->num_cfg_resets,
+                                          host->cfg_resets);
+}
+
+static int rzg3s_pcie_config_deinit(struct rzg3s_pcie_host *host)
+{
+       return reset_control_bulk_assert(host->data->num_cfg_resets,
+                                        host->cfg_resets);
+}
+
 static void rzg3s_pcie_irq_init(struct rzg3s_pcie_host *host)
 {
        /*
@@ -1257,22 +1275,26 @@ static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host)
        u32 val;
        int ret;
 
+       /* SoC-specific pre-configuration */
+       if (host->data->config_pre_init)
+               host->data->config_pre_init(host);
+
        /* Initialize the PCIe related registers */
        ret = rzg3s_pcie_config_init(host);
        if (ret)
-               return ret;
+               goto config_deinit;
 
        ret = rzg3s_pcie_host_init_port(host);
        if (ret)
-               return ret;
+               goto config_deinit;
 
        /* Initialize the interrupts */
        rzg3s_pcie_irq_init(host);
 
-       ret = reset_control_bulk_deassert(host->data->num_cfg_resets,
-                                         host->cfg_resets);
+       /* SoC-specific post-configuration */
+       ret = host->data->config_post_init(host);
        if (ret)
-               goto disable_port_refclk;
+               goto config_deinit_and_refclk;
 
        /* Wait for link up */
        ret = readl_poll_timeout(host->axi + RZG3S_PCI_PCSTAT1, val,
@@ -1281,18 +1303,20 @@ static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host)
                                 PCIE_LINK_WAIT_SLEEP_MS * MILLI *
                                 PCIE_LINK_WAIT_MAX_RETRIES);
        if (ret)
-               goto cfg_resets_deassert;
+               goto config_deinit_post;
 
        val = readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2);
        dev_info(host->dev, "PCIe link status [0x%x]\n", val);
 
        return 0;
 
-cfg_resets_deassert:
-       reset_control_bulk_assert(host->data->num_cfg_resets,
-                                 host->cfg_resets);
-disable_port_refclk:
+config_deinit_post:
+       host->data->config_deinit(host);
+config_deinit_and_refclk:
        clk_disable_unprepare(host->port.refclk);
+config_deinit:
+       if (host->data->config_pre_init)
+               host->data->config_deinit(host);
        return ret;
 }
 
@@ -1653,7 +1677,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
 
 host_probe_teardown:
        rzg3s_pcie_teardown_irqdomain(host);
-       reset_control_bulk_assert(host->data->num_cfg_resets, host->cfg_resets);
+       host->data->config_deinit(host);
 rpm_put:
        pm_runtime_put_sync(dev);
 rpm_disable:
@@ -1686,15 +1710,15 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev)
 
        clk_disable_unprepare(port->refclk);
 
-       ret = reset_control_bulk_assert(data->num_cfg_resets,
-                                       host->cfg_resets);
+       /* SoC-specific de-initialization */
+       ret = data->config_deinit(host);
        if (ret)
                goto refclk_restore;
 
        ret = reset_control_bulk_assert(data->num_power_resets,
                                        host->power_resets);
        if (ret)
-               goto cfg_resets_restore;
+               goto config_reinit;
 
        ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0);
        if (ret)
@@ -1706,9 +1730,10 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev)
 power_resets_restore:
        reset_control_bulk_deassert(data->num_power_resets,
                                    host->power_resets);
-cfg_resets_restore:
-       reset_control_bulk_deassert(data->num_cfg_resets,
-                                   host->cfg_resets);
+config_reinit:
+       if (data->config_pre_init)
+               data->config_pre_init(host);
+       data->config_post_init(host);
 refclk_restore:
        clk_prepare_enable(port->refclk);
        pm_runtime_resume_and_get(dev);
@@ -1773,6 +1798,8 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_data = {
        .num_power_resets = ARRAY_SIZE(rzg3s_soc_power_resets),
        .cfg_resets = rzg3s_soc_cfg_resets,
        .num_cfg_resets = ARRAY_SIZE(rzg3s_soc_cfg_resets),
+       .config_post_init = rzg3s_pcie_config_post_init,
+       .config_deinit = rzg3s_pcie_config_deinit,
        .init_phy = rzg3s_soc_pcie_init_phy,
        .sysc_info = {
                .functions = {