Commit 7ce4669c authored by Bengt Jonsson's avatar Bengt Jonsson Committed by Mark Brown

regulator: ab8500: Added get_optimum_mode on regulators with idle mode

With this change, Vtvout, Vintcore12, Vaux1, 2 and 3 regulators
support DRMS (Dynamic Regulator Mode Switching) which will
dynamically handle requests for max current consumption from
several consumers and select a suitable regulator mode.
Signed-off-by: default avatarBengt Jonsson <bengt.g.jonsson@stericsson.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
Reviewed-by: default avatarMattias WALLIN <mattias.wallin@stericsson.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent bd28a157
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
* @desc: regulator description * @desc: regulator description
* @regulator_dev: regulator device * @regulator_dev: regulator device
* @is_enabled: status of regulator (on/off) * @is_enabled: status of regulator (on/off)
* @load_lp_uA: maximum load in idle (low power) mode
* @update_bank: bank to control on/off * @update_bank: bank to control on/off
* @update_reg: register to control on/off * @update_reg: register to control on/off
* @update_mask: mask to enable/disable and set mode of regulator * @update_mask: mask to enable/disable and set mode of regulator
...@@ -48,6 +49,7 @@ struct ab8500_regulator_info { ...@@ -48,6 +49,7 @@ struct ab8500_regulator_info {
struct regulator_desc desc; struct regulator_desc desc;
struct regulator_dev *regulator; struct regulator_dev *regulator;
bool is_enabled; bool is_enabled;
int load_lp_uA;
u8 update_bank; u8 update_bank;
u8 update_reg; u8 update_reg;
u8 update_mask; u8 update_mask;
...@@ -156,6 +158,27 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) ...@@ -156,6 +158,27 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev)
return ret; return ret;
} }
static unsigned int ab8500_regulator_get_optimum_mode(
struct regulator_dev *rdev, int input_uV,
int output_uV, int load_uA)
{
unsigned int mode;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
if (info == NULL) {
dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
return -EINVAL;
}
if (load_uA <= info->load_lp_uA)
mode = REGULATOR_MODE_IDLE;
else
mode = REGULATOR_MODE_NORMAL;
return mode;
}
static int ab8500_regulator_set_mode(struct regulator_dev *rdev, static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
unsigned int mode) unsigned int mode)
{ {
...@@ -186,6 +209,12 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, ...@@ -186,6 +209,12 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
if (ret < 0) if (ret < 0)
dev_err(rdev_get_dev(rdev), dev_err(rdev_get_dev(rdev),
"couldn't set regulator mode\n"); "couldn't set regulator mode\n");
dev_vdbg(rdev_get_dev(rdev),
"%s-set_mode (bank, reg, mask, value): "
"0x%x, 0x%x, 0x%x, 0x%x\n",
info->desc.name, info->update_bank, info->update_reg,
info->update_mask, info->update_val);
} }
return ret; return ret;
...@@ -313,23 +342,37 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, ...@@ -313,23 +342,37 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
return info->delay; return info->delay;
} }
static struct regulator_ops ab8500_regulator_ops = { static struct regulator_ops ab8500_regulator_volt_mode_ops = {
.enable = ab8500_regulator_enable, .enable = ab8500_regulator_enable,
.disable = ab8500_regulator_disable, .disable = ab8500_regulator_disable,
.set_mode = ab8500_regulator_set_mode, .is_enabled = ab8500_regulator_is_enabled,
.get_mode = ab8500_regulator_get_mode, .get_optimum_mode = ab8500_regulator_get_optimum_mode,
.is_enabled = ab8500_regulator_is_enabled, .set_mode = ab8500_regulator_set_mode,
.get_voltage_sel = ab8500_regulator_get_voltage_sel, .get_mode = ab8500_regulator_get_mode,
.set_voltage_sel = ab8500_regulator_set_voltage_sel, .get_voltage_sel = ab8500_regulator_get_voltage_sel,
.list_voltage = regulator_list_voltage_table, .set_voltage_sel = ab8500_regulator_set_voltage_sel,
.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, .list_voltage = regulator_list_voltage_table,
.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
}; };
static struct regulator_ops ab8500_regulator_fixed_ops = { static struct regulator_ops ab8500_regulator_mode_ops = {
.enable = ab8500_regulator_enable, .enable = ab8500_regulator_enable,
.disable = ab8500_regulator_disable, .disable = ab8500_regulator_disable,
.is_enabled = ab8500_regulator_is_enabled, .is_enabled = ab8500_regulator_is_enabled,
.list_voltage = regulator_list_voltage_linear, .get_optimum_mode = ab8500_regulator_get_optimum_mode,
.set_mode = ab8500_regulator_set_mode,
.get_mode = ab8500_regulator_get_mode,
.get_voltage_sel = ab8500_regulator_get_voltage_sel,
.list_voltage = regulator_list_voltage_table,
.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
};
static struct regulator_ops ab8500_regulator_ops = {
.enable = ab8500_regulator_enable,
.disable = ab8500_regulator_disable,
.is_enabled = ab8500_regulator_is_enabled,
.get_voltage_sel = ab8500_regulator_get_voltage_sel,
.list_voltage = regulator_list_voltage_table,
}; };
static struct ab8500_regulator_info static struct ab8500_regulator_info
...@@ -343,13 +386,14 @@ static struct ab8500_regulator_info ...@@ -343,13 +386,14 @@ static struct ab8500_regulator_info
[AB8500_LDO_AUX1] = { [AB8500_LDO_AUX1] = {
.desc = { .desc = {
.name = "LDO-AUX1", .name = "LDO-AUX1",
.ops = &ab8500_regulator_ops, .ops = &ab8500_regulator_volt_mode_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_AUX1, .id = AB8500_LDO_AUX1,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
.volt_table = ldo_vauxn_voltages, .volt_table = ldo_vauxn_voltages,
}, },
.load_lp_uA = 5000,
.update_bank = 0x04, .update_bank = 0x04,
.update_reg = 0x09, .update_reg = 0x09,
.update_mask = 0x03, .update_mask = 0x03,
...@@ -363,13 +407,14 @@ static struct ab8500_regulator_info ...@@ -363,13 +407,14 @@ static struct ab8500_regulator_info
[AB8500_LDO_AUX2] = { [AB8500_LDO_AUX2] = {
.desc = { .desc = {
.name = "LDO-AUX2", .name = "LDO-AUX2",
.ops = &ab8500_regulator_ops, .ops = &ab8500_regulator_volt_mode_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_AUX2, .id = AB8500_LDO_AUX2,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
.volt_table = ldo_vauxn_voltages, .volt_table = ldo_vauxn_voltages,
}, },
.load_lp_uA = 5000,
.update_bank = 0x04, .update_bank = 0x04,
.update_reg = 0x09, .update_reg = 0x09,
.update_mask = 0x0c, .update_mask = 0x0c,
...@@ -383,13 +428,14 @@ static struct ab8500_regulator_info ...@@ -383,13 +428,14 @@ static struct ab8500_regulator_info
[AB8500_LDO_AUX3] = { [AB8500_LDO_AUX3] = {
.desc = { .desc = {
.name = "LDO-AUX3", .name = "LDO-AUX3",
.ops = &ab8500_regulator_ops, .ops = &ab8500_regulator_volt_mode_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_AUX3, .id = AB8500_LDO_AUX3,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages),
.volt_table = ldo_vaux3_voltages, .volt_table = ldo_vaux3_voltages,
}, },
.load_lp_uA = 5000,
.update_bank = 0x04, .update_bank = 0x04,
.update_reg = 0x0a, .update_reg = 0x0a,
.update_mask = 0x03, .update_mask = 0x03,
...@@ -403,13 +449,14 @@ static struct ab8500_regulator_info ...@@ -403,13 +449,14 @@ static struct ab8500_regulator_info
[AB8500_LDO_INTCORE] = { [AB8500_LDO_INTCORE] = {
.desc = { .desc = {
.name = "LDO-INTCORE", .name = "LDO-INTCORE",
.ops = &ab8500_regulator_ops, .ops = &ab8500_regulator_volt_mode_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_INTCORE, .id = AB8500_LDO_INTCORE,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages),
.volt_table = ldo_vintcore_voltages, .volt_table = ldo_vintcore_voltages,
}, },
.load_lp_uA = 5000,
.update_bank = 0x03, .update_bank = 0x03,
.update_reg = 0x80, .update_reg = 0x80,
.update_mask = 0x44, .update_mask = 0x44,
...@@ -430,7 +477,7 @@ static struct ab8500_regulator_info ...@@ -430,7 +477,7 @@ static struct ab8500_regulator_info
[AB8500_LDO_TVOUT] = { [AB8500_LDO_TVOUT] = {
.desc = { .desc = {
.name = "LDO-TVOUT", .name = "LDO-TVOUT",
.ops = &ab8500_regulator_fixed_ops, .ops = &ab8500_regulator_mode_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_TVOUT, .id = AB8500_LDO_TVOUT,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -439,10 +486,13 @@ static struct ab8500_regulator_info ...@@ -439,10 +486,13 @@ static struct ab8500_regulator_info
.enable_time = 10000, .enable_time = 10000,
}, },
.delay = 10000, .delay = 10000,
.load_lp_uA = 1000,
.update_bank = 0x03, .update_bank = 0x03,
.update_reg = 0x80, .update_reg = 0x80,
.update_mask = 0x82, .update_mask = 0x82,
.update_val = 0x02, .update_val = 0x02,
.update_val_idle = 0x82,
.update_val_normal = 0x02,
}, },
[AB8500_LDO_USB] = { [AB8500_LDO_USB] = {
.desc = { .desc = {
...@@ -458,10 +508,14 @@ static struct ab8500_regulator_info ...@@ -458,10 +508,14 @@ static struct ab8500_regulator_info
.update_reg = 0x82, .update_reg = 0x82,
.update_mask = 0x03, .update_mask = 0x03,
}, },
/*
* Regulators with fixed voltage and normal mode
*/
[AB8500_LDO_AUDIO] = { [AB8500_LDO_AUDIO] = {
.desc = { .desc = {
.name = "LDO-AUDIO", .name = "LDO-AUDIO",
.ops = &ab8500_regulator_fixed_ops, .ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_AUDIO, .id = AB8500_LDO_AUDIO,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -476,7 +530,7 @@ static struct ab8500_regulator_info ...@@ -476,7 +530,7 @@ static struct ab8500_regulator_info
[AB8500_LDO_ANAMIC1] = { [AB8500_LDO_ANAMIC1] = {
.desc = { .desc = {
.name = "LDO-ANAMIC1", .name = "LDO-ANAMIC1",
.ops = &ab8500_regulator_fixed_ops, .ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_ANAMIC1, .id = AB8500_LDO_ANAMIC1,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -491,7 +545,7 @@ static struct ab8500_regulator_info ...@@ -491,7 +545,7 @@ static struct ab8500_regulator_info
[AB8500_LDO_ANAMIC2] = { [AB8500_LDO_ANAMIC2] = {
.desc = { .desc = {
.name = "LDO-ANAMIC2", .name = "LDO-ANAMIC2",
.ops = &ab8500_regulator_fixed_ops, .ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_ANAMIC2, .id = AB8500_LDO_ANAMIC2,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -506,7 +560,7 @@ static struct ab8500_regulator_info ...@@ -506,7 +560,7 @@ static struct ab8500_regulator_info
[AB8500_LDO_DMIC] = { [AB8500_LDO_DMIC] = {
.desc = { .desc = {
.name = "LDO-DMIC", .name = "LDO-DMIC",
.ops = &ab8500_regulator_fixed_ops, .ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_DMIC, .id = AB8500_LDO_DMIC,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -518,20 +572,27 @@ static struct ab8500_regulator_info ...@@ -518,20 +572,27 @@ static struct ab8500_regulator_info
.update_mask = 0x04, .update_mask = 0x04,
.update_val = 0x04, .update_val = 0x04,
}, },
/*
* Regulators with fixed voltage and normal/idle modes
*/
[AB8500_LDO_ANA] = { [AB8500_LDO_ANA] = {
.desc = { .desc = {
.name = "LDO-ANA", .name = "LDO-ANA",
.ops = &ab8500_regulator_fixed_ops, .ops = &ab8500_regulator_mode_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.id = AB8500_LDO_ANA, .id = AB8500_LDO_ANA,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.n_voltages = 1, .n_voltages = 1,
.min_uV = 1200000, .min_uV = 1200000,
}, },
.load_lp_uA = 1000,
.update_bank = 0x04, .update_bank = 0x04,
.update_reg = 0x06, .update_reg = 0x06,
.update_mask = 0x0c, .update_mask = 0x0c,
.update_val = 0x04, .update_val = 0x04,
.update_val_idle = 0x0c,
.update_val_normal = 0x04,
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment