/**
* 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
*/
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;
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 rzg3s_pcie_irq_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;
/* 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,
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;
}
host_probe_teardown:
rzg3s_pcie_teardown_irqdomain(host);
- reset_control_bulk_assert(host->data->num_cfg_resets, host->cfg_resets);
+ host->data->config_deinit(host);
rpm_put:
pm_runtime_put_sync(dev);
rpm_disable:
clk_disable_unprepare(port->refclk);
- ret = reset_control_bulk_assert(data->num_cfg_resets,
- host->cfg_resets);
+ /* SoC-specific de-initialization */
+ ret = data->config_deinit(host);
if (ret)
goto refclk_restore;
ret = reset_control_bulk_assert(data->num_power_resets,
host->power_resets);
if (ret)
- goto cfg_resets_restore;
+ goto config_reinit;
ret = rzg3s_sysc_config_func(sysc, RZG3S_SYSC_FUNC_ID_RST_RSM_B, 0);
if (ret)
power_resets_restore:
reset_control_bulk_deassert(data->num_power_resets,
host->power_resets);
-cfg_resets_restore:
- reset_control_bulk_deassert(data->num_cfg_resets,
- host->cfg_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);
.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 = {