diff options
Diffstat (limited to 'drivers/regulator/da9052-regulator.c')
| -rw-r--r-- | drivers/regulator/da9052-regulator.c | 84 | 
1 files changed, 66 insertions, 18 deletions
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 1e4d483f616..fdb6ea8ae7e 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -70,6 +70,7 @@ struct da9052_regulator_info {  	int step_uV;  	int min_uV;  	int max_uV; +	unsigned char activate_bit;  };  struct da9052_regulator { @@ -209,6 +210,61 @@ 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 int da9052_regulator_set_voltage_time_sel(struct regulator_dev *rdev, +						 unsigned int old_sel, +						 unsigned int new_sel) +{ +	struct da9052_regulator *regulator = rdev_get_drvdata(rdev); +	struct da9052_regulator_info *info = regulator->info; +	int id = rdev_get_id(rdev); +	int ret = 0; + +	/* The DVC controlled LDOs and DCDCs ramp with 6.25mV/µs after enabling +	 * the activate bit. +	 */ +	switch (id) { +	case DA9052_ID_BUCK1: +	case DA9052_ID_BUCK2: +	case DA9052_ID_BUCK3: +	case DA9052_ID_LDO2: +	case DA9052_ID_LDO3: +		ret = (new_sel - old_sel) * info->step_uV / 6250; +		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, @@ -216,7 +272,8 @@ 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 = regulator_set_voltage_sel_regmap, +	.set_voltage_sel = da9052_regulator_set_voltage_sel, +	.set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,  	.is_enabled = regulator_is_enabled_regmap,  	.enable = regulator_enable_regmap,  	.disable = regulator_disable_regmap, @@ -226,7 +283,8 @@ 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 = regulator_set_voltage_sel_regmap, +	.set_voltage_sel = da9052_regulator_set_voltage_sel, +	.set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,  	.is_enabled = regulator_is_enabled_regmap,  	.enable = regulator_enable_regmap,  	.disable = regulator_disable_regmap, @@ -243,14 +301,13 @@ 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) \ @@ -264,14 +321,13 @@ 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[] = { @@ -372,7 +428,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)  		if (!nproot)  			return -ENODEV; -		nproot = of_find_node_by_name(nproot, "regulators"); +		nproot = of_get_child_by_name(nproot, "regulators");  		if (!nproot)  			return -ENODEV; @@ -389,8 +445,9 @@ static int da9052_regulator_probe(struct platform_device *pdev)  #endif  	} -	regulator->rdev = regulator_register(®ulator->info->reg_desc, -					     &config); +	regulator->rdev = devm_regulator_register(&pdev->dev, +						  ®ulator->info->reg_desc, +						  &config);  	if (IS_ERR(regulator->rdev)) {  		dev_err(&pdev->dev, "failed to register regulator %s\n",  			regulator->info->reg_desc.name); @@ -402,17 +459,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)  	return 0;  } -static int da9052_regulator_remove(struct platform_device *pdev) -{ -	struct da9052_regulator *regulator = platform_get_drvdata(pdev); - -	regulator_unregister(regulator->rdev); -	return 0; -} -  static struct platform_driver da9052_regulator_driver = {  	.probe = da9052_regulator_probe, -	.remove = da9052_regulator_remove,  	.driver = {  		.name = "da9052-regulator",  		.owner = THIS_MODULE,  | 
