diff options
Diffstat (limited to 'drivers/regulator')
27 files changed, 887 insertions, 437 deletions
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 2b557119adad..a957e8c53205 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -30,8 +30,6 @@ struct pm8607_regulator_info { unsigned int *vol_table; unsigned int *vol_suspend; - int update_reg; - int update_bit; int slope_double; }; @@ -222,29 +220,6 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) return ret; } -static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) -{ - struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); - uint8_t val; - int ret; - - val = (uint8_t)(selector << (ffs(rdev->desc->vsel_mask) - 1)); - - ret = pm860x_set_bits(info->i2c, rdev->desc->vsel_reg, - rdev->desc->vsel_mask, val); - if (ret) - return ret; - switch (info->desc.id) { - case PM8607_ID_BUCK1: - case PM8607_ID_BUCK3: - ret = pm860x_set_bits(info->i2c, info->update_reg, - 1 << info->update_bit, - 1 << info->update_bit); - break; - } - return ret; -} - static int pm8606_preg_enable(struct regulator_dev *rdev) { struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); @@ -276,7 +251,7 @@ static int pm8606_preg_is_enabled(struct regulator_dev *rdev) static struct regulator_ops pm8607_regulator_ops = { .list_voltage = pm8607_list_voltage, - .set_voltage_sel = pm8607_set_voltage_sel, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -313,11 +288,11 @@ static struct regulator_ops pm8606_preg_ops = { .n_voltages = ARRAY_SIZE(vreg##_table), \ .vsel_reg = PM8607_##vreg, \ .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ + .apply_reg = PM8607_##ureg, \ + .apply_bit = (ubit), \ .enable_reg = PM8607_##ereg, \ .enable_mask = 1 << (ebit), \ }, \ - .update_reg = PM8607_##ureg, \ - .update_bit = (ubit), \ .slope_double = (0), \ .vol_table = (unsigned int *)&vreg##_table, \ .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ @@ -343,9 +318,9 @@ static struct regulator_ops pm8606_preg_ops = { } static struct pm8607_regulator_info pm8607_regulator_info[] = { - PM8607_DVC(BUCK1, GO, 0, SUPPLIES_EN11, 0), - PM8607_DVC(BUCK2, GO, 1, SUPPLIES_EN11, 1), - PM8607_DVC(BUCK3, GO, 2, SUPPLIES_EN11, 2), + PM8607_DVC(BUCK1, GO, BIT(0), SUPPLIES_EN11, 0), + PM8607_DVC(BUCK2, GO, BIT(1), SUPPLIES_EN11, 1), + PM8607_DVC(BUCK3, GO, BIT(2), SUPPLIES_EN11, 2), PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3), PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4), diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 551a22b07538..a5d97eaee99e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -91,6 +91,7 @@ config REGULATOR_AAT2870 config REGULATOR_ARIZONA tristate "Wolfson Arizona class devices" depends on MFD_ARIZONA + depends on SND_SOC help Support for the regulators found on Wolfson Arizona class devices. @@ -277,6 +278,15 @@ config REGULATOR_LP872X help This driver supports LP8720/LP8725 PMIC +config REGULATOR_LP8755 + tristate "TI LP8755 High Performance PMU driver" + depends on I2C + select REGMAP_I2C + help + This driver supports LP8755 High Performance PMU driver. This + chip contains six step-down DC/DC converters which can support + 9 mode multiphase configuration. + config REGULATOR_LP8788 bool "TI LP8788 Power Regulators" depends on MFD_LP8788 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index b802b0c7fb02..6e8250382def 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o +obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 8f39cac661d2..0d4a8ccbb536 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -31,12 +31,18 @@ #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> +#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */ +#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ + struct anatop_regulator { const char *name; u32 control_reg; struct regmap *anatop; int vol_bit_shift; int vol_bit_width; + u32 delay_reg; + int delay_bit_shift; + int delay_bit_width; int min_bit_val; int min_voltage; int max_voltage; @@ -55,6 +61,32 @@ static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg, return regulator_set_voltage_sel_regmap(reg, selector); } +static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg, + unsigned int old_sel, + unsigned int new_sel) +{ + struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); + u32 val; + int ret = 0; + + /* check whether need to care about LDO ramp up speed */ + if (anatop_reg->delay_bit_width && new_sel > old_sel) { + /* + * the delay for LDO ramp up time is + * based on the register setting, we need + * to calculate how many steps LDO need to + * ramp up, and how much delay needed. (us) + */ + regmap_read(anatop_reg->anatop, anatop_reg->delay_reg, &val); + val = (val >> anatop_reg->delay_bit_shift) & + ((1 << anatop_reg->delay_bit_width) - 1); + ret = (new_sel - old_sel) * (LDO_RAMP_UP_UNIT_IN_CYCLES << + val) / LDO_RAMP_UP_FREQ_IN_MHZ + 1; + } + + return ret; +} + static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); @@ -67,6 +99,7 @@ static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) static struct regulator_ops anatop_rops = { .set_voltage_sel = anatop_regmap_set_voltage_sel, + .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel, .get_voltage_sel = anatop_regmap_get_voltage_sel, .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -143,6 +176,14 @@ static int anatop_regulator_probe(struct platform_device *pdev) goto anatop_probe_end; } + /* read LDO ramp up setting, only for core reg */ + of_property_read_u32(np, "anatop-delay-reg-offset", + &sreg->delay_reg); + of_property_read_u32(np, "anatop-delay-bit-width", + &sreg->delay_bit_width); + of_property_read_u32(np, "anatop-delay-bit-shift", + &sreg->delay_bit_shift); + rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1 + sreg->min_bit_val; rdesc->min_uV = sreg->min_voltage; diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index a6d040cbf8ac..e87536bf0bed 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -21,6 +21,8 @@ #include <linux/regulator/machine.h> #include <linux/gpio.h> #include <linux/slab.h> +#include <linux/workqueue.h> +#include <sound/soc.h> #include <linux/mfd/arizona/core.h> #include <linux/mfd/arizona/pdata.h> @@ -34,6 +36,8 @@ struct arizona_micsupp { struct regulator_consumer_supply supply; struct regulator_init_data init_data; + + struct work_struct check_cp_work; }; static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, @@ -72,9 +76,73 @@ static int arizona_micsupp_map_voltage(struct regulator_dev *rdev, return selector; } +static void arizona_micsupp_check_cp(struct work_struct *work) +{ + struct arizona_micsupp *micsupp = + container_of(work, struct arizona_micsupp, check_cp_work); + struct snd_soc_dapm_context *dapm = micsupp->arizona->dapm; + struct arizona *arizona = micsupp->arizona; + struct regmap *regmap = arizona->regmap; + unsigned int reg; + int ret; + + ret = regmap_read(regmap, ARIZONA_MIC_CHARGE_PUMP_1, ®); + if (ret != 0) { + dev_err(arizona->dev, "Failed to read CP state: %d\n", ret); + return; + } + + if (dapm) { + if ((reg & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) == + ARIZONA_CPMIC_ENA) + snd_soc_dapm_force_enable_pin(dapm, "MICSUPP"); + else + snd_soc_dapm_disable_pin(dapm, "MICSUPP"); + + snd_soc_dapm_sync(dapm); + } +} + +static int arizona_micsupp_enable(struct regulator_dev *rdev) +{ + struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); + int ret; + + ret = regulator_enable_regmap(rdev); + + if (ret == 0) + schedule_work(&micsupp->check_cp_work); + + return ret; +} + +static int arizona_micsupp_disable(struct regulator_dev *rdev) +{ + struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); + int ret; + + ret = regulator_disable_regmap(rdev); + if (ret == 0) + schedule_work(&micsupp->check_cp_work); + + return ret; +} + +static int arizona_micsupp_set_bypass(struct regulator_dev *rdev, bool ena) +{ + struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); + int ret; + + ret = regulator_set_bypass_regmap(rdev, ena); + if (ret == 0) + schedule_work(&micsupp->check_cp_work); + + return ret; +} + static struct regulator_ops arizona_micsupp_ops = { - .enable = regulator_enable_regmap, - .disable = regulator_disable_regmap, + .enable = arizona_micsupp_enable, + .disable = arizona_micsupp_disable, .is_enabled = regulator_is_enabled_regmap, .list_voltage = arizona_micsupp_list_voltage, @@ -84,7 +152,7 @@ static struct regulator_ops arizona_micsupp_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_bypass = regulator_get_bypass_regmap, - .set_bypass = regulator_set_bypass_regmap, + .set_bypass = arizona_micsupp_set_bypass, }; static const struct regulator_desc arizona_micsupp = { @@ -109,7 +177,8 @@ static const struct regulator_desc arizona_micsupp = { static const struct regulator_init_data arizona_micsupp_default = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS | - REGULATOR_CHANGE_VOLTAGE, + REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_BYPASS, .min_uV = 1700000, .max_uV = 3300000, }, @@ -131,6 +200,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev) } micsupp->arizona = arizona; + INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp); /* * Since the chip usually supplies itself we provide some diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c index 2f1341db38a0..f0ba8c4eefa9 100644 --- a/drivers/regulator/as3711-regulator.c +++ b/drivers/regulator/as3711-regulator.c @@ -303,7 +303,7 @@ static int as3711_regulator_probe(struct platform_device *pdev) reg_data = pdata ? pdata->init_data[id] : NULL; /* No need to register if there is no regulator data */ - if (!ri->desc.name) + if (!reg_data) continue; reg = ®s[id]; diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 278584302f2d..da9782bd27d0 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -200,8 +200,8 @@ static int regulator_check_consumers(struct regulator_dev *rdev, } if (*min_uV > *max_uV) { - dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n", - regulator->min_uV, regulator->max_uV); + rdev_err(rdev, "Restricting voltage, %u-%uuV\n", + *min_uV, *max_uV); return -EINVAL; } @@ -2080,10 +2080,20 @@ EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); */ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) { + int ret; + sel <<= ffs(rdev->desc->vsel_mask) - 1; - return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, + ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, rdev->desc->vsel_mask, sel); + if (ret) + return ret; + + if (rdev->desc->apply_bit) + ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, + rdev->desc->apply_bit, + rdev->desc->apply_bit); + return ret; } EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); @@ -2229,8 +2239,11 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, best_val = rdev->desc->ops->list_voltage(rdev, ret); if (min_uV <= best_val && max_uV >= best_val) { selector = ret; - ret = rdev->desc->ops->set_voltage_sel(rdev, - ret); + if (old_selector == selector) + ret = 0; + else + ret = rdev->desc->ops->set_voltage_sel( + rdev, ret); } else { ret = -EINVAL; } @@ -2241,7 +2254,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, /* Call set_voltage_time_sel if successfully obtained old_selector */ if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && - rdev->desc->ops->set_voltage_time_sel) { + old_selector != selector && rdev->desc->ops->set_voltage_time_sel) { delay = rdev->desc->ops->set_voltage_time_sel(rdev, old_selector, selector); @@ -2294,6 +2307,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) { struct regulator_dev *rdev = regulator->rdev; int ret = 0; + int old_min_uV, old_max_uV; mutex_lock(&rdev->mutex); @@ -2315,18 +2329,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) ret = regulator_check_voltage(rdev, &min_uV, &max_uV); if (ret < 0) goto out; + + /* restore original values in case of error */ + old_min_uV = regulator->min_uV; + old_max_uV = regulator->max_uV; regulator->min_uV = min_uV; regulator->max_uV = max_uV; ret = regulator_check_consumers(rdev, &min_uV, &max_uV); if (ret < 0) - goto out; + goto out2; ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); - + if (ret < 0) + goto out2; + out: mutex_unlock(&rdev->mutex); return ret; +out2: + regulator->min_uV = old_min_uV; + regulator->max_uV = old_max_uV; + mutex_unlock(&rdev->mutex); + return ret; } EXPORT_SYMBOL_GPL(regulator_set_voltage); @@ -3208,7 +3233,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev) if (status < 0) return status; } - if (ops->is_enabled) { + if (rdev->ena_gpio || ops->is_enabled) { status = device_create_file(dev, &dev_attr_state); if (status < 0) return status; diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index d0963090442d..c6d8651fd329 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -70,7 +70,6 @@ struct da9052_regulator_info { int step_uV; int min_uV; int max_uV; - unsigned char activate_bit; }; struct da9052_regulator { @@ -210,36 +209,6 @@ static int da9052_map_voltage(struct regulator_dev *rdev, return sel; } -static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev, - unsigned int selector) -{ - struct da9052_regulator *regulator = rdev_get_drvdata(rdev); - struct da9052_regulator_info *info = regulator->info; - int id = rdev_get_id(rdev); - int ret; - - ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg, - rdev->desc->vsel_mask, selector); - if (ret < 0) - return ret; - - /* Some LDOs and DCDCs are DVC controlled which requires enabling of - * the activate bit to implment the changes on the output. - */ - switch (id) { - case DA9052_ID_BUCK1: - case DA9052_ID_BUCK2: - case DA9052_ID_BUCK3: - case DA9052_ID_LDO2: - case DA9052_ID_LDO3: - ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, - info->activate_bit, info->activate_bit); - break; - } - - return ret; -} - static struct regulator_ops da9052_dcdc_ops = { .get_current_limit = da9052_dcdc_get_current_limit, .set_current_limit = da9052_dcdc_set_current_limit, @@ -247,7 +216,7 @@ static struct regulator_ops da9052_dcdc_ops = { .list_voltage = da9052_list_voltage, .map_voltage = da9052_map_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = da9052_regulator_set_voltage_sel, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -257,7 +226,7 @@ static struct regulator_ops da9052_ldo_ops = { .list_voltage = da9052_list_voltage, .map_voltage = da9052_map_voltage, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = da9052_regulator_set_voltage_sel, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -274,13 +243,14 @@ static struct regulator_ops da9052_ldo_ops = { .owner = THIS_MODULE,\ .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ .vsel_mask = (1 << (sbits)) - 1,\ + .apply_reg = DA9052_SUPPLY_REG, \ + .apply_bit = (abits), \ .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ .enable_mask = 1 << (ebits),\ },\ .min_uV = (min) * 1000,\ .max_uV = (max) * 1000,\ .step_uV = (step) * 1000,\ - .activate_bit = (abits),\ } #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ @@ -294,13 +264,14 @@ static struct regulator_ops da9052_ldo_ops = { .owner = THIS_MODULE,\ .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ .vsel_mask = (1 << (sbits)) - 1,\ + .apply_reg = DA9052_SUPPLY_REG, \ + .apply_bit = (abits), \ .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ .enable_mask = 1 << (ebits),\ },\ .min_uV = (min) * 1000,\ .max_uV = (max) * 1000,\ .step_uV = (step) * 1000,\ - .activate_bit = (abits),\ } static struct da9052_regulator_info da9052_regulator_info[] = { diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index 1a05ac66878f..30221099d09c 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c @@ -58,7 +58,6 @@ struct da9055_volt_reg { int reg_b; int sl_shift; int v_mask; - int v_shift; }; struct da9055_mode_reg { @@ -388,7 +387,6 @@ static struct regulator_ops da9055_ldo_ops = { .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ .sl_shift = 7,\ .v_mask = (1 << (vbits)) - 1,\ - .v_shift = (vbits),\ },\ } @@ -417,7 +415,6 @@ static struct regulator_ops da9055_ldo_ops = { .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ .sl_shift = 7,\ .v_mask = (1 << (vbits)) - 1,\ - .v_shift = (vbits),\ },\ .mode = {\ .reg = DA9055_REG_BCORE_MODE,\ diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c index 261f3d2299bc..89bd2faaef8c 100644 --- a/drivers/regulator/dbx500-prcmu.c +++ b/drivers/regulator/dbx500-prcmu.c @@ -14,6 +14,7 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/slab.h> +#include <linux/module.h> #include "dbx500-prcmu.h" diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index bae681ccd3ea..9d39eb4aafa3 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -132,7 +132,7 @@ static struct regulator_ops gpio_regulator_voltage_ops = { .list_voltage = gpio_regulator_list_voltage, }; -struct gpio_regulator_config * +static struct gpio_regulator_config * of_get_gpio_regulator_config(struct device *dev, struct device_node *np) { struct gpio_regulator_config *config; @@ -163,10 +163,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); /* Fetch GPIOs. */ - for (i = 0; ; i++) - if (of_get_named_gpio(np, "gpios", i) < 0) - break; - config->nr_gpios = i; + config->nr_gpios = of_gpio_count(np); config->gpios = devm_kzalloc(dev, sizeof(struct gpio) * config->nr_gpios, diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 5f68ff11a298..9cb2c0f34515 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -73,8 +73,6 @@ static const unsigned int buck_voltage_map[] = { }; #define BUCK_TARGET_VOL_MASK 0x3f -#define BUCK_TARGET_VOL_MIN_IDX 0x01 -#define BUCK_TARGET_VOL_MAX_IDX 0x19 #define LP3971_BUCK_RAMP_REG(x) (buck_base_addr[x]+2) @@ -140,7 +138,7 @@ static int lp3971_ldo_disable(struct regulator_dev *dev) return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0); } -static int lp3971_ldo_get_voltage(struct regulator_dev *dev) +static int lp3971_ldo_get_voltage_sel(struct regulator_dev *dev) { struct lp3971 *lp3971 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) - LP3971_LDO1; @@ -149,7 +147,7 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev) reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo)); val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK; - return dev->desc->volt_table[val]; + return val; } static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, @@ -168,7 +166,7 @@ static struct regulator_ops lp3971_ldo_ops = { .is_enabled = lp3971_ldo_is_enabled, .enable = lp3971_ldo_enable, .disable = lp3971_ldo_disable, - .get_voltage = lp3971_ldo_get_voltage, + .get_voltage_sel = lp3971_ldo_get_voltage_sel, .set_voltage_sel = lp3971_ldo_set_voltage_sel, }; @@ -201,24 +199,16 @@ static int lp3971_dcdc_disable(struct regulator_dev *dev) return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0); } -static int lp3971_dcdc_get_voltage(struct regulator_dev *dev) +static int lp3971_dcdc_get_voltage_sel(struct regulator_dev *dev) { struct lp3971 *lp3971 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) - LP3971_DCDC1; u16 reg; - int val; reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck)); reg &= BUCK_TARGET_VOL_MASK; - if (reg <= BUCK_TARGET_VOL_MAX_IDX) - val = buck_voltage_map[reg]; - else { - val = 0; - dev_warn(&dev->dev, "chip reported incorrect voltage value.\n"); - } - - return val; + return reg; } static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, @@ -249,7 +239,7 @@ static struct regulator_ops lp3971_dcdc_ops = { .is_enabled = lp3971_dcdc_is_enabled, .enable = lp3971_dcdc_enable, .disable = lp3971_dcdc_disable, - .get_voltage = lp3971_dcdc_get_voltage, + .get_voltage_sel = lp3971_dcdc_get_voltage_sel, .set_voltage_sel = lp3971_dcdc_set_voltage_sel, }; diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 69c42c318b87..0baabcfb578a 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -165,8 +165,6 @@ static const int buck_base_addr[] = { #define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x]) #define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x]) #define LP3972_BUCK_VOL_MASK 0x1f -#define LP3972_BUCK_VOL_MIN_IDX(x) ((x) ? 0x01 : 0x00) -#define LP3972_BUCK_VOL_MAX_IDX(x) ((x) ? 0x19 : 0x1f) static int lp3972_i2c_read(struct i2c_client *i2c, char reg, int count, u16 *dest) @@ -257,7 +255,7 @@ static int lp3972_ldo_disable(struct regulator_dev *dev) mask, 0); } -static int lp3972_ldo_get_voltage(struct regulator_dev *dev) +static int lp3972_ldo_get_voltage_sel(struct regulator_dev *dev) { struct lp3972 *lp3972 = rdev_get_drvdata(dev); int ldo = rdev_get_id(dev) - LP3972_LDO1; @@ -267,7 +265,7 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev) reg = lp3972_reg_read(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo)); val = (reg >> LP3972_LDO_VOL_CONTR_SHIFT(ldo)) & mask; - return dev->desc->volt_table[val]; + return val; } static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, @@ -314,7 +312,7 @@ static struct regulator_ops lp3972_ldo_ops = { .is_enabled = lp3972_ldo_is_enabled, .enable = lp3972_ldo_enable, .disable = lp3972_ldo_disable, - .get_voltage = lp3972_ldo_get_voltage, + .get_voltage_sel = lp3972_ldo_get_voltage_sel, .set_voltage_sel = lp3972_ldo_set_voltage_sel, }; @@ -353,24 +351,16 @@ static int lp3972_dcdc_disable(struct regulator_dev *dev) return val; } -static int lp3972_dcdc_get_voltage(struct regulator_dev *dev) +static int lp3972_dcdc_get_voltage_sel(struct regulator_dev *dev) { struct lp3972 *lp3972 = rdev_get_drvdata(dev); int buck = rdev_get_id(dev) - LP3972_DCDC1; u16 reg; - int val; reg = lp3972_reg_read(lp3972, LP3972_BUCK_VOL1_REG(buck)); reg &= LP3972_BUCK_VOL_MASK; - if (reg <= LP3972_BUCK_VOL_MAX_IDX(buck)) - val = dev->desc->volt_table[reg]; - else { - val = 0; - dev_warn(&dev->dev, "chip reported incorrect voltage value." - " reg = %d\n", reg); - } - return val; + return reg; } static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev, @@ -402,7 +392,7 @@ static struct regulator_ops lp3972_dcdc_ops = { .is_enabled = lp3972_dcdc_is_enabled, .enable = lp3972_dcdc_enable, .disable = lp3972_dcdc_disable, - .get_voltage = lp3972_dcdc_get_voltage, + .get_voltage_sel = lp3972_dcdc_get_voltage_sel, .set_voltage_sel = lp3972_dcdc_set_voltage_sel, }; diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 9289ead715ca..8e3c7ae0047f 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -181,20 +181,6 @@ static inline int lp872x_update_bits(struct lp872x *lp, u8 addr, return regmap_update_bits(lp->regmap, addr, mask, data); } -static int _rdev_to_offset(struct regulator_dev *rdev) -{ - enum lp872x_regulator_id id = rdev_get_id(rdev); - - switch (id) { - case LP8720_ID_LDO1 ... LP8720_ID_BUCK: - return id; - case LP8725_ID_LDO1 ... LP8725_ID_BUCK2: - return id - LP8725_ID_BASE; - default: - return -EINVAL; - } -} - static int lp872x_get_timestep_usec(struct lp872x *lp) { enum lp872x_id chip = lp->chipid; @@ -234,28 +220,20 @@ static int lp872x_get_timestep_usec(struct lp872x *lp) static int lp872x_regulator_enable_time(struct regulator_dev *rdev) { struct lp872x *lp = rdev_get_drvdata(rdev); - enum lp872x_regulator_id regulator = rdev_get_id(rdev); + enum lp872x_regulator_id rid = rdev_get_id(rdev); int time_step_us = lp872x_get_timestep_usec(lp); - int ret, offset; + int ret; u8 addr, val; if (time_step_us < 0) return -EINVAL; - switch (regulator) { - case LP8720_ID_LDO1 ... LP8720_ID_LDO5: - case LP8725_ID_LDO1 ... LP8725_ID_LILO2: - offset = _rdev_to_offset(rdev); - if (offset < 0) - return -EINVAL; - - addr = LP872X_LDO1_VOUT + offset; - break; - case LP8720_ID_BUCK: - addr = LP8720_BUCK_VOUT1; + switch (rid) { + case LP8720_ID_LDO1 ... LP8720_ID_BUCK: + addr = LP872X_LDO1_VOUT + rid; break; - case LP8725_ID_BUCK1: - addr = LP8725_BUCK1_VOUT1; + case LP8725_ID_LDO1 ... LP8725_ID_BUCK1: + addr = LP872X_LDO1_VOUT + rid - LP8725_ID_BASE; break; case LP8725_ID_BUCK2: addr = LP8725_BUCK2_VOUT1; diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c new file mode 100644 index 000000000000..f0f6ea05065b --- /dev/null +++ b/drivers/regulator/lp8755.c @@ -0,0 +1,566 @@ +/* + * LP8755 High Performance Power Management Unit : System Interface Driver + * (based on rev. 0.26) + * Copyright 2012 Texas Instruments + * + * Author: Daniel(Geon Si) Jeong <daniel.jeong@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/err.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/regmap.h> +#include <linux/delay.h> +#include <linux/uaccess.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/platform_data/lp8755.h> + +#define LP8755_REG_BUCK0 0x00 +#define LP8755_REG_BUCK1 0x03 +#define LP8755_REG_BUCK2 0x04 +#define LP8755_REG_BUCK3 0x01 +#define LP8755_REG_BUCK4 0x05 +#define LP8755_REG_BUCK5 0x02 +#define LP8755_REG_MAX 0xFF + +#define LP8755_BUCK_EN_M BIT(7) +#define LP8755_BUCK_LINEAR_OUT_MAX 0x76 +#define LP8755_BUCK_VOUT_M 0x7F + +struct lp8755_mphase { + int nreg; + int buck_num[LP8755_BUCK_MAX]; +}; + +struct lp8755_chip { + struct device *dev; + struct regmap *regmap; + struct lp8755_platform_data *pdata; + + int irq; + unsigned int irqmask; + + int mphase; + struct regulator_dev *rdev[LP8755_BUCK_MAX]; +}; + +/** + *lp8755_read : read a single register value from lp8755. + *@pchip : device to read from + *@reg : register to read from + *@val : pointer to store read value + */ +static int lp8755_read(struct lp8755_chip *pchip, unsigned int reg, + unsigned int *val) +{ + return regmap_read(pchip->regmap, reg, val); +} + +/** + *lp8755_write : write a single register value to lp8755. + *@pchip : device to write to + *@reg : register to write to + *@val : value to be written + */ +static int lp8755_write(struct lp8755_chip *pchip, unsigned int reg, + unsigned int val) +{ + return regmap_write(pchip->regmap, reg, val); +} + +/** + *lp8755_update_bits : set the values of bit fields in lp8755 register. + *@pchip : device to read from + *@reg : register to update + *@mask : bitmask to be changed + *@val : value for bitmask + */ +static int lp8755_update_bits(struct lp8755_chip *pchip, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits(pchip->regmap, reg, mask, val); +} + +static int lp8755_buck_enable_time(struct regulator_dev *rdev) +{ + int ret; + unsigned int regval; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + ret = lp8755_read(pchip, 0x12 + id, ®val); + if (ret < 0) { + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; + } + return (regval & 0xff) * 100; +} + +static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + int ret; + unsigned int regbval = 0x0; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + switch (mode) { + case REGULATOR_MODE_FAST: + /* forced pwm mode */ + regbval = (0x01 << id); + break; + case REGULATOR_MODE_NORMAL: + /* enable automatic pwm/pfm mode */ + ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x00); + if (ret < 0) + goto err_i2c; + break; + case REGULATOR_MODE_IDLE: + /* enable automatic pwm/pfm/lppfm mode */ + ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x20); + if (ret < 0) + goto err_i2c; + + ret = lp8755_update_bits(pchip, 0x10, 0x01, 0x01); + if (ret < 0) + goto err_i2c; + break; + default: + dev_err(pchip->dev, "Not supported buck mode %s\n", __func__); + /* forced pwm mode */ + regbval = (0x01 << id); + } + + ret = lp8755_update_bits(pchip, 0x06, 0x01 << id, regbval); + if (ret < 0) + goto err_i2c; + return ret; +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) +{ + int ret; + unsigned int regval; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + ret = lp8755_read(pchip, 0x06, ®val); + if (ret < 0) + goto err_i2c; + + /* mode fast means forced pwm mode */ + if (regval & (0x01 << id)) + return REGULATOR_MODE_FAST; + + ret = lp8755_read(pchip, 0x08 + id, ®val); + if (ret < 0) + goto err_i2c; + + /* mode idle means automatic pwm/pfm/lppfm mode */ + if (regval & 0x20) + return REGULATOR_MODE_IDLE; + + /* mode normal means automatic pwm/pfm mode */ + return REGULATOR_MODE_NORMAL; + +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return 0; +} + +static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp) +{ + int ret; + unsigned int regval = 0x00; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + /* uV/us */ + switch (ramp) { + case 0 ... 230: + regval = 0x07; + break; + case 231 ... 470: + regval = 0x06; + break; + case 471 ... 940: + regval = 0x05; + break; + case 941 ... 1900: + regval = 0x04; + break; + case 1901 ... 3800: + regval = 0x03; + break; + case 3801 ... 7500: + regval = 0x02; + break; + case 7501 ... 15000: + regval = 0x01; + break; + case 15001 ... 30000: + regval = 0x00; + break; + default: + dev_err(pchip->dev, + "Not supported ramp value %d %s\n", ramp, __func__); + return -EINVAL; + } + + ret = lp8755_update_bits(pchip, 0x07 + id, 0x07, regval); + if (ret < 0) + goto err_i2c; + return ret; +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +static struct regulator_ops lp8755_buck_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .enable_time = lp8755_buck_enable_time, + .set_mode = lp8755_buck_set_mode, + .get_mode = lp8755_buck_get_mode, + .set_ramp_delay = lp8755_buck_set_ramp, +}; + +#define lp8755_rail(_id) "lp8755_buck"#_id +#define lp8755_buck_init(_id)\ +{\ + .constraints = {\ + .name = lp8755_rail(_id),\ + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,\ + .min_uV = 500000,\ + .max_uV = 1675000,\ + },\ +} + +static struct regulator_init_data lp8755_reg_default[LP8755_BUCK_MAX] = { + [LP8755_BUCK0] = lp8755_buck_init(0), + [LP8755_BUCK1] = lp8755_buck_init(1), + [LP8755_BUCK2] = lp8755_buck_init(2), + [LP8755_BUCK3] = lp8755_buck_init(3), + [LP8755_BUCK4] = lp8755_buck_init(4), + [LP8755_BUCK5] = lp8755_buck_init(5), +}; + +static const struct lp8755_mphase mphase_buck[MPHASE_CONF_MAX] = { + { 3, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK5 } }, + { 6, { LP8755_BUCK0, LP8755_BUCK1, LP8755_BUCK2, LP8755_BUCK3, + LP8755_BUCK4, LP8755_BUCK5 } }, + { 5, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK4, + LP8755_BUCK5} }, + { 4, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK4, LP8755_BUCK5} }, + { 3, { LP8755_BUCK0, LP8755_BUCK4, LP8755_BUCK5} }, + { 2, { LP8755_BUCK0, LP8755_BUCK5} }, + { 1, { LP8755_BUCK0} }, + { 2, { LP8755_BUCK0, LP8755_BUCK3} }, + { 4, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK5} }, +}; + +static int lp8755_init_data(struct lp8755_chip *pchip) +{ + unsigned int regval; + int ret, icnt, buck_num; + struct lp8755_platform_data *pdata = pchip->pdata; + + /* read back muti-phase configuration */ + ret = lp8755_read(pchip, 0x3D, ®val); + if (ret < 0) + goto out_i2c_error; + pchip->mphase = regval & 0x0F; + + /* set default data based on multi-phase config */ + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { + buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; + pdata->buck_data[buck_num] = &lp8755_reg_default[buck_num]; + } + return ret; + +out_i2c_error: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +#define lp8755_buck_desc(_id)\ +{\ + .name = lp8755_rail(_id),\ + .id = LP8755_BUCK##_id,\ + .ops = &lp8755_buck_ops,\ + .n_voltages = LP8755_BUCK_LINEAR_OUT_MAX+1,\ + .uV_step = 10000,\ + .min_uV = 500000,\ + .type = REGULATOR_VOLTAGE,\ + .owner = THIS_MODULE,\ + .enable_reg = LP8755_REG_BUCK##_id,\ + .enable_mask = LP8755_BUCK_EN_M,\ + .vsel_reg = LP8755_REG_BUCK##_id,\ + .vsel_mask = LP8755_BUCK_VOUT_M,\ +} + +static struct regulator_desc lp8755_regulators[] = { + lp8755_buck_desc(0), + lp8755_buck_desc(1), + lp8755_buck_desc(2), + lp8755_buck_desc(3), + lp8755_buck_desc(4), + lp8755_buck_desc(5), +}; + +static int lp8755_regulator_init(struct lp8755_chip *pchip) +{ + int ret, icnt, buck_num; + struct lp8755_platform_data *pdata = pchip->pdata; + struct regulator_config rconfig = { }; + + rconfig.regmap = pchip->regmap; + rconfig.dev = pchip->dev; + rconfig.driver_data = pchip; + + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { + buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; + rconfig.init_data = pdata->buck_data[buck_num]; + rconfig.of_node = pchip->dev->of_node; + pchip->rdev[buck_num] = + regulator_register(&lp8755_regulators[buck_num], &rconfig); + if (IS_ERR(pchip->rdev[buck_num])) { + ret = PTR_ERR(pchip->rdev[buck_num]); + pchip->rdev[buck_num] = NULL; + dev_err(pchip->dev, "regulator init failed: buck %d\n", + buck_num); + goto err_buck; + } + } + + return 0; + +err_buck: + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + regulator_unregister(pchip->rdev[icnt]); + return ret; +} + +static irqreturn_t lp8755_irq_handler(int irq, void *data) +{ + int ret, icnt; + unsigned int flag0, flag1; + struct lp8755_chip *pchip = data; + + /* read flag0 register */ + ret = lp8755_read(pchip, 0x0D, &flag0); + if (ret < 0) + goto err_i2c; + /* clear flag register to pull up int. pin */ + ret = lp8755_write(pchip, 0x0D, 0x00); + if (ret < 0) + goto err_i2c; + + /* sent power fault detection event to specific regulator */ + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + if ((flag0 & (0x4 << icnt)) + && (pchip->irqmask & (0x04 << icnt)) + && (pchip->rdev[icnt] != NULL)) + regulator_notifier_call_chain(pchip->rdev[icnt], + LP8755_EVENT_PWR_FAULT, + NULL); + + /* read flag1 register */ + ret = lp8755_read(pchip, 0x0E, &flag1); + if (ret < 0) + goto err_i2c; + /* clear flag register to pull up int. pin */ + ret = lp8755_write(pchip, 0x0E, 0x00); + if (ret < 0) + goto err_i2c; + + /* send OCP event to all regualtor devices */ + if ((flag1 & 0x01) && (pchip->irqmask & 0x01)) + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + if (pchip->rdev[icnt] != NULL) + regulator_notifier_call_chain(pchip->rdev[icnt], + LP8755_EVENT_OCP, + NULL); + + /* send OVP event to all regualtor devices */ + if ((flag1 & 0x02) && (pchip->irqmask & 0x02)) + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + if (pchip->rdev[icnt] != NULL) + regulator_notifier_call_chain(pchip->rdev[icnt], + LP8755_EVENT_OVP, + NULL); + return IRQ_HANDLED; + +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return IRQ_NONE; +} + +static int lp8755_int_config(struct lp8755_chip *pchip) +{ + int ret; + unsigned int regval; + + if (pchip->irq == 0) { + dev_warn(pchip->dev, "not use interrupt : %s\n", __func__); + return 0; + } + + ret = lp8755_read(pchip, 0x0F, ®val); + if (ret < 0) + goto err_i2c; + pchip->irqmask = regval; + ret = request_threaded_irq(pchip->irq, NULL, lp8755_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "lp8755-irq", pchip); + if (ret) + return ret; + + return ret; + +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +static const struct regmap_config lp8755_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = LP8755_REG_MAX, +}; + +static int lp8755_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret, icnt; + struct lp8755_chip *pchip; + struct lp8755_platform_data *pdata = client->dev.platform_data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "i2c functionality check fail.\n"); + return -EOPNOTSUPP; + } + + pchip = devm_kzalloc(&client->dev, + sizeof(struct lp8755_chip), GFP_KERNEL); + if (!pchip) + return -ENOMEM; + + pchip->dev = &client->dev; + pchip->regmap = devm_regmap_init_i2c(client, &lp8755_regmap); + if (IS_ERR(pchip->regmap)) { + ret = PTR_ERR(pchip->regmap); + dev_err(&client->dev, "fail to allocate regmap %d\n", ret); + return ret; + } + i2c_set_clientdata(client, pchip); + + if (pdata != NULL) { + pchip->pdata = pdata; + pchip->mphase = pdata->mphase; + } else { + pchip->pdata = devm_kzalloc(pchip->dev, + sizeof(struct lp8755_platform_data), + GFP_KERNEL); + if (!pchip->pdata) + return -ENOMEM; + ret = lp8755_init_data(pchip); + if (ret < 0) { + dev_err(&client->dev, "fail to initialize chip\n"); + return ret; + } + } + + ret = lp8755_regulator_init(pchip); + if (ret < 0) { + dev_err(&client->dev, "fail to initialize regulators\n"); + goto err_regulator; + } + + pchip->irq = client->irq; + ret = lp8755_int_config(pchip); + if (ret < 0) { + dev_err(&client->dev, "fail to irq config\n"); + goto err_irq; + } + + return ret; + +err_irq: + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) + regulator_unregister(pchip->rdev[icnt]); + +err_regulator: + /* output disable */ + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + lp8755_write(pchip, icnt, 0x00); + + return ret; +} + +static int lp8755_remove(struct i2c_client *client) +{ + int icnt; + struct lp8755_chip *pchip = i2c_get_clientdata(client); + + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) + regulator_unregister(pchip->rdev[icnt]); + + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + lp8755_write(pchip, icnt, 0x00); + + if (pchip->irq != 0) + free_irq(pchip->irq, pchip); + + return 0; +} + +static const struct i2c_device_id lp8755_id[] = { + {LP8755_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, lp8755_id); + +static struct i2c_driver lp8755_i2c_driver = { + .driver = { + .name = LP8755_NAME, + }, + .probe = lp8755_probe, + .remove = lp8755_remove, + .id_table = lp8755_id, +}; + +static int __init lp8755_init(void) +{ + return i2c_add_driver(&lp8755_i2c_driver); +} + +subsys_initcall(lp8755_init); + +static void __exit lp8755_exit(void) +{ + i2c_del_driver(&lp8755_i2c_driver); +} + +module_exit(lp8755_exit); + +MODULE_DESCRIPTION("Texas Instruments lp8755 driver"); +MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c index aef3f2b0c5ea..97891a7ea7b2 100644 --- a/drivers/regulator/lp8788-buck.c +++ b/drivers/regulator/lp8788-buck.c @@ -103,16 +103,6 @@ static const int lp8788_buck_vtbl[] = { 1950000, 2000000, }; -static const u8 buck1_vout_addr[] = { - LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1, - LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3, -}; - -static const u8 buck2_vout_addr[] = { - LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1, - LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3, -}; - static void lp8788_buck1_set_dvs(struct lp8788_buck *buck) { struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs; @@ -235,7 +225,7 @@ static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck, lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S; } - addr = buck1_vout_addr[idx]; + addr = LP8788_BUCK1_VOUT0 + idx; break; case BUCK2: if (mode == EXTPIN) { @@ -258,7 +248,7 @@ static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck, lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S; } - addr = buck2_vout_addr[idx]; + addr = LP8788_BUCK2_VOUT0 + idx; break; default: goto err; @@ -429,7 +419,8 @@ static struct regulator_desc lp8788_buck_desc[] = { }, }; -static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, +static int lp8788_dvs_gpio_request(struct platform_device *pdev, + struct lp8788_buck *buck, enum lp8788_buck_id id) { struct lp8788_platform_data *pdata = buck->lp->pdata; @@ -440,7 +431,7 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, switch (id) { case BUCK1: gpio = pdata->buck1_dvs->gpio; - ret = devm_gpio_request_one(buck->lp->dev, gpio, DVS_LOW, + ret = devm_gpio_request_one(&pdev->dev, gpio, DVS_LOW, b1_name); if (ret) return ret; @@ -448,9 +439,9 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, buck->dvs = pdata->buck1_dvs; break; case BUCK2: - for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) { + for (i = 0; i < LP8788_NUM_BUCK2_DVS; i++) { gpio = pdata->buck2_dvs->gpio[i]; - ret = devm_gpio_request_one(buck->lp->dev, gpio, + ret = devm_gpio_request_one(&pdev->dev, gpio, DVS_LOW, b2_name[i]); if (ret) return ret; @@ -464,7 +455,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, return 0; } -static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) +static int lp8788_init_dvs(struct platform_device *pdev, + struct lp8788_buck *buck, enum lp8788_buck_id id) { struct lp8788_platform_data *pdata = buck->lp->pdata; u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M }; @@ -472,7 +464,7 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C }; /* no dvs for buck3, 4 */ - if (id == BUCK3 || id == BUCK4) + if (id > BUCK2) return 0; /* no dvs platform data, then dvs will be selected by I2C registers */ @@ -483,7 +475,7 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) (id == BUCK2 && !pdata->buck2_dvs)) goto set_default_dvs_mode; - if (lp8788_dvs_gpio_request(buck, id)) + if (lp8788_dvs_gpio_request(pdev, buck, id)) goto set_default_dvs_mode; return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], @@ -503,17 +495,20 @@ static int lp8788_buck_probe(struct platform_device *pdev) struct regulator_dev *rdev; int ret; - buck = devm_kzalloc(lp->dev, sizeof(struct lp8788_buck), GFP_KERNEL); + if (id >= LP8788_NUM_BUCKS) + return -EINVAL; + + buck = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_buck), GFP_KERNEL); if (!buck) return -ENOMEM; buck->lp = lp; - ret = lp8788_init_dvs(buck, id); + ret = lp8788_init_dvs(pdev, buck, id); if (ret) return ret; - cfg.dev = lp->dev; + cfg.dev = pdev->dev.parent; cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL; cfg.driver_data = buck; cfg.regmap = lp->regmap; @@ -521,7 +516,7 @@ static int lp8788_buck_probe(struct platform_device *pdev) rdev = regulator_register(&lp8788_buck_desc[id], &cfg); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); - dev_err(lp->dev, "BUCK%d regulator register err = %d\n", + dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n", id + 1, ret); return ret; } diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index 3792741708ce..cd5a14ad9263 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c @@ -88,11 +88,6 @@ #define ENABLE GPIOF_OUT_INIT_HIGH #define DISABLE GPIOF_OUT_INIT_LOW -enum lp8788_enable_mode { - REGISTER, - EXTPIN, -}; - enum lp8788_ldo_id { DLDO1, DLDO2, @@ -189,114 +184,38 @@ static enum lp8788_ldo_id lp8788_aldo_id[] = { ALDO10, }; -/* DLDO 7, 9 and 11, ALDO 1 ~ 5 and 7 - : can be enabled either by external pin or by i2c register */ -static enum lp8788_enable_mode -lp8788_get_ldo_enable_mode(struct lp8788_ldo *ldo, enum lp8788_ldo_id id) -{ - int ret; - u8 val, mask; - - ret = lp8788_read_byte(ldo->lp, LP8788_EN_SEL, &val); - if (ret) - return ret; - - switch (id) { - case DLDO7: - mask = LP8788_EN_SEL_DLDO7_M; - break; - case DLDO9: - case DLDO11: - mask = LP8788_EN_SEL_DLDO911_M; - break; - case ALDO1: - mask = LP8788_EN_SEL_ALDO1_M; - break; - case ALDO2 ... ALDO4: - mask = LP8788_EN_SEL_ALDO234_M; - break; - case ALDO5: - mask = LP8788_EN_SEL_ALDO5_M; - break; - case ALDO7: - mask = LP8788_EN_SEL_ALDO7_M; - break; - default: - return REGISTER; - } - - return val & mask ? EXTPIN : REGISTER; -} - -static int lp8788_ldo_ctrl_by_extern_pin(struct lp8788_ldo *ldo, int pinstate) -{ - struct lp8788_ldo_enable_pin *pin = ldo->en_pin; - - if (!pin) - return -EINVAL; - - if (gpio_is_valid(pin->gpio)) - gpio_set_value(pin->gpio, pinstate); - - return 0; -} - -static int lp8788_ldo_is_enabled_by_extern_pin(struct lp8788_ldo *ldo) -{ - struct lp8788_ldo_enable_pin *pin = ldo->en_pin; - - if (!pin) - return -EINVAL; - - return gpio_get_value(pin->gpio) ? 1 : 0; -} - static int lp8788_ldo_enable(struct regulator_dev *rdev) { struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); - enum lp8788_ldo_id id = rdev_get_id(rdev); - enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); - switch (mode) { - case EXTPIN: - return lp8788_ldo_ctrl_by_extern_pin(ldo, ENABLE); - case REGISTER: + if (ldo->en_pin) { + gpio_set_value(ldo->en_pin->gpio, ENABLE); + return 0; + } else { return regulator_enable_regmap(rdev); - default: - return -EINVAL; } } static int lp8788_ldo_disable(struct regulator_dev *rdev) { struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); - enum lp8788_ldo_id id = rdev_get_id(rdev); - enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); - switch (mode) { - case EXTPIN: - return lp8788_ldo_ctrl_by_extern_pin(ldo, DISABLE); - case REGISTER: + if (ldo->en_pin) { + gpio_set_value(ldo->en_pin->gpio, DISABLE); + return 0; + } else { return regulator_disable_regmap(rdev); - default: - return -EINVAL; } } static int lp8788_ldo_is_enabled(struct regulator_dev *rdev) { struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); - enum lp8788_ldo_id id = rdev_get_id(rdev); - enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); - switch (mode) { - case EXTPIN: - return lp8788_ldo_is_enabled_by_extern_pin(ldo); - case REGISTER: + if (ldo->en_pin) + return gpio_get_value(ldo->en_pin->gpio) ? 1 : 0; + else return regulator_is_enabled_regmap(rdev); - default: - return -EINVAL; - } } static int lp8788_ldo_enable_time(struct regulator_dev *rdev) @@ -616,10 +535,11 @@ static struct regulator_desc lp8788_aldo_desc[] = { }, }; -static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo, +static int lp8788_gpio_request_ldo_en(struct platform_device *pdev, + struct lp8788_ldo *ldo, enum lp8788_ext_ldo_en_id id) { - struct device *dev = ldo->lp->dev; + struct device *dev = &pdev->dev; struct lp8788_ldo_enable_pin *pin = ldo->en_pin; int ret, gpio, pinstate; char *name[] = { @@ -647,7 +567,8 @@ static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo, return ret; } -static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo, +static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, + struct lp8788_ldo *ldo, enum lp8788_ldo_id id) { int ret; @@ -693,9 +614,11 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo, ldo->en_pin = pdata->ldo_pin[enable_id]; - ret = lp8788_gpio_request_ldo_en(ldo, enable_id); - if (ret) + ret = lp8788_gpio_request_ldo_en(pdev, ldo, enable_id); + if (ret) { + ldo->en_pin = NULL; goto set_default_ldo_enable_mode; + } return ret; @@ -712,16 +635,16 @@ static int lp8788_dldo_probe(struct platform_device *pdev) struct regulator_dev *rdev; int ret; - ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); + ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); if (!ldo) return -ENOMEM; ldo->lp = lp; - ret = lp8788_config_ldo_enable_mode(ldo, lp8788_dldo_id[id]); + ret = lp8788_config_ldo_enable_mode(pdev, ldo, lp8788_dldo_id[id]); if (ret) return ret; - cfg.dev = lp->dev; + cfg.dev = pdev->dev.parent; cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL; cfg.driver_data = ldo; cfg.regmap = lp->regmap; @@ -729,7 +652,7 @@ static int lp8788_dldo_probe(struct platform_device *pdev) rdev = regulator_register(&lp8788_dldo_desc[id], &cfg); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); - dev_err(lp->dev, "DLDO%d regulator register err = %d\n", + dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n", id + 1, ret); return ret; } @@ -768,16 +691,16 @@ static int lp8788_aldo_probe(struct platform_device *pdev) struct regulator_dev *rdev; int ret; - ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); + ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); if (!ldo) return -ENOMEM; ldo->lp = lp; - ret = lp8788_config_ldo_enable_mode(ldo, lp8788_aldo_id[id]); + ret = lp8788_config_ldo_enable_mode(pdev, ldo, lp8788_aldo_id[id]); if (ret) return ret; - cfg.dev = lp->dev; + cfg.dev = pdev->dev.parent; cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL; cfg.driver_data = ldo; cfg.regmap = lp->regmap; @@ -785,7 +708,7 @@ static int lp8788_aldo_probe(struct platform_device *pdev) rdev = regulator_register(&lp8788_aldo_desc[id], &cfg); if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); - dev_err(lp->dev, "ALDO%d regulator register err = %d\n", + dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n", id + 1, ret); return ret; } diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index b85040caaea3..e4586ee8858d 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c @@ -75,13 +75,14 @@ static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev) { unsigned int val; struct max77686_data *max77686 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); - if (rdev->desc->id == MAX77686_BUCK1) + if (id == MAX77686_BUCK1) val = 0x1; else val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT; - max77686->opmode[rdev->desc->id] = val; + max77686->opmode[id] = val; return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val); @@ -93,9 +94,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, { struct max77686_data *max77686 = rdev_get_drvdata(rdev); unsigned int val; + int id = rdev_get_id(rdev); /* BUCK[5-9] doesn't support this feature */ - if (rdev->desc->id >= MAX77686_BUCK5) + if (id >= MAX77686_BUCK5) return 0; switch (mode) { @@ -111,7 +113,7 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, return -EINVAL; } - max77686->opmode[rdev->desc->id] = val; + max77686->opmode[id] = val; return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val); @@ -140,7 +142,7 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, return -EINVAL; } - max77686->opmode[rdev->desc->id] = val; + max77686->opmode[rdev_get_id(rdev)] = val; return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, val); @@ -152,7 +154,7 @@ static int max77686_enable(struct regulator_dev *rdev) return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, rdev->desc->enable_mask, - max77686->opmode[rdev->desc->id]); + max77686->opmode[rdev_get_id(rdev)]); } static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) @@ -379,9 +381,10 @@ static struct regulator_desc regulators[] = { }; #ifdef CONFIG_OF -static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, +static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, struct max77686_platform_data *pdata) { + struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct device_node *pmic_np, *regulators_np; struct max77686_regulator_data *rdata; struct of_regulator_match rmatch; @@ -390,15 +393,15 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, pmic_np = iodev->dev->of_node; regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators"); if (!regulators_np) { - dev_err(iodev->dev, "could not find regulators sub-node\n"); + dev_err(&pdev->dev, "could not find regulators sub-node\n"); return -EINVAL; } pdata->num_regulators = ARRAY_SIZE(regulators); - rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * + rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * pdata->num_regulators, GFP_KERNEL); if (!rdata) { - dev_err(iodev->dev, + dev_err(&pdev->dev, "could not allocate memory for regulator data\n"); return -ENOMEM; } @@ -407,7 +410,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, rmatch.name = regulators[i].name; rmatch.init_data = NULL; rmatch.of_node = NULL; - of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); + of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1); rdata[i].initdata = rmatch.init_data; rdata[i].of_node = rmatch.of_node; } @@ -417,7 +420,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, return 0; } #else -static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, +static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, struct max77686_platform_data *pdata) { return 0; @@ -440,7 +443,7 @@ static int max77686_pmic_probe(struct platform_device *pdev) } if (iodev->dev->of_node) { - ret = max77686_pmic_dt_parse_pdata(iodev, pdata); + ret = max77686_pmic_dt_parse_pdata(pdev, pdata); if (ret) return ret; } diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index d1a77512d83e..d40cf7fdb546 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c @@ -237,8 +237,7 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev) return -EINVAL; } - ret = of_regulator_match(pdev->dev.parent, regulators, - max8907_matches, + ret = of_regulator_match(&pdev->dev, regulators, max8907_matches, ARRAY_SIZE(max8907_matches)); if (ret < 0) { dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 02be7fcae32f..5556a15743fd 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -54,6 +54,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; @@ -130,29 +137,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) { @@ -522,7 +506,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) { @@ -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, }; @@ -934,7 +891,7 @@ static struct regulator_desc regulators[] = { }; #ifdef CONFIG_OF -static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev, +static int max8997_pmic_dt_parse_dvs_gpio(struct platform_device *pdev, struct max8997_platform_data *pdata, struct device_node *pmic_np) { @@ -944,7 +901,7 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev, gpio = of_get_named_gpio(pmic_np, "max8997,pmic-buck125-dvs-gpios", i); if (!gpio_is_valid(gpio)) { - dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); + dev_err(&pdev->dev, "invalid gpio[%d]: %d\n", i, gpio); return -EINVAL; } pdata->buck125_gpios[i] = gpio; @@ -952,22 +909,23 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev, return 0; } -static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, +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 = iodev->dev->of_node; if (!pmic_np) { - dev_err(iodev->dev, "could not find pmic sub-node\n"); + dev_err(&pdev->dev, "could not find pmic sub-node\n"); return -ENODEV; } regulators_np = of_find_node_by_name(pmic_np, "regulators"); if (!regulators_np) { - dev_err(iodev->dev, "could not find regulators sub-node\n"); + dev_err(&pdev->dev, "could not find regulators sub-node\n"); return -EINVAL; } @@ -976,11 +934,10 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, for_each_child_of_node(regulators_np, reg_np) pdata->num_regulators++; - rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * + rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * pdata->num_regulators, GFP_KERNEL); if (!rdata) { - dev_err(iodev->dev, "could not allocate memory for " - "regulator data\n"); + dev_err(&pdev->dev, "could not allocate memory for regulator data\n"); return -ENOMEM; } @@ -991,14 +948,14 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, break; if (i == ARRAY_SIZE(regulators)) { - dev_warn(iodev->dev, "don't know how to configure " - "regulator %s\n", reg_np->name); + 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( - iodev->dev, reg_np); + rdata->initdata = of_get_regulator_init_data(&pdev->dev, + reg_np); rdata->reg_node = reg_np; rdata++; } @@ -1014,7 +971,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs || pdata->buck5_gpiodvs) { - ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); + ret = max8997_pmic_dt_parse_dvs_gpio(pdev, pdata, pmic_np); if (ret) return -EINVAL; @@ -1025,8 +982,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, } else { if (pdata->buck125_default_idx >= 8) { pdata->buck125_default_idx = 0; - dev_info(iodev->dev, "invalid value for " - "default dvs index, using 0 instead\n"); + dev_info(&pdev->dev, "invalid value for default dvs index, using 0 instead\n"); } } @@ -1040,28 +996,28 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, if (of_property_read_u32_array(pmic_np, "max8997,pmic-buck1-dvs-voltage", pdata->buck1_voltage, dvs_voltage_nr)) { - dev_err(iodev->dev, "buck1 voltages not specified\n"); + 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(iodev->dev, "buck2 voltages not specified\n"); + 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(iodev->dev, "buck5 voltages not specified\n"); + dev_err(&pdev->dev, "buck5 voltages not specified\n"); return -EINVAL; } return 0; } #else -static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, +static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, struct max8997_platform_data *pdata) { return 0; @@ -1085,7 +1041,7 @@ static int max8997_pmic_probe(struct platform_device *pdev) } if (iodev->dev->of_node) { - ret = max8997_pmic_dt_parse_pdata(iodev, pdata); + ret = max8997_pmic_dt_parse_pdata(pdev, pdata); if (ret) return ret; } @@ -1234,13 +1190,15 @@ static 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; diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 1f0df4046b86..b588f07c7cad 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -65,7 +65,7 @@ static const struct voltage_map_desc ldo9_voltage_map_desc = { .min = 2800000, .step = 100000, .max = 3100000, }; static const struct voltage_map_desc ldo10_voltage_map_desc = { - .min = 95000, .step = 50000, .max = 1300000, + .min = 950000, .step = 50000, .max = 1300000, }; static const struct voltage_map_desc ldo1213_voltage_map_desc = { .min = 800000, .step = 100000, .max = 3300000, @@ -311,25 +311,13 @@ static int max8998_set_voltage_buck_sel(struct regulator_dev *rdev, dev_get_platdata(max8998->iodev->dev); struct i2c_client *i2c = max8998->iodev->i2c; int buck = rdev_get_id(rdev); - int reg, shift = 0, mask, ret; - int j, previous_sel; + int reg, shift = 0, mask, ret, j; static u8 buck1_last_val; ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); if (ret) return ret; - previous_sel = max8998_get_voltage_sel(rdev); - - /* Check if voltage needs to be changed */ - /* if previous_voltage equal new voltage, return */ - if (previous_sel == selector) { - dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n", - regulator_list_voltage_linear(rdev, previous_sel), - regulator_list_voltage_linear(rdev, selector)); - return ret; - } - switch (buck) { case MAX8998_BUCK1: dev_dbg(max8998->dev, diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 6f684916fd79..66ca769287ab 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -120,6 +120,12 @@ int of_regulator_match(struct device *dev, struct device_node *node, if (!dev || !node) return -EINVAL; + for (i = 0; i < num_matches; i++) { + struct of_regulator_match *match = &matches[i]; + match->init_data = NULL; + match->of_node = NULL; + } + for_each_child_of_node(node, child) { name = of_get_property(child, "regulator-compatible", NULL); diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index bd062a2ffbe2..cd9ea2ea1826 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -174,9 +174,9 @@ static struct regulator_ops s2mps11_buck_ops = { .min_uV = S2MPS11_BUCK_MIN2, \ .uV_step = S2MPS11_BUCK_STEP2, \ .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ - .vsel_reg = S2MPS11_REG_B9CTRL2, \ + .vsel_reg = S2MPS11_REG_B10CTRL2, \ .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ - .enable_reg = S2MPS11_REG_B9CTRL1, \ + .enable_reg = S2MPS11_REG_B10CTRL1, \ .enable_mask = S2MPS11_ENABLE_MASK \ } diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 73dce7664126..df395187c063 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c @@ -305,8 +305,8 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) if (!regs) return NULL; - count = of_regulator_match(pdev->dev.parent, regs, - reg_matches, TPS65217_NUM_REGULATOR); + count = of_regulator_match(&pdev->dev, regs, reg_matches, + TPS65217_NUM_REGULATOR); of_node_put(regs); if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) return NULL; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index f86da672c758..e68382d0e1ea 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -61,10 +61,6 @@ struct tps6586x_regulator { int enable_bit[2]; int enable_reg[2]; - - /* for DVM regulators */ - int go_reg; - int go_bit; }; static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) @@ -72,37 +68,10 @@ static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) return rdev_get_dev(rdev)->parent; } -static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, - unsigned selector) -{ - struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); - struct device *parent = to_tps6586x_dev(rdev); - int ret, val, rid = rdev_get_id(rdev); - uint8_t mask; - - val = selector << (ffs(rdev->desc->vsel_mask) - 1); - mask = rdev->desc->vsel_mask; - - ret = tps6586x_update(parent, rdev->desc->vsel_reg, val, mask); - if (ret) - return ret; - - /* Update go bit for DVM regulators */ - switch (rid) { - case TPS6586X_ID_LDO_2: - case TPS6586X_ID_LDO_4: - case TPS6586X_ID_SM_0: - case TPS6586X_ID_SM_1: - ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); - break; - } - return ret; -} - static struct regulator_ops tps6586x_regulator_ops = { .list_voltage = regulator_list_voltage_table, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = tps6586x_set_voltage_sel, + .set_voltage_sel = regulator_set_voltage_sel_regmap, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, @@ -142,7 +111,7 @@ static const unsigned int tps6586x_dvm_voltages[] = { }; #define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \ - ereg0, ebit0, ereg1, ebit1) \ + ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ .desc = { \ .supply_name = _pin_name, \ .name = "REG-" #_id, \ @@ -156,29 +125,26 @@ static const unsigned int tps6586x_dvm_voltages[] = { .enable_mask = 1 << (ebit0), \ .vsel_reg = TPS6586X_##vreg, \ .vsel_mask = ((1 << (nbits)) - 1) << (shift), \ + .apply_reg = (goreg), \ + .apply_bit = (gobit), \ }, \ .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ .enable_bit[0] = (ebit0), \ .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ .enable_bit[1] = (ebit1), -#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ - .go_reg = TPS6586X_##goreg, \ - .go_bit = (gobit), - #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1) \ { \ TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ - ereg0, ebit0, ereg1, ebit1) \ + ereg0, ebit0, ereg1, ebit1, 0, 0) \ } #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ { \ TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ - ereg0, ebit0, ereg1, ebit1) \ - TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ + ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ } #define TPS6586X_SYS_REGULATOR() \ @@ -207,13 +173,13 @@ static struct tps6586x_regulator tps6586x_regulator[] = { TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3, - ENB, 3, VCC2, 6), + ENB, 3, TPS6586X_VCC2, BIT(6)), TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3, - END, 3, VCC1, 6), + END, 3, TPS6586X_VCC1, BIT(6)), TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1, - ENB, 1, VCC1, 2), + ENB, 1, TPS6586X_VCC1, BIT(2)), TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0, - ENB, 0, VCC1, 0), + ENB, 0, TPS6586X_VCC1, BIT(0)), }; /* diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 59c3770fa77d..b0e4c0bc85c3 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -998,7 +998,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( return NULL; } - ret = of_regulator_match(pdev->dev.parent, regulators, matches, count); + ret = of_regulator_match(&pdev->dev, regulators, matches, count); if (ret < 0) { dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret); diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c index b15d711bc8c6..9019d0e7ecb6 100644 --- a/drivers/regulator/tps80031-regulator.c +++ b/drivers/regulator/tps80031-regulator.c @@ -728,7 +728,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev) } } rdev = regulator_register(&ri->rinfo->desc, &config); - if (IS_ERR_OR_NULL(rdev)) { + if (IS_ERR(rdev)) { dev_err(&pdev->dev, "register regulator failed %s\n", ri->rinfo->desc.name); |