diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2026-04-13 12:50:53 -0500 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-04-13 12:50:53 -0500 |
| commit | b274423c79277a34521a7553d07e3dc25b0b96c6 (patch) | |
| tree | 308b62354bcc679da7131c661a8bec3f2930b54c /drivers/pci | |
| parent | d096bd7d8bf75a09d6d10438449e0c33d5f51081 (diff) | |
| parent | 8197ec49a2062185f6bd432a19969ce0b3752e94 (diff) | |
| download | linux-next-b274423c79277a34521a7553d07e3dc25b0b96c6.tar.gz linux-next-b274423c79277a34521a7553d07e3dc25b0b96c6.zip | |
Merge branch 'pci/controller/rzg3s-host'
- Assert (not deassert) resets in probe error path (John Madieu)
- Assert resets in suspend path in reverse order they were deasserted
during probe (John Madieu)
- Rework inbound window algorithm to prevent mapping more than intended
region and enforce alignment on size, to prepare for RZ/G3E support (John
Madieu)
- Fix renesas,r9a08g045s33-pcie 'serr_cor' typo and convert properties from
'description' to 'const' for better validation (John Madieu)
- Add RZ/G3E to DT binding and to driver (John Madieu)
* pci/controller/rzg3s-host:
PCI: rzg3s-host: Add support for RZ/G3E PCIe controller
PCI: rzg3s-host: Add PCIe Gen3 (8.0 GT/s) link speed support
PCI: rzg3s-host: Explicitly set class code for RZ/G3E compatibility
PCI: rzg3s-host: Add SoC-specific configuration and initialization callbacks
PCI: rzg3s-host: Make configuration reset lines optional
PCI: rzg3s-host: Make SYSC register offsets SoC-specific
dt-bindings: PCI: renesas,r9a08g045s33-pcie: Document RZ/G3E SoC
dt-bindings: PCI: renesas,r9a08g045s33-pcie: Fix naming properties
PCI: rzg3s-host: Rework inbound window algorithm for supporting RZ/G3E SoC
PCI: rzg3s-host: Reorder reset assertion during suspend
PCI: rzg3s-host: Fix reset handling in probe error path
# Conflicts:
# drivers/pci/controller/pcie-rzg3s-host.c
Diffstat (limited to 'drivers/pci')
| -rw-r--r-- | drivers/pci/controller/pcie-rzg3s-host.c | 365 |
1 files changed, 285 insertions, 80 deletions
diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c index 00a11f986117..d86e7516dcc2 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -111,6 +111,15 @@ #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) @@ -159,10 +168,6 @@ #define RZG3S_PCI_CFG_PCIEC 0x60 -/* System controller registers */ -#define RZG3S_SYS_PCIE_RST_RSM_B 0xd74 -#define RZG3S_SYS_PCIE_RST_RSM_B_MASK BIT(0) - /* Maximum number of windows */ #define RZG3S_MAX_WINDOWS 8 @@ -175,6 +180,48 @@ #define RZG3S_REQ_ISSUE_TIMEOUT_US 2500 /** + * struct rzg3s_sysc_function - System Controller function descriptor + * @offset: Register offset from the System Controller base address + * @mask: Bit mask for the function within the register + */ +struct rzg3s_sysc_function { + u32 offset; + u32 mask; +}; + +/** + * 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, +}; + +/** + * struct rzg3s_sysc_info - RZ/G3S System Controller info + * @functions: SYSC function descriptors array + */ +struct rzg3s_sysc_info { + const struct rzg3s_sysc_function functions[RZG3S_SYSC_FUNC_ID_MAX]; +}; + +/** + * struct rzg3s_sysc - RZ/G3S System Controller descriptor + * @regmap: System controller regmap + * @info: System controller info + */ +struct rzg3s_sysc { + struct regmap *regmap; + const struct rzg3s_sysc_info *info; +}; + +/** * struct rzg3s_pcie_msi - RZ/G3S PCIe MSI data structure * @domain: IRQ domain * @map: bitmap with the allocated MSIs @@ -199,17 +246,25 @@ 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 * configuration + * @sysc_info: SYSC info * @num_power_resets: number of power resets * @num_cfg_resets: number of configuration resets */ 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; u8 num_power_resets; u8 num_cfg_resets; }; @@ -233,7 +288,7 @@ struct rzg3s_pcie_port { * @dev: struct device * @power_resets: reset control signals that should be set after power up * @cfg_resets: reset control signals that should be set after configuration - * @sysc: SYSC regmap + * @sysc: SYSC descriptor * @intx_domain: INTx IRQ domain * @data: SoC specific data * @msi: MSI data structure @@ -248,7 +303,7 @@ struct rzg3s_pcie_host { struct device *dev; struct reset_control_bulk_data *power_resets; struct reset_control_bulk_data *cfg_resets; - struct regmap *sysc; + struct rzg3s_sysc *sysc; struct irq_domain *intx_domain; const struct rzg3s_pcie_soc_data *data; struct rzg3s_pcie_msi msi; @@ -260,6 +315,23 @@ struct rzg3s_pcie_host { #define rzg3s_msi_to_host(_msi) container_of(_msi, struct rzg3s_pcie_host, msi) +static int rzg3s_sysc_config_func(struct rzg3s_sysc *sysc, + enum rzg3s_sysc_func_id fid, u32 val) +{ + const struct rzg3s_sysc_info *info = sysc->info; + const struct rzg3s_sysc_function *functions = info->functions; + + if (fid >= RZG3S_SYSC_FUNC_ID_MAX) + return -EINVAL; + + if (!functions[fid].mask) + return 0; + + return regmap_update_bits(sysc->regmap, functions[fid].offset, + functions[fid].mask, + field_prep(functions[fid].mask, val)); +} + static void rzg3s_pcie_update_bits(void __iomem *base, u32 offset, u32 mask, u32 val) { @@ -945,8 +1017,9 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) { u32 remote_supported_link_speeds, max_supported_link_speeds; u32 cs2, tmp, pcie_cap = RZG3S_PCI_CFG_PCIEC; - u32 cur_link_speed, link_speed; + u32 cur_link_speed, link_speed, hw_max_speed; u8 ltssm_state_l0 = 0xc; + u32 lnkcap; int ret; u16 ls; @@ -966,7 +1039,22 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) ls = readw_relaxed(host->pcie + pcie_cap + PCI_EXP_LNKSTA); cs2 = readl_relaxed(host->axi + RZG3S_PCI_PCSTAT2); - switch (pcie_get_link_speed(host->max_link_speed)) { + /* Read hardware supported link speed from Link Capabilities Register */ + lnkcap = readl_relaxed(host->pcie + pcie_cap + PCI_EXP_LNKCAP); + hw_max_speed = FIELD_GET(PCI_EXP_LNKCAP_SLS, lnkcap); + + /* + * Use DT max-link-speed only as a limit. If specified and lower + * than hardware capability, cap to that value. + */ + if (host->max_link_speed > 0 && host->max_link_speed < hw_max_speed) + hw_max_speed = host->max_link_speed; + + switch (pcie_get_link_speed(hw_max_speed)) { + case PCIE_SPEED_8_0GT: + max_supported_link_speeds = GENMASK(PCI_EXP_LNKSTA_CLS_8_0GB - 1, 0); + link_speed = PCI_EXP_LNKCTL2_TLS_8_0GT; + break; case PCIE_SPEED_5_0GT: max_supported_link_speeds = GENMASK(PCI_EXP_LNKSTA_CLS_5_0GB - 1, 0); link_speed = PCI_EXP_LNKCTL2_TLS_5_0GT; @@ -982,10 +1070,10 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) remote_supported_link_speeds &= max_supported_link_speeds; /* - * Return if max link speed is already set or the connected device + * Return if target link speed is already set or the connected device * doesn't support it. */ - if (cur_link_speed == host->max_link_speed || + if (cur_link_speed == hw_max_speed || remote_supported_link_speeds != max_supported_link_speeds) return 0; @@ -1022,6 +1110,7 @@ static int rzg3s_pcie_set_max_link_speed(struct rzg3s_pcie_host *host) static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host) { struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host); + u32 mask = GENMASK(31, 8); struct resource_entry *ft; struct resource *bus; u8 subordinate_bus; @@ -1045,6 +1134,13 @@ static int rzg3s_pcie_config_init(struct rzg3s_pcie_host *host) writel_relaxed(0xffffffff, host->pcie + RZG3S_PCI_CFG_BARMSK00L); writel_relaxed(0xffffffff, host->pcie + RZG3S_PCI_CFG_BARMSK00U); + /* + * Explicitly program class code. RZ/G3E requires this configuration. + * Harmless for RZ/G3S where this matches the hardware default. + */ + rzg3s_pcie_update_bits(host->pcie, PCI_CLASS_REVISION, mask, + field_prep(mask, PCI_CLASS_BRIDGE_PCI_NORMAL)); + /* Disable access control to the CFGU */ writel_relaxed(0, host->axi + RZG3S_PCI_PERM); @@ -1056,6 +1152,57 @@ 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 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) { /* @@ -1135,9 +1282,9 @@ static int rzg3s_pcie_resets_prepare_and_get(struct rzg3s_pcie_host *host) if (ret) return ret; - return devm_reset_control_bulk_get_exclusive(host->dev, - data->num_cfg_resets, - host->cfg_resets); + return devm_reset_control_bulk_get_optional_exclusive(host->dev, + data->num_cfg_resets, + host->cfg_resets); } static int rzg3s_pcie_host_parse_port(struct rzg3s_pcie_host *host) @@ -1204,22 +1351,32 @@ 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; + + /* 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); - 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, @@ -1228,18 +1385,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; } @@ -1271,50 +1430,55 @@ static int rzg3s_pcie_set_inbound_windows(struct rzg3s_pcie_host *host, u64 pci_addr = entry->res->start - entry->offset; u64 cpu_addr = entry->res->start; u64 cpu_end = entry->res->end; - u64 size_id = 0; int id = *index; u64 size; - while (cpu_addr < cpu_end) { + /* + * According to the RZ/G3S HW manual (Rev.1.10, section 34.6.6.7) and + * RZ/G3E HW manual (Rev.1.15, section 6.6.7.6): + * - Each window must be a single memory size of power of two + * - Mask registers must be set to (2^N - 1) + * - Bit carry must not occur when adding base and mask registers, + * meaning the base address must be aligned to the window size + * + * Split non-power-of-2 regions into multiple windows to satisfy + * these constraints without over-mapping. + */ + while (cpu_addr <= cpu_end) { + u64 remaining_size = cpu_end - cpu_addr + 1; + u64 align_limit; + if (id >= RZG3S_MAX_WINDOWS) return dev_err_probe(host->dev, -ENOSPC, "Failed to map inbound window for resource (%s)\n", entry->res->name); - size = resource_size(entry->res) - size_id; - - /* - * According to the RZ/G3S HW manual (Rev.1.10, - * section 34.3.1.71 AXI Window Mask (Lower) Registers) the min - * size is 4K. - */ - size = max(size, SZ_4K); + /* Start with largest power-of-two that fits in remaining size */ + size = 1ULL << __fls(remaining_size); /* - * According the RZ/G3S HW manual (Rev.1.10, sections: - * - 34.3.1.69 AXI Window Base (Lower) Registers - * - 34.3.1.71 AXI Window Mask (Lower) Registers - * - 34.3.1.73 AXI Destination (Lower) Registers) - * the CPU addr, PCIe addr, size should be 4K aligned and be a - * power of 2. + * The "no bit carry" rule requires base addresses to be + * aligned to the window size. Find the maximum window size + * that both addresses can support based on their natural + * alignment (lowest set bit). */ - size = ALIGN(size, SZ_4K); - size = roundup_pow_of_two(size); + align_limit = min(cpu_addr ? (1ULL << __ffs(cpu_addr)) : ~0ULL, + pci_addr ? (1ULL << __ffs(pci_addr)) : ~0ULL); - cpu_addr = ALIGN(cpu_addr, SZ_4K); - pci_addr = ALIGN(pci_addr, SZ_4K); + size = min(size, align_limit); /* - * According to the RZ/G3S HW manual (Rev.1.10, section - * 34.3.1.71 AXI Window Mask (Lower) Registers) HW expects first - * 12 LSB bits to be 0xfff. Subtract 1 from size for this. + * Minimum window size is 4KB. + * See RZ/G3S HW manual (Rev.1.10, section 34.3.1.71) and + * RZ/G3E HW manual (Rev.1.15, section 6.6.4.1.3.(74)). */ + size = max(size, SZ_4K); + rzg3s_pcie_set_inbound_window(host, cpu_addr, pci_addr, size - 1, id); pci_addr += size; cpu_addr += size; - size_id = size; id++; } *index = id; @@ -1517,6 +1681,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev) struct device_node *sysc_np __free(device_node) = of_parse_phandle(np, "renesas,sysc", 0); struct rzg3s_pcie_host *host; + struct rzg3s_sysc *sysc; int ret; bridge = devm_pci_alloc_host_bridge(dev, sizeof(*host)); @@ -1528,28 +1693,36 @@ static int rzg3s_pcie_probe(struct platform_device *pdev) host->data = device_get_match_data(dev); platform_set_drvdata(pdev, host); + host->sysc = devm_kzalloc(dev, sizeof(*host->sysc), GFP_KERNEL); + if (!host->sysc) + return -ENOMEM; + + sysc = host->sysc; + sysc->info = &host->data->sysc_info; + host->axi = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(host->axi)) return PTR_ERR(host->axi); host->pcie = host->axi + RZG3S_PCI_CFG_BASE; host->max_link_speed = of_pci_get_max_link_speed(np); - if (host->max_link_speed < 0) - host->max_link_speed = 2; ret = rzg3s_pcie_host_parse_port(host); if (ret) return ret; - host->sysc = syscon_node_to_regmap(sysc_np); - if (IS_ERR(host->sysc)) { - ret = PTR_ERR(host->sysc); + sysc->regmap = syscon_node_to_regmap(sysc_np); + if (IS_ERR(sysc->regmap)) { + ret = PTR_ERR(sysc->regmap); goto port_refclk_put; } - ret = regmap_update_bits(host->sysc, RZG3S_SYS_PCIE_RST_RSM_B, - RZG3S_SYS_PCIE_RST_RSM_B_MASK, - FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 1)); + /* 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; @@ -1589,8 +1762,7 @@ static int rzg3s_pcie_probe(struct platform_device *pdev) host_probe_teardown: rzg3s_pcie_teardown_irqdomain(host); - reset_control_bulk_deassert(host->data->num_cfg_resets, - host->cfg_resets); + host->data->config_deinit(host); rpm_put: pm_runtime_put_sync(dev); rpm_disable: @@ -1602,9 +1774,7 @@ sysc_signal_restore: * SYSC RST_RSM_B signal need to be asserted before turning off the * power to the PHY. */ - regmap_update_bits(host->sysc, RZG3S_SYS_PCIE_RST_RSM_B, - RZG3S_SYS_PCIE_RST_RSM_B_MASK, - FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 0)); + rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); port_refclk_put: clk_put(host->port.refclk); @@ -1616,7 +1786,7 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev) struct rzg3s_pcie_host *host = dev_get_drvdata(dev); const struct rzg3s_pcie_soc_data *data = host->data; struct rzg3s_pcie_port *port = &host->port; - struct regmap *sysc = host->sysc; + struct rzg3s_sysc *sysc = host->sysc; int ret; ret = pm_runtime_put_sync(dev); @@ -1625,31 +1795,30 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev) clk_disable_unprepare(port->refclk); - ret = reset_control_bulk_assert(data->num_power_resets, - host->power_resets); + /* SoC-specific de-initialization */ + ret = data->config_deinit(host); if (ret) goto refclk_restore; - ret = reset_control_bulk_assert(data->num_cfg_resets, - host->cfg_resets); + ret = reset_control_bulk_assert(data->num_power_resets, + host->power_resets); if (ret) - goto power_resets_restore; + goto config_reinit; - ret = regmap_update_bits(sysc, RZG3S_SYS_PCIE_RST_RSM_B, - RZG3S_SYS_PCIE_RST_RSM_B_MASK, - FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 0)); + ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); if (ret) - goto cfg_resets_restore; + goto power_resets_restore; return 0; /* Restore the previous state if any error happens */ -cfg_resets_restore: - reset_control_bulk_deassert(data->num_cfg_resets, - host->cfg_resets); power_resets_restore: reset_control_bulk_deassert(data->num_power_resets, host->power_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); @@ -1660,12 +1829,14 @@ static int rzg3s_pcie_resume_noirq(struct device *dev) { struct rzg3s_pcie_host *host = dev_get_drvdata(dev); const struct rzg3s_pcie_soc_data *data = host->data; - struct regmap *sysc = host->sysc; + struct rzg3s_sysc *sysc = host->sysc; int ret; - ret = regmap_update_bits(sysc, RZG3S_SYS_PCIE_RST_RSM_B, - RZG3S_SYS_PCIE_RST_RSM_B_MASK, - FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 1)); + 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; @@ -1694,9 +1865,7 @@ assert_power_resets: reset_control_bulk_assert(data->num_power_resets, host->power_resets); assert_rst_rsm_b: - regmap_update_bits(sysc, RZG3S_SYS_PCIE_RST_RSM_B, - RZG3S_SYS_PCIE_RST_RSM_B_MASK, - FIELD_PREP(RZG3S_SYS_PCIE_RST_RSM_B_MASK, 0)); + rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0); return ret; } @@ -1718,7 +1887,39 @@ 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 = { + [RZG3S_SYSC_FUNC_ID_RST_RSM_B] = { + .offset = 0xd74, + .mask = BIT(0), + }, + }, + }, +}; + +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[] = { @@ -1726,6 +1927,10 @@ 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, + }, {} }; |
