[PATCH v5 13/16] PCI: rzg3s-host: Add support for RZ/G3E PCIe controller
From: John Madieu <john.madieu.xa@bp.renesas.com>
Date: 2026-02-10 11:33:30
Also in:
linux-clk, linux-pci, linux-renesas-soc
Subsystem:
pci native host bridge and endpoint drivers, pci subsystem, pcie driver for renesas rz/g3s series, the rest · Maintainers:
Lorenzo Pieralisi, Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Helgaas, Claudiu Beznea, Linus Torvalds
Add support for the PCIe controller found in RZ/G3E SoCs to the existing RZ/G3S PCIe host driver. The RZ/G3E PCIe controller is similar to the RZ/G3S's, 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> --- Changes: v5: - Introduce rzg3s_sysc_config() helper for sys configuration v4: No changes v3: No changes v2: Collected tag. drivers/pci/controller/pcie-rzg3s-host.c | 152 ++++++++++++++++++++--- 1 file changed, 137 insertions(+), 15 deletions(-)
diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c
index 22858a876fd8..77313cc01c02 100644
--- a/drivers/pci/controller/pcie-rzg3s-host.c
+++ b/drivers/pci/controller/pcie-rzg3s-host.c@@ -111,6 +111,16 @@ #define RZG3S_PCI_PERM_CFG_HWINIT_EN BIT(2) #define RZG3S_PCI_PERM_PIPE_PHY_REG_EN BIT(1) +/* RZ/G3E specific registers */ +#define RZG3E_PCI_RESET 0x310 +#define RZG3E_PCI_RESET_RST_OUT_B BIT(6) +#define RZG3E_PCI_RESET_RST_PS_B BIT(5) +#define RZG3E_PCI_RESET_RST_LOAD_B BIT(4) +#define RZG3E_PCI_RESET_RST_CFG_B BIT(3) +#define RZG3E_PCI_RESET_RST_RSM_B BIT(2) +#define RZG3E_PCI_RESET_RST_GP_B BIT(1) +#define RZG3E_PCI_RESET_RST_B BIT(0) + #define RZG3S_PCI_MSIRE(id) (0x600 + (id) * 0x10) #define RZG3S_PCI_MSIRE_ENA BIT(0)
@@ -183,9 +193,13 @@ struct rzg3s_sysc_function { /** * struct rzg3s_sysc_info - RZ/G3S System Controller function info * @rst_rsm_b: Reset RSM_B function descriptor + * @l1_allow: L1 power state management function descriptor + * @mode: Mode configuration function descriptor */ struct rzg3s_sysc_info { struct rzg3s_sysc_function rst_rsm_b; + struct rzg3s_sysc_function l1_allow; + struct rzg3s_sysc_function mode; }; /**
@@ -1124,6 +1138,49 @@ static int rzg3s_config_deinit(struct rzg3s_pcie_host *host) host->cfg_resets); } +/* RZ/G3E SoC-specific config implementations */ +static void rzg3e_pcie_config_pre_init(struct rzg3s_pcie_host *host) +{ + /* + * De-assert LOAD_B and CFG_B during configuration phase. + * These are part of the RZ/G3E reset register, not reset framework. + * Other reset bits remain asserted until config_post_init. + */ + rzg3s_pcie_update_bits(host->axi, RZG3E_PCI_RESET, + RZG3E_PCI_RESET_RST_LOAD_B | RZG3E_PCI_RESET_RST_CFG_B, + RZG3E_PCI_RESET_RST_LOAD_B | RZG3E_PCI_RESET_RST_CFG_B); +} + +static int rzg3e_config_deinit(struct rzg3s_pcie_host *host) +{ + writel_relaxed(0, host->axi + RZG3E_PCI_RESET); + return 0; +} + +static int rzg3e_config_post_init(struct rzg3s_pcie_host *host) +{ + /* De-assert PS_B, GP_B, RST_B */ + rzg3s_pcie_update_bits(host->axi, RZG3E_PCI_RESET, + RZG3E_PCI_RESET_RST_PS_B | RZG3E_PCI_RESET_RST_GP_B | + RZG3E_PCI_RESET_RST_B, + RZG3E_PCI_RESET_RST_PS_B | RZG3E_PCI_RESET_RST_GP_B | + RZG3E_PCI_RESET_RST_B); + + /* + * 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 to complete reset sequence */ + rzg3s_pcie_update_bits(host->axi, RZG3E_PCI_RESET, + RZG3E_PCI_RESET_RST_OUT_B | RZG3E_PCI_RESET_RST_RSM_B, + RZG3E_PCI_RESET_RST_OUT_B | RZG3E_PCI_RESET_RST_RSM_B); + + return 0; +} + static void rzg3s_pcie_irq_init(struct rzg3s_pcie_host *host) { /*
@@ -1266,6 +1323,47 @@ static int rzg3s_pcie_host_init_port(struct rzg3s_pcie_host *host) return ret; } +/** + * rzg3s_sysc_config - Configure SYSC registers for PCIe + * @sysc: SYSC descriptor + * @mode: Mode value to set (-1 to skip) + * @rsm_b: RST_RSM_B value to set (-1 to skip) + * @l1_allow: L1_ALLOW value to set (-1 to skip) + * + * Return: 0 on success, negative error code on failure + */ +static int rzg3s_sysc_config(struct rzg3s_sysc *sysc, int mode, int rsm_b, + int l1_allow) +{ + const struct rzg3s_sysc_info *info = sysc->info; + int ret; + + if (mode >= 0 && info->mode.mask) { + ret = regmap_write(sysc->regmap, info->mode.offset, + field_prep(info->mode.mask, mode)); + if (ret) + return ret; + } + + if (rsm_b >= 0 && info->rst_rsm_b.mask) { + ret = regmap_update_bits(sysc->regmap, info->rst_rsm_b.offset, + info->rst_rsm_b.mask, + field_prep(info->rst_rsm_b.mask, rsm_b)); + if (ret) + return ret; + } + + if (l1_allow >= 0 && info->l1_allow.mask) { + ret = regmap_update_bits(sysc->regmap, info->l1_allow.offset, + info->l1_allow.mask, + field_prep(info->l1_allow.mask, l1_allow)); + if (ret) + return ret; + } + + return 0; +} + static int rzg3s_pcie_host_init(struct rzg3s_pcie_host *host) { u32 val;
@@ -1284,6 +1382,11 @@ 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(host->sysc, -1, -1, 1); + if (ret) + goto config_deinit; + /* Initialize the interrupts */ rzg3s_pcie_irq_init(host);
@@ -1631,9 +1734,12 @@ static int rzg3s_pcie_probe(struct platform_device *pdev) goto port_refclk_put; } - ret = regmap_update_bits(sysc->regmap, sysc->info->rst_rsm_b.offset, - sysc->info->rst_rsm_b.mask, - field_prep(sysc->info->rst_rsm_b.mask, 1)); + /* + * Put controller in RC (Root Complex) mode for SoCs that + * support it. These can operate in either EP or RC mode. + * While at it, do also de-assert RST_RSM_B. + */ + ret = rzg3s_sysc_config(sysc, 1, 1, -1); if (ret) goto port_refclk_put;
@@ -1685,9 +1791,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev) * SYSC RST_RSM_B signal need to be asserted before turning off the * power to the PHY. */ - regmap_update_bits(sysc->regmap, sysc->info->rst_rsm_b.offset, - sysc->info->rst_rsm_b.mask, - field_prep(sysc->info->rst_rsm_b.mask, 0)); + rzg3s_sysc_config(sysc, -1, 0, -1); port_refclk_put: clk_put(host->port.refclk);
@@ -1718,9 +1822,7 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev) if (ret) goto config_reinit; - ret = regmap_update_bits(sysc->regmap, sysc->info->rst_rsm_b.offset, - sysc->info->rst_rsm_b.mask, - field_prep(sysc->info->rst_rsm_b.mask, 0)); + ret = rzg3s_sysc_config(sysc, -1, 0, -1); if (ret) goto power_resets_restore;
@@ -1745,9 +1847,7 @@ static int rzg3s_pcie_resume_noirq(struct device *dev) struct rzg3s_sysc *sysc = host->sysc; int ret; - ret = regmap_update_bits(sysc->regmap, sysc->info->rst_rsm_b.offset, - sysc->info->rst_rsm_b.mask, - field_prep(sysc->info->rst_rsm_b.mask, 1)); + ret = rzg3s_sysc_config(sysc, 1, 1, -1); if (ret) return ret;
@@ -1776,9 +1876,7 @@ static int rzg3s_pcie_resume_noirq(struct device *dev) reset_control_bulk_assert(data->num_power_resets, host->power_resets); assert_rst_rsm_b: - regmap_update_bits(sysc->regmap, sysc->info->rst_rsm_b.offset, - sysc->info->rst_rsm_b.mask, - field_prep(sysc->info->rst_rsm_b.mask, 0)); + rzg3s_sysc_config(sysc, -1, 0, -1); return ret; }
@@ -1811,11 +1909,35 @@ 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_config_post_init, + .config_deinit = rzg3e_config_deinit, + .sysc_info = { + .l1_allow = { + .offset = 0x1020, + .mask = BIT(0), + }, + .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, + }, {} };
--
2.25.1