@@ -66,7 +66,8 @@ struct samsung_pcie_pdata {
* @clks: list of clocks required for the controller
* @clk_cnt: count of clocks required for the controller
* @phy: PHY device associated with the controller
- * @supplies: array of regulators required for the controller
+ * @supplies: list of regulators required for the controller
+ * @supplies_cnt: count of regulators required for the controller
*/
struct samsung_pcie {
struct dw_pcie pci;
@@ -75,10 +76,12 @@ struct samsung_pcie {
struct clk_bulk_data *clks;
int clk_cnt;
struct phy *phy;
- struct regulator_bulk_data supplies[2];
+ struct regulator_bulk_data *supplies;
+ int supplies_cnt;
};
struct samsung_res_ops {
+ int (*init_regulator)(struct samsung_pcie *sp);
int (*irq_init)(struct samsung_pcie *sp, struct platform_device *pdev);
};
@@ -111,6 +114,34 @@ static unsigned int samsung_pcie_appl_readl(struct samsung_pcie *sp, u32 reg)
return readl(sp->appl_base + reg);
}
+static int samsung_regulator_enable(struct samsung_pcie *sp)
+{
+ struct device *dev = sp->pci.dev;
+ int ret;
+
+ if (sp->supplies_cnt == 0)
+ return 0;
+
+ ret = devm_regulator_bulk_get(dev, sp->supplies_cnt,
+ sp->supplies);
+ if (ret)
+ return ret;
+
+ ret = regulator_bulk_enable(sp->supplies_cnt, sp->supplies);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void samsung_regulator_disable(struct samsung_pcie *sp)
+{
+ if (sp->supplies_cnt == 0)
+ return;
+
+ regulator_bulk_disable(sp->supplies_cnt, sp->supplies);
+}
+
static void exynos_pcie_sideband_dbi_w_mode(struct samsung_pcie *sp, bool on)
{
u32 val;
@@ -281,6 +312,24 @@ static const struct dw_pcie_host_ops exynos_pcie_host_ops = {
.host_init = exynos_pcie_host_init,
};
+static int exynos_init_regulator(struct samsung_pcie *sp)
+{
+ struct device *dev = sp->pci.dev;
+
+ sp->supplies_cnt = 2;
+
+ sp->supplies = devm_kcalloc(dev, sp->supplies_cnt,
+ sizeof(*sp->supplies),
+ GFP_KERNEL);
+ if (!sp->supplies)
+ return -ENOMEM;
+
+ sp->supplies[0].supply = "vdd18";
+ sp->supplies[1].supply = "vdd10";
+
+ return 0;
+}
+
static int exynos_irq_init(struct samsung_pcie *sp,
struct platform_device *pdev)
{
@@ -313,6 +362,7 @@ static const struct dw_pcie_ops exynos_dw_pcie_ops = {
};
static const struct samsung_res_ops exynos_res_ops_data = {
+ .init_regulator = exynos_init_regulator,
.irq_init = exynos_irq_init,
};
@@ -346,16 +396,15 @@ static int samsung_pcie_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
- sp->supplies[0].supply = "vdd18";
- sp->supplies[1].supply = "vdd10";
- ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(sp->supplies),
- sp->supplies);
- if (ret)
- return ret;
+ if (pdata->res_ops && pdata->res_ops->init_regulator) {
+ ret = sp->pdata->res_ops->init_regulator(sp);
+ if (ret)
+ goto fail_regulator;
+ }
- ret = regulator_bulk_enable(ARRAY_SIZE(sp->supplies), sp->supplies);
+ ret = samsung_regulator_enable(sp);
if (ret)
- return ret;
+ goto fail_regulator;
platform_set_drvdata(pdev, sp);
@@ -372,7 +421,8 @@ static int samsung_pcie_probe(struct platform_device *pdev)
fail_probe:
phy_exit(sp->phy);
- regulator_bulk_disable(ARRAY_SIZE(sp->supplies), sp->supplies);
+ samsung_regulator_disable(sp);
+fail_regulator:
samsung_pcie_deinit_clk_resources(sp);
return ret;
@@ -387,8 +437,7 @@ static int __exit samsung_pcie_remove(struct platform_device *pdev)
phy_power_off(sp->phy);
phy_exit(sp->phy);
samsung_pcie_deinit_clk_resources(sp);
- regulator_bulk_disable(ARRAY_SIZE(sp->supplies), sp->supplies);
-
+ samsung_regulator_disable(sp);
return 0;
}
@@ -399,7 +448,7 @@ static int samsung_pcie_suspend_noirq(struct device *dev)
exynos_pcie_assert_core_reset(sp);
phy_power_off(sp->phy);
phy_exit(sp->phy);
- regulator_bulk_disable(ARRAY_SIZE(sp->supplies), sp->supplies);
+ samsung_regulator_disable(sp);
return 0;
}
@@ -411,7 +460,7 @@ static int samsung_pcie_resume_noirq(struct device *dev)
struct dw_pcie_rp *pp = &pci->pp;
int ret;
- ret = regulator_bulk_enable(ARRAY_SIZE(sp->supplies), sp->supplies);
+ ret = samsung_regulator_enable(sp);
if (ret)
return ret;
Use pointers instead of fixed size array to store regulator related information. Add common regulator initialization and de-initialization functions. For platform specific init, add a res_ops function pointer. Suggested-by: Pankaj Dubey <pankaj.dubey@samsung.com> Signed-off-by: Shradha Todi <shradha.t@samsung.com> --- drivers/pci/controller/dwc/pci-samsung.c | 79 +++++++++++++++++++----- 1 file changed, 64 insertions(+), 15 deletions(-)