#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
/* Timeouts experimentally determined */
#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
* 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
*/
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;
};
* @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
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;
#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)
{
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));
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);
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;
* 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);
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);
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;
{
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;
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;
}
.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[] = {