regulator: tps65090: fix multiple regulator registration issue
Laxman Dewangan [Thu, 2 Aug 2012 14:16:17 +0000 (19:16 +0530)]
The regulator of tps65090 is registered as mfd sub device
and hence all regulator should be register in one call
of tps65090 regulator probe.
Fixing this by providing the list of regulator platform data
and registering the regulators in single probe call.

Change-Id: I06600d0bf4dfd62238bed77713ee8abf2afe2371
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/120838

drivers/regulator/tps65090-regulator.c
include/linux/mfd/tps65090.h
include/linux/regulator/tps65090-regulator.h

index e18679c..ebefbf5 100644 (file)
@@ -142,47 +142,89 @@ static inline struct tps65090_regulator_info *find_regulator_info(int id)
 static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
 {
        struct tps65090_regulator_info *rinfo = NULL;
-       struct tps65090_regulator *ri = NULL;
+       struct tps65090_regulator *ri;
+       struct tps65090_regulator *pmic;
        struct regulator_dev *rdev;
        struct tps65090_regulator_platform_data *tps_pdata;
-       int id = pdev->id;
+       struct tps65090_platform_data *tps65090_pdata;
+       int id;
+       int num;
+       int ret;
 
-       dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+       dev_dbg(&pdev->dev, "Probing regulator\n");
 
-       rinfo = find_regulator_info(id);
-       if (rinfo == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+       tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+       if (!tps65090_pdata || !tps65090_pdata->num_reg_pdata) {
+               dev_err(&pdev->dev, "Proper platform data missing\n");
                return -EINVAL;
        }
-       tps_pdata = pdev->dev.platform_data;
 
-       ri = devm_kzalloc(&pdev->dev, sizeof(*ri), GFP_KERNEL);
-       if (!ri) {
-               dev_err(&pdev->dev, "mem alloc for ri failed\n");
+       pmic = devm_kzalloc(&pdev->dev,
+                       tps65090_pdata->num_reg_pdata * sizeof(*pmic),
+                       GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
                return -ENOMEM;
        }
 
-       ri->dev = &pdev->dev;
-       ri->rinfo = rinfo;
-
-       rdev = regulator_register(&ri->rinfo->desc, &pdev->dev,
+       for (num = 0; num < tps65090_pdata->num_reg_pdata; ++num) {
+               tps_pdata = tps65090_pdata->reg_pdata[num];
+               if (!tps_pdata || !tps_pdata->reg_init_data) {
+                       dev_err(&pdev->dev,
+                               "Null platform data for regultor %d\n", num);
+                       ret = -EINVAL;
+                       goto scrub;
+               }
+
+               id = tps_pdata->id;
+               rinfo = find_regulator_info(id);
+               if (!rinfo) {
+                       dev_err(&pdev->dev,
+                               "invalid regulator ID %d specified\n", id);
+                       ret = -EINVAL;
+                       goto scrub;
+               }
+
+               ri = &pmic[num];
+               ri->dev = &pdev->dev;
+               ri->rinfo = rinfo;
+               rdev = regulator_register(&ri->rinfo->desc, &pdev->dev,
                                tps_pdata->reg_init_data, ri);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register regulator %s\n",
                                ri->rinfo->desc.name);
-               return PTR_ERR(rdev);
+                       ret = PTR_ERR(rdev);
+                       goto scrub;
+               }
+               ri->rdev = rdev;
        }
-       ri->rdev = rdev;
 
-       platform_set_drvdata(pdev, ri);
+       platform_set_drvdata(pdev, pmic);
        return 0;
+
+scrub:
+       while (--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
 }
 
 static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
 {
-       struct tps65090_regulator *ri = platform_get_drvdata(pdev);
-
-       regulator_unregister(ri->rdev);
+       struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps65090_platform_data *tps65090_pdata;
+       struct tps65090_regulator *ri;
+       int num;
+
+       tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+       if (!tps65090_pdata || !tps65090_pdata->num_reg_pdata)
+               return 0;
+
+       for (num = 0; num < tps65090_pdata->num_reg_pdata; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
        return 0;
 }
 
index 38e31c5..df4cf81 100644 (file)
@@ -32,6 +32,8 @@ struct tps65090_platform_data {
        int irq_base;
        int num_subdevs;
        struct tps65090_subdev_info *subdevs;
+       struct tps65090_regulator_platform_data **reg_pdata;
+       int num_reg_pdata;
 };
 
 /*
index e352a93..2b7d0a1 100644 (file)
@@ -40,10 +40,12 @@ enum {
  * struct tps65090_regulator_platform_data
  *
  * @reg_init_data: The regulator init data.
+ * @id: Regulator ID.
  * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
  */
 
 struct tps65090_regulator_platform_data {
+       int id;
        struct regulator_init_data *reg_init_data;
 };