diff options
Diffstat (limited to 'drivers/regulator/lp3971.c')
| -rw-r--r-- | drivers/regulator/lp3971.c | 216 | 
1 files changed, 60 insertions, 156 deletions
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 3bb82b624e1..66fd2330dca 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -16,6 +16,7 @@  #include <linux/err.h>  #include <linux/i2c.h>  #include <linux/kernel.h> +#include <linux/module.h>  #include <linux/regulator/driver.h>  #include <linux/regulator/lp3971.h>  #include <linux/slab.h> @@ -24,8 +25,6 @@ struct lp3971 {  	struct device *dev;  	struct mutex io_lock;  	struct i2c_client *i2c; -	int num_regulators; -	struct regulator_dev **rdev;  };  static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg); @@ -64,16 +63,14 @@ static const int buck_base_addr[] = {  #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])  #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1) -static const int buck_voltage_map[] = { -	   0,  800,  850,  900,  950, 1000, 1050, 1100, -	1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500, -	1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800, -	3000, 3300, +static const unsigned int buck_voltage_map[] = { +	      0,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, +	1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, +	1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000, +	3000000, 3300000,  };  #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) @@ -97,35 +94,19 @@ static const int buck_voltage_map[] = {  #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)  #define LDO_VOL_CONTR_MASK 0x0f -static const int ldo45_voltage_map[] = { -	1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350, -	1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300, +static const unsigned int ldo45_voltage_map[] = { +	1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000, +	1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000,  }; -static const int ldo123_voltage_map[] = { -	1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, -	2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, +static const unsigned int ldo123_voltage_map[] = { +	1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000, +	2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,  }; -static const int *ldo_voltage_map[] = { -	ldo123_voltage_map, /* LDO1 */ -	ldo123_voltage_map, /* LDO2 */ -	ldo123_voltage_map, /* LDO3 */ -	ldo45_voltage_map, /* LDO4 */ -	ldo45_voltage_map, /* LDO5 */ -}; - -#define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)]) -  #define LDO_VOL_MIN_IDX 0x00  #define LDO_VOL_MAX_IDX 0x0f -static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index) -{ -	int ldo = rdev_get_id(dev) - LP3971_LDO1; -	return 1000 * LDO_VOL_VALUE_MAP(ldo)[index]; -} -  static int lp3971_ldo_is_enabled(struct regulator_dev *dev)  {  	struct lp3971 *lp3971 = rdev_get_drvdata(dev); @@ -155,7 +136,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; @@ -164,48 +145,30 @@ 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 1000 * LDO_VOL_VALUE_MAP(ldo)[val]; +	return val;  } -static int lp3971_ldo_set_voltage(struct regulator_dev *dev, -				  int min_uV, int max_uV) +static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, +				      unsigned int selector)  {  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);  	int ldo = rdev_get_id(dev) - LP3971_LDO1; -	int min_vol = min_uV / 1000, max_vol = max_uV / 1000; -	const int *vol_map = LDO_VOL_VALUE_MAP(ldo); -	u16 val; - -	if (min_vol < vol_map[LDO_VOL_MIN_IDX] || -	    min_vol > vol_map[LDO_VOL_MAX_IDX]) -		return -EINVAL; - -	for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++) -		if (vol_map[val] >= min_vol) -			break; - -	if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol) -		return -EINVAL;  	return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),  			LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), -			val << LDO_VOL_CONTR_SHIFT(ldo)); +			selector << LDO_VOL_CONTR_SHIFT(ldo));  }  static struct regulator_ops lp3971_ldo_ops = { -	.list_voltage = lp3971_ldo_list_voltage, +	.list_voltage = regulator_list_voltage_table, +	.map_voltage = regulator_map_voltage_ascend,  	.is_enabled = lp3971_ldo_is_enabled,  	.enable = lp3971_ldo_enable,  	.disable = lp3971_ldo_disable, -	.get_voltage = lp3971_ldo_get_voltage, -	.set_voltage = lp3971_ldo_set_voltage, +	.get_voltage_sel = lp3971_ldo_get_voltage_sel, +	.set_voltage_sel = lp3971_ldo_set_voltage_sel,  }; -static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) -{ -	return 1000 * buck_voltage_map[index]; -} -  static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)  {  	struct lp3971 *lp3971 = rdev_get_drvdata(dev); @@ -235,50 +198,27 @@ 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 = 1000 * 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(struct regulator_dev *dev, -				  int min_uV, int max_uV) +static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, +				       unsigned int selector)  {  	struct lp3971 *lp3971 = rdev_get_drvdata(dev);  	int buck = rdev_get_id(dev) - LP3971_DCDC1; -	int min_vol = min_uV / 1000, max_vol = max_uV / 1000; -	const int *vol_map = buck_voltage_map; -	u16 val;  	int ret; -	if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] || -	    min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX]) -		return -EINVAL; - -	for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX; -	     val++) -		if (vol_map[val] >= min_vol) -			break; - -	if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol) -		return -EINVAL; -  	ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck), -	       BUCK_TARGET_VOL_MASK, val); +	       BUCK_TARGET_VOL_MASK, selector);  	if (ret)  		return ret; @@ -294,20 +234,22 @@ static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,  }  static struct regulator_ops lp3971_dcdc_ops = { -	.list_voltage = lp3971_dcdc_list_voltage, +	.list_voltage = regulator_list_voltage_table, +	.map_voltage = regulator_map_voltage_ascend,  	.is_enabled = lp3971_dcdc_is_enabled,  	.enable = lp3971_dcdc_enable,  	.disable = lp3971_dcdc_disable, -	.get_voltage = lp3971_dcdc_get_voltage, -	.set_voltage = lp3971_dcdc_set_voltage, +	.get_voltage_sel = lp3971_dcdc_get_voltage_sel, +	.set_voltage_sel = lp3971_dcdc_set_voltage_sel,  }; -static struct regulator_desc regulators[] = { +static const struct regulator_desc regulators[] = {  	{  		.name = "LDO1",  		.id = LP3971_LDO1,  		.ops = &lp3971_ldo_ops,  		.n_voltages = ARRAY_SIZE(ldo123_voltage_map), +		.volt_table = ldo123_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -316,6 +258,7 @@ static struct regulator_desc regulators[] = {  		.id = LP3971_LDO2,  		.ops = &lp3971_ldo_ops,  		.n_voltages = ARRAY_SIZE(ldo123_voltage_map), +		.volt_table = ldo123_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -324,6 +267,7 @@ static struct regulator_desc regulators[] = {  		.id = LP3971_LDO3,  		.ops = &lp3971_ldo_ops,  		.n_voltages = ARRAY_SIZE(ldo123_voltage_map), +		.volt_table = ldo123_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -332,6 +276,7 @@ static struct regulator_desc regulators[] = {  		.id = LP3971_LDO4,  		.ops = &lp3971_ldo_ops,  		.n_voltages = ARRAY_SIZE(ldo45_voltage_map), +		.volt_table = ldo45_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -340,6 +285,7 @@ static struct regulator_desc regulators[] = {  		.id = LP3971_LDO5,  		.ops = &lp3971_ldo_ops,  		.n_voltages = ARRAY_SIZE(ldo45_voltage_map), +		.volt_table = ldo45_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -348,6 +294,7 @@ static struct regulator_desc regulators[] = {  		.id = LP3971_DCDC1,  		.ops = &lp3971_dcdc_ops,  		.n_voltages = ARRAY_SIZE(buck_voltage_map), +		.volt_table = buck_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -356,6 +303,7 @@ static struct regulator_desc regulators[] = {  		.id = LP3971_DCDC2,  		.ops = &lp3971_dcdc_ops,  		.n_voltages = ARRAY_SIZE(buck_voltage_map), +		.volt_table = buck_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -364,6 +312,7 @@ static struct regulator_desc regulators[] = {  		.id = LP3971_DCDC3,  		.ops = &lp3971_dcdc_ops,  		.n_voltages = ARRAY_SIZE(buck_voltage_map), +		.volt_table = buck_voltage_map,  		.type = REGULATOR_VOLTAGE,  		.owner = THIS_MODULE,  	}, @@ -378,7 +327,7 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count,  		return -EIO;  	ret = i2c_smbus_read_byte_data(i2c, reg);  	if (ret < 0) -		return -EIO; +		return ret;  	*dest = ret;  	return 0; @@ -427,49 +376,39 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)  	return ret;  } -static int __devinit setup_regulators(struct lp3971 *lp3971, +static int setup_regulators(struct lp3971 *lp3971,  				      struct lp3971_platform_data *pdata)  {  	int i, err; -	lp3971->num_regulators = pdata->num_regulators; -	lp3971->rdev = kcalloc(pdata->num_regulators, -				sizeof(struct regulator_dev *), GFP_KERNEL); -	if (!lp3971->rdev) { -		err = -ENOMEM; -		goto err_nomem; -	} -  	/* Instantiate the regulators */  	for (i = 0; i < pdata->num_regulators; i++) { +		struct regulator_config config = { };  		struct lp3971_regulator_subdev *reg = &pdata->regulators[i]; -		lp3971->rdev[i] = regulator_register(®ulators[reg->id], -					lp3971->dev, reg->initdata, lp3971); +		struct regulator_dev *rdev; + +		config.dev = lp3971->dev; +		config.init_data = reg->initdata; +		config.driver_data = lp3971; -		if (IS_ERR(lp3971->rdev[i])) { -			err = PTR_ERR(lp3971->rdev[i]); +		rdev = devm_regulator_register(lp3971->dev, +					       ®ulators[reg->id], &config); +		if (IS_ERR(rdev)) { +			err = PTR_ERR(rdev);  			dev_err(lp3971->dev, "regulator init failed: %d\n",  				err); -			goto error; +			return err;  		}  	}  	return 0; - -error: -	while (--i >= 0) -		regulator_unregister(lp3971->rdev[i]); -	kfree(lp3971->rdev); -	lp3971->rdev = NULL; -err_nomem: -	return err;  } -static int __devinit lp3971_i2c_probe(struct i2c_client *i2c, +static int lp3971_i2c_probe(struct i2c_client *i2c,  			    const struct i2c_device_id *id)  {  	struct lp3971 *lp3971; -	struct lp3971_platform_data *pdata = i2c->dev.platform_data; +	struct lp3971_platform_data *pdata = dev_get_platdata(&i2c->dev);  	int ret;  	u16 val; @@ -478,7 +417,7 @@ static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,  		return -ENODEV;  	} -	lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL); +	lp3971 = devm_kzalloc(&i2c->dev, sizeof(struct lp3971), GFP_KERNEL);  	if (lp3971 == NULL)  		return -ENOMEM; @@ -493,38 +432,20 @@ static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,  		ret = -ENODEV;  	if (ret < 0) {  		dev_err(&i2c->dev, "failed to detect device\n"); -		goto err_detect; +		return ret;  	}  	ret = setup_regulators(lp3971, pdata);  	if (ret < 0) -		goto err_detect; +		return ret;  	i2c_set_clientdata(i2c, lp3971);  	return 0; - -err_detect: -	kfree(lp3971); -	return ret; -} - -static int __devexit lp3971_i2c_remove(struct i2c_client *i2c) -{ -	struct lp3971 *lp3971 = i2c_get_clientdata(i2c); -	int i; - -	for (i = 0; i < lp3971->num_regulators; i++) -		regulator_unregister(lp3971->rdev[i]); - -	kfree(lp3971->rdev); -	kfree(lp3971); - -	return 0;  }  static const struct i2c_device_id lp3971_i2c_id[] = { -       { "lp3971", 0 }, -       { } +	{ "lp3971", 0 }, +	{ }  };  MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id); @@ -534,27 +455,10 @@ static struct i2c_driver lp3971_i2c_driver = {  		.owner = THIS_MODULE,  	},  	.probe    = lp3971_i2c_probe, -	.remove   = __devexit_p(lp3971_i2c_remove),  	.id_table = lp3971_i2c_id,  }; -static int __init lp3971_module_init(void) -{ -	int ret; - -	ret = i2c_add_driver(&lp3971_i2c_driver); -	if (ret != 0) -		pr_err("Failed to register I2C driver: %d\n", ret); - -	return ret; -} -module_init(lp3971_module_init); - -static void __exit lp3971_module_exit(void) -{ -	i2c_del_driver(&lp3971_i2c_driver); -} -module_exit(lp3971_module_exit); +module_i2c_driver(lp3971_i2c_driver);  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>");  | 
