]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI: rzg3s-host: Add support for RZ/G3E PCIe controller
authorJohn Madieu <john.madieu.xa@bp.renesas.com>
Fri, 6 Mar 2026 14:34:19 +0000 (15:34 +0100)
committerManivannan Sadhasivam <mani@kernel.org>
Sun, 15 Mar 2026 15:50:23 +0000 (21:20 +0530)
Add support for the PCIe controller found in RZ/G3E SoCs to the existing
RZ/G3S PCIe host controller driver. The RZ/G3E PCIe controller is similar
to the RZ/G3S, with the following key differences:

 - Supports PCIe Gen3 (8.0 GT/s) link speeds alongside Gen2 (5.0 GT/s)
 - Uses a different reset control mechanism via AXI registers instead
   of the Linux reset framework
 - Requires specific SYSC configuration for link state control and
   Root Complex mode selection

Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
[mani: added a readl_relaxed() before fsleep() to flush previous write]
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-13-john.madieu.xa@bp.renesas.com
drivers/pci/controller/pcie-rzg3s-host.c

index 182f135fd5e305a9ea418690ba48d8afcdd6b12d..bfc210e696ed2055c6e2059c79d7f6a45eb61ad4 100644 (file)
 #define RZG3S_PCI_PERM_CFG_HWINIT_EN           BIT(2)
 #define RZG3S_PCI_PERM_PIPE_PHY_REG_EN         BIT(1)
 
+#define RZG3S_PCI_RESET                                0x310
+#define RZG3S_PCI_RESET_RST_OUT_B              BIT(6)
+#define RZG3S_PCI_RESET_RST_PS_B               BIT(5)
+#define RZG3S_PCI_RESET_RST_LOAD_B             BIT(4)
+#define RZG3S_PCI_RESET_RST_CFG_B              BIT(3)
+#define RZG3S_PCI_RESET_RST_RSM_B              BIT(2)
+#define RZG3S_PCI_RESET_RST_GP_B               BIT(1)
+#define RZG3S_PCI_RESET_RST_B                  BIT(0)
+
 #define RZG3S_PCI_MSIRE(id)                    (0x600 + (id) * 0x10)
 #define RZG3S_PCI_MSIRE_ENA                    BIT(0)
 
@@ -183,10 +192,14 @@ struct rzg3s_sysc_function {
 /**
  * enum rzg3s_sysc_func_id - System controller function IDs
  * @RZG3S_SYSC_FUNC_ID_RST_RSM_B: RST_RSM_B SYSC function ID
+ * @RZG3S_SYSC_FUNC_ID_L1_ALLOW: L1 allow SYSC function ID
+ * @RZG3S_SYSC_FUNC_ID_MODE: Mode SYSC function ID
  * @RZG3S_SYSC_FUNC_ID_MAX: Max SYSC function ID
  */
 enum rzg3s_sysc_func_id {
        RZG3S_SYSC_FUNC_ID_RST_RSM_B,
+       RZG3S_SYSC_FUNC_ID_L1_ALLOW,
+       RZG3S_SYSC_FUNC_ID_MODE,
        RZG3S_SYSC_FUNC_ID_MAX,
 };
 
@@ -1151,6 +1164,45 @@ static int rzg3s_pcie_config_deinit(struct rzg3s_pcie_host *host)
                                         host->cfg_resets);
 }
 
+static void rzg3e_pcie_config_pre_init(struct rzg3s_pcie_host *host)
+{
+       u32 mask = RZG3S_PCI_RESET_RST_LOAD_B | RZG3S_PCI_RESET_RST_CFG_B;
+
+       /* De-assert LOAD_B and CFG_B */
+       rzg3s_pcie_update_bits(host->axi, RZG3S_PCI_RESET, mask, mask);
+}
+
+static int rzg3e_pcie_config_deinit(struct rzg3s_pcie_host *host)
+{
+       writel_relaxed(0, host->axi + RZG3S_PCI_RESET);
+       return 0;
+}
+
+static int rzg3e_pcie_config_post_init(struct rzg3s_pcie_host *host)
+{
+       u32 mask = RZG3S_PCI_RESET_RST_PS_B | RZG3S_PCI_RESET_RST_GP_B |
+                  RZG3S_PCI_RESET_RST_B;
+
+       /* De-assert PS_B, GP_B, RST_B */
+       rzg3s_pcie_update_bits(host->axi, RZG3S_PCI_RESET, mask, mask);
+
+       /* Flush deassert */
+       readl_relaxed(host->axi + RZG3S_PCI_RESET);
+
+       /*
+        * According to the RZ/G3E HW manual (Rev.1.15, Table 6.6-130
+        * Initialization Procedure (RC)), hardware requires >= 500us delay
+        * before final reset deassert.
+        */
+       fsleep(500);
+
+       /* De-assert OUT_B and RSM_B */
+       mask = RZG3S_PCI_RESET_RST_OUT_B | RZG3S_PCI_RESET_RST_RSM_B;
+       rzg3s_pcie_update_bits(host->axi, RZG3S_PCI_RESET, mask, mask);
+
+       return 0;
+}
+
 static void rzg3s_pcie_irq_init(struct rzg3s_pcie_host *host)
 {
        /*
@@ -1312,6 +1364,12 @@ static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host)
        if (ret)
                goto config_deinit;
 
+       /* Enable ASPM L1 transition for SoCs that use it */
+       ret = rzg3s_sysc_config_func(host->sysc,
+                                    RZG3S_SYSC_FUNC_ID_L1_ALLOW, 1);
+       if (ret)
+               goto config_deinit_and_refclk;
+
        /* Initialize the interrupts */
        rzg3s_pcie_irq_init(host);
 
@@ -1659,6 +1717,11 @@ static int rzg3s_pcie_probe(struct platform_device *pdev)
                goto port_refclk_put;
        }
 
+       /* Put controller in RC mode */
+       ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_MODE, 1);
+       if (ret)
+               goto port_refclk_put;
+
        ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 1);
        if (ret)
                goto port_refclk_put;
@@ -1769,6 +1832,10 @@ static int rzg3s_pcie_resume_noirq(struct device *dev)
        struct rzg3s_sysc *sysc = host->sysc;
        int ret;
 
+       ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_MODE, 1);
+       if (ret)
+               return ret;
+
        ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 1);
        if (ret)
                return ret;
@@ -1833,11 +1900,37 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_data = {
        },
 };
 
+static const char * const rzg3e_soc_power_resets[] = { "aresetn" };
+
+static const struct rzg3s_pcie_soc_data rzg3e_soc_data = {
+       .power_resets = rzg3e_soc_power_resets,
+       .num_power_resets = ARRAY_SIZE(rzg3e_soc_power_resets),
+       .config_pre_init = rzg3e_pcie_config_pre_init,
+       .config_post_init = rzg3e_pcie_config_post_init,
+       .config_deinit = rzg3e_pcie_config_deinit,
+       .sysc_info = {
+               .functions = {
+                       [RZG3S_SYSC_FUNC_ID_L1_ALLOW] = {
+                               .offset = 0x1020,
+                               .mask = BIT(0),
+                       },
+                       [RZG3S_SYSC_FUNC_ID_MODE] = {
+                               .offset = 0x1024,
+                               .mask = BIT(0),
+                       },
+               },
+       },
+};
+
 static const struct of_device_id rzg3s_pcie_of_match[] = {
        {
                .compatible = "renesas,r9a08g045-pcie",
                .data = &rzg3s_soc_data,
        },
+       {
+               .compatible = "renesas,r9a09g047-pcie",
+               .data = &rzg3e_soc_data,
+       },
        {}
 };