diff options
Diffstat (limited to 'drivers/regulator/max8997.c')
| -rw-r--r-- | drivers/regulator/max8997.c | 353 |
1 files changed, 215 insertions, 138 deletions
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index e39a0c7260d..90b4c530dee 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -24,6 +24,7 @@ #include <linux/bug.h> #include <linux/err.h> #include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -31,12 +32,12 @@ #include <linux/regulator/machine.h> #include <linux/mfd/max8997.h> #include <linux/mfd/max8997-private.h> +#include <linux/regulator/of_regulator.h> struct max8997_data { struct device *dev; struct max8997_dev *iodev; int num_regulators; - struct regulator_dev **rdev; int ramp_delay; /* in mV/us */ bool buck1_gpiodvs; @@ -52,6 +53,13 @@ struct max8997_data { u8 saved_states[MAX8997_REG_MAX]; }; +static const unsigned int safeoutvolt[] = { + 4850000, + 4900000, + 4950000, + 3300000, +}; + static inline void max8997_set_gpio(struct max8997_data *max8997) { int set3 = (max8997->buck125_gpioindex) & 0x1; @@ -69,26 +77,26 @@ struct voltage_map_desc { int step; }; -/* Voltage maps in mV */ +/* Voltage maps in uV */ static const struct voltage_map_desc ldo_voltage_map_desc = { - .min = 800, .max = 3950, .step = 50, + .min = 800000, .max = 3950000, .step = 50000, }; /* LDO1 ~ 18, 21 all */ static const struct voltage_map_desc buck1245_voltage_map_desc = { - .min = 650, .max = 2225, .step = 25, + .min = 650000, .max = 2225000, .step = 25000, }; /* Buck1, 2, 4, 5 */ static const struct voltage_map_desc buck37_voltage_map_desc = { - .min = 750, .max = 3900, .step = 50, + .min = 750000, .max = 3900000, .step = 50000, }; /* Buck3, 7 */ -/* current map in mA */ +/* current map in uA */ static const struct voltage_map_desc charger_current_map_desc = { - .min = 200, .max = 950, .step = 50, + .min = 200000, .max = 950000, .step = 50000, }; static const struct voltage_map_desc topoff_current_map_desc = { - .min = 50, .max = 200, .step = 10, + .min = 50000, .max = 200000, .step = 10000, }; static const struct voltage_map_desc *reg_voltage_map[] = { @@ -128,29 +136,6 @@ static const struct voltage_map_desc *reg_voltage_map[] = { [MAX8997_CHARGER_TOPOFF] = &topoff_current_map_desc, }; -static int max8997_list_voltage_safeout(struct regulator_dev *rdev, - unsigned int selector) -{ - int rid = rdev_get_id(rdev); - - if (rid == MAX8997_ESAFEOUT1 || rid == MAX8997_ESAFEOUT2) { - switch (selector) { - case 0: - return 4850000; - case 1: - return 4900000; - case 2: - return 4950000; - case 3: - return 3300000; - default: - return -EINVAL; - } - } - - return -EINVAL; -} - static int max8997_list_voltage_charger_cv(struct regulator_dev *rdev, unsigned int selector) { @@ -192,7 +177,7 @@ static int max8997_list_voltage(struct regulator_dev *rdev, if (val > desc->max) return -EINVAL; - return val * 1000; + return val; } static int max8997_get_enable_register(struct regulator_dev *rdev, @@ -483,7 +468,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, { struct max8997_data *max8997 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8997->iodev->i2c; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; const struct voltage_map_desc *desc; int rid = rdev_get_id(rdev); int i, reg, shift, mask, ret; @@ -507,7 +491,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, desc = reg_voltage_map[rid]; - i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); + i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); if (i < 0) return i; @@ -521,7 +505,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, return ret; } -static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, +static int max8997_set_voltage_buck_time_sel(struct regulator_dev *rdev, unsigned int old_selector, unsigned int new_selector) { @@ -555,7 +539,7 @@ static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, case MAX8997_BUCK4: case MAX8997_BUCK5: return DIV_ROUND_UP(desc->step * (new_selector - old_selector), - max8997->ramp_delay); + max8997->ramp_delay * 1000); } return 0; @@ -654,7 +638,6 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, const struct voltage_map_desc *desc; int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; bool gpio_dvs_mode = false; - int min_vol = min_uV / 1000, max_vol = max_uV / 1000; if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) return -EINVAL; @@ -679,7 +662,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, selector); desc = reg_voltage_map[rid]; - new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); + new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); if (new_val < 0) return new_val; @@ -706,8 +689,9 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, if (max8997->ignore_gpiodvs_side_effect == false) return -EINVAL; - dev_warn(&rdev->dev, "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:" - " %d -> %d\n", max8997->buck125_gpioindex, tmp_idx); + dev_warn(&rdev->dev, + "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET: %d -> %d\n", + max8997->buck125_gpioindex, tmp_idx); out: if (new_idx < 0 || new_val < 0) @@ -720,49 +704,23 @@ out: return 0; } -static const int safeoutvolt[] = { - 3300000, - 4850000, - 4900000, - 4950000, -}; - /* For SAFEOUT1 and SAFEOUT2 */ -static int max8997_set_voltage_safeout(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) +static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev, + unsigned selector) { struct max8997_data *max8997 = rdev_get_drvdata(rdev); struct i2c_client *i2c = max8997->iodev->i2c; int rid = rdev_get_id(rdev); int reg, shift = 0, mask, ret; - int i = 0; - u8 val; if (rid != MAX8997_ESAFEOUT1 && rid != MAX8997_ESAFEOUT2) return -EINVAL; - for (i = 0; i < ARRAY_SIZE(safeoutvolt); i++) { - if (min_uV <= safeoutvolt[i] && - max_uV >= safeoutvolt[i]) - break; - } - - if (i >= ARRAY_SIZE(safeoutvolt)) - return -EINVAL; - - if (i == 0) - val = 0x3; - else - val = i - 1; - ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); if (ret) return ret; - ret = max8997_update_reg(i2c, reg, val << shift, mask << shift); - *selector = val; - - return ret; + return max8997_update_reg(i2c, reg, selector << shift, mask << shift); } static int max8997_reg_disable_suspend(struct regulator_dev *rdev) @@ -799,7 +757,6 @@ static struct regulator_ops max8997_ldo_ops = { .disable = max8997_reg_disable, .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_ldobuck, - .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, .set_suspend_disable = max8997_reg_disable_suspend, }; @@ -810,7 +767,7 @@ static struct regulator_ops max8997_buck_ops = { .disable = max8997_reg_disable, .get_voltage_sel = max8997_get_voltage_sel, .set_voltage = max8997_set_voltage_buck, - .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, + .set_voltage_time_sel = max8997_set_voltage_buck_time_sel, .set_suspend_disable = max8997_reg_disable_suspend, }; @@ -823,12 +780,12 @@ static struct regulator_ops max8997_fixedvolt_ops = { }; static struct regulator_ops max8997_safeout_ops = { - .list_voltage = max8997_list_voltage_safeout, + .list_voltage = regulator_list_voltage_table, .is_enabled = max8997_reg_is_enabled, .enable = max8997_reg_enable, .disable = max8997_reg_disable, .get_voltage_sel = max8997_get_voltage_sel, - .set_voltage = max8997_set_voltage_safeout, + .set_voltage_sel = max8997_set_voltage_safeout_sel, .set_suspend_disable = max8997_reg_disable_suspend, }; @@ -933,33 +890,166 @@ static struct regulator_desc regulators[] = { max8997_charger_fixedstate_ops), }; -static __devinit int max8997_pmic_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static int max8997_pmic_dt_parse_dvs_gpio(struct platform_device *pdev, + struct max8997_platform_data *pdata, + struct device_node *pmic_np) +{ + int i, gpio; + + for (i = 0; i < 3; i++) { + gpio = of_get_named_gpio(pmic_np, + "max8997,pmic-buck125-dvs-gpios", i); + if (!gpio_is_valid(gpio)) { + dev_err(&pdev->dev, "invalid gpio[%d]: %d\n", i, gpio); + return -EINVAL; + } + pdata->buck125_gpios[i] = gpio; + } + return 0; +} + +static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, + struct max8997_platform_data *pdata) +{ + struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct device_node *pmic_np, *regulators_np, *reg_np; + struct max8997_regulator_data *rdata; + unsigned int i, dvs_voltage_nr = 1, ret; + + pmic_np = of_node_get(iodev->dev->of_node); + if (!pmic_np) { + dev_err(&pdev->dev, "could not find pmic sub-node\n"); + return -ENODEV; + } + + regulators_np = of_get_child_by_name(pmic_np, "regulators"); + if (!regulators_np) { + dev_err(&pdev->dev, "could not find regulators sub-node\n"); + return -EINVAL; + } + + /* count the number of regulators to be supported in pmic */ + pdata->num_regulators = of_get_child_count(regulators_np); + + rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * + pdata->num_regulators, GFP_KERNEL); + if (!rdata) { + of_node_put(regulators_np); + return -ENOMEM; + } + + pdata->regulators = rdata; + for_each_child_of_node(regulators_np, reg_np) { + for (i = 0; i < ARRAY_SIZE(regulators); i++) + if (!of_node_cmp(reg_np->name, regulators[i].name)) + break; + + if (i == ARRAY_SIZE(regulators)) { + dev_warn(&pdev->dev, "don't know how to configure regulator %s\n", + reg_np->name); + continue; + } + + rdata->id = i; + rdata->initdata = of_get_regulator_init_data(&pdev->dev, + reg_np); + rdata->reg_node = reg_np; + rdata++; + } + of_node_put(regulators_np); + + if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL)) + pdata->buck1_gpiodvs = true; + + if (of_get_property(pmic_np, "max8997,pmic-buck2-uses-gpio-dvs", NULL)) + pdata->buck2_gpiodvs = true; + + if (of_get_property(pmic_np, "max8997,pmic-buck5-uses-gpio-dvs", NULL)) + pdata->buck5_gpiodvs = true; + + if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs || + pdata->buck5_gpiodvs) { + ret = max8997_pmic_dt_parse_dvs_gpio(pdev, pdata, pmic_np); + if (ret) + return -EINVAL; + + if (of_property_read_u32(pmic_np, + "max8997,pmic-buck125-default-dvs-idx", + &pdata->buck125_default_idx)) { + pdata->buck125_default_idx = 0; + } else { + if (pdata->buck125_default_idx >= 8) { + pdata->buck125_default_idx = 0; + dev_info(&pdev->dev, "invalid value for default dvs index, using 0 instead\n"); + } + } + + if (of_get_property(pmic_np, + "max8997,pmic-ignore-gpiodvs-side-effect", NULL)) + pdata->ignore_gpiodvs_side_effect = true; + + dvs_voltage_nr = 8; + } + + if (of_property_read_u32_array(pmic_np, + "max8997,pmic-buck1-dvs-voltage", + pdata->buck1_voltage, dvs_voltage_nr)) { + dev_err(&pdev->dev, "buck1 voltages not specified\n"); + return -EINVAL; + } + + if (of_property_read_u32_array(pmic_np, + "max8997,pmic-buck2-dvs-voltage", + pdata->buck2_voltage, dvs_voltage_nr)) { + dev_err(&pdev->dev, "buck2 voltages not specified\n"); + return -EINVAL; + } + + if (of_property_read_u32_array(pmic_np, + "max8997,pmic-buck5-dvs-voltage", + pdata->buck5_voltage, dvs_voltage_nr)) { + dev_err(&pdev->dev, "buck5 voltages not specified\n"); + return -EINVAL; + } + + return 0; +} +#else +static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, + struct max8997_platform_data *pdata) +{ + return 0; +} +#endif /* CONFIG_OF */ + +static int max8997_pmic_probe(struct platform_device *pdev) { struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev); + struct max8997_platform_data *pdata = iodev->pdata; struct regulator_config config = { }; - struct regulator_dev **rdev; + struct regulator_dev *rdev; struct max8997_data *max8997; struct i2c_client *i2c; - int i, ret, size; + int i, ret, nr_dvs; u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0; if (!pdata) { - dev_err(pdev->dev.parent, "No platform init data supplied.\n"); + dev_err(&pdev->dev, "No platform init data supplied.\n"); return -ENODEV; } + if (iodev->dev->of_node) { + ret = max8997_pmic_dt_parse_pdata(pdev, pdata); + if (ret) + return ret; + } + 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 = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); - if (!max8997->rdev) - return -ENOMEM; - - rdev = max8997->rdev; max8997->dev = &pdev->dev; max8997->iodev = iodev; max8997->num_regulators = pdata->num_regulators; @@ -973,33 +1063,36 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) memcpy(max8997->buck125_gpios, pdata->buck125_gpios, sizeof(int) * 3); max8997->ignore_gpiodvs_side_effect = pdata->ignore_gpiodvs_side_effect; - for (i = 0; i < 8; i++) { + nr_dvs = (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs || + pdata->buck5_gpiodvs) ? 8 : 1; + + for (i = 0; i < nr_dvs; i++) { max8997->buck1_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck1_voltage[i] / 1000, - pdata->buck1_voltage[i] / 1000 + + pdata->buck1_voltage[i], + pdata->buck1_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) - goto err_out; + return ret; max8997->buck2_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck2_voltage[i] / 1000, - pdata->buck2_voltage[i] / 1000 + + pdata->buck2_voltage[i], + pdata->buck2_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) - goto err_out; + return ret; max8997->buck5_vol[i] = ret = max8997_get_voltage_proper_val( &buck1245_voltage_map_desc, - pdata->buck5_voltage[i] / 1000, - pdata->buck5_voltage[i] / 1000 + + pdata->buck5_voltage[i], + pdata->buck5_voltage[i] + buck1245_voltage_map_desc.step); if (ret < 0) - goto err_out; + return ret; if (max_buck1 < max8997->buck1_vol[i]) max_buck1 = max8997->buck1_vol[i]; @@ -1019,6 +1112,19 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) max_buck5, 0x3f); } + /* Initialize all the DVS related BUCK registers */ + for (i = 0; i < nr_dvs; i++) { + max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i, + max8997->buck1_vol[i], + 0x3f); + max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i, + max8997->buck2_vol[i], + 0x3f); + max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i, + max8997->buck5_vol[i], + 0x3f); + } + /* * If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them. * If at least one of them cares, set gpios. @@ -1030,24 +1136,23 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) !gpio_is_valid(pdata->buck125_gpios[1]) || !gpio_is_valid(pdata->buck125_gpios[2])) { dev_err(&pdev->dev, "GPIO NOT VALID\n"); - ret = -EINVAL; - goto err_out; + return -EINVAL; } ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0], "MAX8997 SET1"); if (ret) - goto err_out; + return ret; ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1], "MAX8997 SET2"); if (ret) - goto err_out; + return ret; ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2], "MAX8997 SET3"); if (ret) - goto err_out; + return ret; gpio_direction_output(pdata->buck125_gpios[0], (max8997->buck125_gpioindex >> 2) @@ -1068,19 +1173,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); - /* Initialize all the DVS related BUCK registers */ - for (i = 0; i < 8; i++) { - max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i, - max8997->buck1_vol[i], - 0x3f); - max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i, - max8997->buck2_vol[i], - 0x3f); - max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i, - max8997->buck5_vol[i], - 0x3f); - } - /* Misc Settings */ max8997->ramp_delay = 10; /* set 10mV/us, which is the default */ max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9); @@ -1090,45 +1182,31 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) int id = pdata->regulators[i].id; desc = reg_voltage_map[id]; - if (desc) + if (desc) { regulators[id].n_voltages = (desc->max - desc->min) / desc->step + 1; - else if (id == MAX8997_ESAFEOUT1 || id == MAX8997_ESAFEOUT2) - regulators[id].n_voltages = 4; - else if (id == MAX8997_CHARGER_CV) + } else if (id == MAX8997_ESAFEOUT1 || id == MAX8997_ESAFEOUT2) { + regulators[id].volt_table = safeoutvolt; + regulators[id].n_voltages = ARRAY_SIZE(safeoutvolt); + } else if (id == MAX8997_CHARGER_CV) { regulators[id].n_voltages = 16; + } config.dev = max8997->dev; config.init_data = pdata->regulators[i].initdata; config.driver_data = max8997; + config.of_node = pdata->regulators[i].reg_node; - rdev[i] = regulator_register(®ulators[id], &config); - if (IS_ERR(rdev[i])) { - ret = PTR_ERR(rdev[i]); + rdev = devm_regulator_register(&pdev->dev, ®ulators[id], + &config); + if (IS_ERR(rdev)) { dev_err(max8997->dev, "regulator init failed for %d\n", id); - rdev[i] = NULL; - goto err; + return PTR_ERR(rdev); } } return 0; -err: - while (--i >= 0) - regulator_unregister(rdev[i]); -err_out: - return ret; -} - -static int __devexit max8997_pmic_remove(struct platform_device *pdev) -{ - struct max8997_data *max8997 = platform_get_drvdata(pdev); - struct regulator_dev **rdev = max8997->rdev; - int i; - - for (i = 0; i < max8997->num_regulators; i++) - regulator_unregister(rdev[i]); - return 0; } static const struct platform_device_id max8997_pmic_id[] = { @@ -1143,7 +1221,6 @@ static struct platform_driver max8997_pmic_driver = { .owner = THIS_MODULE, }, .probe = max8997_pmic_probe, - .remove = __devexit_p(max8997_pmic_remove), .id_table = max8997_pmic_id, }; |
