[PATCH 16/16] PCI: samsung: Make handling of regulators generic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxx>
Signed-off-by: Shradha Todi <shradha.t@xxxxxxxxxxx>
---
 drivers/pci/controller/dwc/pci-samsung.c | 79 +++++++++++++++++++-----
 1 file changed, 64 insertions(+), 15 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-samsung.c b/drivers/pci/controller/dwc/pci-samsung.c
index 01882f2d06c7..bf18020c14da 100644
--- a/drivers/pci/controller/dwc/pci-samsung.c
+++ b/drivers/pci/controller/dwc/pci-samsung.c
@@ -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;
 
-- 
2.17.1




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux