summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/controller/pcie-rzg3s-host.c111
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[] = {