diff options
Diffstat (limited to 'drivers/regulator/helpers.c')
| -rw-r--r-- | drivers/regulator/helpers.c | 43 | 
1 files changed, 30 insertions, 13 deletions
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index d49268336553..6e1ace660b8c 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -161,6 +161,32 @@ int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev)  }  EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap); +static int write_separate_vsel_and_range(struct regulator_dev *rdev, +					 unsigned int sel, unsigned int range) +{ +	bool range_updated; +	int ret; + +	ret = regmap_update_bits_base(rdev->regmap, rdev->desc->vsel_range_reg, +				      rdev->desc->vsel_range_mask, +				      range, &range_updated, false, false); +	if (ret) +		return ret; + +	/* +	 * Some PMICs treat the vsel_reg same as apply-bit. Force it to be +	 * written if the range changed, even if the old selector was same as +	 * the new one +	 */ +	if (rdev->desc->range_applied_by_vsel && range_updated) +		return regmap_write_bits(rdev->regmap, +					rdev->desc->vsel_reg, +					rdev->desc->vsel_mask, sel); + +	return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, +				  rdev->desc->vsel_mask, sel); +} +  /**   * regulator_set_voltage_sel_pickable_regmap - pickable range set_voltage_sel   * @@ -199,21 +225,12 @@ int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev,  	range = rdev->desc->linear_range_selectors_bitfield[i];  	range <<= ffs(rdev->desc->vsel_range_mask) - 1; -	if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) { -		ret = regmap_update_bits(rdev->regmap, -					 rdev->desc->vsel_reg, +	if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) +		ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,  					 rdev->desc->vsel_range_mask |  					 rdev->desc->vsel_mask, sel | range); -	} else { -		ret = regmap_update_bits(rdev->regmap, -					 rdev->desc->vsel_range_reg, -					 rdev->desc->vsel_range_mask, range); -		if (ret) -			return ret; - -		ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, -				  rdev->desc->vsel_mask, sel); -	} +	else +		ret = write_separate_vsel_and_range(rdev, sel, range);  	if (ret)  		return ret;  |