summaryrefslogtreecommitdiffstats
path: root/drivers/regulator/max8997.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-05-12 11:10:25 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-05-12 11:10:25 +0100
commit5949a7e9ab2db04edaeee7c368eb4c99131f4629 (patch)
tree13e8da5dc42cc62b9721659c41045d2c27c31cc3 /drivers/regulator/max8997.c
parent178e43aef2979525d7864daefd9499614e13800e (diff)
parent411a2df5090ccb88f4c3726e4951ebed579fec11 (diff)
downloadblackbird-op-linux-5949a7e9ab2db04edaeee7c368eb4c99131f4629.tar.gz
blackbird-op-linux-5949a7e9ab2db04edaeee7c368eb4c99131f4629.zip
Merge remote-tracking branch 'regulator/topic/drivers' into regulator-next
Conflicts: drivers/regulator/88pm8607.c (simple overlap with a bugfix in v3.4)
Diffstat (limited to 'drivers/regulator/max8997.c')
-rw-r--r--drivers/regulator/max8997.c163
1 files changed, 90 insertions, 73 deletions
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index db09244bb3ed..b88551be4521 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -22,7 +22,6 @@
*/
#include <linux/bug.h>
-#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -278,9 +277,7 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
u8 val;
ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
- if (ret == -EINVAL)
- return 1; /* "not controllable" */
- else if (ret)
+ if (ret)
return ret;
ret = max8997_read_reg(i2c, reg, &val);
@@ -382,7 +379,7 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
return 0;
}
-static int max8997_get_voltage(struct regulator_dev *rdev)
+static int max8997_get_voltage_sel(struct regulator_dev *rdev)
{
struct max8997_data *max8997 = rdev_get_drvdata(rdev);
struct i2c_client *i2c = max8997->iodev->i2c;
@@ -400,15 +397,7 @@ static int max8997_get_voltage(struct regulator_dev *rdev)
val >>= shift;
val &= mask;
- if (rdev->desc && rdev->desc->ops && rdev->desc->ops->list_voltage)
- return rdev->desc->ops->list_voltage(rdev, val);
-
- /*
- * max8997_list_voltage returns value for any rdev with voltage_map,
- * which works for "CHARGER" and "CHARGER TOPOFF" that do not have
- * list_voltage ops (they are current regulators).
- */
- return max8997_list_voltage(rdev, val);
+ return val;
}
static inline int max8997_get_voltage_proper_val(
@@ -497,9 +486,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
const struct voltage_map_desc *desc;
int rid = rdev_get_id(rdev);
- int reg, shift = 0, mask, ret;
- int i;
- u8 org;
+ int i, reg, shift, mask, ret;
switch (rid) {
case MAX8997_LDO1 ... MAX8997_LDO21:
@@ -528,21 +515,50 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
if (ret)
return ret;
- max8997_read_reg(i2c, reg, &org);
- org = (org & mask) >> shift;
-
ret = max8997_update_reg(i2c, reg, i << shift, mask << shift);
*selector = i;
- if (rid == MAX8997_BUCK1 || rid == MAX8997_BUCK2 ||
- rid == MAX8997_BUCK4 || rid == MAX8997_BUCK5) {
- /* If the voltage is increasing */
- if (org < i)
- udelay(DIV_ROUND_UP(desc->step * (i - org),
- max8997->ramp_delay));
+ return ret;
+}
+
+static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev,
+ unsigned int old_selector,
+ unsigned int new_selector)
+{
+ struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+ int rid = rdev_get_id(rdev);
+ const struct voltage_map_desc *desc = reg_voltage_map[rid];
+
+ /* Delay is required only if the voltage is increasing */
+ if (old_selector >= new_selector)
+ return 0;
+
+ /* No need to delay if gpio_dvs_mode */
+ switch (rid) {
+ case MAX8997_BUCK1:
+ if (max8997->buck1_gpiodvs)
+ return 0;
+ break;
+ case MAX8997_BUCK2:
+ if (max8997->buck2_gpiodvs)
+ return 0;
+ break;
+ case MAX8997_BUCK5:
+ if (max8997->buck5_gpiodvs)
+ return 0;
+ break;
}
- return ret;
+ switch (rid) {
+ case MAX8997_BUCK1:
+ case MAX8997_BUCK2:
+ case MAX8997_BUCK4:
+ case MAX8997_BUCK5:
+ return DIV_ROUND_UP(desc->step * (new_selector - old_selector),
+ max8997->ramp_delay);
+ }
+
+ return 0;
}
/*
@@ -749,11 +765,6 @@ static int max8997_set_voltage_safeout(struct regulator_dev *rdev,
return ret;
}
-static int max8997_reg_enable_suspend(struct regulator_dev *rdev)
-{
- return 0;
-}
-
static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
{
struct max8997_data *max8997 = rdev_get_drvdata(rdev);
@@ -786,9 +797,9 @@ static struct regulator_ops max8997_ldo_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_ldobuck,
- .set_suspend_enable = max8997_reg_enable_suspend,
+ .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel,
.set_suspend_disable = max8997_reg_disable_suspend,
};
@@ -797,9 +808,9 @@ static struct regulator_ops max8997_buck_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_buck,
- .set_suspend_enable = max8997_reg_enable_suspend,
+ .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel,
.set_suspend_disable = max8997_reg_disable_suspend,
};
@@ -808,7 +819,6 @@ static struct regulator_ops max8997_fixedvolt_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .set_suspend_enable = max8997_reg_enable_suspend,
.set_suspend_disable = max8997_reg_disable_suspend,
};
@@ -817,39 +827,56 @@ static struct regulator_ops max8997_safeout_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_safeout,
- .set_suspend_enable = max8997_reg_enable_suspend,
.set_suspend_disable = max8997_reg_disable_suspend,
};
static struct regulator_ops max8997_fixedstate_ops = {
.list_voltage = max8997_list_voltage_charger_cv,
- .get_voltage = max8997_get_voltage,
+ .get_voltage_sel = max8997_get_voltage_sel,
.set_voltage = max8997_set_voltage_charger_cv,
};
-static int max8997_set_voltage_ldobuck_wrap(struct regulator_dev *rdev,
- int min_uV, int max_uV)
+static int max8997_set_current_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
{
unsigned dummy;
+ int rid = rdev_get_id(rdev);
+
+ if (rid != MAX8997_CHARGER && rid != MAX8997_CHARGER_TOPOFF)
+ return -EINVAL;
- return max8997_set_voltage_ldobuck(rdev, min_uV, max_uV, &dummy);
+ /* Reuse max8997_set_voltage_ldobuck to set current_limit. */
+ return max8997_set_voltage_ldobuck(rdev, min_uA, max_uA, &dummy);
}
+static int max8997_get_current_limit(struct regulator_dev *rdev)
+{
+ int sel, rid = rdev_get_id(rdev);
+
+ if (rid != MAX8997_CHARGER && rid != MAX8997_CHARGER_TOPOFF)
+ return -EINVAL;
+
+ sel = max8997_get_voltage_sel(rdev);
+ if (sel < 0)
+ return sel;
+
+ /* Reuse max8997_list_voltage to get current_limit. */
+ return max8997_list_voltage(rdev, sel);
+}
static struct regulator_ops max8997_charger_ops = {
.is_enabled = max8997_reg_is_enabled,
.enable = max8997_reg_enable,
.disable = max8997_reg_disable,
- .get_current_limit = max8997_get_voltage,
- .set_current_limit = max8997_set_voltage_ldobuck_wrap,
+ .get_current_limit = max8997_get_current_limit,
+ .set_current_limit = max8997_set_current_limit,
};
static struct regulator_ops max8997_charger_fixedstate_ops = {
- .is_enabled = max8997_reg_is_enabled,
- .get_current_limit = max8997_get_voltage,
- .set_current_limit = max8997_set_voltage_ldobuck_wrap,
+ .get_current_limit = max8997_get_current_limit,
+ .set_current_limit = max8997_set_current_limit,
};
#define MAX8997_VOLTAGE_REGULATOR(_name, _ops) {\
@@ -922,16 +949,15 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
return -ENODEV;
}
- max8997 = kzalloc(sizeof(struct max8997_data), GFP_KERNEL);
+ max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
+ GFP_KERNEL);
if (!max8997)
return -ENOMEM;
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
- max8997->rdev = kzalloc(size, GFP_KERNEL);
- if (!max8997->rdev) {
- kfree(max8997);
+ max8997->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (!max8997->rdev)
return -ENOMEM;
- }
rdev = max8997->rdev;
max8997->dev = &pdev->dev;
@@ -955,7 +981,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck1_voltage[i] / 1000 +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_alloc;
+ goto err_out;
max8997->buck2_vol[i] = ret =
max8997_get_voltage_proper_val(
@@ -964,7 +990,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck2_voltage[i] / 1000 +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_alloc;
+ goto err_out;
max8997->buck5_vol[i] = ret =
max8997_get_voltage_proper_val(
@@ -973,7 +999,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck5_voltage[i] / 1000 +
buck1245_voltage_map_desc.step);
if (ret < 0)
- goto err_alloc;
+ goto err_out;
if (max_buck1 < max8997->buck1_vol[i])
max_buck1 = max8997->buck1_vol[i];
@@ -1006,7 +1032,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
!gpio_is_valid(pdata->buck125_gpios[2])) {
dev_err(&pdev->dev, "GPIO NOT VALID\n");
ret = -EINVAL;
- goto err_alloc;
+ goto err_out;
}
ret = gpio_request(pdata->buck125_gpios[0],
@@ -1015,7 +1041,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "Duplicated gpio request"
" on SET1\n");
else if (ret)
- goto err_alloc;
+ goto err_out;
else
gpio1set = true;
@@ -1027,7 +1053,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
else if (ret) {
if (gpio1set)
gpio_free(pdata->buck125_gpios[0]);
- goto err_alloc;
+ goto err_out;
} else
gpio2set = true;
@@ -1041,7 +1067,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
gpio_free(pdata->buck125_gpios[0]);
if (gpio2set)
gpio_free(pdata->buck125_gpios[1]);
- goto err_alloc;
+ goto err_out;
}
gpio_direction_output(pdata->buck125_gpios[0],
@@ -1110,13 +1136,9 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
return 0;
err:
- for (i = 0; i < max8997->num_regulators; i++)
- if (rdev[i])
- regulator_unregister(rdev[i]);
-err_alloc:
- kfree(max8997->rdev);
- kfree(max8997);
-
+ while (--i >= 0)
+ regulator_unregister(rdev[i]);
+err_out:
return ret;
}
@@ -1127,12 +1149,7 @@ static int __devexit max8997_pmic_remove(struct platform_device *pdev)
int i;
for (i = 0; i < max8997->num_regulators; i++)
- if (rdev[i])
- regulator_unregister(rdev[i]);
-
- kfree(max8997->rdev);
- kfree(max8997);
-
+ regulator_unregister(rdev[i]);
return 0;
}
OpenPOWER on IntegriCloud