From 43530b69d758328d3ffe6ab98fd640463e8e3667 Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Mon, 7 Nov 2011 08:16:04 +0900 Subject: regulator: Use regmap_read/write(), regmap_update_bits functions directly Current driver had the regmapcalls within the bodies of the driver specific read/write fuctions. This patch removes the original read/write functions and makes the call sites use regmap directly. Signed-off-by: Jonghwan Choi Signed-off-by: Mark Brown diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 9fb4c7b..e0bcd75 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -152,48 +152,21 @@ struct tps_driver_data { u8 core_regulator; }; -static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) -{ - return regmap_update_bits(tps->regmap, reg, mask, mask); -} - -static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask) -{ - return regmap_update_bits(tps->regmap, reg, mask, 0); -} - -static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg) -{ - unsigned int val; - int ret; - - ret = regmap_read(tps->regmap, reg, &val); - - if (ret != 0) - return ret; - else - return val; -} - -static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val) -{ - return regmap_write(tps->regmap, reg, val); -} - static int tps65023_dcdc_is_enabled(struct regulator_dev *dev) { struct tps_pmic *tps = rdev_get_drvdata(dev); int data, dcdc = rdev_get_id(dev); + int ret; u8 shift; if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) return -EINVAL; shift = TPS65023_NUM_REGULATOR - dcdc; - data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL); + ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data); - if (data < 0) - return data; + if (ret != 0) + return ret; else return (data & 1< TPS65023_LDO_2) return -EINVAL; shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL); + ret = regmap_read(tps->regmap, TPS65023_REG_REG_CTRL, &data); - if (data < 0) - return data; + if (ret != 0) + return ret; else return (data & 1<regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift); } static int tps65023_dcdc_disable(struct regulator_dev *dev) @@ -239,7 +213,7 @@ static int tps65023_dcdc_disable(struct regulator_dev *dev) return -EINVAL; shift = TPS65023_NUM_REGULATOR - dcdc; - return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift); + return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0); } static int tps65023_ldo_enable(struct regulator_dev *dev) @@ -252,7 +226,7 @@ static int tps65023_ldo_enable(struct regulator_dev *dev) return -EINVAL; shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift); + return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 1 << shift); } static int tps65023_ldo_disable(struct regulator_dev *dev) @@ -265,21 +239,22 @@ static int tps65023_ldo_disable(struct regulator_dev *dev) return -EINVAL; shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift); + return regmap_update_bits(tps->regmap, TPS65023_REG_REG_CTRL, 1 << shift, 0); } static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) { struct tps_pmic *tps = rdev_get_drvdata(dev); + int ret; int data, dcdc = rdev_get_id(dev); if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) return -EINVAL; if (dcdc == tps->core_regulator) { - data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE); - if (data < 0) - return data; + ret = regmap_read(tps->regmap, TPS65023_REG_DEF_CORE, &data); + if (ret != 0) + return ret; data &= (tps->info[dcdc]->table_len - 1); return tps->info[dcdc]->table[data] * 1000; } else @@ -318,13 +293,13 @@ static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, if (vsel == tps->info[dcdc]->table_len) goto failed; - ret = tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel); + ret = regmap_write(tps->regmap, TPS65023_REG_DEF_CORE, vsel); /* Tell the chip that we have changed the value in DEFCORE * and its time to update the core voltage */ - tps_65023_set_bits(tps, TPS65023_REG_CON_CTRL2, - TPS65023_REG_CTRL2_GO); + regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, + TPS65023_REG_CTRL2_GO, TPS65023_REG_CTRL2_GO); return ret; @@ -336,13 +311,14 @@ static int tps65023_ldo_get_voltage(struct regulator_dev *dev) { struct tps_pmic *tps = rdev_get_drvdata(dev); int data, ldo = rdev_get_id(dev); + int ret; if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) return -EINVAL; - data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL); - if (data < 0) - return data; + ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data); + if (ret != 0) + return ret; data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)); data &= (tps->info[ldo]->table_len - 1); @@ -354,6 +330,7 @@ static int tps65023_ldo_set_voltage(struct regulator_dev *dev, { struct tps_pmic *tps = rdev_get_drvdata(dev); int data, vsel, ldo = rdev_get_id(dev); + int ret; if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) return -EINVAL; @@ -377,13 +354,13 @@ static int tps65023_ldo_set_voltage(struct regulator_dev *dev, *selector = vsel; - data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL); - if (data < 0) - return data; + ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data); + if (ret != 0) + return ret; data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1); data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1))); - return tps_65023_reg_write(tps, TPS65023_REG_LDO_CTRL, data); + return regmap_write(tps->regmap, TPS65023_REG_LDO_CTRL, data); } static int tps65023_dcdc_list_voltage(struct regulator_dev *dev, @@ -511,12 +488,12 @@ static int __devinit tps_65023_probe(struct i2c_client *client, i2c_set_clientdata(client, tps); /* Enable setting output voltage by I2C */ - tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2, - TPS65023_REG_CTRL2_CORE_ADJ); + regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, + TPS65023_REG_CTRL2_CORE_ADJ, TPS65023_REG_CTRL2_CORE_ADJ); /* Enable setting output voltage by I2C */ - tps_65023_clear_bits(tps, TPS65023_REG_CON_CTRL2, - TPS65023_REG_CTRL2_CORE_ADJ); + regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2, + TPS65023_REG_CTRL2_CORE_ADJ, TPS65023_REG_CTRL2_CORE_ADJ); return 0; -- cgit v0.10.2 From c5b68d47bb06ca0df9c4d1a1ce5a46ee879aa85c Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Mon, 24 Oct 2011 22:26:26 +0900 Subject: regulator: max8649 Convert max8649 to use regmap api Signed-off-by: Jonghwan Choi Signed-off-by: Mark Brown diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 9713b1b..4e919b2 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -93,6 +93,7 @@ config REGULATOR_MAX1586 config REGULATOR_MAX8649 tristate "Maxim 8649 voltage regulator" depends on I2C + select REGMAP_I2C help This driver controls a Maxim 8649 voltage output regulator via I2C bus. diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 1062cf9..c54d0ad 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -16,6 +16,7 @@ #include #include #include +#include #define MAX8649_DCDC_VMIN 750000 /* uV */ #define MAX8649_DCDC_VMAX 1380000 /* uV */ @@ -49,9 +50,8 @@ struct max8649_regulator_info { struct regulator_dev *regulator; - struct i2c_client *i2c; struct device *dev; - struct mutex io_lock; + struct regmap *regmap; int vol_reg; unsigned mode:2; /* bit[1:0] = VID1, VID0 */ @@ -63,71 +63,6 @@ struct max8649_regulator_info { /* I2C operations */ -static inline int max8649_read_device(struct i2c_client *i2c, - int reg, int bytes, void *dest) -{ - unsigned char data; - int ret; - - data = (unsigned char)reg; - ret = i2c_master_send(i2c, &data, 1); - if (ret < 0) - return ret; - ret = i2c_master_recv(i2c, dest, bytes); - if (ret < 0) - return ret; - return 0; -} - -static inline int max8649_write_device(struct i2c_client *i2c, - int reg, int bytes, void *src) -{ - unsigned char buf[bytes + 1]; - int ret; - - buf[0] = (unsigned char)reg; - memcpy(&buf[1], src, bytes); - - ret = i2c_master_send(i2c, buf, bytes + 1); - if (ret < 0) - return ret; - return 0; -} - -static int max8649_reg_read(struct i2c_client *i2c, int reg) -{ - struct max8649_regulator_info *info = i2c_get_clientdata(i2c); - unsigned char data; - int ret; - - mutex_lock(&info->io_lock); - ret = max8649_read_device(i2c, reg, 1, &data); - mutex_unlock(&info->io_lock); - - if (ret < 0) - return ret; - return (int)data; -} - -static int max8649_set_bits(struct i2c_client *i2c, int reg, - unsigned char mask, unsigned char data) -{ - struct max8649_regulator_info *info = i2c_get_clientdata(i2c); - unsigned char value; - int ret; - - mutex_lock(&info->io_lock); - ret = max8649_read_device(i2c, reg, 1, &value); - if (ret < 0) - goto out; - value &= ~mask; - value |= data; - ret = max8649_write_device(i2c, reg, 1, &value); -out: - mutex_unlock(&info->io_lock); - return ret; -} - static inline int check_range(int min_uV, int max_uV) { if ((min_uV < MAX8649_DCDC_VMIN) || (max_uV > MAX8649_DCDC_VMAX) @@ -144,13 +79,14 @@ static int max8649_list_voltage(struct regulator_dev *rdev, unsigned index) static int max8649_get_voltage(struct regulator_dev *rdev) { struct max8649_regulator_info *info = rdev_get_drvdata(rdev); + unsigned int val; unsigned char data; int ret; - ret = max8649_reg_read(info->i2c, info->vol_reg); - if (ret < 0) + ret = regmap_read(info->regmap, info->vol_reg, &val); + if (ret != 0) return ret; - data = (unsigned char)ret & MAX8649_VOL_MASK; + data = (unsigned char)val & MAX8649_VOL_MASK; return max8649_list_voltage(rdev, data); } @@ -170,14 +106,14 @@ static int max8649_set_voltage(struct regulator_dev *rdev, mask = MAX8649_VOL_MASK; *selector = data & mask; - return max8649_set_bits(info->i2c, info->vol_reg, mask, data); + return regmap_update_bits(info->regmap, info->vol_reg, mask, data); } /* EN_PD means pulldown on EN input */ static int max8649_enable(struct regulator_dev *rdev) { struct max8649_regulator_info *info = rdev_get_drvdata(rdev); - return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD, 0); + return regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_EN_PD, 0); } /* @@ -187,38 +123,40 @@ static int max8649_enable(struct regulator_dev *rdev) static int max8649_disable(struct regulator_dev *rdev) { struct max8649_regulator_info *info = rdev_get_drvdata(rdev); - return max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_EN_PD, + return regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_EN_PD, MAX8649_EN_PD); } static int max8649_is_enabled(struct regulator_dev *rdev) { struct max8649_regulator_info *info = rdev_get_drvdata(rdev); + unsigned int val; int ret; - ret = max8649_reg_read(info->i2c, MAX8649_CONTROL); - if (ret < 0) + ret = regmap_read(info->regmap, MAX8649_CONTROL, &val); + if (ret != 0) return ret; - return !((unsigned char)ret & MAX8649_EN_PD); + return !((unsigned char)val & MAX8649_EN_PD); } static int max8649_enable_time(struct regulator_dev *rdev) { struct max8649_regulator_info *info = rdev_get_drvdata(rdev); int voltage, rate, ret; + unsigned int val; /* get voltage */ - ret = max8649_reg_read(info->i2c, info->vol_reg); - if (ret < 0) + ret = regmap_read(info->regmap, info->vol_reg, &val); + if (ret != 0) return ret; - ret &= MAX8649_VOL_MASK; + val &= MAX8649_VOL_MASK; voltage = max8649_list_voltage(rdev, (unsigned char)ret); /* uV */ /* get rate */ - ret = max8649_reg_read(info->i2c, MAX8649_RAMP); - if (ret < 0) + ret = regmap_read(info->regmap, MAX8649_RAMP, &val); + if (ret != 0) return ret; - ret = (ret & MAX8649_RAMP_MASK) >> 5; + ret = (val & MAX8649_RAMP_MASK) >> 5; rate = (32 * 1000) >> ret; /* uV/uS */ return DIV_ROUND_UP(voltage, rate); @@ -230,12 +168,12 @@ static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode) switch (mode) { case REGULATOR_MODE_FAST: - max8649_set_bits(info->i2c, info->vol_reg, MAX8649_FORCE_PWM, - MAX8649_FORCE_PWM); + regmap_update_bits(info->regmap, info->vol_reg, MAX8649_FORCE_PWM, + MAX8649_FORCE_PWM); break; case REGULATOR_MODE_NORMAL: - max8649_set_bits(info->i2c, info->vol_reg, - MAX8649_FORCE_PWM, 0); + regmap_update_bits(info->regmap, info->vol_reg, + MAX8649_FORCE_PWM, 0); break; default: return -EINVAL; @@ -246,10 +184,13 @@ static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode) static unsigned int max8649_get_mode(struct regulator_dev *rdev) { struct max8649_regulator_info *info = rdev_get_drvdata(rdev); + unsigned int val; int ret; - ret = max8649_reg_read(info->i2c, info->vol_reg); - if (ret & MAX8649_FORCE_PWM) + ret = regmap_read(info->regmap, info->vol_reg, &val); + if (ret != 0) + return ret; + if (val & MAX8649_FORCE_PWM) return REGULATOR_MODE_FAST; return REGULATOR_MODE_NORMAL; } @@ -275,11 +216,17 @@ static struct regulator_desc dcdc_desc = { .owner = THIS_MODULE, }; +static struct regmap_config max8649_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + static int __devinit max8649_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max8649_platform_data *pdata = client->dev.platform_data; struct max8649_regulator_info *info = NULL; + unsigned int val; unsigned char data; int ret; @@ -289,9 +236,14 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, return -ENOMEM; } - info->i2c = client; + info->regmap = regmap_init_i2c(client, &max8649_regmap_config); + if (IS_ERR(info->regmap)) { + ret = PTR_ERR(info->regmap); + dev_err(&client->dev, "Failed to allocate register map: %d\n", ret); + goto fail; + } + info->dev = &client->dev; - mutex_init(&info->io_lock); i2c_set_clientdata(client, info); info->mode = pdata->mode; @@ -312,8 +264,8 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, break; } - ret = max8649_reg_read(info->i2c, MAX8649_CHIP_ID1); - if (ret < 0) { + ret = regmap_read(info->regmap, MAX8649_CHIP_ID1, &val); + if (ret != 0) { dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n", ret); goto out; @@ -321,29 +273,29 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", ret); /* enable VID0 & VID1 */ - max8649_set_bits(info->i2c, MAX8649_CONTROL, MAX8649_VID_MASK, 0); + regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_VID_MASK, 0); /* enable/disable external clock synchronization */ info->extclk = pdata->extclk; data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0; - max8649_set_bits(info->i2c, info->vol_reg, MAX8649_SYNC_EXTCLK, data); + regmap_update_bits(info->regmap, info->vol_reg, MAX8649_SYNC_EXTCLK, data); if (info->extclk) { /* set external clock frequency */ info->extclk_freq = pdata->extclk_freq; - max8649_set_bits(info->i2c, MAX8649_SYNC, MAX8649_EXT_MASK, - info->extclk_freq << 6); + regmap_update_bits(info->regmap, MAX8649_SYNC, MAX8649_EXT_MASK, + info->extclk_freq << 6); } if (pdata->ramp_timing) { info->ramp_timing = pdata->ramp_timing; - max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_MASK, - info->ramp_timing << 5); + regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_MASK, + info->ramp_timing << 5); } info->ramp_down = pdata->ramp_down; if (info->ramp_down) { - max8649_set_bits(info->i2c, MAX8649_RAMP, MAX8649_RAMP_DOWN, - MAX8649_RAMP_DOWN); + regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_DOWN, + MAX8649_RAMP_DOWN); } info->regulator = regulator_register(&dcdc_desc, &client->dev, @@ -358,6 +310,8 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, dev_info(info->dev, "Max8649 regulator device is detected.\n"); return 0; out: + regmap_exit(info->regmap); +fail: kfree(info); return ret; } @@ -369,6 +323,7 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client) if (info) { if (info->regulator) regulator_unregister(info->regulator); + regmap_exit(info->regmap); kfree(info); } -- cgit v0.10.2 From 72c108cc4947db2fcdd3f3e8a2b60bd65e74a1cc Mon Sep 17 00:00:00 2001 From: Kyle Manna Date: Thu, 3 Nov 2011 12:08:05 -0500 Subject: regulator: TPS65910: Move regulator defs to header Move the regulator defintions to the header so that platform board file can use them to configure specific regulators. Signed-off-by: Kyle Manna Signed-off-by: Mark Brown diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 66d2d60..44b4f22 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -25,30 +25,6 @@ #include #include -#define TPS65910_REG_VRTC 0 -#define TPS65910_REG_VIO 1 -#define TPS65910_REG_VDD1 2 -#define TPS65910_REG_VDD2 3 -#define TPS65910_REG_VDD3 4 -#define TPS65910_REG_VDIG1 5 -#define TPS65910_REG_VDIG2 6 -#define TPS65910_REG_VPLL 7 -#define TPS65910_REG_VDAC 8 -#define TPS65910_REG_VAUX1 9 -#define TPS65910_REG_VAUX2 10 -#define TPS65910_REG_VAUX33 11 -#define TPS65910_REG_VMMC 12 - -#define TPS65911_REG_VDDCTRL 4 -#define TPS65911_REG_LDO1 5 -#define TPS65911_REG_LDO2 6 -#define TPS65911_REG_LDO3 7 -#define TPS65911_REG_LDO4 8 -#define TPS65911_REG_LDO5 9 -#define TPS65911_REG_LDO6 10 -#define TPS65911_REG_LDO7 11 -#define TPS65911_REG_LDO8 12 - #define TPS65910_SUPPLY_STATE_ENABLED 0x1 /* supported VIO voltages in milivolts */ diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index 82b4c88..fc5205d 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -739,6 +739,31 @@ #define TPS65910_GPIO_STS BIT(1) #define TPS65910_GPIO_SET BIT(0) +/* Regulator Index Definitions */ +#define TPS65910_REG_VRTC 0 +#define TPS65910_REG_VIO 1 +#define TPS65910_REG_VDD1 2 +#define TPS65910_REG_VDD2 3 +#define TPS65910_REG_VDD3 4 +#define TPS65910_REG_VDIG1 5 +#define TPS65910_REG_VDIG2 6 +#define TPS65910_REG_VPLL 7 +#define TPS65910_REG_VDAC 8 +#define TPS65910_REG_VAUX1 9 +#define TPS65910_REG_VAUX2 10 +#define TPS65910_REG_VAUX33 11 +#define TPS65910_REG_VMMC 12 + +#define TPS65911_REG_VDDCTRL 4 +#define TPS65911_REG_LDO1 5 +#define TPS65911_REG_LDO2 6 +#define TPS65911_REG_LDO3 7 +#define TPS65911_REG_LDO4 8 +#define TPS65911_REG_LDO5 9 +#define TPS65911_REG_LDO6 10 +#define TPS65911_REG_LDO7 11 +#define TPS65911_REG_LDO8 12 + /** * struct tps65910_board * Board platform data may be used to initialize regulators. -- cgit v0.10.2 From c1fc1480249dfe059254779a4bb7ca27cf5f8038 Mon Sep 17 00:00:00 2001 From: Kyle Manna Date: Thu, 3 Nov 2011 12:08:06 -0500 Subject: regulator: TPS65910: Create an array for init data Create an array of fixed size for the platform to pass regulator initalization data through. Passing an array of pointers to init data also allows more flexible definition of init data as well as prevents reading past the end of the array should the platform define an incorrectly sized array. Signed-off-by: Kyle Manna Signed-off-by: Mark Brown diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 44b4f22..a620e25 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -861,8 +861,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev) if (!pmic_plat_data) return -EINVAL; - reg_data = pmic_plat_data->tps65910_pmic_init_data; - pmic = kzalloc(sizeof(*pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; @@ -913,7 +911,16 @@ static __devinit int tps65910_probe(struct platform_device *pdev) goto err_free_info; } - for (i = 0; i < pmic->num_regulators; i++, info++, reg_data++) { + for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS; + i++, info++) { + + reg_data = pmic_plat_data->tps65910_pmic_init_data[i]; + + /* Regulator API handles empty constraints but not NULL + * constraints */ + if (!reg_data) + continue; + /* Register the regulators */ pmic->info[i] = info; diff --git a/include/linux/mfd/tps65910.h b/include/linux/mfd/tps65910.h index fc5205d..03a035d 100644 --- a/include/linux/mfd/tps65910.h +++ b/include/linux/mfd/tps65910.h @@ -764,6 +764,9 @@ #define TPS65911_REG_LDO7 11 #define TPS65911_REG_LDO8 12 +/* Max number of TPS65910/11 regulators */ +#define TPS65910_NUM_REGS 13 + /** * struct tps65910_board * Board platform data may be used to initialize regulators. @@ -775,7 +778,7 @@ struct tps65910_board { int irq_base; int vmbch_threshold; int vmbch2_threshold; - struct regulator_init_data *tps65910_pmic_init_data; + struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; }; /** -- cgit v0.10.2 From aebe495895f5542213dd17a644647b0aae8353f0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 2 Nov 2011 11:38:45 +0000 Subject: regulator: Don't report zero volts for the fixed voltage regulator If we don't know what voltage the regulator is set to return an error rather than reporting zero volts. Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 21ecf21..ccbead0 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -80,7 +80,10 @@ static int fixed_voltage_get_voltage(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); - return data->microvolts; + if (data->microvolts) + return data->microvolts; + else + return -EINVAL; } static int fixed_voltage_list_voltage(struct regulator_dev *dev, -- cgit v0.10.2 From 4c78899b92335af0da11e104698e329bb50810b5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 2 Nov 2011 11:39:09 +0000 Subject: regulator: Don't create voltage sysfs entries if we can't read voltage Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 669d021..679f92e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2503,7 +2503,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev) int status = 0; /* some attributes need specific methods to be displayed */ - if (ops->get_voltage || ops->get_voltage_sel) { + if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || + (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) { status = device_create_file(dev, &dev_attr_microvolts); if (status < 0) return status; -- cgit v0.10.2 From 8f446e6fa1d506be2cb80f91c214f1705327c7f9 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:17 +0530 Subject: regulator: helper routine to extract regulator_init_data The helper routine is meant to be used by the regulator drivers to extract the regulator_init_data structure from the data that is passed from device tree. 'consumer_supplies' which is part of regulator_init_data is not extracted as the regulator consumer mappings are passed through DT differently, implemented in subsequent patches. Similarly the regulator<-->parent/supply mapping is handled in subsequent patches. Also add documentation for regulator bindings to be used to pass regulator_init_data struct information from device tree. Some of the regulator properties which are linux and board specific, are left out since its not clear if they can be in someway embedded into the kernel or passed in from DT. They will be revisited later. Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt new file mode 100644 index 0000000..82bef20 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -0,0 +1,54 @@ +Voltage/Current Regulators + +Optional properties: +- regulator-name: A string used as a descriptive name for regulator outputs +- regulator-min-microvolt: smallest voltage consumers may set +- regulator-max-microvolt: largest voltage consumers may set +- regulator-microvolt-offset: Offset applied to voltages to compensate for voltage drops +- regulator-min-microamp: smallest current consumers may set +- regulator-max-microamp: largest current consumers may set +- regulator-always-on: boolean, regulator should never be disabled +- regulator-boot-on: bootloader/firmware enabled regulator +- -supply: phandle to the parent supply/regulator node + +Example: + + xyzreg: regulator@0 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + vin-supply = <&vin>; + }; + +Regulator Consumers: +Consumer nodes can reference one or more of its supplies/ +regulators using the below bindings. + +- -supply: phandle to the regulator node + +These are the same bindings that a regulator in the above +example used to reference its own supply, in which case +its just seen as a special case of a regulator being a +consumer itself. + +Example of a consumer device node (mmc) referencing two +regulators (twl-reg1 and twl-reg2), + + twl-reg1: regulator@0 { + ... + ... + ... + }; + + twl-reg2: regulator@1 { + ... + ... + ... + }; + + mmc: mmc@0x0 { + ... + ... + vmmc-supply = <&twl-reg1>; + vmmcaux-supply = <&twl-reg2>; + }; diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 93a6318..c75a522 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_REGULATOR) += core.o dummy.o +obj-$(CONFIG_OF) += of_regulator.o obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c new file mode 100644 index 0000000..76673c7 --- /dev/null +++ b/drivers/regulator/of_regulator.c @@ -0,0 +1,81 @@ +/* + * OF helpers for regulator framework + * + * Copyright (C) 2011 Texas Instruments, Inc. + * Rajendra Nayak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +static void of_get_regulation_constraints(struct device_node *np, + struct regulator_init_data **init_data) +{ + const __be32 *min_uV, *max_uV, *uV_offset; + const __be32 *min_uA, *max_uA; + struct regulation_constraints *constraints = &(*init_data)->constraints; + + constraints->name = of_get_property(np, "regulator-name", NULL); + + min_uV = of_get_property(np, "regulator-min-microvolt", NULL); + if (min_uV) + constraints->min_uV = be32_to_cpu(*min_uV); + max_uV = of_get_property(np, "regulator-max-microvolt", NULL); + if (max_uV) + constraints->max_uV = be32_to_cpu(*max_uV); + + /* Voltage change possible? */ + if (constraints->min_uV != constraints->max_uV) + constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + + uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); + if (uV_offset) + constraints->uV_offset = be32_to_cpu(*uV_offset); + min_uA = of_get_property(np, "regulator-min-microamp", NULL); + if (min_uA) + constraints->min_uA = be32_to_cpu(*min_uA); + max_uA = of_get_property(np, "regulator-max-microamp", NULL); + if (max_uA) + constraints->max_uA = be32_to_cpu(*max_uA); + + /* Current change possible? */ + if (constraints->min_uA != constraints->max_uA) + constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; + + if (of_find_property(np, "regulator-boot-on", NULL)) + constraints->boot_on = true; + + if (of_find_property(np, "regulator-always-on", NULL)) + constraints->always_on = true; + else /* status change should be possible if not always on. */ + constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; +} + +/** + * of_get_regulator_init_data - extract regulator_init_data structure info + * @dev: device requesting for regulator_init_data + * + * Populates regulator_init_data structure by extracting data from device + * tree node, returns a pointer to the populated struture or NULL if memory + * alloc fails. + */ +struct regulator_init_data *of_get_regulator_init_data(struct device *dev) +{ + struct regulator_init_data *init_data; + + if (!dev->of_node) + return NULL; + + init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); + if (!init_data) + return NULL; /* Out of memory? */ + + of_get_regulation_constraints(dev->of_node, &init_data); + return init_data; +} diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h new file mode 100644 index 0000000..d83a98d --- /dev/null +++ b/include/linux/regulator/of_regulator.h @@ -0,0 +1,20 @@ +/* + * OpenFirmware regulator support routines + * + */ + +#ifndef __LINUX_OF_REG_H +#define __LINUX_OF_REG_H + +#if defined(CONFIG_OF) +extern struct regulator_init_data + *of_get_regulator_init_data(struct device *dev); +#else +static inline struct regulator_init_data + *of_get_regulator_init_data(struct device *dev) +{ + return NULL; +} +#endif /* CONFIG_OF */ + +#endif /* __LINUX_OF_REG_H */ -- cgit v0.10.2 From cef49102c1d6b1e7adcb3f8b706757e0731e955c Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:18 +0530 Subject: regulator: adapt fixed regulator driver to dt The fixed regulator driver uses of_get_fixed_voltage_config() to extract fixed_voltage_config structure contents from device tree. Also add documenation for additional bindings for fixed regulators that can be passed through dt. Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt new file mode 100644 index 0000000..9cf57fd --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt @@ -0,0 +1,29 @@ +Fixed Voltage regulators + +Required properties: +- compatible: Must be "regulator-fixed"; + +Optional properties: +- gpio: gpio to use for enable control +- startup-delay-us: startup time in microseconds +- enable-active-high: Polarity of GPIO is Active high +If this property is missing, the default assumed is Active low. + +Any property defined as part of the core regulator +binding, defined in regulator.txt, can also be used. +However a fixed voltage regulator is expected to have the +regulator-min-microvolt and regulator-max-microvolt +to be the same. + +Example: + + abc: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "fixed-supply"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + gpio = <&gpio1 16 0>; + startup-delay-us = <70000>; + enable-active-high; + regulator-boot-on + }; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 21ecf21..0650856 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -27,6 +27,10 @@ #include #include #include +#include +#include +#include +#include struct fixed_voltage_data { struct regulator_desc desc; @@ -38,6 +42,53 @@ struct fixed_voltage_data { bool is_enabled; }; + +/** + * of_get_fixed_voltage_config - extract fixed_voltage_config structure info + * @dev: device requesting for fixed_voltage_config + * + * Populates fixed_voltage_config structure by extracting data from device + * tree node, returns a pointer to the populated structure of NULL if memory + * alloc fails. + */ +struct fixed_voltage_config *of_get_fixed_voltage_config(struct device *dev) +{ + struct fixed_voltage_config *config; + struct device_node *np = dev->of_node; + const __be32 *delay; + struct regulator_init_data *init_data; + + config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), + GFP_KERNEL); + if (!config) + return NULL; + + config->init_data = of_get_regulator_init_data(dev); + init_data = config->init_data; + + config->supply_name = init_data->constraints.name; + if (init_data->constraints.min_uV == init_data->constraints.max_uV) { + config->microvolts = init_data->constraints.min_uV; + } else { + dev_err(dev, + "Fixed regulator specified with variable voltages\n"); + return NULL; + } + + if (init_data->constraints.boot_on) + config->enabled_at_boot = true; + + config->gpio = of_get_named_gpio(np, "gpio", 0); + delay = of_get_property(np, "startup-delay-us", NULL); + if (delay) + config->startup_delay = be32_to_cpu(*delay); + + if (of_find_property(np, "enable-active-high", NULL)) + config->enable_high = true; + + return config; +} + static int fixed_voltage_is_enabled(struct regulator_dev *dev) { struct fixed_voltage_data *data = rdev_get_drvdata(dev); @@ -109,6 +160,9 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) struct fixed_voltage_data *drvdata; int ret; + if (pdev->dev.of_node) + config = of_get_fixed_voltage_config(&pdev->dev); + drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); if (drvdata == NULL) { dev_err(&pdev->dev, "Failed to allocate device data\n"); @@ -217,12 +271,23 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev) return 0; } +#if defined(CONFIG_OF) +static const struct of_device_id fixed_of_match[] __devinitconst = { + { .compatible = "regulator-fixed", }, + {}, +}; +MODULE_DEVICE_TABLE(of, fixed_of_match); +#else +#define fixed_of_match NULL +#endif + static struct platform_driver regulator_fixed_voltage_driver = { .probe = reg_fixed_voltage_probe, .remove = __devexit_p(reg_fixed_voltage_remove), .driver = { .name = "reg-fixed-voltage", .owner = THIS_MODULE, + .of_match_table = fixed_of_match, }, }; -- cgit v0.10.2 From 2c043bcbf287dc69848054d5c02c55c20f7a7bc5 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:19 +0530 Subject: regulator: pass additional of_node to regulator_register() With device tree support for regulators, its needed that the regulator_dev->dev device has the right of_node attached. To be able to do this add an additional parameter to the regulator_register() api, wherein the dt-adapted driver can then pass this additional info onto the regulator core. Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index ca0d608..df33530 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -427,7 +427,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev) /* replace driver_data with info */ info->regulator = regulator_register(&info->desc, &pdev->dev, - pdata, info); + pdata, info, NULL); if (IS_ERR(info->regulator)) { dev_err(&pdev->dev, "failed to register regulator %s\n", info->desc.name); diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 5abeb3a..07e98ec6 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -188,7 +188,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev) ri->pdev = pdev; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 585e494..042271a 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -634,7 +634,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) rdev = regulator_register(&ab3100_regulator_desc[i], &pdev->dev, &plfdata->reg_constraints[i], - reg); + reg, NULL); if (IS_ERR(rdev)) { err = PTR_ERR(rdev); diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 6e1ae69..e91b8dd 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -822,7 +822,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev) /* register regulator with framework */ info->regulator = regulator_register(&info->desc, &pdev->dev, - &pdata->regulator[i], info); + &pdata->regulator[i], info, NULL); if (IS_ERR(info->regulator)) { err = PTR_ERR(info->regulator); dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index a4be416..483c809 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -233,7 +233,7 @@ static int __devinit ad5398_probe(struct i2c_client *client, chip->current_mask = (chip->current_level - 1) << chip->current_offset; chip->rdev = regulator_register(&ad5398_reg, &client->dev, - init_data, chip); + init_data, chip, NULL); if (IS_ERR(chip->rdev)) { ret = PTR_ERR(chip->rdev); dev_err(&client->dev, "failed to register %s %s\n", diff --git a/drivers/regulator/bq24022.c b/drivers/regulator/bq24022.c index e24d1b7..9fab6d1 100644 --- a/drivers/regulator/bq24022.c +++ b/drivers/regulator/bq24022.c @@ -107,7 +107,7 @@ static int __init bq24022_probe(struct platform_device *pdev) ret = gpio_direction_output(pdata->gpio_nce, 1); bq24022 = regulator_register(&bq24022_desc, &pdev->dev, - pdata->init_data, pdata); + pdata->init_data, pdata, NULL); if (IS_ERR(bq24022)) { dev_dbg(&pdev->dev, "couldn't register regulator\n"); ret = PTR_ERR(bq24022); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 669d021..8b01eb0 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2637,7 +2637,7 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) */ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, - void *driver_data) + void *driver_data, struct device_node *of_node) { static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; @@ -2696,6 +2696,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, /* register with sysfs */ rdev->dev.class = ®ulator_class; + rdev->dev.of_node = of_node; rdev->dev.parent = dev; dev_set_name(&rdev->dev, "regulator.%d", atomic_inc_return(®ulator_no) - 1); diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index e23ddfa..8dbc54d 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -537,7 +537,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) ri->desc.ops = &da9030_regulator_ldo1_15_ops; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 7832975..515443f 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -486,7 +486,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) /* register with the regulator framework */ info->rdev = regulator_register(&info->desc, &pdev->dev, - init_data, info); + init_data, info, NULL); if (IS_ERR(info->rdev)) { err = PTR_ERR(info->rdev); dev_err(&pdev->dev, "failed to register %s: err %i\n", diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index b8f5205..0ee00de 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -42,7 +42,7 @@ static int __devinit dummy_regulator_probe(struct platform_device *pdev) int ret; dummy_regulator_rdev = regulator_register(&dummy_desc, NULL, - &dummy_initdata, NULL); + &dummy_initdata, NULL, NULL); if (IS_ERR(dummy_regulator_rdev)) { ret = PTR_ERR(dummy_regulator_rdev); pr_err("Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 0650856..db90919 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -234,7 +234,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) } drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata); + config->init_data, drvdata, NULL); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index e4b3592..c1a456c 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -170,7 +170,7 @@ static int __devinit isl6271a_probe(struct i2c_client *i2c, for (i = 0; i < 3; i++) { pmic->rdev[i] = regulator_register(&isl_rd[i], &i2c->dev, - init_data, pmic); + init_data, pmic, NULL); if (IS_ERR(pmic->rdev[i])) { dev_err(&i2c->dev, "failed to register %s\n", id->name); err = PTR_ERR(pmic->rdev[i]); diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 72b16b5..0cfabd3 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -451,7 +451,7 @@ static int __devinit setup_regulators(struct lp3971 *lp3971, for (i = 0; i < pdata->num_regulators; i++) { struct lp3971_regulator_subdev *reg = &pdata->regulators[i]; lp3971->rdev[i] = regulator_register(®ulators[reg->id], - lp3971->dev, reg->initdata, lp3971); + lp3971->dev, reg->initdata, lp3971, NULL); if (IS_ERR(lp3971->rdev[i])) { err = PTR_ERR(lp3971->rdev[i]); diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index fbc5e37..49a15ee 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -555,7 +555,7 @@ static int __devinit setup_regulators(struct lp3972 *lp3972, for (i = 0; i < pdata->num_regulators; i++) { struct lp3972_regulator_subdev *reg = &pdata->regulators[i]; lp3972->rdev[i] = regulator_register(®ulators[reg->id], - lp3972->dev, reg->initdata, lp3972); + lp3972->dev, reg->initdata, lp3972, NULL); if (IS_ERR(lp3972->rdev[i])) { err = PTR_ERR(lp3972->rdev[i]); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 3f49512..40e7a4d 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -214,7 +214,7 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client, } rdev[i] = regulator_register(&max1586_reg[id], &client->dev, pdata->subdevs[i].platform_data, - max1586); + max1586, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index 1062cf9..524a5da 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -347,7 +347,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, } info->regulator = regulator_register(&dcdc_desc, &client->dev, - pdata->regulator, info); + pdata->regulator, info, NULL); if (IS_ERR(info->regulator)) { dev_err(info->dev, "failed to register regulator %s\n", dcdc_desc.name); diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 33f5d9a..a838e66 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -449,7 +449,7 @@ static int __devinit max8660_probe(struct i2c_client *client, rdev[i] = regulator_register(&max8660_reg[id], &client->dev, pdata->subdevs[i].platform_data, - max8660); + max8660, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(&client->dev, "failed to register %s\n", diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index cc9ec0e..f976e5d 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -266,7 +266,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev) ri->chip = chip; rdev = regulator_register(&ri->desc, &pdev->dev, - pdata->regulator[pdev->id], ri); + pdata->regulator[pdev->id], ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 3883d85..75d8940 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -208,7 +208,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client, max8952->pdata = pdata; max8952->rdev = regulator_register(®ulator, max8952->dev, - &pdata->reg_data, max8952); + &pdata->reg_data, max8952, NULL); if (IS_ERR(max8952->rdev)) { ret = PTR_ERR(max8952->rdev); diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index 6176129..d26e864 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c @@ -1146,7 +1146,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev) regulators[id].n_voltages = 16; rdev[i] = regulator_register(®ulators[id], max8997->dev, - pdata->regulators[i].initdata, max8997); + pdata->regulators[i].initdata, max8997, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8997->dev, "regulator init failed for %d\n", diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index 41a1495..2d38c24 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c @@ -847,7 +847,7 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev) regulators[index].n_voltages = count; } rdev[i] = regulator_register(®ulators[index], max8998->dev, - pdata->regulators[i].initdata, max8998); + pdata->regulators[i].initdata, max8998, NULL); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); dev_err(max8998->dev, "regulator init failed\n"); diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 8479082..56d4a67 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -357,7 +357,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) init_data = &pdata->regulators[i]; priv->regulators[i] = regulator_register( &mc13783_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv); + &pdev->dev, init_data->init_data, priv, NULL); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 023d17d..2824804 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -573,7 +573,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) init_data = &pdata->regulators[i]; priv->regulators[i] = regulator_register( &mc13892_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv); + &pdev->dev, init_data->init_data, priv, NULL); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 31f6e11..a5aab1b 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -277,7 +277,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev) void *pcap = dev_get_drvdata(pdev->dev.parent); rdev = regulator_register(&pcap_regulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcap); + pdev->dev.platform_data, pcap, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 69a11d9..1d1c310 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -320,7 +320,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) pcf = dev_to_pcf50633(pdev->dev.parent); rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, pcf); + pdev->dev.platform_data, pcf, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/tps6105x-regulator.c b/drivers/regulator/tps6105x-regulator.c index 1011873..d9278da 100644 --- a/drivers/regulator/tps6105x-regulator.c +++ b/drivers/regulator/tps6105x-regulator.c @@ -151,7 +151,8 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev) /* Register regulator with framework */ tps6105x->regulator = regulator_register(&tps6105x_regulator_desc, &tps6105x->client->dev, - pdata->regulator_data, tps6105x); + pdata->regulator_data, tps6105x, + NULL); if (IS_ERR(tps6105x->regulator)) { ret = PTR_ERR(tps6105x->regulator); dev_err(&tps6105x->client->dev, diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 9fb4c7b..7fd3b90 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -496,7 +496,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client, /* Register the regulators */ rdev = regulator_register(&tps->desc[i], &client->dev, - init_data, tps); + init_data, tps, NULL); if (IS_ERR(rdev)) { dev_err(&client->dev, "failed to register %s\n", id->name); diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index bdef703..0b63ef7 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -599,7 +599,7 @@ int tps6507x_pmic_probe(struct platform_device *pdev) tps->desc[i].owner = THIS_MODULE; rdev = regulator_register(&tps->desc[i], - tps6507x_dev->dev, init_data, tps); + tps6507x_dev->dev, init_data, tps, NULL); if (IS_ERR(rdev)) { dev_err(tps6507x_dev->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 9166aa0..70b7b1f 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -651,7 +651,7 @@ static int __devinit pmic_probe(struct spi_device *spi) hw->desc[i].n_voltages = 1; hw->rdev[i] = regulator_register(&hw->desc[i], dev, - init_data, hw); + init_data, hw, NULL); if (IS_ERR(hw->rdev[i])) { ret = PTR_ERR(hw->rdev[i]); hw->rdev[i] = NULL; diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 14b9389..c75fb20 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -396,7 +396,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) return err; rdev = regulator_register(&ri->desc, &pdev->dev, - pdev->dev.platform_data, ri); + pdev->dev.platform_data, ri, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 66d2d60..eaea9b4 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -963,7 +963,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev) pmic->desc[i].owner = THIS_MODULE; rdev = regulator_register(&pmic->desc[i], - tps65910->dev, reg_data, pmic); + tps65910->dev, reg_data, pmic, NULL); if (IS_ERR(rdev)) { dev_err(tps65910->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 39d4a17..da00d88 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -727,7 +727,7 @@ static __devinit int tps65912_probe(struct platform_device *pdev) pmic->desc[i].owner = THIS_MODULE; range = tps65912_get_range(pmic, i); rdev = regulator_register(&pmic->desc[i], - tps65912->dev, reg_data, pmic); + tps65912->dev, reg_data, pmic, NULL); if (IS_ERR(rdev)) { dev_err(tps65912->dev, "failed to register %s regulator\n", diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index ee8747f..9a2e07a 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1070,7 +1070,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev) break; } - rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); + rdev = regulator_register(&info->desc, &pdev->dev, initdata, info, NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "can't register %s, %ld\n", info->desc.name, PTR_ERR(rdev)); diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index bd3531d..7558a96 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -553,7 +553,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data); dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -747,7 +747,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -874,7 +874,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->dcdc[id], dcdc); + pdata->dcdc[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n", @@ -973,7 +973,7 @@ static __devinit int wm831x_epe_probe(struct platform_device *pdev) dcdc->desc.owner = THIS_MODULE; dcdc->regulator = regulator_register(&dcdc->desc, &pdev->dev, - pdata->epe[id], dcdc); + pdata->epe[id], dcdc, NULL); if (IS_ERR(dcdc->regulator)) { ret = PTR_ERR(dcdc->regulator); dev_err(wm831x->dev, "Failed to register EPE%d: %d\n", diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 01f27c7..d3ad3f5 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -189,7 +189,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) isink->desc.owner = THIS_MODULE; isink->regulator = regulator_register(&isink->desc, &pdev->dev, - pdata->isink[id], isink); + pdata->isink[id], isink, NULL); if (IS_ERR(isink->regulator)) { ret = PTR_ERR(isink->regulator); dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n", diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 6709710..5e96a23 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -351,7 +351,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -621,7 +621,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", @@ -818,7 +818,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) ldo->desc.owner = THIS_MODULE; ldo->regulator = regulator_register(&ldo->desc, &pdev->dev, - pdata->ldo[id], ldo); + pdata->ldo[id], ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm831x->dev, "Failed to register LDO%d: %d\n", diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 1bcb22c..6894009 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1428,7 +1428,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev) /* register regulator */ rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev, pdev->dev.platform_data, - dev_get_drvdata(&pdev->dev)); + dev_get_drvdata(&pdev->dev), NULL); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s\n", wm8350_reg[pdev->id].name); diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 71632dd..706f395 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -326,7 +326,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; rdev = regulator_register(®ulators[pdev->id], &pdev->dev, - pdev->dev.platform_data, wm8400); + pdev->dev.platform_data, wm8400, NULL); if (IS_ERR(rdev)) return PTR_ERR(rdev); diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index b87bf5c..435e335 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -269,7 +269,7 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev) ldo->is_enabled = true; ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &pdev->dev, - pdata->ldo[id].init_data, ldo); + pdata->ldo[id].init_data, ldo, NULL); if (IS_ERR(ldo->regulator)) { ret = PTR_ERR(ldo->regulator); dev_err(wm8994->dev, "Failed to register LDO%d: %d\n", diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 52c89ae..8fbb696 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -212,7 +212,7 @@ struct regulator_dev { struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, - void *driver_data); + void *driver_data, struct device_node *of_node); void regulator_unregister(struct regulator_dev *rdev); int regulator_notifier_call_chain(struct regulator_dev *rdev, diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index d15695d..fc7ab30 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -833,7 +833,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec, ldo->voltage = voltage; ldo->dev = regulator_register(&ldo->desc, codec->dev, - init_data, ldo); + init_data, ldo, NULL); if (IS_ERR(ldo->dev)) { int ret = PTR_ERR(ldo->dev); -- cgit v0.10.2 From 69511a452e6dc6b74fe4f3671a51b1b44b9c57e3 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Fri, 18 Nov 2011 16:47:20 +0530 Subject: regulator: map consumer regulator based on device tree Device nodes in DT can associate themselves with one or more regulators/supply by providing a list of phandles (to regulator nodes) and corresponding supply names. For Example: devicenode: node@0x0 { ... ... vmmc-supply = <®ulator1>; vpll-supply = <®ulator2>; }; The driver would then do a regulator_get(dev, "vmmc"); to get regulator1 and do a regulator_get(dev, "vpll"); to get regulator2. of_get_regulator() extracts the regulator node for a given device, based on the supply name. Use it to look up the regulator for a given consumer from device tree, during a regulator_get(). If not found fallback and lookup through the regulator_map_list instead. Also, since the regulator dt nodes can use the same binding to associate with a parent regulator/supply, allow the drivers to specify a supply_name, which can then be used to lookup dt to find the parent phandle. Signed-off-by: Rajendra Nayak Acked-by: Grant Likely Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 8b01eb0..9867ebc 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -132,6 +134,33 @@ static struct regulator *get_device_regulator(struct device *dev) return NULL; } +/** + * of_get_regulator - get a regulator device node based on supply name + * @dev: Device pointer for the consumer (of regulator) device + * @supply: regulator supply name + * + * Extract the regulator device node corresponding to the supply name. + * retruns the device node corresponding to the regulator if found, else + * returns NULL. + */ +static struct device_node *of_get_regulator(struct device *dev, const char *supply) +{ + struct device_node *regnode = NULL; + char prop_name[32]; /* 32 is max size of property name */ + + dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); + + snprintf(prop_name, 32, "%s-supply", supply); + regnode = of_parse_phandle(dev->of_node, prop_name, 0); + + if (!regnode) { + dev_warn(dev, "%s property in node %s references invalid phandle", + prop_name, dev->of_node->full_name); + return NULL; + } + return regnode; +} + /* Platform voltage constraint check */ static int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV) @@ -1148,6 +1177,30 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev) return rdev->desc->ops->enable_time(rdev); } +static struct regulator_dev *regulator_dev_lookup(struct device *dev, + const char *supply) +{ + struct regulator_dev *r; + struct device_node *node; + + /* first do a dt based lookup */ + if (dev && dev->of_node) { + node = of_get_regulator(dev, supply); + if (node) + list_for_each_entry(r, ®ulator_list, list) + if (r->dev.parent && + node == r->dev.of_node) + return r; + } + + /* if not found, try doing it non-dt way */ + list_for_each_entry(r, ®ulator_list, list) + if (strcmp(rdev_get_name(r), supply) == 0) + return r; + + return NULL; +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) @@ -1168,6 +1221,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, mutex_lock(®ulator_list_mutex); + rdev = regulator_dev_lookup(dev, id); + if (rdev) + goto found; + list_for_each_entry(map, ®ulator_map_list, list) { /* If the mapping has a device set up it must match */ if (map->dev_name && @@ -2642,6 +2699,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; int ret, i; + const char *supply = NULL; if (regulator_desc == NULL) return ERR_PTR(-EINVAL); @@ -2718,21 +2776,18 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, if (ret < 0) goto scrub; - if (init_data->supply_regulator) { + if (init_data->supply_regulator) + supply = init_data->supply_regulator; + else if (regulator_desc->supply_name) + supply = regulator_desc->supply_name; + + if (supply) { struct regulator_dev *r; - int found = 0; - list_for_each_entry(r, ®ulator_list, list) { - if (strcmp(rdev_get_name(r), - init_data->supply_regulator) == 0) { - found = 1; - break; - } - } + r = regulator_dev_lookup(dev, supply); - if (!found) { - dev_err(dev, "Failed to find supply %s\n", - init_data->supply_regulator); + if (!r) { + dev_err(dev, "Failed to find supply %s\n", supply); ret = -ENODEV; goto scrub; } diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 8fbb696..4214b9a 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -154,6 +154,7 @@ enum regulator_type { * this type. * * @name: Identifying name for the regulator. + * @supply_name: Identifying the regulator supply * @id: Numerical identifier for the regulator. * @n_voltages: Number of selectors available for ops.list_voltage(). * @ops: Regulator operations table. @@ -163,6 +164,7 @@ enum regulator_type { */ struct regulator_desc { const char *name; + const char *supply_name; int id; unsigned n_voltages; struct regulator_ops *ops; -- cgit v0.10.2 From 156843470c4b9ea9698cc245d2cff769b3784088 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Thu, 24 Nov 2011 12:57:17 +0530 Subject: regulator: Fix compile break due to missing arguments to regulator_register The commit 2c043bcbf287 ("regulator: pass additional of_node to regulator_register()") caused a compile break because it missed updating the regulator_register() call in gpio-regulator.c with the additional parameter (NULL). The compile break as reported by Stephen Rothwell with the x86_64 allmodconfig looked like this drivers/regulator/gpio-regulator.c: In function 'gpio_regulator_probe': drivers/regulator/gpio-regulator.c:287:8: error: too few arguments to function 'regulator_register' include/linux/regulator/driver.h:215:23: note: declared here Reported-by: Stephen Rothwell Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index f0acf52..42e1cb1 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -284,7 +284,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev) drvdata->state = state; drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata); + config->init_data, drvdata, NULL); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); -- cgit v0.10.2 From e69af5e9677b1e5bf2a2432747ecd714aa537f2a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 26 Nov 2011 18:50:58 +0800 Subject: regulator: export of_get_regulator_init_data of_get_regulator_init_data is called in drivers/regulator/fixed.c which could be a module. Export of_get_regulator_init_data to fix below build error: ERROR: "of_get_regulator_init_data" [drivers/regulator/fixed.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 Reported-by: Randy Dunlap Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 76673c7..acd7045 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -10,6 +10,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -79,3 +80,4 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev) of_get_regulation_constraints(dev->of_node, &init_data); return init_data; } +EXPORT_SYMBOL_GPL(of_get_regulator_init_data); -- cgit v0.10.2 From 4b864af1a370103148e34044670cd9913de5c1be Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 26 Nov 2011 20:19:19 +0800 Subject: regulator: Checking return value of of_get_regulator_init_data of_get_regulator_init_data() may return NULL, thus check the return value to avoid NULL pointer dereference. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index db90919..2997f11 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -64,6 +64,9 @@ struct fixed_voltage_config *of_get_fixed_voltage_config(struct device *dev) return NULL; config->init_data = of_get_regulator_init_data(dev); + if (!config->init_data) + return NULL; + init_data = config->init_data; config->supply_name = init_data->constraints.name; -- cgit v0.10.2 From bc91396b0b0a0d1300e151264b81f010c72a8bbf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 27 Nov 2011 10:35:08 +0800 Subject: regulator: Staticise of_get_fixed_voltage_config() It is not used outside this driver so no need to make the symbol global. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 2997f11..703c26b 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -51,7 +51,8 @@ struct fixed_voltage_data { * tree node, returns a pointer to the populated structure of NULL if memory * alloc fails. */ -struct fixed_voltage_config *of_get_fixed_voltage_config(struct device *dev) +static struct fixed_voltage_config * +of_get_fixed_voltage_config(struct device *dev) { struct fixed_voltage_config *config; struct device_node *np = dev->of_node; -- cgit v0.10.2 From 22d881c068403c155fbe320c0a26e3b1bcdaa1b8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 27 Nov 2011 20:07:57 +0800 Subject: regulator: Avoid potential NULL dereference in reg_fixed_voltage_probe() of_get_fixed_voltage_config() may return NULL, return -ENOMEM in this case so we don't dereference NULL pointer. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 703c26b..ebec5e0 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -160,12 +160,17 @@ static struct regulator_ops fixed_voltage_ops = { static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) { - struct fixed_voltage_config *config = pdev->dev.platform_data; + struct fixed_voltage_config *config; struct fixed_voltage_data *drvdata; int ret; if (pdev->dev.of_node) config = of_get_fixed_voltage_config(&pdev->dev); + else + config = pdev->dev.platform_data; + + if (!config) + return -ENOMEM; drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); if (drvdata == NULL) { -- cgit v0.10.2 From a5228d2e5ea02c90581d5957cb6c4c73c191298f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 28 Nov 2011 14:07:48 +0800 Subject: regulator: aat2870: Remove a redundant bitwise and operation The implementation in aat2870_update() already did the bitwise and operation against mask parameter. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 07e98ec6..5c94d95 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -63,7 +63,7 @@ static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev, struct aat2870_data *aat2870 = dev_get_drvdata(ri->pdev->dev.parent); return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask, - (selector << ri->voltage_shift) & ri->voltage_mask); + selector << ri->voltage_shift); } static int aat2870_ldo_get_voltage_sel(struct regulator_dev *rdev) -- cgit v0.10.2 From 005d610f2abc550172726b997f5cfe683769cc1c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 28 Nov 2011 11:38:39 +0800 Subject: regulator: Convert virtual and userspace regulator consumer drivers to use module_platform_driver() This patch converts virtual and userspace regulator consumer drivers to use the module_platform_driver() macro which makes the code smaller and a bit simpler. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c index fc66551..518667e 100644 --- a/drivers/regulator/userspace-consumer.c +++ b/drivers/regulator/userspace-consumer.c @@ -185,18 +185,7 @@ static struct platform_driver regulator_userspace_consumer_driver = { }, }; - -static int __init regulator_userspace_consumer_init(void) -{ - return platform_driver_register(®ulator_userspace_consumer_driver); -} -module_init(regulator_userspace_consumer_init); - -static void __exit regulator_userspace_consumer_exit(void) -{ - platform_driver_unregister(®ulator_userspace_consumer_driver); -} -module_exit(regulator_userspace_consumer_exit); +module_platform_driver(regulator_userspace_consumer_driver); MODULE_AUTHOR("Mike Rapoport "); MODULE_DESCRIPTION("Userspace consumer for voltage and current regulators"); diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c index 858c1f8..ee0b161 100644 --- a/drivers/regulator/virtual.c +++ b/drivers/regulator/virtual.c @@ -352,17 +352,7 @@ static struct platform_driver regulator_virtual_consumer_driver = { }, }; -static int __init regulator_virtual_consumer_init(void) -{ - return platform_driver_register(®ulator_virtual_consumer_driver); -} -module_init(regulator_virtual_consumer_init); - -static void __exit regulator_virtual_consumer_exit(void) -{ - platform_driver_unregister(®ulator_virtual_consumer_driver); -} -module_exit(regulator_virtual_consumer_exit); +module_platform_driver(regulator_virtual_consumer_driver); MODULE_AUTHOR("Mark Brown "); MODULE_DESCRIPTION("Virtual regulator consumer"); -- cgit v0.10.2 From 7728c14a785f934ffccc4f45ecd9646fc07ea679 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 28 Nov 2011 21:37:16 +0800 Subject: regulator: fix label names used in device tree bindings Device tree compiler does not recognize '-' in label name. Instead, '_' works fine. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 82bef20..5b7a408 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -32,15 +32,15 @@ its just seen as a special case of a regulator being a consumer itself. Example of a consumer device node (mmc) referencing two -regulators (twl-reg1 and twl-reg2), +regulators (twl_reg1 and twl_reg2), - twl-reg1: regulator@0 { + twl_reg1: regulator@0 { ... ... ... }; - twl-reg2: regulator@1 { + twl_reg2: regulator@1 { ... ... ... @@ -49,6 +49,6 @@ regulators (twl-reg1 and twl-reg2), mmc: mmc@0x0 { ... ... - vmmc-supply = <&twl-reg1>; - vmmcaux-supply = <&twl-reg2>; + vmmc-supply = <&twl_reg1>; + vmmcaux-supply = <&twl_reg2>; }; -- cgit v0.10.2 From 9a8f5e07200dd80fe5979490c36b62f64f70825b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 29 Nov 2011 18:11:19 +0000 Subject: regulator: Allow regulators to register with no init_data This allows read-only access to the device configuration which may be useful for diagnostics. Signed-off-by: Mark Brown Acked-by: Liam Girdwood diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index ca2efca..dbdebed6 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -912,8 +912,12 @@ static int set_machine_constraints(struct regulator_dev *rdev, int ret = 0; struct regulator_ops *ops = rdev->desc->ops; - rdev->constraints = kmemdup(constraints, sizeof(*constraints), - GFP_KERNEL); + if (constraints) + rdev->constraints = kmemdup(constraints, sizeof(*constraints), + GFP_KERNEL); + else + rdev->constraints = kzalloc(sizeof(*constraints), + GFP_KERNEL); if (!rdev->constraints) return -ENOMEM; @@ -922,7 +926,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, goto out; /* do we need to setup our suspend state */ - if (constraints->initial_state) { + if (rdev->constraints->initial_state) { ret = suspend_prepare(rdev, rdev->constraints->initial_state); if (ret < 0) { rdev_err(rdev, "failed to set suspend state\n"); @@ -930,7 +934,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, } } - if (constraints->initial_mode) { + if (rdev->constraints->initial_mode) { if (!ops->set_mode) { rdev_err(rdev, "no set_mode operation\n"); ret = -EINVAL; @@ -2697,6 +2701,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, const struct regulator_init_data *init_data, void *driver_data, struct device_node *of_node) { + const struct regulation_constraints *constraints = NULL; static atomic_t regulator_no = ATOMIC_INIT(0); struct regulator_dev *rdev; int ret, i; @@ -2712,9 +2717,6 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, regulator_desc->type != REGULATOR_CURRENT) return ERR_PTR(-EINVAL); - if (!init_data) - return ERR_PTR(-EINVAL); - /* Only one of each should be implemented */ WARN_ON(regulator_desc->ops->get_voltage && regulator_desc->ops->get_voltage_sel); @@ -2747,7 +2749,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); /* preform any regulator specific init */ - if (init_data->regulator_init) { + if (init_data && init_data->regulator_init) { ret = init_data->regulator_init(rdev->reg_data); if (ret < 0) goto clean; @@ -2768,7 +2770,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, dev_set_drvdata(&rdev->dev, rdev); /* set regulator constraints */ - ret = set_machine_constraints(rdev, &init_data->constraints); + if (init_data) + constraints = &init_data->constraints; + + ret = set_machine_constraints(rdev, constraints); if (ret < 0) goto scrub; @@ -2777,7 +2782,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, if (ret < 0) goto scrub; - if (init_data->supply_regulator) + if (init_data && init_data->supply_regulator) supply = init_data->supply_regulator; else if (regulator_desc->supply_name) supply = regulator_desc->supply_name; @@ -2799,15 +2804,17 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, } /* add consumers devices */ - for (i = 0; i < init_data->num_consumer_supplies; i++) { - ret = set_consumer_device_supply(rdev, - init_data->consumer_supplies[i].dev, - init_data->consumer_supplies[i].dev_name, - init_data->consumer_supplies[i].supply); - if (ret < 0) { - dev_err(dev, "Failed to set supply %s\n", + if (init_data) { + for (i = 0; i < init_data->num_consumer_supplies; i++) { + ret = set_consumer_device_supply(rdev, + init_data->consumer_supplies[i].dev, + init_data->consumer_supplies[i].dev_name, init_data->consumer_supplies[i].supply); - goto unset_supplies; + if (ret < 0) { + dev_err(dev, "Failed to set supply %s\n", + init_data->consumer_supplies[i].supply); + goto unset_supplies; + } } } -- cgit v0.10.2 From 068df0f34e81bc06c5eb5012ec2eda25624e87aa Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Mon, 5 Dec 2011 12:47:42 +0530 Subject: regulator: Fix regulator_register() API signature in Documentation The commit 2c043bcbf287 ("regulator: pass additional of_node to regulator_register()") added an additional parameter to the regulator_register() API. Update the Documentation accordingly to reflect the change in the function signature. Reported-by: Thomas Abraham Signed-off-by: Rajendra Nayak Signed-off-by: Mark Brown diff --git a/Documentation/power/regulator/regulator.txt b/Documentation/power/regulator/regulator.txt index 3f8b528..e272d99 100644 --- a/Documentation/power/regulator/regulator.txt +++ b/Documentation/power/regulator/regulator.txt @@ -12,7 +12,7 @@ Drivers can register a regulator by calling :- struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, struct device *dev, struct regulator_init_data *init_data, - void *driver_data); + void *driver_data, struct device_node *of_node); This will register the regulators capabilities and operations to the regulator core. -- cgit v0.10.2 From ab62aa931ed3512bc67857a03636756b96c78eae Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 5 Dec 2011 10:58:41 +0000 Subject: regulator: If a single voltage is set with device tree then set apply_uV Otherwise there is no way in the bindings to configure a fixed voltage via software. It seems reasonable to assume that if the binding explicitly specifies a voltage we want to actually use that voltage. Signed-off-by: Mark Brown diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index acd7045..b7b3fc3 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -34,6 +34,9 @@ static void of_get_regulation_constraints(struct device_node *np, /* Voltage change possible? */ if (constraints->min_uV != constraints->max_uV) constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + /* Only one voltage? Then make sure it's set. */ + if (constraints->min_uV == constraints->max_uV) + constraints->apply_uV = true; uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); if (uV_offset) -- cgit v0.10.2 From d9a861cce10596ae1f10cffefe1ad4519a253475 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 1 Dec 2011 17:21:06 +0800 Subject: regulator: pass device_node to of_get_regulator_init_data() It's not always true that the device_node of regulator can be found at dev->of_node at the time when of_get_regulator_init_data() is being called, because in some cases the regulator nodes in device tree do not have 'struct device' behind them until regulator_dev gets created for it by core function regulator_register(). The patch adds device_node as a new parameter to of_get_regulator_init_data(), so that caller can pass in the node of regulator directly. Signed-off-by: Shawn Guo Cc: Mark Brown Cc: Liam Girdwood Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index ebec5e0..12d08c6 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -64,7 +64,7 @@ of_get_fixed_voltage_config(struct device *dev) if (!config) return NULL; - config->init_data = of_get_regulator_init_data(dev); + config->init_data = of_get_regulator_init_data(dev, dev->of_node); if (!config->init_data) return NULL; diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index b7b3fc3..f1651eb 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -69,18 +69,19 @@ static void of_get_regulation_constraints(struct device_node *np, * tree node, returns a pointer to the populated struture or NULL if memory * alloc fails. */ -struct regulator_init_data *of_get_regulator_init_data(struct device *dev) +struct regulator_init_data *of_get_regulator_init_data(struct device *dev, + struct device_node *node) { struct regulator_init_data *init_data; - if (!dev->of_node) + if (!node) return NULL; init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); if (!init_data) return NULL; /* Out of memory? */ - of_get_regulation_constraints(dev->of_node, &init_data); + of_get_regulation_constraints(node, &init_data); return init_data; } EXPORT_SYMBOL_GPL(of_get_regulator_init_data); diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h index d83a98d..769704f 100644 --- a/include/linux/regulator/of_regulator.h +++ b/include/linux/regulator/of_regulator.h @@ -8,10 +8,12 @@ #if defined(CONFIG_OF) extern struct regulator_init_data - *of_get_regulator_init_data(struct device *dev); + *of_get_regulator_init_data(struct device *dev, + struct device_node *node); #else static inline struct regulator_init_data - *of_get_regulator_init_data(struct device *dev) + *of_get_regulator_init_data(struct device *dev, + struct device_node *node) { return NULL; } -- cgit v0.10.2 From 08bf1c0ae97f4e322471ec2111fd5d57d3d696e0 Mon Sep 17 00:00:00 2001 From: Ashish Jangam Date: Fri, 9 Dec 2011 19:48:20 +0530 Subject: regulator: DA9052/53 Regulator support The Dialog PMIC has below featured regulators:- DA9052-BC - 4 DVS Buck converters 0.5V - 3.6V upto 1Amp. DA9053-AA/BX - 4 DVS Buck converters 0.5V - 2.5V upto 3Amp. DA9052/53 - 10 Programmable LDO's High PSSR, 1% accuracy. This patch support all the DA9052 and Da9053 regulators. The output voltages are fully programmable via I2C or SPI interface. The platform data with regulation constraints is passed down from the board to the regulator. Signed-off-by: David Dajun Chen Signed-off-by: Ashish Jangam Tested-by: Ying-Chun Liu (PaulLiu) Signed-off-by: Mark Brown diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4e919b2..7a61b17 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -178,6 +178,13 @@ config REGULATOR_DA903X Say y here to support the BUCKs and LDOs regulators found on Dialog Semiconductor DA9030/DA9034 PMIC. +config REGULATOR_DA9052 + tristate "Dialog DA9052/DA9053 regulators" + depends on PMIC_DA9052 + help + This driver supports the voltage regulators of DA9052-BC and + DA9053-AA/Bx PMIC. + config REGULATOR_PCF50633 tristate "PCF50633 regulator driver" depends on MFD_PCF50633 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index c75a522..503bac8 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o +obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c new file mode 100644 index 0000000..30c647f --- /dev/null +++ b/drivers/regulator/da9052-regulator.c @@ -0,0 +1,600 @@ +/* +* da9052-regulator.c: Regulator driver for DA9052 +* +* Copyright(c) 2011 Dialog Semiconductor Ltd. +* +* Author: David Dajun Chen +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Buck step size */ +#define DA9052_BUCK_PERI_3uV_STEP 100000 +#define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24 +#define DA9052_CONST_3uV 3000000 + +#define DA9052_MIN_UA 0 +#define DA9052_MAX_UA 3 +#define DA9052_CURRENT_RANGE 4 + +/* Bit masks */ +#define DA9052_BUCK_ILIM_MASK_EVEN 0x0c +#define DA9052_BUCK_ILIM_MASK_ODD 0xc0 + +static const u32 da9052_current_limits[3][4] = { + {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */ + {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */ + {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO, + * BUCK-MEM and BUCK-PERI + */ +}; + +struct da9052_regulator_info { + struct regulator_desc reg_desc; + int step_uV; + int min_uV; + int max_uV; + unsigned char volt_shift; + unsigned char en_bit; + unsigned char activate_bit; +}; + +struct da9052_regulator { + struct da9052 *da9052; + struct da9052_regulator_info *info; + struct regulator_dev *rdev; +}; + +static int verify_range(struct da9052_regulator_info *info, + int min_uV, int max_uV) +{ + if (min_uV > info->max_uV || max_uV < info->min_uV) + return -EINVAL; + + return 0; +} + +static int da9052_regulator_enable(struct regulator_dev *rdev) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int offset = rdev_get_id(rdev); + + return da9052_reg_update(regulator->da9052, + DA9052_BUCKCORE_REG + offset, + 1 << info->en_bit, 1 << info->en_bit); +} + +static int da9052_regulator_disable(struct regulator_dev *rdev) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int offset = rdev_get_id(rdev); + + return da9052_reg_update(regulator->da9052, + DA9052_BUCKCORE_REG + offset, + 1 << info->en_bit, 0); +} + +static int da9052_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int offset = rdev_get_id(rdev); + int ret; + + ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset); + if (ret < 0) + return ret; + + return ret & (1 << info->en_bit); +} + +static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + int offset = rdev_get_id(rdev); + int ret, row = 2; + + ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2); + if (ret < 0) + return ret; + + /* Determine the even or odd position of the buck current limit + * register field + */ + if (offset % 2 == 0) + ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2; + else + ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6; + + /* Select the appropriate current limit range */ + if (regulator->da9052->chip_id == DA9052) + row = 0; + else if (offset == 0) + row = 1; + + return da9052_current_limits[row][ret]; +} + +static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, + int max_uA) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + int offset = rdev_get_id(rdev); + int reg_val = 0; + int i, row = 2; + + /* Select the appropriate current limit range */ + if (regulator->da9052->chip_id == DA9052) + row = 0; + else if (offset == 0) + row = 1; + + if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] || + max_uA < da9052_current_limits[row][DA9052_MIN_UA]) + return -EINVAL; + + for (i = 0; i < DA9052_CURRENT_RANGE; i++) { + if (min_uA <= da9052_current_limits[row][i]) { + reg_val = i; + break; + } + } + + /* Determine the even or odd position of the buck current limit + * register field + */ + if (offset % 2 == 0) + return da9052_reg_update(regulator->da9052, + DA9052_BUCKA_REG + offset/2, + DA9052_BUCK_ILIM_MASK_EVEN, + reg_val << 2); + else + return da9052_reg_update(regulator->da9052, + DA9052_BUCKA_REG + offset/2, + DA9052_BUCK_ILIM_MASK_ODD, + reg_val << 6); +} + +static int da9052_list_buckperi_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int volt_uV; + + if ((regulator->da9052->chip_id == DA9052) && + (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) { + volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV) + + info->min_uV); + volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV) + * (DA9052_BUCK_PERI_3uV_STEP); + } else + volt_uV = (selector * info->step_uV) + info->min_uV; + + if (volt_uV > info->max_uV) + return -EINVAL; + + return volt_uV; +} + +static int da9052_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int volt_uV; + + volt_uV = info->min_uV + info->step_uV * selector; + + if (volt_uV > info->max_uV) + return -EINVAL; + + return volt_uV; +} + +static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned int *selector) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int offset = rdev_get_id(rdev); + int ret; + + ret = verify_range(info, min_uV, max_uV); + if (ret < 0) + return ret; + + if (min_uV < info->min_uV) + min_uV = info->min_uV; + + *selector = (min_uV - info->min_uV) / info->step_uV; + + ret = da9052_list_voltage(rdev, *selector); + if (ret < 0) + return ret; + + return da9052_reg_update(regulator->da9052, + DA9052_BUCKCORE_REG + offset, + (1 << info->volt_shift) - 1, *selector); +} + +static int da9052_set_ldo_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned int *selector) +{ + return da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector); +} + +static int da9052_set_ldo5_6_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned int *selector) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int ret; + + ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector); + if (ret < 0) + return ret; + + /* Some LDOs are DVC controlled which requires enabling of + * the LDO activate bit to implment the changes on the + * LDO output. + */ + return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, 0, + info->activate_bit); +} + +static int da9052_set_dcdc_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, + unsigned int *selector) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int ret; + + ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector); + if (ret < 0) + return ret; + + /* Some DCDCs are DVC controlled which requires enabling of + * the DCDC activate bit to implment the changes on the + * DCDC output. + */ + return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, 0, + info->activate_bit); +} + +static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int offset = rdev_get_id(rdev); + int ret; + + ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset); + if (ret < 0) + return ret; + + ret &= ((1 << info->volt_shift) - 1); + + return ret; +} + +static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV, + int max_uV, unsigned int *selector) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int offset = rdev_get_id(rdev); + int ret; + + ret = verify_range(info, min_uV, max_uV); + if (ret < 0) + return ret; + + if (min_uV < info->min_uV) + min_uV = info->min_uV; + + if ((regulator->da9052->chip_id == DA9052) && + (min_uV >= DA9052_CONST_3uV)) + *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV + + ((min_uV - DA9052_CONST_3uV) / + (DA9052_BUCK_PERI_3uV_STEP)); + else + *selector = (min_uV - info->min_uV) / info->step_uV; + + ret = da9052_list_buckperi_voltage(rdev, *selector); + if (ret < 0) + return ret; + + return da9052_reg_update(regulator->da9052, + DA9052_BUCKCORE_REG + offset, + (1 << info->volt_shift) - 1, *selector); +} + +static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev) +{ + struct da9052_regulator *regulator = rdev_get_drvdata(rdev); + struct da9052_regulator_info *info = regulator->info; + int offset = rdev_get_id(rdev); + int ret; + + ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset); + if (ret < 0) + return ret; + + ret &= ((1 << info->volt_shift) - 1); + + return ret; +} + +static struct regulator_ops da9052_buckperi_ops = { + .list_voltage = da9052_list_buckperi_voltage, + .get_voltage_sel = da9052_get_buckperi_voltage_sel, + .set_voltage = da9052_set_buckperi_voltage, + + .get_current_limit = da9052_dcdc_get_current_limit, + .set_current_limit = da9052_dcdc_set_current_limit, + + .is_enabled = da9052_regulator_is_enabled, + .enable = da9052_regulator_enable, + .disable = da9052_regulator_disable, +}; + +static struct regulator_ops da9052_dcdc_ops = { + .set_voltage = da9052_set_dcdc_voltage, + .get_current_limit = da9052_dcdc_get_current_limit, + .set_current_limit = da9052_dcdc_set_current_limit, + + .list_voltage = da9052_list_voltage, + .get_voltage_sel = da9052_get_regulator_voltage_sel, + .is_enabled = da9052_regulator_is_enabled, + .enable = da9052_regulator_enable, + .disable = da9052_regulator_disable, +}; + +static struct regulator_ops da9052_ldo5_6_ops = { + .set_voltage = da9052_set_ldo5_6_voltage, + + .list_voltage = da9052_list_voltage, + .get_voltage_sel = da9052_get_regulator_voltage_sel, + .is_enabled = da9052_regulator_is_enabled, + .enable = da9052_regulator_enable, + .disable = da9052_regulator_disable, +}; + +static struct regulator_ops da9052_ldo_ops = { + .set_voltage = da9052_set_ldo_voltage, + + .list_voltage = da9052_list_voltage, + .get_voltage_sel = da9052_get_regulator_voltage_sel, + .is_enabled = da9052_regulator_is_enabled, + .enable = da9052_regulator_enable, + .disable = da9052_regulator_disable, +}; + +#define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \ +{\ + .reg_desc = {\ + .name = "LDO" #_id,\ + .ops = &da9052_ldo5_6_ops,\ + .type = REGULATOR_VOLTAGE,\ + .id = _id,\ + .owner = THIS_MODULE,\ + },\ + .min_uV = (min) * 1000,\ + .max_uV = (max) * 1000,\ + .step_uV = (step) * 1000,\ + .volt_shift = (sbits),\ + .en_bit = (ebits),\ + .activate_bit = (abits),\ +} + +#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \ +{\ + .reg_desc = {\ + .name = "LDO" #_id,\ + .ops = &da9052_ldo_ops,\ + .type = REGULATOR_VOLTAGE,\ + .id = _id,\ + .owner = THIS_MODULE,\ + },\ + .min_uV = (min) * 1000,\ + .max_uV = (max) * 1000,\ + .step_uV = (step) * 1000,\ + .volt_shift = (sbits),\ + .en_bit = (ebits),\ + .activate_bit = (abits),\ +} + +#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ +{\ + .reg_desc = {\ + .name = "BUCK" #_id,\ + .ops = &da9052_dcdc_ops,\ + .type = REGULATOR_VOLTAGE,\ + .id = _id,\ + .owner = THIS_MODULE,\ + },\ + .min_uV = (min) * 1000,\ + .max_uV = (max) * 1000,\ + .step_uV = (step) * 1000,\ + .volt_shift = (sbits),\ + .en_bit = (ebits),\ + .activate_bit = (abits),\ +} + +#define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \ +{\ + .reg_desc = {\ + .name = "BUCK" #_id,\ + .ops = &da9052_buckperi_ops,\ + .type = REGULATOR_VOLTAGE,\ + .id = _id,\ + .owner = THIS_MODULE,\ + },\ + .min_uV = (min) * 1000,\ + .max_uV = (max) * 1000,\ + .step_uV = (step) * 1000,\ + .volt_shift = (sbits),\ + .en_bit = (ebits),\ + .activate_bit = (abits),\ +} + +struct da9052_regulator_info da9052_regulator_info[] = { + /* Buck1 - 4 */ + DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), + DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), + DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), + DA9052_BUCKPERI(3, 50, 1800, 3600, 5, 6, 0), + /* LD01 - LDO10 */ + DA9052_LDO(4, 50, 600, 1800, 5, 6, 0), + DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0), + DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0), + DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0), +}; + +struct da9052_regulator_info da9053_regulator_info[] = { + /* Buck1 - 4 */ + DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), + DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), + DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO), + DA9052_BUCKPERI(3, 25, 925, 2500, 6, 6, 0), + /* LD01 - LDO10 */ + DA9052_LDO(4, 50, 600, 1800, 5, 6, 0), + DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO), + DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO), + DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0), + DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0), + DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0), + DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0), +}; + +static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, + int id) +{ + struct da9052_regulator_info *info; + int i; + + if (chip_id == DA9052) { + for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) { + info = &da9052_regulator_info[i]; + if (info->reg_desc.id == id) + return info; + } + } else { + for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) { + info = &da9053_regulator_info[i]; + if (info->reg_desc.id == id) + return info; + } + } + + return NULL; +} + +static int __devinit da9052_regulator_probe(struct platform_device *pdev) +{ + struct da9052_regulator *regulator; + struct da9052 *da9052; + struct da9052_pdata *pdata; + int ret; + + regulator = kzalloc(sizeof(struct da9052_regulator), GFP_KERNEL); + if (!regulator) + return -ENOMEM; + + da9052 = dev_get_drvdata(pdev->dev.parent); + pdata = da9052->dev->platform_data; + regulator->da9052 = da9052; + + regulator->info = find_regulator_info(regulator->da9052->chip_id, + pdev->id); + if (regulator->info == NULL) { + dev_err(&pdev->dev, "invalid regulator ID specified\n"); + ret = -EINVAL; + goto err; + } + regulator->rdev = regulator_register(®ulator->info->reg_desc, + &pdev->dev, + pdata->regulators[pdev->id], + regulator); + if (IS_ERR(regulator->rdev)) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + regulator->info->reg_desc.name); + ret = PTR_ERR(regulator->rdev); + goto err; + } + + platform_set_drvdata(pdev, regulator); + + return 0; +err: + kfree(regulator); + return ret; +} + +static int __devexit da9052_regulator_remove(struct platform_device *pdev) +{ + struct da9052_regulator *regulator = platform_get_drvdata(pdev); + + regulator_unregister(regulator->rdev); + kfree(regulator); + + return 0; +} + +static struct platform_driver da9052_regulator_driver = { + .probe = da9052_regulator_probe, + .remove = __devexit_p(da9052_regulator_remove), + .driver = { + .name = "da9052-regulator", + .owner = THIS_MODULE, + }, +}; + +static int __init da9052_regulator_init(void) +{ + return platform_driver_register(&da9052_regulator_driver); +} +subsys_initcall(da9052_regulator_init); + +static void __exit da9052_regulator_exit(void) +{ + platform_driver_unregister(&da9052_regulator_driver); +} +module_exit(da9052_regulator_exit); + +MODULE_AUTHOR("David Dajun Chen "); +MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9052-regulator"); -- cgit v0.10.2 From 47aed92c7740c33f3acbd9dbdefb5ec6f9effdc0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 15 Dec 2011 15:03:38 +0800 Subject: regulator: Update da9052-regulator for DT changes Reported-by: Stephen Rothwell Signed-off-by: Mark Brown diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 30c647f..bdb4375 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -547,7 +547,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) regulator->rdev = regulator_register(®ulator->info->reg_desc, &pdev->dev, pdata->regulators[pdev->id], - regulator); + regulator, NULL); if (IS_ERR(regulator->rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", regulator->info->reg_desc.name); -- cgit v0.10.2 From 984b5a6ba550f41edda86d0b6deba2b5187f5e44 Mon Sep 17 00:00:00 2001 From: Ashish Jangam Date: Thu, 15 Dec 2011 18:59:53 +0530 Subject: regulator: Replace kzalloc with devm_kzalloc and if-else with a switch-case for da9052-regulator Reported-by: Mark Brown Signed-off-by: David Dajun Chen Signed-off-by: Ashish Jangam Signed-off-by: Mark Brown diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index bdb4375..f2840b5 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -505,18 +505,23 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id, struct da9052_regulator_info *info; int i; - if (chip_id == DA9052) { + switch (chip_id) { + case DA9052: for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) { info = &da9052_regulator_info[i]; if (info->reg_desc.id == id) return info; } - } else { + break; + case DA9053_AA: + case DA9053_BA: + case DA9053_BB: for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) { info = &da9053_regulator_info[i]; if (info->reg_desc.id == id) return info; } + break; } return NULL; @@ -529,7 +534,8 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) struct da9052_pdata *pdata; int ret; - regulator = kzalloc(sizeof(struct da9052_regulator), GFP_KERNEL); + regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator), + GFP_KERNEL); if (!regulator) return -ENOMEM; @@ -559,7 +565,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev) return 0; err: - kfree(regulator); + devm_kfree(&pdev->dev, regulator); return ret; } @@ -568,7 +574,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev) struct da9052_regulator *regulator = platform_get_drvdata(pdev); regulator_unregister(regulator->rdev); - kfree(regulator); + devm_kfree(&pdev->dev, regulator); return 0; } -- cgit v0.10.2 From 6242eae9bce864467bc4d6a8b67d1846ecaccf23 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 20 Dec 2011 17:12:00 +0800 Subject: regulator: da9052: Staticize non-exported symbols da9052_regulator_info and da9053_regulator_info are not used outside this driver so no need to make the symbol global. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index f2840b5..3767364 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -461,7 +461,7 @@ static struct regulator_ops da9052_ldo_ops = { .activate_bit = (abits),\ } -struct da9052_regulator_info da9052_regulator_info[] = { +static struct da9052_regulator_info da9052_regulator_info[] = { /* Buck1 - 4 */ DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), @@ -480,7 +480,7 @@ struct da9052_regulator_info da9052_regulator_info[] = { DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0), }; -struct da9052_regulator_info da9053_regulator_info[] = { +static struct da9052_regulator_info da9053_regulator_info[] = { /* Buck1 - 4 */ DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO), DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO), -- cgit v0.10.2 From fded2f4faee7670b0545ac05bd2b3ed6b9afcda2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 15 Dec 2011 02:11:14 +0800 Subject: regulator: Convert wm831x regulator drivers to devm_kzalloc() Signed-off-by: Mark Brown diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 7558a96..4904a40 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -511,7 +511,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) if (pdata == NULL || pdata->dcdc[id] == NULL) return -ENODEV; - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), + GFP_KERNEL); if (dcdc == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -590,7 +591,6 @@ err_regulator: err: if (dcdc->dvs_gpio) gpio_free(dcdc->dvs_gpio); - kfree(dcdc); return ret; } @@ -605,7 +605,6 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev) regulator_unregister(dcdc->regulator); if (dcdc->dvs_gpio) gpio_free(dcdc->dvs_gpio); - kfree(dcdc); return 0; } @@ -722,7 +721,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) if (pdata == NULL || pdata->dcdc[id] == NULL) return -ENODEV; - dcdc = kzalloc(sizeof(struct wm831x_dcdc), GFP_KERNEL); + dcdc = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_dcdc), + GFP_KERNEL); if (dcdc == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -771,7 +771,6 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) err_regulator: regulator_unregister(dcdc->regulator); err: - kfree(dcdc); return ret; } @@ -783,7 +782,6 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev) free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); regulator_unregister(dcdc->regulator); - kfree(dcdc); return 0; } diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index d3ad3f5..634aac3 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -162,7 +162,8 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) if (pdata == NULL || pdata->isink[id] == NULL) return -ENODEV; - isink = kzalloc(sizeof(struct wm831x_isink), GFP_KERNEL); + isink = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_isink), + GFP_KERNEL); if (isink == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -213,7 +214,6 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) err_regulator: regulator_unregister(isink->regulator); err: - kfree(isink); return ret; } @@ -226,7 +226,6 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev) free_irq(platform_get_irq(pdev, 0), isink); regulator_unregister(isink->regulator); - kfree(isink); return 0; } diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 5e96a23..f1e4ab0 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -326,7 +326,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) if (pdata == NULL || pdata->ldo[id] == NULL) return -ENODEV; - ldo = kzalloc(sizeof(struct wm831x_ldo), GFP_KERNEL); + ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL); if (ldo == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -376,7 +376,6 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) err_regulator: regulator_unregister(ldo->regulator); err: - kfree(ldo); return ret; } @@ -388,7 +387,6 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev) free_irq(platform_get_irq_byname(pdev, "UV"), ldo); regulator_unregister(ldo->regulator); - kfree(ldo); return 0; } @@ -596,7 +594,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) if (pdata == NULL || pdata->ldo[id] == NULL) return -ENODEV; - ldo = kzalloc(sizeof(struct wm831x_ldo), GFP_KERNEL); + ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL); if (ldo == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -645,7 +643,6 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) err_regulator: regulator_unregister(ldo->regulator); err: - kfree(ldo); return ret; } @@ -655,7 +652,6 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev) free_irq(platform_get_irq_byname(pdev, "UV"), ldo); regulator_unregister(ldo->regulator); - kfree(ldo); return 0; } @@ -793,7 +789,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) if (pdata == NULL || pdata->ldo[id] == NULL) return -ENODEV; - ldo = kzalloc(sizeof(struct wm831x_ldo), GFP_KERNEL); + ldo = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ldo), GFP_KERNEL); if (ldo == NULL) { dev_err(&pdev->dev, "Unable to allocate private data\n"); return -ENOMEM; @@ -831,7 +827,6 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev) return 0; err: - kfree(ldo); return ret; } @@ -840,7 +835,6 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev) struct wm831x_ldo *ldo = platform_get_drvdata(pdev); regulator_unregister(ldo->regulator); - kfree(ldo); return 0; } -- cgit v0.10.2 From 3a5d03158d0174ae700e15b63eab2023f27aeb88 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 21 Dec 2011 23:00:45 +0800 Subject: regulator: mc13892: remove the unnecessary prefix from regulator name It's not really necessary to add a prefix 'MC13892__' for each mc13892 regulator name, since the chip must have been identified as mc13892 when we look at the regulator name. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 2775826..75e3832 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -48,7 +48,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; #define MC13xxx_DEFINE(prefix, _name, _reg, _vsel_reg, _voltages, _ops) \ [prefix ## _name] = { \ .desc = { \ - .name = #prefix "_" #_name, \ + .name = #_name, \ .n_voltages = ARRAY_SIZE(_voltages), \ .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -66,7 +66,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; #define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops) \ [prefix ## _name] = { \ .desc = { \ - .name = #prefix "_" #_name, \ + .name = #_name, \ .n_voltages = ARRAY_SIZE(_voltages), \ .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ @@ -81,7 +81,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops; #define MC13xxx_GPO_DEFINE(prefix, _name, _reg, _voltages, _ops) \ [prefix ## _name] = { \ .desc = { \ - .name = #prefix "_" #_name, \ + .name = #_name, \ .n_voltages = ARRAY_SIZE(_voltages), \ .ops = &_ops, \ .type = REGULATOR_VOLTAGE, \ -- cgit v0.10.2 From 93bcb23b38f634e8fb4ddda0d3f4862fda5cedae Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Wed, 21 Dec 2011 23:00:46 +0800 Subject: regulator: mc13892: add device tree probe support It adds device tree probe support for mc13892-regulator driver. Signed-off-by: Shawn Guo Signed-off-by: Mark Brown diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 2824804..46bfa4a 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -527,18 +527,27 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent); struct mc13xxx_regulator_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct mc13xxx_regulator_init_data *init_data; + struct mc13xxx_regulator_init_data *mc13xxx_data; int i, ret; + int num_regulators = 0; u32 val; + num_regulators = mc13xxx_get_num_regulators_dt(pdev); + if (num_regulators <= 0 && pdata) + num_regulators = pdata->num_regulators; + if (num_regulators <= 0) + return -EINVAL; + priv = kzalloc(sizeof(*priv) + - pdata->num_regulators * sizeof(priv->regulators[0]), + num_regulators * sizeof(priv->regulators[0]), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->num_regulators = num_regulators; priv->mc13xxx_regulators = mc13892_regulators; priv->mc13xxx = mc13892; + platform_set_drvdata(pdev, priv); mc13xxx_lock(mc13892); ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val); @@ -569,11 +578,27 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) = mc13892_vcam_set_mode; mc13892_regulators[MC13892_VCAM].desc.ops->get_mode = mc13892_vcam_get_mode; - for (i = 0; i < pdata->num_regulators; i++) { - init_data = &pdata->regulators[i]; + + mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, + ARRAY_SIZE(mc13892_regulators)); + for (i = 0; i < num_regulators; i++) { + struct regulator_init_data *init_data; + struct regulator_desc *desc; + struct device_node *node = NULL; + int id; + + if (mc13xxx_data) { + id = mc13xxx_data[i].id; + init_data = mc13xxx_data[i].init_data; + node = mc13xxx_data[i].node; + } else { + id = pdata->regulators[i].id; + init_data = pdata->regulators[i].init_data; + } + desc = &mc13892_regulators[id].desc; + priv->regulators[i] = regulator_register( - &mc13892_regulators[init_data->id].desc, - &pdev->dev, init_data->init_data, priv, NULL); + desc, &pdev->dev, init_data, priv, node); if (IS_ERR(priv->regulators[i])) { dev_err(&pdev->dev, "failed to register regulator %s\n", @@ -583,8 +608,6 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) } } - platform_set_drvdata(pdev, priv); - return 0; err: while (--i >= 0) @@ -600,13 +623,11 @@ err_free: static int __devexit mc13892_regulator_remove(struct platform_device *pdev) { struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); - struct mc13xxx_regulator_platform_data *pdata = - dev_get_platdata(&pdev->dev); int i; platform_set_drvdata(pdev, NULL); - for (i = 0; i < pdata->num_regulators; i++) + for (i = 0; i < priv->num_regulators; i++) regulator_unregister(priv->regulators[i]); kfree(priv); diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 6532853..80ecafe 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -18,12 +18,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "mc13xxx.h" static int mc13xxx_regulator_enable(struct regulator_dev *rdev) @@ -236,6 +238,61 @@ int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev) } EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled); +#ifdef CONFIG_OF +int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev) +{ + struct device_node *parent, *child; + int num = 0; + + of_node_get(pdev->dev.parent->of_node); + parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); + if (!parent) + return -ENODEV; + + for_each_child_of_node(parent, child) + num++; + + return num; +} + +struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt( + struct platform_device *pdev, struct mc13xxx_regulator *regulators, + int num_regulators) +{ + struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); + struct mc13xxx_regulator_init_data *data, *p; + struct device_node *parent, *child; + int i; + + of_node_get(pdev->dev.parent->of_node); + parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); + if (!parent) + return NULL; + + data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, + GFP_KERNEL); + if (!data) + return NULL; + p = data; + + for_each_child_of_node(parent, child) { + for (i = 0; i < num_regulators; i++) { + if (!of_node_cmp(child->name, + regulators[i].desc.name)) { + p->id = i; + p->init_data = of_get_regulator_init_data( + &pdev->dev, child); + p->node = child; + p++; + break; + } + } + } + + return data; +} +#endif + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Yong Shen "); MODULE_DESCRIPTION("Regulator Driver for Freescale MC13xxx PMIC"); diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 75e3832..b3961c6 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h @@ -29,6 +29,7 @@ struct mc13xxx_regulator_priv { struct mc13xxx *mc13xxx; u32 powermisc_pwgt_state; struct mc13xxx_regulator *mc13xxx_regulators; + int num_regulators; struct regulator_dev *regulators[]; }; @@ -42,6 +43,25 @@ extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector); extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev); +#ifdef CONFIG_OF +extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev); +extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( + struct platform_device *pdev, struct mc13xxx_regulator *regulators, + int num_regulators); +#else +static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) +{ + return -ENODEV; +} + +static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( + struct platform_device *pdev, struct mc13xxx_regulator *regulators, + int num_regulators) +{ + return NULL; +} +#endif + extern struct regulator_ops mc13xxx_regulator_ops; extern struct regulator_ops mc13xxx_fixed_regulator_ops; diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h index 3816c2f..a98e2a3 100644 --- a/include/linux/mfd/mc13xxx.h +++ b/include/linux/mfd/mc13xxx.h @@ -69,6 +69,7 @@ struct regulator_init_data; struct mc13xxx_regulator_init_data { int id; struct regulator_init_data *init_data; + struct device_node *node; }; struct mc13xxx_regulator_platform_data { -- cgit v0.10.2 From a398eaa23e42b73216efbe03dc1d754b2e5d603c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 28 Dec 2011 12:48:45 +0000 Subject: regulator: Export regulator_is_supported_voltage() It's part of the driver interface so should be available to modules. Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index dbdebed6..6f7d411 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1787,6 +1787,7 @@ int regulator_is_supported_voltage(struct regulator *regulator, return 0; } +EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) -- cgit v0.10.2 From bcda432194fc7c4a2dbe9d7146f00b4b21e66c8c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 29 Dec 2011 17:02:08 +0800 Subject: regulator: Fix the error handling if create_regulator fails In the case of create_regulator() fails, goto the error path immediately. It does not make sense to update rdev->open_count if create_regulator fails. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6f7d411..6cb9d39 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1282,6 +1282,7 @@ found: if (regulator == NULL) { regulator = ERR_PTR(-ENOMEM); module_put(rdev->owner); + goto out; } rdev->open_count++; -- cgit v0.10.2 From 32c78de8f17369def492ea3ddd785f0cc140af02 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 29 Dec 2011 17:03:20 +0800 Subject: regulator: Fix checking return value of create_regulator create_regulator() returns NULL on fail. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6cb9d39..e70e15c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -985,9 +985,8 @@ static int set_supply(struct regulator_dev *rdev, rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); - if (IS_ERR(rdev->supply)) { - err = PTR_ERR(rdev->supply); - rdev->supply = NULL; + if (rdev->supply == NULL) { + err = -ENOMEM; return err; } -- cgit v0.10.2 From cbe10a3674ba1cfa227d0d4e990353bada85fa09 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 29 Dec 2011 13:56:02 -0200 Subject: regulator: mc13783: Convert to devm_kzalloc() Convert mc13783-regulator driver to use devm_kzalloc(). Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c index 56d4a67..8e9b90a 100644 --- a/drivers/regulator/mc13783-regulator.c +++ b/drivers/regulator/mc13783-regulator.c @@ -344,7 +344,7 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s id %d\n", __func__, pdev->id); - priv = kzalloc(sizeof(*priv) + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + pdata->num_regulators * sizeof(priv->regulators[0]), GFP_KERNEL); if (!priv) @@ -374,8 +374,6 @@ err: while (--i >= 0) regulator_unregister(priv->regulators[i]); - kfree(priv); - return ret; } @@ -391,7 +389,6 @@ static int __devexit mc13783_regulator_remove(struct platform_device *pdev) for (i = 0; i < pdata->num_regulators; i++) regulator_unregister(priv->regulators[i]); - kfree(priv); return 0; } -- cgit v0.10.2 From 4fef21eaacb9d739f0120c930c78dac4f6875b9f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 29 Dec 2011 20:05:00 -0200 Subject: regulator: mc13892: Convert to devm_kzalloc() Convert mc13892-regulator driver to use devm_kzalloc(). Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 46bfa4a..e8cfc99 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c @@ -538,7 +538,7 @@ static int __devinit mc13892_regulator_probe(struct platform_device *pdev) if (num_regulators <= 0) return -EINVAL; - priv = kzalloc(sizeof(*priv) + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + num_regulators * sizeof(priv->regulators[0]), GFP_KERNEL); if (!priv) @@ -615,7 +615,6 @@ err: err_free: mc13xxx_unlock(mc13892); - kfree(priv); return ret; } @@ -630,7 +629,6 @@ static int __devexit mc13892_regulator_remove(struct platform_device *pdev) for (i = 0; i < priv->num_regulators; i++) regulator_unregister(priv->regulators[i]); - kfree(priv); return 0; } -- cgit v0.10.2 From b2296bd43e781976743354c668a356b0df98e1da Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 2 Jan 2012 13:08:45 +0530 Subject: regulator: Enable supply regulator if child rail is enabled. During regulator_register, the rail is set on the provided machine constraints and if it is enabled then it is also require to enable the supply regulator. This will make sure that: 1. Proper reference count for supply regulator to be maintain. 2. Supply regulator should be enable when given rail is enabled. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e70e15c..eb750a1 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2802,6 +2802,14 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, ret = set_supply(rdev, r); if (ret < 0) goto scrub; + + /* Enable supply if rail is enabled */ + if (rdev->desc->ops->is_enabled && + rdev->desc->ops->is_enabled(rdev)) { + ret = regulator_enable(rdev->supply); + if (ret < 0) + goto scrub; + } } /* add consumers devices */ -- cgit v0.10.2 From 935a521066113e16c15b842852ed681bbbdfbc63 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Mon, 2 Jan 2012 18:49:32 +0900 Subject: regulator: add regulator_force_disable() definition for !CONFIG_REGULATOR regulator_force_disable() was omitted in consumer.h for !CONFIG_REGULATOR case. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Signed-off-by: Mark Brown diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index f7756d1..889ab5a 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -212,6 +212,11 @@ static inline int regulator_disable(struct regulator *regulator) return 0; } +static inline int regulator_force_disable(struct regulator *regulator) +{ + return 0; +} + static inline int regulator_disable_deferred(struct regulator *regulator, int ms) { -- cgit v0.10.2 From 1bb50b28a984857c2487d13187af5b3701aed38a Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Sat, 31 Dec 2011 20:51:16 +0800 Subject: regulator: pass regulator_register of_node in fixed voltage driver regulator_get needs of_node to find right regulator. Signed-off-by: Richard Zhao Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index a44a017..393f039 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -246,7 +246,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev) } drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, - config->init_data, drvdata, NULL); + config->init_data, drvdata, + pdev->dev.of_node); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); -- cgit v0.10.2 From e1de2f423462a5c6ba2c902dff1f5ddd8d3dbde3 Mon Sep 17 00:00:00 2001 From: Donggeun Kim Date: Tue, 3 Jan 2012 16:22:03 +0900 Subject: regulator: add regulator_bulk_force_disable function This patch allows consumers to forcibly disable multiple regulator clients in a single API call. Signed-off-by: Donggeun Kim Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index eb750a1..ca86f39 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2491,6 +2491,43 @@ err: EXPORT_SYMBOL_GPL(regulator_bulk_disable); /** + * regulator_bulk_force_disable - force disable multiple regulator consumers + * + * @num_consumers: Number of consumers + * @consumers: Consumer data; clients are stored here. + * @return 0 on success, an errno on failure + * + * This convenience API allows consumers to forcibly disable multiple regulator + * clients in a single API call. + * NOTE: This should be used for situations when device damage will + * likely occur if the regulators are not disabled (e.g. over temp). + * Although regulator_force_disable function call for some consumers can + * return error numbers, the function is called for all consumers. + */ +int regulator_bulk_force_disable(int num_consumers, + struct regulator_bulk_data *consumers) +{ + int i; + int ret; + + for (i = 0; i < num_consumers; i++) + consumers[i].ret = + regulator_force_disable(consumers[i].consumer); + + for (i = 0; i < num_consumers; i++) { + if (consumers[i].ret != 0) { + ret = consumers[i].ret; + goto out; + } + } + + return 0; +out: + return ret; +} +EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); + +/** * regulator_bulk_free - free multiple regulator consumers * * @num_consumers: Number of consumers diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 889ab5a..f2698a0 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -149,6 +149,8 @@ int regulator_bulk_enable(int num_consumers, struct regulator_bulk_data *consumers); int regulator_bulk_disable(int num_consumers, struct regulator_bulk_data *consumers); +int regulator_bulk_force_disable(int num_consumers, + struct regulator_bulk_data *consumers); void regulator_bulk_free(int num_consumers, struct regulator_bulk_data *consumers); @@ -247,6 +249,12 @@ static inline int regulator_bulk_disable(int num_consumers, return 0; } +static inline int regulator_bulk_force_disable(int num_consumers, + struct regulator_bulk_data *consumers) +{ + return 0; +} + static inline void regulator_bulk_free(int num_consumers, struct regulator_bulk_data *consumers) { -- cgit v0.10.2 From 65364e9ab958f4ad21c5c7b6cc8e2e458128dbcb Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Wed, 4 Jan 2012 15:12:04 +0800 Subject: regulator: max8925: fix enabled/disabled judgement mistake Max8925 ldo status should be determined by two factors: 1. power up/down sequence selection(LDOCTL[4:2]). 2. i2c enable bit(LDOCTL[0]). Max8925 ldo support two types of power up/down sequence: 1. flexible sequence(LDOCTL[4:2] = 0~6). 2. i2c sequence(LDOCTL[4:2] = 7). With flexible sequence selected, the ldo is enabled during power up by default. With i2c sequence selected, the ldo is controlled by the i2c enable bit(LDOCTL[0]). Signed-off-by: Kevin Liu Signed-off-by: Haojian Zhuang Signed-off-by: Mark Brown diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index f976e5d..cc290d3 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -24,9 +24,13 @@ #define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */ #define SD1_DVM_EN 6 /* SDV1 bit 6 */ -/* bit definitions in SD & LDO control registers */ -#define OUT_ENABLE 0x1f /* Power U/D sequence as I2C */ -#define OUT_DISABLE 0x1e /* Power U/D sequence as I2C */ +/* bit definitions in LDO control registers */ +#define LDO_SEQ_I2C 0x7 /* Power U/D by i2c */ +#define LDO_SEQ_MASK 0x7 /* Power U/D sequence mask */ +#define LDO_SEQ_SHIFT 2 /* Power U/D sequence offset */ +#define LDO_I2C_EN 0x1 /* Enable by i2c */ +#define LDO_I2C_EN_MASK 0x1 /* Enable mask by i2c */ +#define LDO_I2C_EN_SHIFT 0 /* Enable offset by i2c */ struct max8925_regulator_info { struct regulator_desc desc; @@ -40,7 +44,6 @@ struct max8925_regulator_info { int vol_reg; int vol_shift; int vol_nbits; - int enable_bit; int enable_reg; }; @@ -98,8 +101,10 @@ static int max8925_enable(struct regulator_dev *rdev) struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->enable_reg, - OUT_ENABLE << info->enable_bit, - OUT_ENABLE << info->enable_bit); + LDO_SEQ_MASK << LDO_SEQ_SHIFT | + LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT, + LDO_SEQ_I2C << LDO_SEQ_SHIFT | + LDO_I2C_EN << LDO_I2C_EN_SHIFT); } static int max8925_disable(struct regulator_dev *rdev) @@ -107,20 +112,24 @@ static int max8925_disable(struct regulator_dev *rdev) struct max8925_regulator_info *info = rdev_get_drvdata(rdev); return max8925_set_bits(info->i2c, info->enable_reg, - OUT_ENABLE << info->enable_bit, - OUT_DISABLE << info->enable_bit); + LDO_SEQ_MASK << LDO_SEQ_SHIFT | + LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT, + LDO_SEQ_I2C << LDO_SEQ_SHIFT); } static int max8925_is_enabled(struct regulator_dev *rdev) { struct max8925_regulator_info *info = rdev_get_drvdata(rdev); - int ret; + int ldo_seq, ret; ret = max8925_reg_read(info->i2c, info->enable_reg); if (ret < 0) return ret; - - return ret & (1 << info->enable_bit); + ldo_seq = (ret >> LDO_SEQ_SHIFT) & LDO_SEQ_MASK; + if (ldo_seq != LDO_SEQ_I2C) + return 1; + else + return ret & (LDO_I2C_EN_MASK << LDO_I2C_EN_SHIFT); } static int max8925_set_dvm_voltage(struct regulator_dev *rdev, int uV) @@ -188,7 +197,6 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .vol_shift = 0, \ .vol_nbits = 6, \ .enable_reg = MAX8925_SDCTL##_id, \ - .enable_bit = 0, \ } #define MAX8925_LDO(_id, min, max, step) \ @@ -207,7 +215,6 @@ static struct regulator_ops max8925_regulator_ldo_ops = { .vol_shift = 0, \ .vol_nbits = 6, \ .enable_reg = MAX8925_LDOCTL##_id, \ - .enable_bit = 0, \ } static struct max8925_regulator_info max8925_regulator_info[] = { -- cgit v0.10.2 From 0c437c4ae71c0a8110eb21c06b99853c7056b317 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 4 Jan 2012 11:07:29 +0800 Subject: regulator: set constraints.apply_uV to 0 in of_get_fixed_voltage_config Fix fixed regulator using DT failed to call regulator_register. of_get_regulator_init_data set apply_uV to 1, but fixed regulator doesn't need it. Set it back to 0. Signed-off-by: Richard Zhao Signed-off-by: Mark Brown diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 393f039..e24e3a1 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -69,6 +69,7 @@ of_get_fixed_voltage_config(struct device *dev) return NULL; init_data = config->init_data; + init_data->constraints.apply_uV = 0; config->supply_name = init_data->constraints.name; if (init_data->constraints.min_uV == init_data->constraints.max_uV) { -- cgit v0.10.2