diff options
| -rw-r--r-- | drivers/pci/controller/pcie-rzg3s-host.c | 111 |
1 files changed, 85 insertions, 26 deletions
diff --git a/drivers/pci/controller/pcie-rzg3s-host.c b/drivers/pci/controller/pcie-rzg3s-host.c index 872683211bab..f5a0b7c6e773 100644 --- a/drivers/pci/controller/pcie-rzg3s-host.c +++ b/drivers/pci/controller/pcie-rzg3s-host.c @@ -159,10 +159,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 +171,44 @@ #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_MAX: Max SYSC function ID + */ +enum rzg3s_sysc_func_id { + RZG3S_SYSC_FUNC_ID_RST_RSM_B, + 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 @@ -203,6 +237,7 @@ struct rzg3s_pcie_host; * 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 */ @@ -210,6 +245,7 @@ struct rzg3s_pcie_soc_data { int (*init_phy)(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 +269,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 +284,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 +296,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) { @@ -1522,6 +1575,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)); @@ -1533,6 +1587,13 @@ 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); @@ -1546,15 +1607,13 @@ static int rzg3s_pcie_probe(struct platform_device *pdev) 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)); + ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 1); if (ret) goto port_refclk_put; @@ -1606,9 +1665,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); @@ -1620,7 +1677,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); @@ -1639,9 +1696,7 @@ static int rzg3s_pcie_suspend_noirq(struct device *dev) if (ret) goto cfg_resets_restore; - 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 power_resets_restore; @@ -1664,12 +1719,10 @@ 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_RST_RSM_B, 1); if (ret) return ret; @@ -1698,9 +1751,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; } @@ -1723,6 +1774,14 @@ static const struct rzg3s_pcie_soc_data rzg3s_soc_data = { .cfg_resets = rzg3s_soc_cfg_resets, .num_cfg_resets = ARRAY_SIZE(rzg3s_soc_cfg_resets), .init_phy = rzg3s_soc_pcie_init_phy, + .sysc_info = { + .functions = { + [RZG3S_SYSC_FUNC_ID_RST_RSM_B] = { + .offset = 0xd74, + .mask = BIT(0), + }, + }, + }, }; static const struct of_device_id rzg3s_pcie_of_match[] = { |
