From d79df329d0bd425c00856915b7b12f54dd100154 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Mar 2013 15:58:58 +0000 Subject: regulator: ab8500: Further populate initialisation registers This patch supplies access to some extra settings provided by the AB8500 regulator device. We also update some of the existing initialisation values in accordance with internal ST-Ericsson code submissions. This single patch was originally a collection of updates which have been squashed together to aid with clarity. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 09014f38a948..4d9d556a47cc 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -477,7 +477,7 @@ struct ab8500_reg_init { static struct ab8500_reg_init ab8500_reg_init[] = { /* * 0x30, VanaRequestCtrl - * 0x0C, VpllRequestCtrl + * 0x0c, VpllRequestCtrl * 0xc0, VextSupply1RequestCtrl */ REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xfc), @@ -494,12 +494,16 @@ static struct ab8500_reg_init ab8500_reg_init[] = { */ REG_INIT(AB8500_REGUREQUESTCTRL4, 0x03, 0x06, 0x07), /* + * 0x01, Vsmps1SysClkReq1HPValid + * 0x02, Vsmps2SysClkReq1HPValid + * 0x04, Vsmps3SysClkReq1HPValid * 0x08, VanaSysClkReq1HPValid + * 0x10, VpllSysClkReq1HPValid * 0x20, Vaux1SysClkReq1HPValid * 0x40, Vaux2SysClkReq1HPValid * 0x80, Vaux3SysClkReq1HPValid */ - REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xe8), + REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), /* * 0x10, VextSupply1SysClkReq1HPValid * 0x20, VextSupply2SysClkReq1HPValid @@ -577,6 +581,34 @@ static struct ab8500_reg_init ab8500_reg_init[] = { * 0x02, Vamic2_dzout */ REG_INIT(AB8500_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), + /* + * 0x0c, VBBNRegu + * 0x03, VBBPRegu + * NOTE! PRCMU register + */ + REG_INIT(AB8500_ARMREGU2, 0x04, 0x01, 0x0f), + /* + * 0x0c, VBBPSel1 + * 0x03, VBBNSel1 + * NOTE! PRCMU register + */ + REG_INIT(AB8500_VBBSEL1, 0x04, 0x11, 0x0f), + /* + * 0x0c, VBBNSel2 + * 0x03, VBBPSel2 + * NOTE! PRCMU register + */ + REG_INIT(AB8500_VBBSEL2, 0x04, 0x12, 0x0f), + /* + * 0x03, Vsmps1Regu + * 0x0c, Vsmps1SelCtrl + */ + REG_INIT(AB8500_VSMPS1REGU, 0x04, 0x03, 0x0f), + /* + * 0x03, Vsmps2Regu + * 0x0c, Vsmps2SelCtrl + */ + REG_INIT(AB8500_VSMPS2REGU, 0x04, 0x04, 0x0f), /* * 0x0c, VanaRegu * 0x03, VpllRegu @@ -601,9 +633,10 @@ static struct ab8500_reg_init ab8500_reg_init[] = { */ REG_INIT(AB8500_VAUX12REGU, 0x04, 0x09, 0x0f), /* + * 0x0c, Vrf1Regu * 0x03, Vaux3Regu */ - REG_INIT(AB8500_VRF1VAUX3REGU, 0x04, 0x0a, 0x03), + REG_INIT(AB8500_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f), /* * 0x3f, Vsmps1Sel1 */ -- cgit v1.2.3 From bd28a15733df2f3e66e6abc073cdf300df0f01e6 Mon Sep 17 00:00:00 2001 From: Emeric Vigier Date: Thu, 21 Mar 2013 15:58:59 +0000 Subject: regulator: ab8500: Add set_mode/get_mode support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ludovic Barré Signed-off-by: Emeric Vigier Signed-off-by: Lee Jones Reviewed-by: Bengt JONSSON Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 112 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 18 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 4d9d556a47cc..283d9a51114b 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -30,10 +30,13 @@ * @dev: device pointer * @desc: regulator description * @regulator_dev: regulator device + * @is_enabled: status of regulator (on/off) * @update_bank: bank to control on/off * @update_reg: register to control on/off - * @update_mask: mask to enable/disable regulator - * @update_val_enable: bits to enable the regulator in normal (high power) mode + * @update_mask: mask to enable/disable and set mode of regulator + * @update_val: bits holding the regulator current mode + * @update_val_idle: bits to enable the regulator in idle (low power) mode + * @update_val_normal: bits to enable the regulator in normal (high power) mode * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage @@ -44,10 +47,13 @@ struct ab8500_regulator_info { struct device *dev; struct regulator_desc desc; struct regulator_dev *regulator; + bool is_enabled; u8 update_bank; u8 update_reg; u8 update_mask; - u8 update_val_enable; + u8 update_val; + u8 update_val_idle; + u8 update_val_normal; u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; @@ -108,15 +114,17 @@ static int ab8500_regulator_enable(struct regulator_dev *rdev) ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, - info->update_mask, info->update_val_enable); + info->update_mask, info->update_val); if (ret < 0) dev_err(rdev_get_dev(rdev), "couldn't set enable bits for regulator\n"); + info->is_enabled = true; + dev_vdbg(rdev_get_dev(rdev), "%s-enable (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_enable); + info->update_mask, info->update_val); return ret; } @@ -138,6 +146,8 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) dev_err(rdev_get_dev(rdev), "couldn't set disable bits for regulator\n"); + info->is_enabled = false; + dev_vdbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", info->desc.name, info->update_bank, info->update_reg, @@ -146,6 +156,61 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) return ret; } +static int ab8500_regulator_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + int ret = 0; + + 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; + } + + switch (mode) { + case REGULATOR_MODE_NORMAL: + info->update_val = info->update_val_normal; + break; + case REGULATOR_MODE_IDLE: + info->update_val = info->update_val_idle; + break; + default: + return -EINVAL; + } + + if (info->is_enabled) { + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->update_bank, info->update_reg, + info->update_mask, info->update_val); + if (ret < 0) + dev_err(rdev_get_dev(rdev), + "couldn't set regulator mode\n"); + } + + return ret; +} + +static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + int ret; + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + if (info->update_val == info->update_val_normal) + ret = REGULATOR_MODE_NORMAL; + else if (info->update_val == info->update_val_idle) + ret = REGULATOR_MODE_IDLE; + else + ret = -EINVAL; + + return ret; +} + static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) { int ret; @@ -172,9 +237,11 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) info->update_mask, regval); if (regval & info->update_mask) - return true; + info->is_enabled = true; else - return false; + info->is_enabled = false; + + return info->is_enabled; } static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) @@ -249,6 +316,8 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, static struct regulator_ops ab8500_regulator_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, + .set_mode = ab8500_regulator_set_mode, + .get_mode = ab8500_regulator_get_mode, .is_enabled = ab8500_regulator_is_enabled, .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, @@ -284,7 +353,9 @@ static struct ab8500_regulator_info .update_bank = 0x04, .update_reg = 0x09, .update_mask = 0x03, - .update_val_enable = 0x01, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, .voltage_bank = 0x04, .voltage_reg = 0x1f, .voltage_mask = 0x0f, @@ -302,7 +373,9 @@ static struct ab8500_regulator_info .update_bank = 0x04, .update_reg = 0x09, .update_mask = 0x0c, - .update_val_enable = 0x04, + .update_val = 0x04, + .update_val_idle = 0x0c, + .update_val_normal = 0x04, .voltage_bank = 0x04, .voltage_reg = 0x20, .voltage_mask = 0x0f, @@ -320,7 +393,9 @@ static struct ab8500_regulator_info .update_bank = 0x04, .update_reg = 0x0a, .update_mask = 0x03, - .update_val_enable = 0x01, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, .voltage_bank = 0x04, .voltage_reg = 0x21, .voltage_mask = 0x07, @@ -338,7 +413,9 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x44, - .update_val_enable = 0x04, + .update_val = 0x04, + .update_val_idle = 0x44, + .update_val_normal = 0x04, .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, @@ -365,7 +442,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x82, - .update_val_enable = 0x02, + .update_val = 0x02, }, [AB8500_LDO_USB] = { .desc = { @@ -380,7 +457,6 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x82, .update_mask = 0x03, - .update_val_enable = 0x01, }, [AB8500_LDO_AUDIO] = { .desc = { @@ -395,7 +471,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x02, - .update_val_enable = 0x02, + .update_val = 0x02, }, [AB8500_LDO_ANAMIC1] = { .desc = { @@ -410,7 +486,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x08, - .update_val_enable = 0x08, + .update_val = 0x08, }, [AB8500_LDO_ANAMIC2] = { .desc = { @@ -425,7 +501,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x10, - .update_val_enable = 0x10, + .update_val = 0x10, }, [AB8500_LDO_DMIC] = { .desc = { @@ -440,7 +516,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x04, - .update_val_enable = 0x04, + .update_val = 0x04, }, [AB8500_LDO_ANA] = { .desc = { @@ -455,7 +531,7 @@ static struct ab8500_regulator_info .update_bank = 0x04, .update_reg = 0x06, .update_mask = 0x0c, - .update_val_enable = 0x04, + .update_val = 0x04, }, -- cgit v1.2.3 From 7ce4669c8feefe0c772e9d5f3ae65160e20d8458 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Thu, 21 Mar 2013 15:59:00 +0000 Subject: 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: Bengt Jonsson Signed-off-by: Lee Jones Reviewed-by: Mattias WALLIN Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 111 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 86 insertions(+), 25 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 283d9a51114b..3465ac38bffe 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -31,6 +31,7 @@ * @desc: regulator description * @regulator_dev: regulator device * @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_reg: register to control on/off * @update_mask: mask to enable/disable and set mode of regulator @@ -48,6 +49,7 @@ struct ab8500_regulator_info { struct regulator_desc desc; struct regulator_dev *regulator; bool is_enabled; + int load_lp_uA; u8 update_bank; u8 update_reg; u8 update_mask; @@ -156,6 +158,27 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) 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, unsigned int mode) { @@ -186,6 +209,12 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, if (ret < 0) dev_err(rdev_get_dev(rdev), "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; @@ -313,23 +342,37 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, return info->delay; } -static struct regulator_ops ab8500_regulator_ops = { - .enable = ab8500_regulator_enable, - .disable = ab8500_regulator_disable, - .set_mode = ab8500_regulator_set_mode, - .get_mode = ab8500_regulator_get_mode, - .is_enabled = ab8500_regulator_is_enabled, - .get_voltage_sel = ab8500_regulator_get_voltage_sel, - .set_voltage_sel = ab8500_regulator_set_voltage_sel, - .list_voltage = regulator_list_voltage_table, - .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, +static struct regulator_ops ab8500_regulator_volt_mode_ops = { + .enable = ab8500_regulator_enable, + .disable = ab8500_regulator_disable, + .is_enabled = ab8500_regulator_is_enabled, + .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, + .set_voltage_sel = ab8500_regulator_set_voltage_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 = { - .enable = ab8500_regulator_enable, - .disable = ab8500_regulator_disable, - .is_enabled = ab8500_regulator_is_enabled, - .list_voltage = regulator_list_voltage_linear, +static struct regulator_ops ab8500_regulator_mode_ops = { + .enable = ab8500_regulator_enable, + .disable = ab8500_regulator_disable, + .is_enabled = ab8500_regulator_is_enabled, + .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 @@ -343,13 +386,14 @@ static struct ab8500_regulator_info [AB8500_LDO_AUX1] = { .desc = { .name = "LDO-AUX1", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, }, + .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x09, .update_mask = 0x03, @@ -363,13 +407,14 @@ static struct ab8500_regulator_info [AB8500_LDO_AUX2] = { .desc = { .name = "LDO-AUX2", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, }, + .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x09, .update_mask = 0x0c, @@ -383,13 +428,14 @@ static struct ab8500_regulator_info [AB8500_LDO_AUX3] = { .desc = { .name = "LDO-AUX3", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), .volt_table = ldo_vaux3_voltages, }, + .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x0a, .update_mask = 0x03, @@ -403,13 +449,14 @@ static struct ab8500_regulator_info [AB8500_LDO_INTCORE] = { .desc = { .name = "LDO-INTCORE", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), .volt_table = ldo_vintcore_voltages, }, + .load_lp_uA = 5000, .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x44, @@ -430,7 +477,7 @@ static struct ab8500_regulator_info [AB8500_LDO_TVOUT] = { .desc = { .name = "LDO-TVOUT", - .ops = &ab8500_regulator_fixed_ops, + .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_TVOUT, .owner = THIS_MODULE, @@ -439,10 +486,13 @@ static struct ab8500_regulator_info .enable_time = 10000, }, .delay = 10000, + .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x82, .update_val = 0x02, + .update_val_idle = 0x82, + .update_val_normal = 0x02, }, [AB8500_LDO_USB] = { .desc = { @@ -458,10 +508,14 @@ static struct ab8500_regulator_info .update_reg = 0x82, .update_mask = 0x03, }, + + /* + * Regulators with fixed voltage and normal mode + */ [AB8500_LDO_AUDIO] = { .desc = { .name = "LDO-AUDIO", - .ops = &ab8500_regulator_fixed_ops, + .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_AUDIO, .owner = THIS_MODULE, @@ -476,7 +530,7 @@ static struct ab8500_regulator_info [AB8500_LDO_ANAMIC1] = { .desc = { .name = "LDO-ANAMIC1", - .ops = &ab8500_regulator_fixed_ops, + .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_ANAMIC1, .owner = THIS_MODULE, @@ -491,7 +545,7 @@ static struct ab8500_regulator_info [AB8500_LDO_ANAMIC2] = { .desc = { .name = "LDO-ANAMIC2", - .ops = &ab8500_regulator_fixed_ops, + .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_ANAMIC2, .owner = THIS_MODULE, @@ -506,7 +560,7 @@ static struct ab8500_regulator_info [AB8500_LDO_DMIC] = { .desc = { .name = "LDO-DMIC", - .ops = &ab8500_regulator_fixed_ops, + .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_DMIC, .owner = THIS_MODULE, @@ -518,20 +572,27 @@ static struct ab8500_regulator_info .update_mask = 0x04, .update_val = 0x04, }, + + /* + * Regulators with fixed voltage and normal/idle modes + */ [AB8500_LDO_ANA] = { .desc = { .name = "LDO-ANA", - .ops = &ab8500_regulator_fixed_ops, + .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 1200000, }, + .load_lp_uA = 1000, .update_bank = 0x04, .update_reg = 0x06, .update_mask = 0x0c, .update_val = 0x04, + .update_val_idle = 0x0c, + .update_val_normal = 0x04, }, -- cgit v1.2.3 From 3c1b8438d4bc99269aba560739e3e6cb640584f4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Mar 2013 15:59:01 +0000 Subject: ARM: ux500: regulators: Add mask for configuration There is already before a register mask in the regulator driver to allow some bits of a register to be initialized. The register value is defined in the board configuration. This patch puts a mask in the board configuration to specify which bits should actually be altered. The purpose with this patch is to avoid future mistakes when updating the allowed bits in the regulator driver. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500-regulators.c | 66 +++++++++++++-------------- drivers/regulator/ab8500.c | 36 ++++++--------- include/linux/regulator/ab8500.h | 10 ++-- 3 files changed, 53 insertions(+), 59 deletions(-) (limited to 'drivers/regulator') diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index 4b3c51905071..96dd17490bea 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -129,19 +129,19 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * VpllRequestCtrl = HP/LP depending on VxRequest * VextSupply1RequestCtrl = HP/LP depending on VxRequest */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0xfc, 0x00), /* * VextSupply2RequestCtrl = HP/LP depending on VxRequest * VextSupply3RequestCtrl = HP/LP depending on VxRequest * Vaux1RequestCtrl = HP/LP depending on VxRequest * Vaux2RequestCtrl = HP/LP depending on VxRequest */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0xff, 0x00), /* * Vaux3RequestCtrl = HP/LP depending on VxRequest * SwHPReq = Control through SWValid disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x07, 0x00), /* * Vsmps1SysClkReq1HPValid = enabled * Vsmps2SysClkReq1HPValid = enabled @@ -152,44 +152,44 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * Vaux2SysClkReq1HPValid = disabled * Vaux3SysClkReq1HPValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0x17), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xff, 0x17), /* * VextSupply1SysClkReq1HPValid = disabled * VextSupply2SysClkReq1HPValid = disabled * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x40), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40), /* * VanaHwHPReq1Valid = disabled * Vaux1HwHPreq1Valid = disabled * Vaux2HwHPReq1Valid = disabled * Vaux3HwHPReqValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0xe8, 0x00), /* * VextSupply1HwHPReq1Valid = disabled * VextSupply2HwHPReq1Valid = disabled * VextSupply3HwHPReq1Valid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x07, 0x00), /* * VanaHwHPReq2Valid = disabled * Vaux1HwHPReq2Valid = disabled * Vaux2HwHPReq2Valid = disabled * Vaux3HwHPReq2Valid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0xe8, 0x00), /* * VextSupply1HwHPReq2Valid = disabled * VextSupply2HwHPReq2Valid = disabled * VextSupply3HwHPReq2Valid = HWReq2 controlled */ - INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x04), + INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x07, 0x04), /* * VanaSwHPReqValid = disabled * Vaux1SwHPReqValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0xa0, 0x00), /* * Vaux2SwHPReqValid = disabled * Vaux3SwHPReqValid = disabled @@ -197,7 +197,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * VextSupply2SwHPReqValid = disabled * VextSupply3SwHPReqValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x1f, 0x00), /* * SysClkReq2Valid1 = SysClkReq2 controlled * SysClkReq3Valid1 = disabled @@ -207,7 +207,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * SysClkReq7Valid1 = disabled * SysClkReq8Valid1 = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0x2a), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0xfe, 0x2a), /* * SysClkReq2Valid2 = disabled * SysClkReq3Valid2 = disabled @@ -217,7 +217,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * SysClkReq7Valid2 = disabled * SysClkReq8Valid2 = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0x20), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0xfe, 0x20), /* * VTVoutEna = disabled * Vintcore12Ena = disabled @@ -225,57 +225,57 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * Vintcore12LP = inactive (HP) * VTVoutLP = inactive (HP) */ - INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0x10), + INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0xfe, 0x10), /* * VaudioEna = disabled * VdmicEna = disabled * Vamic1Ena = disabled * Vamic2Ena = disabled */ - INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x00), + INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x1e, 0x00), /* * Vamic1_dzout = high-Z when Vamic1 is disabled * Vamic2_dzout = high-Z when Vamic2 is disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x03, 0x00), /* * VBBN = force OFF * VBBP = force OFF * NOTE! PRCMU register */ - INIT_REGULATOR_REGISTER(AB8500_ARMREGU2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_ARMREGU2, 0x0f, 0x00), /* * VBBNSel1 = VBBP = VBBPFB * VBBPSel1 = 0 V * NOTE! PRCMU register */ - INIT_REGULATOR_REGISTER(AB8500_VBBSEL1, 0x00), + INIT_REGULATOR_REGISTER(AB8500_VBBSEL1, 0x0f, 0x00), /* * VBBNSel2 = VBBP = VBBPFB * VBBPSel2 = 0 V * NOTE! PRCMU register */ - INIT_REGULATOR_REGISTER(AB8500_VBBSEL2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_VBBSEL2, 0x0f, 0x00), /* * Vsmps1Regu = HW control * Vsmps1SelCtrl = Vsmps1 voltage defined by Vsmsp1Sel2 */ - INIT_REGULATOR_REGISTER(AB8500_VSMPS1REGU, 0x06), + INIT_REGULATOR_REGISTER(AB8500_VSMPS1REGU, 0x0f, 0x06), /* * Vsmps2Regu = HW control * Vsmps2SelCtrl = Vsmps2 voltage defined by Vsmsp2Sel2 */ - INIT_REGULATOR_REGISTER(AB8500_VSMPS2REGU, 0x06), + INIT_REGULATOR_REGISTER(AB8500_VSMPS2REGU, 0x0f, 0x06), /* * VPll = Hw controlled * VanaRegu = force off */ - INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x02), + INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x0f, 0x02), /* * VrefDDREna = disabled * VrefDDRSleepMode = inactive (no pulldown) */ - INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x00), + INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x03, 0x00), /* * VextSupply1Regu = HW control * VextSupply2Regu = HW control @@ -283,37 +283,37 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * ExtSupply2Bypass = ExtSupply12LPn ball is 0 when Ena is 0 * ExtSupply3Bypass = ExtSupply3LPn ball is 0 when Ena is 0 */ - INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0x2a), + INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0xff, 0x1a), /* * Vaux1Regu = force HP * Vaux2Regu = force off */ - INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x01), + INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x0f, 0x01), /* * Vrf1Regu = HW control * Vaux3Regu = force off */ - INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x08), + INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x0f, 0x08), /* * Vsmps1 = 1.15V */ - INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x24), + INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x3f, 0x24), /* * Vaux1Sel = 2.5 V */ - INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x08), + INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x0f, 0x08), /* * Vaux2Sel = 2.9 V */ - INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0d), + INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0f, 0x0d), /* * Vaux3Sel = 2.91 V */ - INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07), + INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07, 0x07), /* * VextSupply12LP = disabled (no LP) */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x01, 0x00), /* * Vaux1Disch = short discharge time * Vaux2Disch = short discharge time @@ -322,13 +322,13 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * VTVoutDisch = short discharge time * VaudioDisch = short discharge time */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0xfc, 0x00), /* * VanaDisch = short discharge time * VdmicPullDownEna = pulldown disabled when Vdmic is disabled * VdmicDisch = short discharge time */ - INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x16, 0x00), }; /* AB8500 regulators */ diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 3465ac38bffe..a847744f8c20 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -811,23 +811,20 @@ static struct ab8500_reg_init ab8500_reg_init[] = { REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16), }; -static int -ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value) +static int ab8500_regulator_init_registers(struct platform_device *pdev, + int id, int mask, int value) { int err; - if (value & ~ab8500_reg_init[id].mask) { - dev_err(&pdev->dev, - "Configuration error: value outside mask.\n"); - return -EINVAL; - } + BUG_ON(value & ~mask); + BUG_ON(mask & ~ab8500_reg_init[id].mask); + /* initialize register */ err = abx500_mask_and_set_register_interruptible( &pdev->dev, ab8500_reg_init[id].bank, ab8500_reg_init[id].addr, - ab8500_reg_init[id].mask, - value); + mask, value); if (err < 0) { dev_err(&pdev->dev, "Failed to initialize 0x%02x, 0x%02x.\n", @@ -835,13 +832,11 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value) ab8500_reg_init[id].addr); return err; } - dev_vdbg(&pdev->dev, - "init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - ab8500_reg_init[id].bank, - ab8500_reg_init[id].addr, - ab8500_reg_init[id].mask, - value); + " init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + ab8500_reg_init[id].bank, + ab8500_reg_init[id].addr, + mask, value); return 0; } @@ -960,19 +955,16 @@ static int ab8500_regulator_probe(struct platform_device *pdev) /* initialize registers */ for (i = 0; i < pdata->num_regulator_reg_init; i++) { - int id, value; + int id, mask, value; id = pdata->regulator_reg_init[i].id; + mask = pdata->regulator_reg_init[i].mask; value = pdata->regulator_reg_init[i].value; /* check for configuration errors */ - if (id >= AB8500_NUM_REGULATOR_REGISTERS) { - dev_err(&pdev->dev, - "Configuration error: id outside range.\n"); - return -EINVAL; - } + BUG_ON(id >= AB8500_NUM_REGULATOR_REGISTERS); - err = ab8500_regulator_init_registers(pdev, id, value); + err = ab8500_regulator_init_registers(pdev, id, mask, value); if (err < 0) return err; } diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 2c6c9625013c..a1d245f13d9c 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -48,13 +48,15 @@ enum ab9540_regulator_id { /* AB8500 and AB9540 register initialization */ struct ab8500_regulator_reg_init { int id; + u8 mask; u8 value; }; -#define INIT_REGULATOR_REGISTER(_id, _value) \ - { \ - .id = _id, \ - .value = _value, \ +#define INIT_REGULATOR_REGISTER(_id, _mask, _value) \ + { \ + .id = _id, \ + .mask = _mask, \ + .value = _value, \ } /* AB8500 registers */ -- cgit v1.2.3 From 33bc8f46a8ee3fc1836def9713933435b7ff0b90 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Mar 2013 15:59:02 +0000 Subject: regulator: ab8500: Another push to synchronise recent AB8500 developments This patch ensures that many of the recent developments pertaining to the AB8500 regulator device are propagated out into the public arena. It aims to update some of the existing initialisation values in accordance with internal ST-Ericsson code submissions. This single patch was originally a collection of updates which have been squashed together to aid with clarity. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500-regulators.c | 18 ------ drivers/regulator/ab8500.c | 86 +++++++++++++++++---------- include/linux/regulator/ab8500.h | 21 ++++--- 3 files changed, 65 insertions(+), 60 deletions(-) (limited to 'drivers/regulator') diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index 96dd17490bea..a8141e3e8ca1 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -238,24 +238,6 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { * Vamic2_dzout = high-Z when Vamic2 is disabled */ INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x03, 0x00), - /* - * VBBN = force OFF - * VBBP = force OFF - * NOTE! PRCMU register - */ - INIT_REGULATOR_REGISTER(AB8500_ARMREGU2, 0x0f, 0x00), - /* - * VBBNSel1 = VBBP = VBBPFB - * VBBPSel1 = 0 V - * NOTE! PRCMU register - */ - INIT_REGULATOR_REGISTER(AB8500_VBBSEL1, 0x0f, 0x00), - /* - * VBBNSel2 = VBBP = VBBPFB - * VBBPSel2 = 0 V - * NOTE! PRCMU register - */ - INIT_REGULATOR_REGISTER(AB8500_VBBSEL2, 0x0f, 0x00), /* * Vsmps1Regu = HW control * Vsmps1SelCtrl = Vsmps1 voltage defined by Vsmsp1Sel2 diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index a847744f8c20..c7784c4bff4f 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -613,11 +613,19 @@ struct ab8500_reg_init { static struct ab8500_reg_init ab8500_reg_init[] = { /* - * 0x30, VanaRequestCtrl + * 0x03, VarmRequestCtrl + * 0x0c, VapeRequestCtrl + * 0x30, Vsmps1RequestCtrl + * 0xc0, Vsmps2RequestCtrl + */ + REG_INIT(AB8500_REGUREQUESTCTRL1, 0x03, 0x03, 0xff), + /* + * 0x03, Vsmps3RequestCtrl * 0x0c, VpllRequestCtrl + * 0x30, VanaRequestCtrl * 0xc0, VextSupply1RequestCtrl */ - REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xfc), + REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xff), /* * 0x03, VextSupply2RequestCtrl * 0x0c, VextSupply3RequestCtrl @@ -642,50 +650,71 @@ static struct ab8500_reg_init ab8500_reg_init[] = { */ REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), /* + * 0x01, VapeSysClkReq1HPValid + * 0x02, VarmSysClkReq1HPValid + * 0x04, VbbSysClkReq1HPValid + * 0x08, VmodSysClkReq1HPValid * 0x10, VextSupply1SysClkReq1HPValid * 0x20, VextSupply2SysClkReq1HPValid * 0x40, VextSupply3SysClkReq1HPValid */ - REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x70), + REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x7f), /* + * 0x01, Vsmps1HwHPReq1Valid + * 0x02, Vsmps2HwHPReq1Valid + * 0x04, Vsmps3HwHPReq1Valid * 0x08, VanaHwHPReq1Valid + * 0x10, VpllHwHPReq1Valid * 0x20, Vaux1HwHPReq1Valid * 0x40, Vaux2HwHPReq1Valid * 0x80, Vaux3HwHPReq1Valid */ - REG_INIT(AB8500_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xe8), + REG_INIT(AB8500_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff), /* * 0x01, VextSupply1HwHPReq1Valid * 0x02, VextSupply2HwHPReq1Valid * 0x04, VextSupply3HwHPReq1Valid + * 0x08, VmodHwHPReq1Valid */ - REG_INIT(AB8500_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x07), + REG_INIT(AB8500_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x0f), /* + * 0x01, Vsmps1HwHPReq2Valid + * 0x02, Vsmps2HwHPReq2Valid + * 0x03, Vsmps3HwHPReq2Valid * 0x08, VanaHwHPReq2Valid + * 0x10, VpllHwHPReq2Valid * 0x20, Vaux1HwHPReq2Valid * 0x40, Vaux2HwHPReq2Valid * 0x80, Vaux3HwHPReq2Valid */ - REG_INIT(AB8500_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xe8), + REG_INIT(AB8500_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff), /* * 0x01, VextSupply1HwHPReq2Valid * 0x02, VextSupply2HwHPReq2Valid * 0x04, VextSupply3HwHPReq2Valid + * 0x08, VmodHwHPReq2Valid */ - REG_INIT(AB8500_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x07), + REG_INIT(AB8500_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x0f), /* + * 0x01, VapeSwHPReqValid + * 0x02, VarmSwHPReqValid + * 0x04, Vsmps1SwHPReqValid + * 0x08, Vsmps2SwHPReqValid + * 0x10, Vsmps3SwHPReqValid * 0x20, VanaSwHPReqValid + * 0x40, VpllSwHPReqValid * 0x80, Vaux1SwHPReqValid */ - REG_INIT(AB8500_REGUSWHPREQVALID1, 0x03, 0x0d, 0xa0), + REG_INIT(AB8500_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff), /* * 0x01, Vaux2SwHPReqValid * 0x02, Vaux3SwHPReqValid * 0x04, VextSupply1SwHPReqValid * 0x08, VextSupply2SwHPReqValid * 0x10, VextSupply3SwHPReqValid + * 0x20, VmodSwHPReqValid */ - REG_INIT(AB8500_REGUSWHPREQVALID2, 0x03, 0x0e, 0x1f), + REG_INIT(AB8500_REGUSWHPREQVALID2, 0x03, 0x0e, 0x3f), /* * 0x02, SysClkReq2Valid1 * ... @@ -718,37 +747,23 @@ static struct ab8500_reg_init ab8500_reg_init[] = { * 0x02, Vamic2_dzout */ REG_INIT(AB8500_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), - /* - * 0x0c, VBBNRegu - * 0x03, VBBPRegu - * NOTE! PRCMU register - */ - REG_INIT(AB8500_ARMREGU2, 0x04, 0x01, 0x0f), - /* - * 0x0c, VBBPSel1 - * 0x03, VBBNSel1 - * NOTE! PRCMU register - */ - REG_INIT(AB8500_VBBSEL1, 0x04, 0x11, 0x0f), - /* - * 0x0c, VBBNSel2 - * 0x03, VBBPSel2 - * NOTE! PRCMU register - */ - REG_INIT(AB8500_VBBSEL2, 0x04, 0x12, 0x0f), /* * 0x03, Vsmps1Regu * 0x0c, Vsmps1SelCtrl + * 0x10, Vsmps1AutoMode + * 0x20, Vsmps1PWMMode */ - REG_INIT(AB8500_VSMPS1REGU, 0x04, 0x03, 0x0f), + REG_INIT(AB8500_VSMPS1REGU, 0x04, 0x03, 0x3f), /* * 0x03, Vsmps2Regu * 0x0c, Vsmps2SelCtrl + * 0x10, Vsmps2AutoMode + * 0x20, Vsmps2PWMMode */ - REG_INIT(AB8500_VSMPS2REGU, 0x04, 0x04, 0x0f), + REG_INIT(AB8500_VSMPS2REGU, 0x04, 0x04, 0x3f), /* - * 0x0c, VanaRegu * 0x03, VpllRegu + * 0x0c, VanaRegu */ REG_INIT(AB8500_VPLLVANAREGU, 0x04, 0x06, 0x0f), /* @@ -788,13 +803,16 @@ static struct ab8500_reg_init ab8500_reg_init[] = { REG_INIT(AB8500_VAUX2SEL, 0x04, 0x20, 0x0f), /* * 0x07, Vaux3Sel + * 0x30, Vrf1Sel */ - REG_INIT(AB8500_VRF1VAUX3SEL, 0x04, 0x21, 0x07), + REG_INIT(AB8500_VRF1VAUX3SEL, 0x04, 0x21, 0x37), /* * 0x01, VextSupply12LP */ REG_INIT(AB8500_REGUCTRL2SPARE, 0x04, 0x22, 0x01), /* + * 0x01, VpllDisch + * 0x02, Vrf1Disch * 0x04, Vaux1Disch * 0x08, Vaux2Disch * 0x10, Vaux3Disch @@ -802,13 +820,15 @@ static struct ab8500_reg_init ab8500_reg_init[] = { * 0x40, VTVoutDisch * 0x80, VaudioDisch */ - REG_INIT(AB8500_REGUCTRLDISCH, 0x04, 0x43, 0xfc), + REG_INIT(AB8500_REGUCTRLDISCH, 0x04, 0x43, 0xff), /* + * 0x01, VsimDisch * 0x02, VanaDisch * 0x04, VdmicPullDownEna + * 0x08, VpllPullDownEna * 0x10, VdmicDisch */ - REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16), + REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x1f), }; static int ab8500_regulator_init_registers(struct platform_device *pdev, diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index a1d245f13d9c..dd7944f735d8 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -61,6 +61,7 @@ struct ab8500_regulator_reg_init { /* AB8500 registers */ enum ab8500_regulator_reg { + AB8500_REGUREQUESTCTRL1, AB8500_REGUREQUESTCTRL2, AB8500_REGUREQUESTCTRL3, AB8500_REGUREQUESTCTRL4, @@ -77,26 +78,28 @@ enum ab8500_regulator_reg { AB8500_REGUMISC1, AB8500_VAUDIOSUPPLY, AB8500_REGUCTRL1VAMIC, + AB8500_VSMPS1REGU, + AB8500_VSMPS2REGU, + AB8500_VSMPS3REGU, /* NOTE! PRCMU register */ AB8500_VPLLVANAREGU, AB8500_VREFDDR, AB8500_EXTSUPPLYREGU, AB8500_VAUX12REGU, AB8500_VRF1VAUX3REGU, + AB8500_VSMPS1SEL1, + AB8500_VSMPS1SEL2, + AB8500_VSMPS1SEL3, + AB8500_VSMPS2SEL1, + AB8500_VSMPS2SEL2, + AB8500_VSMPS2SEL3, + AB8500_VSMPS3SEL1, /* NOTE! PRCMU register */ + AB8500_VSMPS3SEL2, /* NOTE! PRCMU register */ AB8500_VAUX1SEL, AB8500_VAUX2SEL, AB8500_VRF1VAUX3SEL, AB8500_REGUCTRL2SPARE, AB8500_REGUCTRLDISCH, AB8500_REGUCTRLDISCH2, - AB8500_ARMREGU2, /* NOTE! PRCMU register */ - AB8500_VBBSEL1, /* NOTE! PRCMU register */ - AB8500_VBBSEL2, /* NOTE! PRCMU register */ - AB8500_VSMPS1REGU, - AB8500_VSMPS2REGU, - AB8500_VSMPS3REGU, /* NOTE! PRCMU register */ - AB8500_VSMPS1SEL1, - AB8500_VSMPS3SEL1, /* NOTE! PRCMU register */ - AB8500_VSMPS3SEL2, /* NOTE! PRCMU register */ AB8500_NUM_REGULATOR_REGISTERS, }; -- cgit v1.2.3 From 732805a563617aafc7405409c03182afafb3943b Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Thu, 21 Mar 2013 15:59:03 +0000 Subject: regulator: ab8500: Separate regulator and MFD platform data The ab8500 MFD should not have knowledge about regulator- specific platform data like number of regulators and regulator registers. As the regulator platform data is about to grow with external regulators, this information is moved to a new structure provided by the regulator driver. Signed-off-by: Bengt Jonsson Signed-off-by: Lee Jones Reviewed-by: Yvan FILLION Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500-regulators.c | 12 +++++++++--- arch/arm/mach-ux500/board-mop500-regulators.h | 4 +--- drivers/regulator/ab8500.c | 21 +++++++++++++++------ include/linux/regulator/ab8500.h | 7 +++++++ 4 files changed, 32 insertions(+), 12 deletions(-) (limited to 'drivers/regulator') diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index a8141e3e8ca1..0fd84d42e1ec 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -122,8 +122,7 @@ static struct regulator_consumer_supply ab8500_vana_consumers[] = { }; /* ab8500 regulator register initialization */ -struct ab8500_regulator_reg_init -ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { +static struct ab8500_regulator_reg_init ab8500_reg_init[] = { /* * VanaRequestCtrl = HP/LP depending on VxRequest * VpllRequestCtrl = HP/LP depending on VxRequest @@ -314,7 +313,7 @@ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = { }; /* AB8500 regulators */ -struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { +static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { /* supplies to the display/camera */ [AB8500_LDO_AUX1] = { .constraints = { @@ -423,3 +422,10 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { .consumer_supplies = ab8500_vana_consumers, }, }; + +struct ab8500_regulator_platform_data ab8500_regulator_plat_data = { + .reg_init = ab8500_reg_init, + .num_reg_init = ARRAY_SIZE(ab8500_reg_init), + .regulator = ab8500_regulators, + .num_regulator = ARRAY_SIZE(ab8500_regulators), +}; diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h index 78a0642a2206..9ca4869a6f23 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.h +++ b/arch/arm/mach-ux500/board-mop500-regulators.h @@ -14,9 +14,7 @@ #include #include -extern struct ab8500_regulator_reg_init -ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS]; -extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS]; +extern struct ab8500_regulator_platform_data ab8500_regulator_plat_data; extern struct regulator_init_data tps61052_regulator; extern struct regulator_init_data gpio_en_3v3_regulator; diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index c7784c4bff4f..f7d1f538c200 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -939,8 +939,9 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np) static int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); - struct ab8500_platform_data *pdata; struct device_node *np = pdev->dev.of_node; + struct ab8500_platform_data *ppdata; + struct ab8500_regulator_platform_data *pdata; int i, err; if (np) { @@ -961,7 +962,14 @@ static int ab8500_regulator_probe(struct platform_device *pdev) dev_err(&pdev->dev, "null mfd parent\n"); return -EINVAL; } - pdata = dev_get_platdata(ab8500->dev); + + ppdata = dev_get_platdata(ab8500->dev); + if (!ppdata) { + dev_err(&pdev->dev, "null parent pdata\n"); + return -EINVAL; + } + + pdata = ppdata->regulator; if (!pdata) { dev_err(&pdev->dev, "null pdata\n"); return -EINVAL; @@ -974,12 +982,12 @@ static int ab8500_regulator_probe(struct platform_device *pdev) } /* initialize registers */ - for (i = 0; i < pdata->num_regulator_reg_init; i++) { + for (i = 0; i < pdata->num_reg_init; i++) { int id, mask, value; - id = pdata->regulator_reg_init[i].id; - mask = pdata->regulator_reg_init[i].mask; - value = pdata->regulator_reg_init[i].value; + id = pdata->reg_init[i].id; + mask = pdata->reg_init[i].mask; + value = pdata->reg_init[i].value; /* check for configuration errors */ BUG_ON(id >= AB8500_NUM_REGULATOR_REGISTERS); @@ -1045,5 +1053,6 @@ module_exit(ab8500_regulator_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Sundar Iyer "); +MODULE_AUTHOR("Bengt Jonsson "); MODULE_DESCRIPTION("Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC"); MODULE_ALIAS("platform:ab8500-regulator"); diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index dd7944f735d8..3a8e02687f7b 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -152,4 +152,11 @@ enum ab9540_regulator_reg { AB9540_NUM_REGULATOR_REGISTERS, }; +struct ab8500_regulator_platform_data { + int num_reg_init; + struct ab8500_regulator_reg_init *reg_init; + int num_regulator; + struct regulator_init_data *regulator; +}; + #endif -- cgit v1.2.3 From 328a5369664d09e9082a8e814a9b2dcdfb7f519b Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 25 Mar 2013 14:53:50 +0800 Subject: regulator: ab8500: Fix build error Fix below build error: CC drivers/regulator/ab8500.o drivers/regulator/ab8500.c:500:23: error: 'ab8500_regulator_fixed_ops' undeclared here (not in a function) drivers/regulator/ab8500.c: In function 'ab8500_regulator_probe': drivers/regulator/ab8500.c:972:8: warning: assignment from incompatible pointer type [enabled by default] make[2]: *** [drivers/regulator/ab8500.o] Error 1 make[1]: *** [drivers/regulator] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index f7d1f538c200..a2d19c650f24 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -494,10 +494,14 @@ static struct ab8500_regulator_info .update_val_idle = 0x82, .update_val_normal = 0x02, }, + + /* + * Regulators with fixed voltage and normal mode + */ [AB8500_LDO_USB] = { .desc = { .name = "LDO-USB", - .ops = &ab8500_regulator_fixed_ops, + .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, .id = AB8500_LDO_USB, .owner = THIS_MODULE, @@ -508,10 +512,6 @@ static struct ab8500_regulator_info .update_reg = 0x82, .update_mask = 0x03, }, - - /* - * Regulators with fixed voltage and normal mode - */ [AB8500_LDO_AUDIO] = { .desc = { .name = "LDO-AUDIO", -- cgit v1.2.3 From 5689e830745b39dbab895e5e8df3f962cb7eecac Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 25 Mar 2013 14:59:00 +0800 Subject: regulator: ab8500: Use regulator_list_voltage_linear for fixed voltage Both ab8500_regulator_mode_ops and ab8500_regulator_ops do not have volt_table setting, thus we can not use regulator_list_voltage_table for them. However, they have min_uV setting with n_voltages = 1, so use regulator_list_voltage_linear instead. Also remove setting set_voltage_time_sel for ab8500_regulator_mode_ops. It is used only for fixed voltage, so it does not need to implement set_voltage_time_sel. Signed-off-by: Axel Lin Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index a2d19c650f24..12e274039ae1 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -363,8 +363,7 @@ static struct regulator_ops ab8500_regulator_mode_ops = { .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, + .list_voltage = regulator_list_voltage_linear, }; static struct regulator_ops ab8500_regulator_ops = { @@ -372,7 +371,7 @@ static struct regulator_ops ab8500_regulator_ops = { .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, .get_voltage_sel = ab8500_regulator_get_voltage_sel, - .list_voltage = regulator_list_voltage_table, + .list_voltage = regulator_list_voltage_linear, }; static struct ab8500_regulator_info -- cgit v1.2.3 From f71bf52808e7089a5a6df9b32ffa13e93e51f1ca Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 26 Mar 2013 16:13:14 +0800 Subject: regulator: ab8500: Don't update is_enabled flag in error paths This avoid setting is_enabled flag to wrong status if enable/disable fails. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 12e274039ae1..4a70323377d3 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -117,9 +117,11 @@ static int ab8500_regulator_enable(struct regulator_dev *rdev) ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, info->update_mask, info->update_val); - if (ret < 0) + if (ret < 0) { dev_err(rdev_get_dev(rdev), "couldn't set enable bits for regulator\n"); + return ret; + } info->is_enabled = true; @@ -144,9 +146,11 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, info->update_mask, 0x0); - if (ret < 0) + if (ret < 0) { dev_err(rdev_get_dev(rdev), "couldn't set disable bits for regulator\n"); + return ret; + } info->is_enabled = false; -- cgit v1.2.3 From 530158b6d2feeb227e0079c8826b4d2a42333e80 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 27 Mar 2013 17:47:22 +0800 Subject: regulator: ab8500: Add missing enable_time settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base on the data provide by Bengt Jönsson, add below enable_time settings: Worst case enable time from data sheet: Vana: enable time = 140 us Vaux1/2: enable time = 200 us Vaux3: enable time = 450 us Vintcore: enable time = 750 us Vamic1/2: enable time = 500 us Vdmic: enable time = 420 us VTVout: enable time = 500 us Vaudio: enable time = 140 us Vusb: enable time = 150 us This discussion thread is available at: https://lkml.org/lkml/2013/3/26/795 Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 4a70323377d3..d9443b9b384a 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -395,6 +395,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, + .enable_time = 200, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -416,6 +417,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, + .enable_time = 200, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -437,6 +439,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), .volt_table = ldo_vaux3_voltages, + .enable_time = 450, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -458,6 +461,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), .volt_table = ldo_vintcore_voltages, + .enable_time = 750, }, .load_lp_uA = 5000, .update_bank = 0x03, @@ -510,6 +514,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 3300000, + .enable_time = 150, }, .update_bank = 0x03, .update_reg = 0x82, @@ -524,6 +529,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 2000000, + .enable_time = 140, }, .update_bank = 0x03, .update_reg = 0x83, @@ -539,6 +545,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 2050000, + .enable_time = 500, }, .update_bank = 0x03, .update_reg = 0x83, @@ -554,6 +561,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 2050000, + .enable_time = 500, }, .update_bank = 0x03, .update_reg = 0x83, @@ -569,6 +577,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 1800000, + .enable_time = 420, }, .update_bank = 0x03, .update_reg = 0x83, @@ -588,6 +597,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 1200000, + .enable_time = 140, }, .load_lp_uA = 1000, .update_bank = 0x04, -- cgit v1.2.3 From 292349287f6dfedf0c1b6ae678cb508d9d63d7ac Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 27 Mar 2013 17:48:29 +0800 Subject: regulator: ab8500: Remove set_voltage_time_sel and delay setting The data sheet does not specify time delay for voltage selection, thus remove set_voltage_time_sel and delay setting. Note, currently set_voltage_time_sel callback returns 0 due to missing delay settings. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index d9443b9b384a..f1453a66a0fd 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -42,7 +42,6 @@ * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage * @voltage_shift: shift to control regulator voltage - * @delay: startup/set voltage delay in us */ struct ab8500_regulator_info { struct device *dev; @@ -60,7 +59,6 @@ struct ab8500_regulator_info { u8 voltage_reg; u8 voltage_mask; u8 voltage_shift; - unsigned int delay; }; /* voltage tables for the vauxn/vintcore supplies */ @@ -337,15 +335,6 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } -static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, - unsigned int old_sel, - unsigned int new_sel) -{ - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - - return info->delay; -} - static struct regulator_ops ab8500_regulator_volt_mode_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -356,7 +345,6 @@ static struct regulator_ops ab8500_regulator_volt_mode_ops = { .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, .list_voltage = regulator_list_voltage_table, - .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; static struct regulator_ops ab8500_regulator_mode_ops = { @@ -492,7 +480,6 @@ static struct ab8500_regulator_info .min_uV = 2000000, .enable_time = 10000, }, - .delay = 10000, .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x80, -- cgit v1.2.3 From 43a5911b3dcec81add87d833cd8c7ddaaa205a47 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Mar 2013 15:59:15 +0000 Subject: regulator: ab8500: Clean out SoC registers Clean out initialisation that is handled by SoC. Regulator settings for Vpll (partly), Vsmps1, Vsmps2, Vsmps3 (partly), Vrf1, Varm, Vape, Vbb, Vmod are cleaned out. They should not be touched by the kernel. We also update many of the initialisation values to be more in-line with the current development efforts of ST-Ericsson internal engineers. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500-regulators.c | 28 ++------ drivers/regulator/ab8500.c | 98 +++++++-------------------- include/linux/regulator/ab8500.h | 12 ---- 3 files changed, 28 insertions(+), 110 deletions(-) (limited to 'drivers/regulator') diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index c962d1d726bb..3d899c51bbac 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -139,10 +139,9 @@ static struct regulator_consumer_supply ab8500_vana_consumers[] = { static struct ab8500_regulator_reg_init ab8500_reg_init[] = { /* * VanaRequestCtrl = HP/LP depending on VxRequest - * VpllRequestCtrl = HP/LP depending on VxRequest * VextSupply1RequestCtrl = HP/LP depending on VxRequest */ - INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0xfc, 0x00), + INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0xf0, 0x00), /* * VextSupply2RequestCtrl = HP/LP depending on VxRequest * VextSupply3RequestCtrl = HP/LP depending on VxRequest @@ -156,16 +155,12 @@ static struct ab8500_regulator_reg_init ab8500_reg_init[] = { */ INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x07, 0x00), /* - * Vsmps1SysClkReq1HPValid = enabled - * Vsmps2SysClkReq1HPValid = enabled - * Vsmps3SysClkReq1HPValid = enabled * VanaSysClkReq1HPValid = disabled - * VpllSysClkReq1HPValid = enabled * Vaux1SysClkReq1HPValid = disabled * Vaux2SysClkReq1HPValid = disabled * Vaux3SysClkReq1HPValid = disabled */ - INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xff, 0x17), + INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00), /* * VextSupply1SysClkReq1HPValid = disabled * VextSupply2SysClkReq1HPValid = disabled @@ -252,17 +247,7 @@ static struct ab8500_regulator_reg_init ab8500_reg_init[] = { */ INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x03, 0x00), /* - * Vsmps1Regu = HW control - * Vsmps1SelCtrl = Vsmps1 voltage defined by Vsmsp1Sel2 - */ - INIT_REGULATOR_REGISTER(AB8500_VSMPS1REGU, 0x0f, 0x06), - /* - * Vsmps2Regu = HW control - * Vsmps2SelCtrl = Vsmps2 voltage defined by Vsmsp2Sel2 - */ - INIT_REGULATOR_REGISTER(AB8500_VSMPS2REGU, 0x0f, 0x06), - /* - * VPll = Hw controlled + * VPll = Hw controlled (NOTE! PRCMU bits) * VanaRegu = force off */ INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x0f, 0x02), @@ -285,14 +270,9 @@ static struct ab8500_regulator_reg_init ab8500_reg_init[] = { */ INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x0f, 0x01), /* - * Vrf1Regu = HW control * Vaux3Regu = force off */ - INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x0f, 0x08), - /* - * Vsmps1 = 1.15V - */ - INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x3f, 0x24), + INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x03, 0x00), /* * Vaux1Sel = 2.5 V */ diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index f1453a66a0fd..919d9fa9605e 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -613,19 +613,10 @@ struct ab8500_reg_init { static struct ab8500_reg_init ab8500_reg_init[] = { /* - * 0x03, VarmRequestCtrl - * 0x0c, VapeRequestCtrl - * 0x30, Vsmps1RequestCtrl - * 0xc0, Vsmps2RequestCtrl - */ - REG_INIT(AB8500_REGUREQUESTCTRL1, 0x03, 0x03, 0xff), - /* - * 0x03, Vsmps3RequestCtrl - * 0x0c, VpllRequestCtrl * 0x30, VanaRequestCtrl * 0xc0, VextSupply1RequestCtrl */ - REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xff), + REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xf0), /* * 0x03, VextSupply2RequestCtrl * 0x0c, VextSupply3RequestCtrl @@ -639,91 +630,74 @@ static struct ab8500_reg_init ab8500_reg_init[] = { */ REG_INIT(AB8500_REGUREQUESTCTRL4, 0x03, 0x06, 0x07), /* - * 0x01, Vsmps1SysClkReq1HPValid - * 0x02, Vsmps2SysClkReq1HPValid - * 0x04, Vsmps3SysClkReq1HPValid * 0x08, VanaSysClkReq1HPValid - * 0x10, VpllSysClkReq1HPValid * 0x20, Vaux1SysClkReq1HPValid * 0x40, Vaux2SysClkReq1HPValid * 0x80, Vaux3SysClkReq1HPValid */ - REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), + REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xe8), /* - * 0x01, VapeSysClkReq1HPValid - * 0x02, VarmSysClkReq1HPValid - * 0x04, VbbSysClkReq1HPValid - * 0x08, VmodSysClkReq1HPValid * 0x10, VextSupply1SysClkReq1HPValid * 0x20, VextSupply2SysClkReq1HPValid * 0x40, VextSupply3SysClkReq1HPValid */ - REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x7f), + REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x70), /* - * 0x01, Vsmps1HwHPReq1Valid - * 0x02, Vsmps2HwHPReq1Valid - * 0x04, Vsmps3HwHPReq1Valid * 0x08, VanaHwHPReq1Valid - * 0x10, VpllHwHPReq1Valid * 0x20, Vaux1HwHPReq1Valid * 0x40, Vaux2HwHPReq1Valid * 0x80, Vaux3HwHPReq1Valid */ - REG_INIT(AB8500_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff), + REG_INIT(AB8500_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xe8), /* * 0x01, VextSupply1HwHPReq1Valid * 0x02, VextSupply2HwHPReq1Valid * 0x04, VextSupply3HwHPReq1Valid - * 0x08, VmodHwHPReq1Valid */ - REG_INIT(AB8500_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x0f), + REG_INIT(AB8500_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x07), /* - * 0x01, Vsmps1HwHPReq2Valid - * 0x02, Vsmps2HwHPReq2Valid - * 0x03, Vsmps3HwHPReq2Valid * 0x08, VanaHwHPReq2Valid - * 0x10, VpllHwHPReq2Valid * 0x20, Vaux1HwHPReq2Valid * 0x40, Vaux2HwHPReq2Valid * 0x80, Vaux3HwHPReq2Valid */ - REG_INIT(AB8500_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff), + REG_INIT(AB8500_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xe8), /* * 0x01, VextSupply1HwHPReq2Valid * 0x02, VextSupply2HwHPReq2Valid * 0x04, VextSupply3HwHPReq2Valid - * 0x08, VmodHwHPReq2Valid */ - REG_INIT(AB8500_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x0f), + REG_INIT(AB8500_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x07), /* - * 0x01, VapeSwHPReqValid - * 0x02, VarmSwHPReqValid - * 0x04, Vsmps1SwHPReqValid - * 0x08, Vsmps2SwHPReqValid - * 0x10, Vsmps3SwHPReqValid * 0x20, VanaSwHPReqValid - * 0x40, VpllSwHPReqValid * 0x80, Vaux1SwHPReqValid */ - REG_INIT(AB8500_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff), + REG_INIT(AB8500_REGUSWHPREQVALID1, 0x03, 0x0d, 0xa0), /* * 0x01, Vaux2SwHPReqValid * 0x02, Vaux3SwHPReqValid * 0x04, VextSupply1SwHPReqValid * 0x08, VextSupply2SwHPReqValid * 0x10, VextSupply3SwHPReqValid - * 0x20, VmodSwHPReqValid */ - REG_INIT(AB8500_REGUSWHPREQVALID2, 0x03, 0x0e, 0x3f), + REG_INIT(AB8500_REGUSWHPREQVALID2, 0x03, 0x0e, 0x1f), /* * 0x02, SysClkReq2Valid1 - * ... + * 0x04, SysClkReq3Valid1 + * 0x08, SysClkReq4Valid1 + * 0x10, SysClkReq5Valid1 + * 0x20, SysClkReq6Valid1 + * 0x40, SysClkReq7Valid1 * 0x80, SysClkReq8Valid1 */ REG_INIT(AB8500_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0xfe), /* * 0x02, SysClkReq2Valid2 - * ... + * 0x04, SysClkReq3Valid2 + * 0x08, SysClkReq4Valid2 + * 0x10, SysClkReq5Valid2 + * 0x20, SysClkReq6Valid2 + * 0x40, SysClkReq7Valid2 * 0x80, SysClkReq8Valid2 */ REG_INIT(AB8500_REGUSYSCLKREQVALID2, 0x03, 0x10, 0xfe), @@ -748,21 +722,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = { */ REG_INIT(AB8500_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), /* - * 0x03, Vsmps1Regu - * 0x0c, Vsmps1SelCtrl - * 0x10, Vsmps1AutoMode - * 0x20, Vsmps1PWMMode - */ - REG_INIT(AB8500_VSMPS1REGU, 0x04, 0x03, 0x3f), - /* - * 0x03, Vsmps2Regu - * 0x0c, Vsmps2SelCtrl - * 0x10, Vsmps2AutoMode - * 0x20, Vsmps2PWMMode - */ - REG_INIT(AB8500_VSMPS2REGU, 0x04, 0x04, 0x3f), - /* - * 0x03, VpllRegu + * 0x03, VpllRegu (NOTE! PRCMU register bits) * 0x0c, VanaRegu */ REG_INIT(AB8500_VPLLVANAREGU, 0x04, 0x06, 0x0f), @@ -785,14 +745,9 @@ static struct ab8500_reg_init ab8500_reg_init[] = { */ REG_INIT(AB8500_VAUX12REGU, 0x04, 0x09, 0x0f), /* - * 0x0c, Vrf1Regu * 0x03, Vaux3Regu */ - REG_INIT(AB8500_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f), - /* - * 0x3f, Vsmps1Sel1 - */ - REG_INIT(AB8500_VSMPS1SEL1, 0x04, 0x13, 0x3f), + REG_INIT(AB8500_VRF1VAUX3REGU, 0x04, 0x0a, 0x03), /* * 0x0f, Vaux1Sel */ @@ -803,16 +758,13 @@ static struct ab8500_reg_init ab8500_reg_init[] = { REG_INIT(AB8500_VAUX2SEL, 0x04, 0x20, 0x0f), /* * 0x07, Vaux3Sel - * 0x30, Vrf1Sel */ - REG_INIT(AB8500_VRF1VAUX3SEL, 0x04, 0x21, 0x37), + REG_INIT(AB8500_VRF1VAUX3SEL, 0x04, 0x21, 0x07), /* * 0x01, VextSupply12LP */ REG_INIT(AB8500_REGUCTRL2SPARE, 0x04, 0x22, 0x01), /* - * 0x01, VpllDisch - * 0x02, Vrf1Disch * 0x04, Vaux1Disch * 0x08, Vaux2Disch * 0x10, Vaux3Disch @@ -820,15 +772,13 @@ static struct ab8500_reg_init ab8500_reg_init[] = { * 0x40, VTVoutDisch * 0x80, VaudioDisch */ - REG_INIT(AB8500_REGUCTRLDISCH, 0x04, 0x43, 0xff), + REG_INIT(AB8500_REGUCTRLDISCH, 0x04, 0x43, 0xfc), /* - * 0x01, VsimDisch * 0x02, VanaDisch * 0x04, VdmicPullDownEna - * 0x08, VpllPullDownEna * 0x10, VdmicDisch */ - REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x1f), + REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16), }; static int ab8500_regulator_init_registers(struct platform_device *pdev, diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 3a8e02687f7b..26792ff360be 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -61,7 +61,6 @@ struct ab8500_regulator_reg_init { /* AB8500 registers */ enum ab8500_regulator_reg { - AB8500_REGUREQUESTCTRL1, AB8500_REGUREQUESTCTRL2, AB8500_REGUREQUESTCTRL3, AB8500_REGUREQUESTCTRL4, @@ -78,22 +77,11 @@ enum ab8500_regulator_reg { AB8500_REGUMISC1, AB8500_VAUDIOSUPPLY, AB8500_REGUCTRL1VAMIC, - AB8500_VSMPS1REGU, - AB8500_VSMPS2REGU, - AB8500_VSMPS3REGU, /* NOTE! PRCMU register */ AB8500_VPLLVANAREGU, AB8500_VREFDDR, AB8500_EXTSUPPLYREGU, AB8500_VAUX12REGU, AB8500_VRF1VAUX3REGU, - AB8500_VSMPS1SEL1, - AB8500_VSMPS1SEL2, - AB8500_VSMPS1SEL3, - AB8500_VSMPS2SEL1, - AB8500_VSMPS2SEL2, - AB8500_VSMPS2SEL3, - AB8500_VSMPS3SEL1, /* NOTE! PRCMU register */ - AB8500_VSMPS3SEL2, /* NOTE! PRCMU register */ AB8500_VAUX1SEL, AB8500_VAUX2SEL, AB8500_VRF1VAUX3SEL, -- cgit v1.2.3 From cc40dc2981396748ebcdde4a313d65ba26b0159d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 21 Mar 2013 15:59:41 +0000 Subject: regulator: ab8500: Amend the update value for AB8500_LDO_INTCORE regulator The issues probably originated from a typo in the initial submission. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 919d9fa9605e..3a1896655557 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -455,7 +455,7 @@ static struct ab8500_regulator_info .update_bank = 0x03, .update_reg = 0x80, .update_mask = 0x44, - .update_val = 0x04, + .update_val = 0x44, .update_val_idle = 0x44, .update_val_normal = 0x04, .voltage_bank = 0x03, -- cgit v1.2.3 From d1a820011b2fbc11d5af80d1a961fe66c613fa4b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:01 +0000 Subject: regulator: ab8500-ext: New driver to control external regulators The ABx500 is capable of controlling three external regulator supplies. Most commonly on and off are supported, but if an external regulator chipset or power supply supports high-power and low-power mode settings, we can control those too. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/Makefile | 2 +- drivers/regulator/ab8500-ext.c | 394 +++++++++++++++++++++++++++++++++++++++ drivers/regulator/ab8500.c | 12 +- include/linux/regulator/ab8500.h | 28 +++ 4 files changed, 434 insertions(+), 2 deletions(-) create mode 100644 drivers/regulator/ab8500-ext.c (limited to 'drivers/regulator') diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 6e8250382def..47a34ff88f98 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o -obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o +obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o ab8500-ext.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c new file mode 100644 index 000000000000..95008dec5190 --- /dev/null +++ b/drivers/regulator/ab8500-ext.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * + * Authors: Bengt Jonsson + * + * This file is based on drivers/regulator/ab8500.c + * + * AB8500 external regulators + * + * ab8500-ext supports the following regulators: + * - VextSupply3 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct ab8500_ext_regulator_info - ab8500 regulator information + * @dev: device pointer + * @desc: regulator description + * @rdev: regulator device + * @is_enabled: status of regulator (on/off) + * @update_bank: bank to control on/off + * @update_reg: register to control on/off + * @update_mask: mask to enable/disable and set mode of regulator + * @update_val: bits holding the regulator current mode + * @update_val_en: bits to set EN pin active (LPn pin deactive) + * normally this means high power mode + * @update_val_en_lp: bits to set EN pin active and LPn pin active + * normally this means low power mode + * @delay: startup delay in ms + */ +struct ab8500_ext_regulator_info { + struct device *dev; + struct regulator_desc desc; + struct regulator_dev *rdev; + bool is_enabled; + u8 update_bank; + u8 update_reg; + u8 update_mask; + u8 update_val; + u8 update_val_en; + u8 update_val_en_lp; +}; + +static int ab8500_ext_regulator_enable(struct regulator_dev *rdev) +{ + int ret; + struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->update_bank, info->update_reg, + info->update_mask, info->update_val); + if (ret < 0) + dev_err(rdev_get_dev(info->rdev), + "couldn't set enable bits for regulator\n"); + + info->is_enabled = true; + + dev_dbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value):" + " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + info->desc.name, info->update_bank, info->update_reg, + info->update_mask, info->update_val); + + return ret; +} + +static int ab8500_ext_regulator_disable(struct regulator_dev *rdev) +{ + int ret; + struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->update_bank, info->update_reg, + info->update_mask, 0x0); + if (ret < 0) + dev_err(rdev_get_dev(info->rdev), + "couldn't set disable bits for regulator\n"); + + info->is_enabled = false; + + dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):" + " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + info->desc.name, info->update_bank, info->update_reg, + info->update_mask, 0x0); + + return ret; +} + +static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev) +{ + int ret; + struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + ret = abx500_get_register_interruptible(info->dev, + info->update_bank, info->update_reg, ®val); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't read 0x%x register\n", info->update_reg); + return ret; + } + + dev_dbg(rdev_get_dev(rdev), "%s-is_enabled (bank, reg, mask, value):" + " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + info->desc.name, info->update_bank, info->update_reg, + info->update_mask, regval); + + if (regval & info->update_mask) + info->is_enabled = true; + else + info->is_enabled = false; + + return info->is_enabled; +} + +static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + int ret = 0; + struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + switch (mode) { + case REGULATOR_MODE_NORMAL: + info->update_val = info->update_val_hp; + break; + case REGULATOR_MODE_IDLE: + info->update_val = info->update_val_lp; + break; + + default: + return -EINVAL; + } + + if (info->is_enabled) { + u8 regval; + + ret = enable(info, ®val); + if (ret < 0) + dev_err(rdev_get_dev(rdev), + "Could not set regulator mode.\n"); + + dev_dbg(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, regval); + } + + return ret; +} + +static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev) +{ + struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + int ret; + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + if (info->update_val == info->update_val_hp) + ret = REGULATOR_MODE_NORMAL; + else if (info->update_val == info->update_val_lp) + ret = REGULATOR_MODE_IDLE; + else + ret = -EINVAL; + + return ret; +} + +static int ab8500_ext_fixed_get_voltage(struct regulator_dev *rdev) +{ + struct regulation_constraints *regu_constraints = rdev->constraints; + + if (regu_constraints == NULL) { + dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n"); + return -EINVAL; + } + if (regu_constraints->min_uV && regu_constraints->max_uV) { + if (regu_constraints->min_uV == regu_constraints->max_uV) + return regu_constraints->min_uV; + } + return -EINVAL; +} + +static int ab8500_ext_list_voltage(struct regulator_dev *rdev, + unsigned selector) +{ + struct regulation_constraints *regu_constraints = rdev->constraints; + + if (regu_constraints == NULL) { + dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n"); + return -EINVAL; + } + /* return the uV for the fixed regulators */ + if (regu_constraints->min_uV && regu_constraints->max_uV) { + if (regu_constraints->min_uV == regu_constraints->max_uV) + return regu_constraints->min_uV; + } + return -EINVAL; +} + +static struct regulator_ops ab8500_ext_regulator_ops = { + .enable = ab8500_ext_regulator_enable, + .disable = ab8500_ext_regulator_disable, + .is_enabled = ab8500_ext_regulator_is_enabled, + .set_mode = ab8500_ext_regulator_set_mode, + .get_mode = ab8500_ext_regulator_get_mode, + .get_voltage = ab8500_ext_fixed_get_voltage, + .list_voltage = ab8500_ext_list_voltage, +}; + + +static struct ab8500_ext_regulator_info + ab8500_ext_regulator_info[AB8500_NUM_EXT_REGULATORS] = { + [AB8500_EXT_SUPPLY1] = { + .desc = { + .name = "VEXTSUPPLY1", + .ops = &ab8500_ext_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_EXT_SUPPLY1, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .update_bank = 0x04, + .update_reg = 0x08, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_hp = 0x01, + .update_val_lp = 0x03, + .update_val_hw = 0x02, + }, + [AB8500_EXT_SUPPLY2] = { + .desc = { + .name = "VEXTSUPPLY2", + .ops = &ab8500_ext_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_EXT_SUPPLY2, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .update_bank = 0x04, + .update_reg = 0x08, + .update_mask = 0x0c, + .update_val = 0x04, + .update_val_hp = 0x04, + .update_val_lp = 0x0c, + .update_val_hw = 0x08, + }, + [AB8500_EXT_SUPPLY3] = { + .desc = { + .name = "VEXTSUPPLY3", + .ops = &ab8500_ext_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_EXT_SUPPLY3, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .update_bank = 0x04, + .update_reg = 0x08, + .update_mask = 0x30, + .update_val = 0x10, + .update_val_en = 0x10, + .update_val_en_lp = 0x30, + }, +}; + +int ab8500_ext_regulator_init(struct platform_device *pdev) +{ + struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); + struct ab8500_platform_data *ppdata; + struct ab8500_regulator_platform_data *pdata; + struct regulator_config config = { }; + int i, err; + + if (!ab8500) { + dev_err(&pdev->dev, "null mfd parent\n"); + return -EINVAL; + } + ppdata = dev_get_platdata(ab8500->dev); + if (!ppdata) { + dev_err(&pdev->dev, "null parent pdata\n"); + return -EINVAL; + } + + pdata = ppdata->regulator; + if (!pdata) { + dev_err(&pdev->dev, "null pdata\n"); + return -EINVAL; + } + + /* make sure the platform data has the correct size */ + if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) { + dev_err(&pdev->dev, "Configuration error: size mismatch.\n"); + return -EINVAL; + } + + /* check for AB8500 2.x */ + if (abx500_get_chip_id(&pdev->dev) < 0x30) { + struct ab8500_ext_regulator_info *info; + + /* VextSupply3LPn is inverted on AB8500 2.x */ + info = &ab8500_ext_regulator_info[AB8500_EXT_SUPPLY3]; + info->update_val = 0x30; + info->update_val_en = 0x30; + info->update_val_en_lp = 0x10; + } + + /* register all regulators */ + for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) { + struct ab8500_ext_regulator_info *info = NULL; + + /* assign per-regulator data */ + info = &ab8500_ext_regulator_info[i]; + info->dev = &pdev->dev; + + config.dev = &pdev->dev; + config.init_data = &pdata->ext_regulator[i]; + config.driver_data = info; + + /* register regulator with framework */ + info->rdev = regulator_register(&info->desc, &config); + + if (IS_ERR(info->rdev)) { + err = PTR_ERR(info->rdev); + dev_err(&pdev->dev, "failed to register regulator %s\n", + info->desc.name); + /* when we fail, un-register all earlier regulators */ + while (--i >= 0) { + info = &ab8500_ext_regulator_info[i]; + regulator_unregister(info->rdev); + } + return err; + } + + dev_dbg(rdev_get_dev(info->rdev), + "%s-probed\n", info->desc.name); + } + + return 0; +} + +int ab8500_ext_regulator_exit(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) { + struct ab8500_ext_regulator_info *info = NULL; + info = &ab8500_ext_regulator_info[i]; + + dev_vdbg(rdev_get_dev(info->rdev), + "%s-remove\n", info->desc.name); + + regulator_unregister(info->rdev); + } + + return 0; +} + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Bengt Jonsson "); +MODULE_DESCRIPTION("AB8500 external regulator driver"); +MODULE_ALIAS("platform:ab8500-ext-regulator"); diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 3a1896655557..49746884923d 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -947,6 +947,11 @@ static int ab8500_regulator_probe(struct platform_device *pdev) return err; } + /* register external regulators (before Vaux1, 2 and 3) */ + err = ab8500_ext_regulator_init(pdev); + if (err) + return err; + /* register all regulators */ for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL); @@ -959,7 +964,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev) static int ab8500_regulator_remove(struct platform_device *pdev) { - int i; + int i, err; for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { struct ab8500_regulator_info *info = NULL; @@ -971,6 +976,11 @@ static int ab8500_regulator_remove(struct platform_device *pdev) regulator_unregister(info->regulator); } + /* remove external regulators (after Vaux1, 2 and 3) */ + err = ab8500_ext_regulator_exit(pdev); + if (err) + return err; + return 0; } diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 26792ff360be..4e92e5b879a5 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -10,6 +10,8 @@ #ifndef __LINUX_MFD_AB8500_REGULATOR_H #define __LINUX_MFD_AB8500_REGULATOR_H +#include + /* AB8500 regulators */ enum ab8500_regulator_id { AB8500_LDO_AUX1, @@ -140,11 +142,37 @@ enum ab9540_regulator_reg { AB9540_NUM_REGULATOR_REGISTERS, }; +/* AB8500 external regulators */ +enum ab8500_ext_regulator_id { + AB8500_EXT_SUPPLY1, + AB8500_EXT_SUPPLY2, + AB8500_EXT_SUPPLY3, + AB8500_NUM_EXT_REGULATORS, +}; + +/* AB8500 regulator platform data */ struct ab8500_regulator_platform_data { int num_reg_init; struct ab8500_regulator_reg_init *reg_init; int num_regulator; struct regulator_init_data *regulator; + int num_ext_regulator; + struct regulator_init_data *ext_regulator; }; +/* AB8500 external regulator functions (internal) */ +#ifdef CONFIG_REGULATOR_AB8500_EXT +int ab8500_ext_regulator_init(struct platform_device *pdev); +int ab8500_ext_regulator_exit(struct platform_device *pdev); +#else +inline int ab8500_ext_regulator_init(struct platform_device *pdev) +{ + return 0; +} +inline int ab8500_ext_regulator_exit(struct platform_device *pdev) +{ + return 0; +} +#endif + #endif -- cgit v1.2.3 From 18bc2b39307b45527efc6c84836953c7a8f2181e Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Thu, 28 Mar 2013 16:11:06 +0000 Subject: regulator: ab8500-ext: Add HW request support Support for HW request is added in the external regulator driver. A flag in the board configuration can be set to let HW control the regulator when there is no SW request. This means that the regulator will be put in high power mode when there is a SW request and in HW-request mode otherwise. Signed-off-by: Bengt Jonsson Signed-off-by: Lee Jones Reviewed-by: Mattias NILSSON Reviewed-by: Jonas ABERG Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 98 +++++++++++++++++++++++++++++----------- include/linux/regulator/ab8500.h | 4 ++ 2 files changed, 75 insertions(+), 27 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 95008dec5190..21b9bfb0fc5e 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -28,80 +28,121 @@ * @dev: device pointer * @desc: regulator description * @rdev: regulator device + * @cfg: regulator configuration (extension of regulator FW configuration) * @is_enabled: status of regulator (on/off) * @update_bank: bank to control on/off * @update_reg: register to control on/off * @update_mask: mask to enable/disable and set mode of regulator * @update_val: bits holding the regulator current mode - * @update_val_en: bits to set EN pin active (LPn pin deactive) + * @update_val_hp: bits to set EN pin active (LPn pin deactive) * normally this means high power mode - * @update_val_en_lp: bits to set EN pin active and LPn pin active - * normally this means low power mode - * @delay: startup delay in ms + * @update_val_lp: bits to set EN pin active and LPn pin active + * normally this means low power mode + * @update_val_hw: bits to set regulator pins in HW control + * SysClkReq pins and logic will choose mode */ struct ab8500_ext_regulator_info { struct device *dev; struct regulator_desc desc; struct regulator_dev *rdev; + struct ab8500_ext_regulator_cfg *cfg; bool is_enabled; u8 update_bank; u8 update_reg; u8 update_mask; u8 update_val; - u8 update_val_en; - u8 update_val_en_lp; + u8 update_val_hp; + u8 update_val_lp; + u8 update_val_hw; }; -static int ab8500_ext_regulator_enable(struct regulator_dev *rdev) +static int enable(struct ab8500_ext_regulator_info *info, u8 *regval) { int ret; - struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } + *regval = info->update_val; + + /* + * To satisfy both HW high power request and SW request, the regulator + * must be on in high power. + */ + if (info->cfg && info->cfg->hwreq) + *regval = info->update_val_hp; ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, - info->update_mask, info->update_val); + info->update_mask, *regval); if (ret < 0) dev_err(rdev_get_dev(info->rdev), "couldn't set enable bits for regulator\n"); info->is_enabled = true; - dev_dbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value):" - " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - info->desc.name, info->update_bank, info->update_reg, - info->update_mask, info->update_val); - return ret; } -static int ab8500_ext_regulator_disable(struct regulator_dev *rdev) +static int ab8500_ext_regulator_enable(struct regulator_dev *rdev) { int ret; struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; if (info == NULL) { dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); return -EINVAL; } + ret = enable(info, ®val); + + dev_dbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value):" + " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + info->desc.name, info->update_bank, info->update_reg, + info->update_mask, regval); + + return ret; +} + +static int disable(struct ab8500_ext_regulator_info *info, u8 *regval) +{ + int ret; + + *regval = 0x0; + + /* + * Set the regulator in HW request mode if configured + */ + if (info->cfg && info->cfg->hwreq) + *regval = info->update_val_hw; + ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, - info->update_mask, 0x0); + info->update_mask, *regval); if (ret < 0) dev_err(rdev_get_dev(info->rdev), "couldn't set disable bits for regulator\n"); info->is_enabled = false; + return ret; +} + +static int ab8500_ext_regulator_disable(struct regulator_dev *rdev) +{ + int ret; + struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + ret = disable(info, ®val); + dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):" " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", info->desc.name, info->update_bank, info->update_reg, - info->update_mask, 0x0); + info->update_mask, regval); return ret; } @@ -130,7 +171,8 @@ static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev) info->desc.name, info->update_bank, info->update_reg, info->update_mask, regval); - if (regval & info->update_mask) + if (((regval & info->update_mask) == info->update_val_lp) || + ((regval & info->update_mask) == info->update_val_hp)) info->is_enabled = true; else info->is_enabled = false; @@ -241,7 +283,6 @@ static struct regulator_ops ab8500_ext_regulator_ops = { .list_voltage = ab8500_ext_list_voltage, }; - static struct ab8500_ext_regulator_info ab8500_ext_regulator_info[AB8500_NUM_EXT_REGULATORS] = { [AB8500_EXT_SUPPLY1] = { @@ -291,8 +332,9 @@ static struct ab8500_ext_regulator_info .update_reg = 0x08, .update_mask = 0x30, .update_val = 0x10, - .update_val_en = 0x10, - .update_val_en_lp = 0x30, + .update_val_hp = 0x10, + .update_val_lp = 0x30, + .update_val_hw = 0x20, }, }; @@ -333,8 +375,8 @@ int ab8500_ext_regulator_init(struct platform_device *pdev) /* VextSupply3LPn is inverted on AB8500 2.x */ info = &ab8500_ext_regulator_info[AB8500_EXT_SUPPLY3]; info->update_val = 0x30; - info->update_val_en = 0x30; - info->update_val_en_lp = 0x10; + info->update_val_hp = 0x30; + info->update_val_lp = 0x10; } /* register all regulators */ @@ -344,6 +386,8 @@ int ab8500_ext_regulator_init(struct platform_device *pdev) /* assign per-regulator data */ info = &ab8500_ext_regulator_info[i]; info->dev = &pdev->dev; + info->cfg = (struct ab8500_ext_regulator_cfg *) + pdata->ext_regulator[i].driver_data; config.dev = &pdev->dev; config.init_data = &pdata->ext_regulator[i]; diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 4e92e5b879a5..cf496e93c0cf 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -143,6 +143,10 @@ enum ab9540_regulator_reg { }; /* AB8500 external regulators */ +struct ab8500_ext_regulator_cfg { + bool hwreq; /* requires hw mode or high power mode */ +}; + enum ab8500_ext_regulator_id { AB8500_EXT_SUPPLY1, AB8500_EXT_SUPPLY2, -- cgit v1.2.3 From 41a06aa738ad889cf96f56024ddf84ecf4a18a6f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:08 +0000 Subject: regulator: ab8500: Remove USB regulator The USB regulator is controlled by hardware. The software support was only needed for early hardware (ED) which is no longer supported. Signed-off-by: Bengt Jonsson Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 20 -------------------- include/linux/regulator/ab8500.h | 1 - 2 files changed, 21 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 49746884923d..4d88a604efd1 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -488,25 +488,6 @@ static struct ab8500_regulator_info .update_val_idle = 0x82, .update_val_normal = 0x02, }, - - /* - * Regulators with fixed voltage and normal mode - */ - [AB8500_LDO_USB] = { - .desc = { - .name = "LDO-USB", - .ops = &ab8500_regulator_ops, - .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_USB, - .owner = THIS_MODULE, - .n_voltages = 1, - .min_uV = 3300000, - .enable_time = 150, - }, - .update_bank = 0x03, - .update_reg = 0x82, - .update_mask = 0x03, - }, [AB8500_LDO_AUDIO] = { .desc = { .name = "LDO-AUDIO", @@ -862,7 +843,6 @@ static struct of_regulator_match ab8500_regulator_matches[] = { { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8500_LDO_AUX3, }, { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8500_LDO_INTCORE, }, { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB8500_LDO_TVOUT, }, - { .name = "ab8500_ldo_usb", .driver_data = (void *) AB8500_LDO_USB, }, { .name = "ab8500_ldo_audio", .driver_data = (void *) AB8500_LDO_AUDIO, }, { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB8500_LDO_ANAMIC1, }, { .name = "ab8500_ldo_amamic2", .driver_data = (void *) AB8500_LDO_ANAMIC2, }, diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index cf496e93c0cf..b86e089195ea 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -19,7 +19,6 @@ enum ab8500_regulator_id { AB8500_LDO_AUX3, AB8500_LDO_INTCORE, AB8500_LDO_TVOUT, - AB8500_LDO_USB, AB8500_LDO_AUDIO, AB8500_LDO_ANAMIC1, AB8500_LDO_ANAMIC2, -- cgit v1.2.3 From da0b0c47dcfd92317e2ece4c3434e1f82b55cf8a Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:09 +0000 Subject: regulator: ab8500: Init debug from regulator driver The purpose of this patch is to guarantee that ab8500-debug will record the regulator registers before they are modified by the ab8500 regulator driver. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 10 ++++++++++ include/linux/regulator/ab8500.h | 14 ++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 4d88a604efd1..bf34c4cd6631 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -911,6 +911,11 @@ static int ab8500_regulator_probe(struct platform_device *pdev) return -EINVAL; } + /* initialize debug (initial state is recorded with this call) */ + err = ab8500_regulator_debug_init(pdev); + if (err) + return err; + /* initialize registers */ for (i = 0; i < pdata->num_reg_init; i++) { int id, mask, value; @@ -961,6 +966,11 @@ static int ab8500_regulator_remove(struct platform_device *pdev) if (err) return err; + /* remove regulator debug */ + err = ab8500_regulator_debug_exit(pdev); + if (err) + return err; + return 0; } diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index b86e089195ea..592a3f3994c0 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -178,4 +178,18 @@ inline int ab8500_ext_regulator_exit(struct platform_device *pdev) } #endif +#ifdef CONFIG_REGULATOR_AB8500_DEBUG +int ab8500_regulator_debug_init(struct platform_device *pdev); +int ab8500_regulator_debug_exit(struct platform_device *pdev); +#else +static inline int ab8500_regulator_debug_init(struct platform_device *pdev) +{ + return 0; +} +static inline int ab8500_regulator_debug_exit(struct platform_device *pdev) +{ + return 0; +} +#endif + #endif -- cgit v1.2.3 From 742a73259d2d07ad6870736749aa8d6821ed96d9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 28 Mar 2013 17:23:00 +0800 Subject: regulator: ab8500: Update info->update_val only when successfully update register Don't update info->update_val if write to the register fails. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index bf34c4cd6631..c7b433a2a3a9 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -184,8 +184,8 @@ static unsigned int ab8500_regulator_get_optimum_mode( static int ab8500_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { - int ret = 0; - + int ret; + u8 update_val; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); if (info == NULL) { @@ -195,31 +195,42 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_NORMAL: - info->update_val = info->update_val_normal; + update_val = info->update_val_normal; break; case REGULATOR_MODE_IDLE: - info->update_val = info->update_val_idle; + update_val = info->update_val_idle; break; default: return -EINVAL; } + /* ab8500 regulators share mode and enable in the same register bits. + off = 0b00 + low power mode= 0b11 + full powermode = 0b01 + (HW control mode = 0b10) + Thus we don't write to the register when regulator is disabled. + */ if (info->is_enabled) { ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, - info->update_mask, info->update_val); - if (ret < 0) + info->update_mask, update_val); + if (ret < 0) { dev_err(rdev_get_dev(rdev), "couldn't set regulator mode\n"); + return ret; + } 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); + info->update_mask, update_val); } - return ret; + info->update_val = update_val; + + return 0; } static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) -- cgit v1.2.3 From b54969ac406f0765989619469d74d79496431624 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:10 +0000 Subject: regulator: ab8500: Prepare the driver for additional platforms More platforms are to be supported by the AB8500 regulator driver, so in this patch we prepare for their arrival. Instead of using the AB8500 settings blindly, we provide an infrastructure where adding a new platform is as easy as providing a couple of platform specific data structures. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 76 ++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 27 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index c7b433a2a3a9..7ccd7fedea91 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -774,46 +774,47 @@ static struct ab8500_reg_init ab8500_reg_init[] = { }; static int ab8500_regulator_init_registers(struct platform_device *pdev, + struct ab8500_reg_init *reg_init, int id, int mask, int value) { int err; BUG_ON(value & ~mask); - BUG_ON(mask & ~ab8500_reg_init[id].mask); + BUG_ON(mask & ~reg_init[id].mask); /* initialize register */ err = abx500_mask_and_set_register_interruptible( &pdev->dev, - ab8500_reg_init[id].bank, - ab8500_reg_init[id].addr, + reg_init[id].bank, + reg_init[id].addr, mask, value); if (err < 0) { dev_err(&pdev->dev, "Failed to initialize 0x%02x, 0x%02x.\n", - ab8500_reg_init[id].bank, - ab8500_reg_init[id].addr); + reg_init[id].bank, + reg_init[id].addr); return err; } dev_vdbg(&pdev->dev, " init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - ab8500_reg_init[id].bank, - ab8500_reg_init[id].addr, + reg_init[id].bank, + reg_init[id].addr, mask, value); return 0; } static int ab8500_regulator_register(struct platform_device *pdev, - struct regulator_init_data *init_data, - int id, - struct device_node *np) + struct regulator_init_data *init_data, + struct ab8500_regulator_info *regulator_info, + int id, struct device_node *np) { struct ab8500_regulator_info *info = NULL; struct regulator_config config = { }; int err; /* assign per-regulator data */ - info = &ab8500_regulator_info[id]; + info = ®ulator_info[id]; info->dev = &pdev->dev; config.dev = &pdev->dev; @@ -839,7 +840,7 @@ static int ab8500_regulator_register(struct platform_device *pdev, info->desc.name); /* when we fail, un-register all earlier regulators */ while (--id >= 0) { - info = &ab8500_regulator_info[id]; + info = ®ulator_info[id]; regulator_unregister(info->regulator); } return err; @@ -848,7 +849,7 @@ static int ab8500_regulator_register(struct platform_device *pdev, return 0; } -static struct of_regulator_match ab8500_regulator_matches[] = { +static struct of_regulator_match ab8500_regulator_match[] = { { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8500_LDO_AUX1, }, { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8500_LDO_AUX2, }, { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8500_LDO_AUX3, }, @@ -862,14 +863,18 @@ static struct of_regulator_match ab8500_regulator_matches[] = { }; static int -ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np) +ab8500_regulator_of_probe(struct platform_device *pdev, + struct ab8500_regulator_info *regulator_info, + int regulator_info_size, + struct of_regulator_match *match, + struct device_node *np) { int err, i; - for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { + for (i = 0; i < regulator_info_size; i++) { err = ab8500_regulator_register( - pdev, ab8500_regulator_matches[i].init_data, - i, ab8500_regulator_matches[i].of_node); + pdev, match[i].init_data, regulator_info, + i, match[i].of_node); if (err) return err; } @@ -881,21 +886,32 @@ static int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct device_node *np = pdev->dev.of_node; + struct of_regulator_match *match; struct ab8500_platform_data *ppdata; struct ab8500_regulator_platform_data *pdata; int i, err; + struct ab8500_regulator_info *regulator_info; + int regulator_info_size; + struct ab8500_reg_init *reg_init; + int reg_init_size; + + regulator_info = ab8500_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); + reg_init = ab8500_reg_init; + reg_init_size = AB8500_NUM_REGULATOR_REGISTERS; + match = ab8500_regulator_match; + match_size = ARRAY_SIZE(ab8500_regulator_match) if (np) { - err = of_regulator_match(&pdev->dev, np, - ab8500_regulator_matches, - ARRAY_SIZE(ab8500_regulator_matches)); + err = of_regulator_match(&pdev->dev, np, match, match_size); if (err < 0) { dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", err); return err; } - err = ab8500_regulator_of_probe(pdev, np); + err = ab8500_regulator_of_probe(pdev, regulator_info, + regulator_info_size, match, np); return err; } @@ -917,7 +933,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev) } /* make sure the platform data has the correct size */ - if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) { + if (pdata->num_regulator != regulator_info_size) { dev_err(&pdev->dev, "Configuration error: size mismatch.\n"); return -EINVAL; } @@ -938,7 +954,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev) /* check for configuration errors */ BUG_ON(id >= AB8500_NUM_REGULATOR_REGISTERS); - err = ab8500_regulator_init_registers(pdev, id, mask, value); + err = ab8500_regulator_init_registers(pdev, reg_init, id, mask, value); if (err < 0) return err; } @@ -949,8 +965,9 @@ static int ab8500_regulator_probe(struct platform_device *pdev) return err; /* register all regulators */ - for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { - err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL); + for (i = 0; i < regulator_info_size; i++) { + err = ab8500_regulator_register(pdev, &pdata->regulator[i], + regulator_info, i, NULL); if (err < 0) return err; } @@ -961,10 +978,15 @@ static int ab8500_regulator_probe(struct platform_device *pdev) static int ab8500_regulator_remove(struct platform_device *pdev) { int i, err; + struct ab8500_regulator_info *regulator_info; + int regulator_info_size; - for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) { + regulator_info = ab8500_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); + + for (i = 0; i < regulator_info_size; i++) { struct ab8500_regulator_info *info = NULL; - info = &ab8500_regulator_info[i]; + info = ®ulator_info[i]; dev_vdbg(rdev_get_dev(info->regulator), "%s-remove\n", info->desc.name); -- cgit v1.2.3 From 8e6a8d7d23f904fb86686bcb835af971b68ae4b8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:11 +0000 Subject: regulator: ab8500: Add support for the ab9540 To obtain full AB9540 regulator support, the AB8500 regulator driver first needs to know its register layout and their initialisation values for each. That information is provided via a couple of large data structures which we provide here. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 582 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 573 insertions(+), 9 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 7ccd7fedea91..4d4d9dc33576 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -377,6 +377,7 @@ static struct regulator_ops ab8500_regulator_ops = { .list_voltage = regulator_list_voltage_linear, }; +/* AB8500 regulator information */ static struct ab8500_regulator_info ab8500_regulator_info[AB8500_NUM_REGULATORS] = { /* @@ -586,8 +587,264 @@ static struct ab8500_regulator_info .update_val_idle = 0x0c, .update_val_normal = 0x04, }, +}; +/* AB9540 regulator information */ +static struct ab8500_regulator_info + ab9540_regulator_info[AB9540_NUM_REGULATORS] = { + /* + * Variable Voltage Regulators + * name, min mV, max mV, + * update bank, reg, mask, enable val + * volt bank, reg, mask, table, table length + */ + [AB9540_LDO_AUX1] = { + .desc = { + .name = "LDO-AUX1", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX1, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x09, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x1f, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB9540_LDO_AUX2] = { + .desc = { + .name = "LDO-AUX2", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX2, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x09, + .update_mask = 0x0c, + .update_val = 0x04, + .update_val_idle = 0x0c, + .update_val_normal = 0x04, + .voltage_bank = 0x04, + .voltage_reg = 0x20, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB9540_LDO_AUX3] = { + .desc = { + .name = "LDO-AUX3", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX3, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x0a, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x21, + .voltage_mask = 0x07, + .voltages = ldo_vaux3_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaux3_voltages), + }, + [AB9540_LDO_AUX4] = { + .desc = { + .name = "LDO-AUX4", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB9540_LDO_AUX4, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + /* values for Vaux4Regu register */ + .update_bank = 0x04, + .update_reg = 0x2e, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + /* values for Vaux4SEL register */ + .voltage_bank = 0x04, + .voltage_reg = 0x2f, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB9540_LDO_INTCORE] = { + .desc = { + .name = "LDO-INTCORE", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_INTCORE, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x03, + .update_reg = 0x80, + .update_mask = 0x44, + .update_val = 0x44, + .update_val_idle = 0x44, + .update_val_normal = 0x04, + .voltage_bank = 0x03, + .voltage_reg = 0x80, + .voltage_mask = 0x38, + .voltages = ldo_vintcore_voltages, + .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), + .voltage_shift = 3, + }, + /* + * Fixed Voltage Regulators + * name, fixed mV, + * update bank, reg, mask, enable val + */ + [AB9540_LDO_TVOUT] = { + .desc = { + .name = "LDO-TVOUT", + .ops = &ab8500_regulator_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_TVOUT, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .delay = 10000, + .fixed_uV = 2000000, + .load_lp_uA = 1000, + .update_bank = 0x03, + .update_reg = 0x80, + .update_mask = 0x82, + .update_val = 0x02, + .update_val_idle = 0x82, + .update_val_normal = 0x02, + }, + [AB9540_LDO_USB] = { + .desc = { + .name = "LDO-USB", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB9540_LDO_USB, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 3300000, + .update_bank = 0x03, + .update_reg = 0x82, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + }, + [AB9540_LDO_AUDIO] = { + .desc = { + .name = "LDO-AUDIO", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUDIO, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 2000000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x02, + .update_val = 0x02, + }, + [AB9540_LDO_ANAMIC1] = { + .desc = { + .name = "LDO-ANAMIC1", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANAMIC1, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 2050000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x08, + .update_val = 0x08, + }, + [AB9540_LDO_ANAMIC2] = { + .desc = { + .name = "LDO-ANAMIC2", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANAMIC2, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 2050000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x10, + .update_val = 0x10, + }, + [AB9540_LDO_DMIC] = { + .desc = { + .name = "LDO-DMIC", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_DMIC, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 1800000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x04, + .update_val = 0x04, + }, + + /* + * Regulators with fixed voltage and normal/idle modes + */ + [AB9540_LDO_ANA] = { + .desc = { + .name = "LDO-ANA", + .ops = &ab8500_regulator_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANA, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 1200000, + .load_lp_uA = 1000, + .update_bank = 0x04, + .update_reg = 0x06, + .update_mask = 0x0c, + .update_val = 0x08, + .update_val_idle = 0x0c, + .update_val_normal = 0x08, + }, }; struct ab8500_reg_init { @@ -603,6 +860,7 @@ struct ab8500_reg_init { .mask = _mask, \ } +/* AB8500 register init */ static struct ab8500_reg_init ab8500_reg_init[] = { /* * 0x30, VanaRequestCtrl @@ -773,6 +1031,281 @@ static struct ab8500_reg_init ab8500_reg_init[] = { REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16), }; +/* AB9540 register init */ +static struct ab8500_reg_init ab9540_reg_init[] = { + /* + * 0x03, VarmRequestCtrl + * 0x0c, VapeRequestCtrl + * 0x30, Vsmps1RequestCtrl + * 0xc0, Vsmps2RequestCtrl + */ + REG_INIT(AB9540_REGUREQUESTCTRL1, 0x03, 0x03, 0xff), + /* + * 0x03, Vsmps3RequestCtrl + * 0x0c, VpllRequestCtrl + * 0x30, VanaRequestCtrl + * 0xc0, VextSupply1RequestCtrl + */ + REG_INIT(AB9540_REGUREQUESTCTRL2, 0x03, 0x04, 0xff), + /* + * 0x03, VextSupply2RequestCtrl + * 0x0c, VextSupply3RequestCtrl + * 0x30, Vaux1RequestCtrl + * 0xc0, Vaux2RequestCtrl + */ + REG_INIT(AB9540_REGUREQUESTCTRL3, 0x03, 0x05, 0xff), + /* + * 0x03, Vaux3RequestCtrl + * 0x04, SwHPReq + */ + REG_INIT(AB9540_REGUREQUESTCTRL4, 0x03, 0x06, 0x07), + /* + * 0x01, Vsmps1SysClkReq1HPValid + * 0x02, Vsmps2SysClkReq1HPValid + * 0x04, Vsmps3SysClkReq1HPValid + * 0x08, VanaSysClkReq1HPValid + * 0x10, VpllSysClkReq1HPValid + * 0x20, Vaux1SysClkReq1HPValid + * 0x40, Vaux2SysClkReq1HPValid + * 0x80, Vaux3SysClkReq1HPValid + */ + REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), + /* + * 0x01, VapeSysClkReq1HPValid + * 0x02, VarmSysClkReq1HPValid + * 0x04, VbbSysClkReq1HPValid + * 0x08, VmodSysClkReq1HPValid + * 0x10, VextSupply1SysClkReq1HPValid + * 0x20, VextSupply2SysClkReq1HPValid + * 0x40, VextSupply3SysClkReq1HPValid + */ + REG_INIT(AB9540_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x7f), + /* + * 0x01, Vsmps1HwHPReq1Valid + * 0x02, Vsmps2HwHPReq1Valid + * 0x04, Vsmps3HwHPReq1Valid + * 0x08, VanaHwHPReq1Valid + * 0x10, VpllHwHPReq1Valid + * 0x20, Vaux1HwHPReq1Valid + * 0x40, Vaux2HwHPReq1Valid + * 0x80, Vaux3HwHPReq1Valid + */ + REG_INIT(AB9540_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff), + /* + * 0x01, VextSupply1HwHPReq1Valid + * 0x02, VextSupply2HwHPReq1Valid + * 0x04, VextSupply3HwHPReq1Valid + * 0x08, VmodHwHPReq1Valid + */ + REG_INIT(AB9540_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x0f), + /* + * 0x01, Vsmps1HwHPReq2Valid + * 0x02, Vsmps2HwHPReq2Valid + * 0x03, Vsmps3HwHPReq2Valid + * 0x08, VanaHwHPReq2Valid + * 0x10, VpllHwHPReq2Valid + * 0x20, Vaux1HwHPReq2Valid + * 0x40, Vaux2HwHPReq2Valid + * 0x80, Vaux3HwHPReq2Valid + */ + REG_INIT(AB9540_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff), + /* + * 0x01, VextSupply1HwHPReq2Valid + * 0x02, VextSupply2HwHPReq2Valid + * 0x04, VextSupply3HwHPReq2Valid + * 0x08, VmodHwHPReq2Valid + */ + REG_INIT(AB9540_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x0f), + /* + * 0x01, VapeSwHPReqValid + * 0x02, VarmSwHPReqValid + * 0x04, Vsmps1SwHPReqValid + * 0x08, Vsmps2SwHPReqValid + * 0x10, Vsmps3SwHPReqValid + * 0x20, VanaSwHPReqValid + * 0x40, VpllSwHPReqValid + * 0x80, Vaux1SwHPReqValid + */ + REG_INIT(AB9540_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff), + /* + * 0x01, Vaux2SwHPReqValid + * 0x02, Vaux3SwHPReqValid + * 0x04, VextSupply1SwHPReqValid + * 0x08, VextSupply2SwHPReqValid + * 0x10, VextSupply3SwHPReqValid + * 0x20, VmodSwHPReqValid + */ + REG_INIT(AB9540_REGUSWHPREQVALID2, 0x03, 0x0e, 0x3f), + /* + * 0x02, SysClkReq2Valid1 + * ... + * 0x80, SysClkReq8Valid1 + */ + REG_INIT(AB9540_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0xfe), + /* + * 0x02, SysClkReq2Valid2 + * ... + * 0x80, SysClkReq8Valid2 + */ + REG_INIT(AB9540_REGUSYSCLKREQVALID2, 0x03, 0x10, 0xfe), + /* + * 0x01, Vaux4SwHPReqValid + * 0x02, Vaux4HwHPReq2Valid + * 0x04, Vaux4HwHPReq1Valid + * 0x08, Vaux4SysClkReq1HPValid + */ + REG_INIT(AB9540_REGUVAUX4REQVALID, 0x03, 0x11, 0x0f), + /* + * 0x02, VTVoutEna + * 0x04, Vintcore12Ena + * 0x38, Vintcore12Sel + * 0x40, Vintcore12LP + * 0x80, VTVoutLP + */ + REG_INIT(AB9540_REGUMISC1, 0x03, 0x80, 0xfe), + /* + * 0x02, VaudioEna + * 0x04, VdmicEna + * 0x08, Vamic1Ena + * 0x10, Vamic2Ena + */ + REG_INIT(AB9540_VAUDIOSUPPLY, 0x03, 0x83, 0x1e), + /* + * 0x01, Vamic1_dzout + * 0x02, Vamic2_dzout + */ + REG_INIT(AB9540_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), + /* + * 0x03, Vsmps1Regu + * 0x0c, Vsmps1SelCtrl + * 0x10, Vsmps1AutoMode + * 0x20, Vsmps1PWMMode + */ + REG_INIT(AB9540_VSMPS1REGU, 0x04, 0x03, 0x3f), + /* + * 0x03, Vsmps2Regu + * 0x0c, Vsmps2SelCtrl + * 0x10, Vsmps2AutoMode + * 0x20, Vsmps2PWMMode + */ + REG_INIT(AB9540_VSMPS2REGU, 0x04, 0x04, 0x3f), + /* + * 0x03, Vsmps3Regu + * 0x0c, Vsmps3SelCtrl + * NOTE! PRCMU register + */ + REG_INIT(AB9540_VSMPS3REGU, 0x04, 0x05, 0x0f), + /* + * 0x03, VpllRegu + * 0x0c, VanaRegu + */ + REG_INIT(AB9540_VPLLVANAREGU, 0x04, 0x06, 0x0f), + /* + * 0x03, VextSupply1Regu + * 0x0c, VextSupply2Regu + * 0x30, VextSupply3Regu + * 0x40, ExtSupply2Bypass + * 0x80, ExtSupply3Bypass + */ + REG_INIT(AB9540_EXTSUPPLYREGU, 0x04, 0x08, 0xff), + /* + * 0x03, Vaux1Regu + * 0x0c, Vaux2Regu + */ + REG_INIT(AB9540_VAUX12REGU, 0x04, 0x09, 0x0f), + /* + * 0x0c, Vrf1Regu + * 0x03, Vaux3Regu + */ + REG_INIT(AB9540_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f), + /* + * 0x3f, Vsmps1Sel1 + */ + REG_INIT(AB9540_VSMPS1SEL1, 0x04, 0x13, 0x3f), + /* + * 0x3f, Vsmps1Sel2 + */ + REG_INIT(AB9540_VSMPS1SEL2, 0x04, 0x14, 0x3f), + /* + * 0x3f, Vsmps1Sel3 + */ + REG_INIT(AB9540_VSMPS1SEL3, 0x04, 0x15, 0x3f), + /* + * 0x3f, Vsmps2Sel1 + */ + REG_INIT(AB9540_VSMPS2SEL1, 0x04, 0x17, 0x3f), + /* + * 0x3f, Vsmps2Sel2 + */ + REG_INIT(AB9540_VSMPS2SEL2, 0x04, 0x18, 0x3f), + /* + * 0x3f, Vsmps2Sel3 + */ + REG_INIT(AB9540_VSMPS2SEL3, 0x04, 0x19, 0x3f), + /* + * 0x7f, Vsmps3Sel1 + * NOTE! PRCMU register + */ + REG_INIT(AB9540_VSMPS3SEL1, 0x04, 0x1b, 0x7f), + /* + * 0x7f, Vsmps3Sel2 + * NOTE! PRCMU register + */ + REG_INIT(AB9540_VSMPS3SEL2, 0x04, 0x1c, 0x7f), + /* + * 0x0f, Vaux1Sel + */ + REG_INIT(AB9540_VAUX1SEL, 0x04, 0x1f, 0x0f), + /* + * 0x0f, Vaux2Sel + */ + REG_INIT(AB9540_VAUX2SEL, 0x04, 0x20, 0x0f), + /* + * 0x07, Vaux3Sel + * 0x30, Vrf1Sel + */ + REG_INIT(AB9540_VRF1VAUX3SEL, 0x04, 0x21, 0x37), + /* + * 0x01, VextSupply12LP + */ + REG_INIT(AB9540_REGUCTRL2SPARE, 0x04, 0x22, 0x01), + /* + * 0x03, Vaux4RequestCtrl + */ + REG_INIT(AB9540_VAUX4REQCTRL, 0x04, 0x2d, 0x03), + /* + * 0x03, Vaux4Regu + */ + REG_INIT(AB9540_VAUX4REGU, 0x04, 0x2e, 0x03), + /* + * 0x08, Vaux4Sel + */ + REG_INIT(AB9540_VAUX4SEL, 0x04, 0x2f, 0x0f), + /* + * 0x01, VpllDisch + * 0x02, Vrf1Disch + * 0x04, Vaux1Disch + * 0x08, Vaux2Disch + * 0x10, Vaux3Disch + * 0x20, Vintcore12Disch + * 0x40, VTVoutDisch + * 0x80, VaudioDisch + */ + REG_INIT(AB9540_REGUCTRLDISCH, 0x04, 0x43, 0xff), + /* + * 0x01, VsimDisch + * 0x02, VanaDisch + * 0x04, VdmicPullDownEna + * 0x08, VpllPullDownEna + * 0x10, VdmicDisch + */ + REG_INIT(AB9540_REGUCTRLDISCH2, 0x04, 0x44, 0x1f), + /* + * 0x01, Vaux4Disch + */ + REG_INIT(AB9540_REGUCTRLDISCH3, 0x04, 0x48, 0x01), +}; + static int ab8500_regulator_init_registers(struct platform_device *pdev, struct ab8500_reg_init *reg_init, int id, int mask, int value) @@ -809,6 +1342,7 @@ static int ab8500_regulator_register(struct platform_device *pdev, struct ab8500_regulator_info *regulator_info, int id, struct device_node *np) { + struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_regulator_info *info = NULL; struct regulator_config config = { }; int err; @@ -823,7 +1357,7 @@ static int ab8500_regulator_register(struct platform_device *pdev, config.of_node = np; /* fix for hardware before ab8500v2.0 */ - if (abx500_get_chip_id(info->dev) < 0x20) { + if (is_ab8500_1p1_or_earlier(ab8500)) { if (info->desc.id == AB8500_LDO_AUX3) { info->desc.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages); @@ -862,6 +1396,20 @@ static struct of_regulator_match ab8500_regulator_match[] = { { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, }, }; +static struct of_regulator_match ab9540_regulator_match[] = { + { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB9540_LDO_AUX1, }, + { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB9540_LDO_AUX2, }, + { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB9540_LDO_AUX3, }, + { .name = "ab8500_ldo_aux4", .driver_data = (void *) AB9540_LDO_AUX4, }, + { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB9540_LDO_INTCORE, }, + { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB9540_LDO_TVOUT, }, + { .name = "ab8500_ldo_audio", .driver_data = (void *) AB9540_LDO_AUDIO, }, + { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB9540_LDO_ANAMIC1, }, + { .name = "ab8500_ldo_amamic2", .driver_data = (void *) AB9540_LDO_ANAMIC2, }, + { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB9540_LDO_DMIC, }, + { .name = "ab8500_ldo_ana", .driver_data = (void *) AB9540_LDO_ANA, }, +}; + static int ab8500_regulator_of_probe(struct platform_device *pdev, struct ab8500_regulator_info *regulator_info, @@ -895,12 +1443,21 @@ static int ab8500_regulator_probe(struct platform_device *pdev) struct ab8500_reg_init *reg_init; int reg_init_size; - regulator_info = ab8500_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); - reg_init = ab8500_reg_init; - reg_init_size = AB8500_NUM_REGULATOR_REGISTERS; - match = ab8500_regulator_match; - match_size = ARRAY_SIZE(ab8500_regulator_match) + if (is_ab9540(ab8500)) { + regulator_info = ab9540_regulator_info; + regulator_info_size = ARRAY_SIZE(ab9540_regulator_info); + reg_init = ab9540_reg_init; + reg_init_size = AB9540_NUM_REGULATOR_REGISTERS; + match = ab9540_regulator_match; + match_size = ARRAY_SIZE(ab9540_regulator_match) + } else { + regulator_info = ab8500_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); + reg_init = ab8500_reg_init; + reg_init_size = AB8500_NUM_REGULATOR_REGISTERS; + match = ab8500_regulator_match; + match_size = ARRAY_SIZE(ab8500_regulator_match) + } if (np) { err = of_regulator_match(&pdev->dev, np, match, match_size); @@ -978,11 +1535,18 @@ static int ab8500_regulator_probe(struct platform_device *pdev) static int ab8500_regulator_remove(struct platform_device *pdev) { int i, err; + struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_regulator_info *regulator_info; int regulator_info_size; - regulator_info = ab8500_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); + + if (is_ab9540(ab8500)) { + regulator_info = ab9540_regulator_info; + regulator_info_size = ARRAY_SIZE(ab9540_regulator_info); + } else { + regulator_info = ab8500_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); + } for (i = 0; i < regulator_info_size; i++) { struct ab8500_regulator_info *info = NULL; -- cgit v1.2.3 From ed3c138eb3a81f4431d5fe545ae2b4b198ebfdfe Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:12 +0000 Subject: regulator: ab8500: Correct TVOUT regulator enable time Update TVOUT regulator to match specification. Was 10ms - changed to 500us. Signed-off-by: Jonas Aaberg Signed-off-by: Lee Jones Reviewed-by: Bengt JONSSON Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 4d4d9dc33576..9de3a211b0b4 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -490,7 +490,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 2000000, - .enable_time = 10000, + .enable_time = 500, }, .load_lp_uA = 1000, .update_bank = 0x03, -- cgit v1.2.3 From a6324709ab4e8a06cb61aa4f7aa3374679d5f426 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Thu, 28 Mar 2013 16:11:13 +0000 Subject: regulator: ab8500-ext: Add support for AB8505/AB9540 The external regulator driver checks for old AB8500 HW to apply a fix. This patch adds a check to see that it is a AB8500 (not AB8505/AB9540). Signed-off-by: Bengt Jonsson Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 21b9bfb0fc5e..debae34b9dd4 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -369,7 +369,7 @@ int ab8500_ext_regulator_init(struct platform_device *pdev) } /* check for AB8500 2.x */ - if (abx500_get_chip_id(&pdev->dev) < 0x30) { + if (is_ab8500_2p0_or_earlier(ab8500)) { struct ab8500_ext_regulator_info *info; /* VextSupply3LPn is inverted on AB8500 2.x */ -- cgit v1.2.3 From 547f384f33dbd6171607f925ab246e25e315961e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:14 +0000 Subject: regulator: ab8500: add support for ab8505 To obtain full AB8505 regulator support, the AB8500 regulator driver first needs to know its register layout and their initialisation values for each. That information is provided via a couple of large data structures which we provide here. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500-regulators.c | 511 ++++++++++++++++++++- arch/arm/mach-ux500/board-mop500-regulators.h | 1 + drivers/regulator/ab8500.c | 617 ++++++++++++++++++++++++++ include/linux/regulator/ab8500.h | 75 +++- 4 files changed, 1195 insertions(+), 9 deletions(-) (limited to 'drivers/regulator') diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index c1173a161a04..816151903d46 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -5,6 +5,7 @@ * * Authors: Sundar Iyer * Bengt Jonsson + * Daniel Willerud * * MOP500 board specific initialization for regulators */ @@ -99,6 +100,27 @@ static struct regulator_consumer_supply ab8500_vaux3_consumers[] = { REGULATOR_SUPPLY("vmmc", "sdi0"), }; +static struct regulator_consumer_supply ab8505_vaux4_consumers[] = { +}; + +static struct regulator_consumer_supply ab8505_vaux5_consumers[] = { +}; + +static struct regulator_consumer_supply ab8505_vaux6_consumers[] = { +}; + +static struct regulator_consumer_supply ab8505_vaux8_consumers[] = { + /* AB8500 audio codec device */ + REGULATOR_SUPPLY("v-aux8", NULL), +}; + +static struct regulator_consumer_supply ab8505_vadc_consumers[] = { + /* Internal general-purpose ADC */ + REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"), + /* ADC for charger */ + REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"), +}; + static struct regulator_consumer_supply ab8500_vtvout_consumers[] = { /* TV-out DENC supply */ REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"), @@ -133,6 +155,11 @@ static struct regulator_consumer_supply ab8500_vintcore_consumers[] = { REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"), }; +static struct regulator_consumer_supply ab8505_usb_consumers[] = { + /* HS USB OTG physical interface */ + REGULATOR_SUPPLY("v-ape", NULL), +}; + static struct regulator_consumer_supply ab8500_vana_consumers[] = { /* External displays, connector on board, 1v8 power supply */ REGULATOR_SUPPLY("vsmps2", "mcde.0"), @@ -469,6 +496,450 @@ static struct regulator_init_data ab8500_ext_regulators[] = { }, }; +/* ab8505 regulator register initialization */ +static struct ab8500_regulator_reg_init ab8505_reg_init[] = { + /* + * VarmRequestCtrl + * VsmpsCRequestCtrl + * VsmpsARequestCtrl + * VsmpsBRequestCtrl + */ + INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL1, 0x00, 0x00), + /* + * VsafeRequestCtrl + * VpllRequestCtrl + * VanaRequestCtrl = HP/LP depending on VxRequest + */ + INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL2, 0x30, 0x00), + /* + * Vaux1RequestCtrl = HP/LP depending on VxRequest + * Vaux2RequestCtrl = HP/LP depending on VxRequest + */ + INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL3, 0xf0, 0x00), + /* + * Vaux3RequestCtrl = HP/LP depending on VxRequest + * SwHPReq = Control through SWValid disabled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUREQUESTCTRL4, 0x07, 0x00), + /* + * VsmpsASysClkReq1HPValid + * VsmpsBSysClkReq1HPValid + * VsafeSysClkReq1HPValid + * VanaSysClkReq1HPValid = disabled + * VpllSysClkReq1HPValid + * Vaux1SysClkReq1HPValid = disabled + * Vaux2SysClkReq1HPValid = disabled + * Vaux3SysClkReq1HPValid = disabled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00), + /* + * VsmpsCSysClkReq1HPValid + * VarmSysClkReq1HPValid + * VbbSysClkReq1HPValid + * VsmpsMSysClkReq1HPValid + */ + INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQ1HPVALID2, 0x00, 0x00), + /* + * VsmpsAHwHPReq1Valid + * VsmpsBHwHPReq1Valid + * VsafeHwHPReq1Valid + * VanaHwHPReq1Valid = disabled + * VpllHwHPReq1Valid + * Vaux1HwHPreq1Valid = disabled + * Vaux2HwHPReq1Valid = disabled + * Vaux3HwHPReqValid = disabled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ1VALID1, 0xe8, 0x00), + /* + * VsmpsMHwHPReq1Valid + */ + INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ1VALID2, 0x00, 0x00), + /* + * VsmpsAHwHPReq2Valid + * VsmpsBHwHPReq2Valid + * VsafeHwHPReq2Valid + * VanaHwHPReq2Valid = disabled + * VpllHwHPReq2Valid + * Vaux1HwHPReq2Valid = disabled + * Vaux2HwHPReq2Valid = disabled + * Vaux3HwHPReq2Valid = disabled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ2VALID1, 0xe8, 0x00), + /* + * VsmpsMHwHPReq2Valid + */ + INIT_REGULATOR_REGISTER(AB8505_REGUHWHPREQ2VALID2, 0x00, 0x00), + /** + * VsmpsCSwHPReqValid + * VarmSwHPReqValid + * VsmpsASwHPReqValid + * VsmpsBSwHPReqValid + * VsafeSwHPReqValid + * VanaSwHPReqValid + * VanaSwHPReqValid = disabled + * VpllSwHPReqValid + * Vaux1SwHPReqValid = disabled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUSWHPREQVALID1, 0xa0, 0x00), + /* + * Vaux2SwHPReqValid = disabled + * Vaux3SwHPReqValid = disabled + * VsmpsMSwHPReqValid + */ + INIT_REGULATOR_REGISTER(AB8505_REGUSWHPREQVALID2, 0x03, 0x00), + /* + * SysClkReq2Valid1 = SysClkReq2 controlled + * SysClkReq3Valid1 = disabled + * SysClkReq4Valid1 = SysClkReq4 controlled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQVALID1, 0x0e, 0x0a), + /* + * SysClkReq2Valid2 = disabled + * SysClkReq3Valid2 = disabled + * SysClkReq4Valid2 = disabled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUSYSCLKREQVALID2, 0x0e, 0x00), + /* + * Vaux4SwHPReqValid + * Vaux4HwHPReq2Valid + * Vaux4HwHPReq1Valid + * Vaux4SysClkReq1HPValid + */ + INIT_REGULATOR_REGISTER(AB8505_REGUVAUX4REQVALID, 0x00, 0x00), + /* + * VadcEna = disabled + * VintCore12Ena = disabled + * VintCore12Sel = 1.25 V + * VintCore12LP = inactive (HP) + * VadcLP = inactive (HP) + */ + INIT_REGULATOR_REGISTER(AB8505_REGUMISC1, 0xfe, 0x10), + /* + * VaudioEna = disabled + * Vaux8Ena = disabled + * Vamic1Ena = disabled + * Vamic2Ena = disabled + */ + INIT_REGULATOR_REGISTER(AB8505_VAUDIOSUPPLY, 0x1e, 0x00), + /* + * Vamic1_dzout = high-Z when Vamic1 is disabled + * Vamic2_dzout = high-Z when Vamic2 is disabled + */ + INIT_REGULATOR_REGISTER(AB8505_REGUCTRL1VAMIC, 0x03, 0x00), + /* + * VsmpsARegu + * VsmpsASelCtrl + * VsmpsAAutoMode + * VsmpsAPWMMode + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSAREGU, 0x00, 0x00), + /* + * VsmpsBRegu + * VsmpsBSelCtrl + * VsmpsBAutoMode + * VsmpsBPWMMode + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSBREGU, 0x00, 0x00), + /* + * VsafeRegu + * VsafeSelCtrl + * VsafeAutoMode + * VsafePWMMode + */ + INIT_REGULATOR_REGISTER(AB8505_VSAFEREGU, 0x00, 0x00), + /* + * VPll = Hw controlled (NOTE! PRCMU bits) + * VanaRegu = force off + */ + INIT_REGULATOR_REGISTER(AB8505_VPLLVANAREGU, 0x0f, 0x02), + /* + * VextSupply1Regu = force OFF (OTP_ExtSupply12LPnPolarity 1) + * VextSupply2Regu = force OFF (OTP_ExtSupply12LPnPolarity 1) + * VextSupply3Regu = force OFF (OTP_ExtSupply3LPnPolarity 0) + * ExtSupply2Bypass = ExtSupply12LPn ball is 0 when Ena is 0 + * ExtSupply3Bypass = ExtSupply3LPn ball is 0 when Ena is 0 + */ + INIT_REGULATOR_REGISTER(AB8505_EXTSUPPLYREGU, 0xff, 0x30), + /* + * Vaux1Regu = force HP + * Vaux2Regu = force off + */ + INIT_REGULATOR_REGISTER(AB8505_VAUX12REGU, 0x0f, 0x01), + /* + * Vaux3Regu = force off + */ + INIT_REGULATOR_REGISTER(AB8505_VRF1VAUX3REGU, 0x03, 0x00), + /* + * VsmpsASel1 + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL1, 0x00, 0x00), + /* + * VsmpsASel2 + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL2, 0x00, 0x00), + /* + * VsmpsASel3 + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSASEL3, 0x00, 0x00), + /* + * VsmpsBSel1 + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL1, 0x00, 0x00), + /* + * VsmpsBSel2 + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL2, 0x00, 0x00), + /* + * VsmpsBSel3 + */ + INIT_REGULATOR_REGISTER(AB8505_VSMPSBSEL3, 0x00, 0x00), + /* + * VsafeSel1 + */ + INIT_REGULATOR_REGISTER(AB8505_VSAFESEL1, 0x00, 0x00), + /* + * VsafeSel2 + */ + INIT_REGULATOR_REGISTER(AB8505_VSAFESEL2, 0x00, 0x00), + /* + * VsafeSel3 + */ + INIT_REGULATOR_REGISTER(AB8505_VSAFESEL3, 0x00, 0x00), + /* + * Vaux1Sel = 2.8 V + */ + INIT_REGULATOR_REGISTER(AB8505_VAUX1SEL, 0x0f, 0x0C), + /* + * Vaux2Sel = 2.9 V + */ + INIT_REGULATOR_REGISTER(AB8505_VAUX2SEL, 0x0f, 0x0d), + /* + * Vaux3Sel = 2.91 V + */ + INIT_REGULATOR_REGISTER(AB8505_VRF1VAUX3SEL, 0x07, 0x07), + /* + * Vaux4RequestCtrl + */ + INIT_REGULATOR_REGISTER(AB8505_VAUX4REQCTRL, 0x00, 0x00), + /* + * Vaux4Regu + */ + INIT_REGULATOR_REGISTER(AB8505_VAUX4REGU, 0x00, 0x00), + /* + * Vaux4Sel + */ + INIT_REGULATOR_REGISTER(AB8505_VAUX4SEL, 0x00, 0x00), + /* + * Vaux1Disch = short discharge time + * Vaux2Disch = short discharge time + * Vaux3Disch = short discharge time + * Vintcore12Disch = short discharge time + * VTVoutDisch = short discharge time + * VaudioDisch = short discharge time + */ + INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH, 0xfc, 0x00), + /* + * VanaDisch = short discharge time + * Vaux8PullDownEna = pulldown disabled when Vaux8 is disabled + * Vaux8Disch = short discharge time + */ + INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH2, 0x16, 0x00), + /* + * Vaux4Disch = short discharge time + */ + INIT_REGULATOR_REGISTER(AB8505_REGUCTRLDISCH3, 0x01, 0x00), + /* + * Vaux5Sel + * Vaux5LP + * Vaux5Ena + * Vaux5Disch + * Vaux5DisSfst + * Vaux5DisPulld + */ + INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX5, 0x00, 0x00), + /* + * Vaux6Sel + * Vaux6LP + * Vaux6Ena + * Vaux6DisPulld + */ + INIT_REGULATOR_REGISTER(AB8505_CTRLVAUX6, 0x00, 0x00), +}; + +struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = { + /* supplies to the display/camera */ + [AB8505_LDO_AUX1] = { + .constraints = { + .name = "V-DISPLAY", + .min_uV = 2800000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS, + .boot_on = 1, /* display is on at boot */ + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers), + .consumer_supplies = ab8500_vaux1_consumers, + }, + /* supplies to the on-board eMMC */ + [AB8505_LDO_AUX2] = { + .constraints = { + .name = "V-eMMC1", + .min_uV = 1100000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers), + .consumer_supplies = ab8500_vaux2_consumers, + }, + /* supply for VAUX3, supplies to SDcard slots */ + [AB8505_LDO_AUX3] = { + .constraints = { + .name = "V-MMC-SD", + .min_uV = 1100000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers), + .consumer_supplies = ab8500_vaux3_consumers, + }, + /* supply for VAUX4, supplies to NFC and standalone secure element */ + [AB8505_LDO_AUX4] = { + .constraints = { + .name = "V-NFC-SE", + .min_uV = 1100000, + .max_uV = 3300000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8505_vaux4_consumers), + .consumer_supplies = ab8505_vaux4_consumers, + }, + /* supply for VAUX5, supplies to TBD */ + [AB8505_LDO_AUX5] = { + .constraints = { + .name = "V-AUX5", + .min_uV = 1050000, + .max_uV = 2790000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8505_vaux5_consumers), + .consumer_supplies = ab8505_vaux5_consumers, + }, + /* supply for VAUX6, supplies to TBD */ + [AB8505_LDO_AUX6] = { + .constraints = { + .name = "V-AUX6", + .min_uV = 1050000, + .max_uV = 2790000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8505_vaux6_consumers), + .consumer_supplies = ab8505_vaux6_consumers, + }, + /* supply for gpadc, ADC LDO */ + [AB8505_LDO_ADC] = { + .constraints = { + .name = "V-ADC", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8505_vadc_consumers), + .consumer_supplies = ab8505_vadc_consumers, + }, + /* supply for ab8500-vaudio, VAUDIO LDO */ + [AB8505_LDO_AUDIO] = { + .constraints = { + .name = "V-AUD", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers), + .consumer_supplies = ab8500_vaud_consumers, + }, + /* supply for v-anamic1 VAMic1-LDO */ + [AB8505_LDO_ANAMIC1] = { + .constraints = { + .name = "V-AMIC1", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers), + .consumer_supplies = ab8500_vamic1_consumers, + }, + /* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */ + [AB8505_LDO_ANAMIC2] = { + .constraints = { + .name = "V-AMIC2", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers), + .consumer_supplies = ab8500_vamic2_consumers, + }, + /* supply for v-aux8, VAUX8 LDO */ + [AB8505_LDO_AUX8] = { + .constraints = { + .name = "V-AUX8", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8505_vaux8_consumers), + .consumer_supplies = ab8505_vaux8_consumers, + }, + /* supply for v-intcore12, VINTCORE12 LDO */ + [AB8505_LDO_INTCORE] = { + .constraints = { + .name = "V-INTCORE", + .min_uV = 1250000, + .max_uV = 1350000, + .input_uV = 1800000, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | + REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE | + REGULATOR_CHANGE_DRMS, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers), + .consumer_supplies = ab8500_vintcore_consumers, + }, + /* supply for LDO USB */ + [AB8505_LDO_USB] = { + .constraints = { + .name = "V-USB", + .valid_ops_mask = REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8505_usb_consumers), + .consumer_supplies = ab8505_usb_consumers, + }, + /* supply for U8500 CSI-DSI, VANA LDO */ + [AB8505_LDO_ANA] = { + .constraints = { + .name = "V-CSI-DSI", + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers), + .consumer_supplies = ab8500_vana_consumers, + }, +}; + struct ab8500_regulator_platform_data ab8500_regulator_plat_data = { .reg_init = ab8500_reg_init, .num_reg_init = ARRAY_SIZE(ab8500_reg_init), @@ -478,18 +949,39 @@ struct ab8500_regulator_platform_data ab8500_regulator_plat_data = { .num_ext_regulator = ARRAY_SIZE(ab8500_ext_regulators), }; +/* Use the AB8500 init settings for AB8505 as they are the same right now */ +struct ab8500_regulator_platform_data ab8505_regulator_plat_data = { + .reg_init = ab8505_reg_init, + .num_reg_init = ARRAY_SIZE(ab8505_reg_init), + .regulator = ab8505_regulators, + .num_regulator = ARRAY_SIZE(ab8505_regulators), +}; + static void ab8500_modify_reg_init(int id, u8 mask, u8 value) { int i; - for (i = ARRAY_SIZE(ab8500_reg_init) - 1; i >= 0; i--) { - if (ab8500_reg_init[i].id == id) { - u8 initval = ab8500_reg_init[i].value; - initval = (initval & ~mask) | (value & mask); - ab8500_reg_init[i].value = initval; + if (cpu_is_u8520()) { + for (i = ARRAY_SIZE(ab8505_reg_init) - 1; i >= 0; i--) { + if (ab8505_reg_init[i].id == id) { + u8 initval = ab8505_reg_init[i].value; + initval = (initval & ~mask) | (value & mask); + ab8505_reg_init[i].value = initval; - BUG_ON(mask & ~ab8500_reg_init[i].mask); - return; + BUG_ON(mask & ~ab8505_reg_init[i].mask); + return; + } + } + } else { + for (i = ARRAY_SIZE(ab8500_reg_init) - 1; i >= 0; i--) { + if (ab8500_reg_init[i].id == id) { + u8 initval = ab8500_reg_init[i].value; + initval = (initval & ~mask) | (value & mask); + ab8500_reg_init[i].value = initval; + + BUG_ON(mask & ~ab8500_reg_init[i].mask); + return; + } } } @@ -511,6 +1003,11 @@ void mop500_regulator_init(void) regulator->constraints.state_standby.disabled = 1; } + if (cpu_is_u8520()) { + /* Vaux2 initialized to be on */ + ab8500_modify_reg_init(AB8505_VAUX12REGU, 0x0f, 0x05); + } + /* * Handle AB8500_EXT_SUPPLY2 on HREFP_V20_V50 boards (do it for * all HREFP_V20 boards) diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h index 3d4c412d0b7a..9bece38fe933 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.h +++ b/arch/arm/mach-ux500/board-mop500-regulators.h @@ -15,6 +15,7 @@ #include extern struct ab8500_regulator_platform_data ab8500_regulator_plat_data; +extern struct ab8500_regulator_platform_data ab8505_regulator_plat_data; extern struct regulator_init_data tps61052_regulator; extern struct regulator_init_data gpio_en_3v3_regulator; diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 9de3a211b0b4..1ab0f8a7c862 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -5,11 +5,15 @@ * * Authors: Sundar Iyer for ST-Ericsson * Bengt Jonsson for ST-Ericsson + * Daniel Willerud for ST-Ericsson * * AB8500 peripheral regulators * * AB8500 supports the following regulators: * VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA + * + * AB8505 supports the following regulators: + * VAUX1/2/3/4/5/6, VINTCORE, VADC, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA */ #include #include @@ -92,6 +96,17 @@ static const unsigned int ldo_vaux3_voltages[] = { 2910000, }; +static const int ldo_vaux56_voltages[] = { + 1800000, + 1050000, + 1100000, + 1200000, + 1500000, + 2200000, + 2500000, + 2790000, +}; + static const unsigned int ldo_vintcore_voltages[] = { 1200000, 1225000, @@ -589,6 +604,313 @@ static struct ab8500_regulator_info }, }; +/* AB8505 regulator information */ +static struct ab8500_regulator_info + ab8505_regulator_info[AB8505_NUM_REGULATORS] = { + /* + * Variable Voltage Regulators + * name, min mV, max mV, + * update bank, reg, mask, enable val + * volt bank, reg, mask, table, table length + */ + [AB8505_LDO_AUX1] = { + .desc = { + .name = "LDO-AUX1", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX1, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x09, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x1f, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB8505_LDO_AUX2] = { + .desc = { + .name = "LDO-AUX2", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX2, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x09, + .update_mask = 0x0c, + .update_val = 0x04, + .update_val_idle = 0x0c, + .update_val_normal = 0x04, + .voltage_bank = 0x04, + .voltage_reg = 0x20, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB8505_LDO_AUX3] = { + .desc = { + .name = "LDO-AUX3", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX3, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x0a, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x21, + .voltage_mask = 0x07, + .voltages = ldo_vaux3_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaux3_voltages), + }, + [AB8505_LDO_AUX4] = { + .desc = { + .name = "LDO-AUX4", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB9540_LDO_AUX4, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + /* values for Vaux4Regu register */ + .update_bank = 0x04, + .update_reg = 0x2e, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + /* values for Vaux4SEL register */ + .voltage_bank = 0x04, + .voltage_reg = 0x2f, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB8505_LDO_AUX5] = { + .desc = { + .name = "LDO-AUX5", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8505_LDO_AUX5, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vaux56_voltages), + }, + .min_uV = 1050000, + .max_uV = 2790000, + .load_lp_uA = 2000, + /* values for CtrlVaux5 register */ + .update_bank = 0x01, + .update_reg = 0x55, + .update_mask = 0x08, + .update_val = 0x00, + .update_val_idle = 0x01, + .update_val_normal = 0x00, + .voltage_bank = 0x01, + .voltage_reg = 0x55, + .voltage_mask = 0x07, + .voltages = ldo_vaux56_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaux56_voltages), + }, + [AB8505_LDO_AUX6] = { + .desc = { + .name = "LDO-AUX6", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8505_LDO_AUX6, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vaux56_voltages), + }, + .min_uV = 1050000, + .max_uV = 2790000, + .load_lp_uA = 2000, + /* values for CtrlVaux6 register */ + .update_bank = 0x01, + .update_reg = 0x56, + .update_mask = 0x08, + .update_val = 0x00, + .update_val_idle = 0x01, + .update_val_normal = 0x00, + .voltage_bank = 0x01, + .voltage_reg = 0x56, + .voltage_mask = 0x07, + .voltages = ldo_vaux56_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaux56_voltages), + }, + [AB8505_LDO_INTCORE] = { + .desc = { + .name = "LDO-INTCORE", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_INTCORE, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), + }, + .min_uV = 1100000, + .max_uV = 3300000, + .load_lp_uA = 5000, + .update_bank = 0x03, + .update_reg = 0x80, + .update_mask = 0x44, + .update_val = 0x04, + .update_val_idle = 0x44, + .update_val_normal = 0x04, + .voltage_bank = 0x03, + .voltage_reg = 0x80, + .voltage_mask = 0x38, + .voltages = ldo_vintcore_voltages, + .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), + .voltage_shift = 3, + }, + + /* + * Fixed Voltage Regulators + * name, fixed mV, + * update bank, reg, mask, enable val + */ + [AB8505_LDO_ADC] = { + .desc = { + .name = "LDO-ADC", + .ops = &ab8500_regulator_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8505_LDO_ADC, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .delay = 10000, + .fixed_uV = 2000000, + .load_lp_uA = 1000, + .update_bank = 0x03, + .update_reg = 0x80, + .update_mask = 0x82, + .update_val = 0x02, + .update_val_idle = 0x82, + .update_val_normal = 0x02, + }, + [AB8505_LDO_USB] = { + .desc = { + .name = "LDO-USB", + .ops = &ab8500_regulator_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB9540_LDO_USB, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 3300000, + .update_bank = 0x03, + .update_reg = 0x82, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + }, + [AB8505_LDO_AUDIO] = { + .desc = { + .name = "LDO-AUDIO", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUDIO, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 2000000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x02, + .update_val = 0x02, + }, + [AB8505_LDO_ANAMIC1] = { + .desc = { + .name = "LDO-ANAMIC1", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANAMIC1, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 2050000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x08, + .update_val = 0x08, + }, + [AB8505_LDO_ANAMIC2] = { + .desc = { + .name = "LDO-ANAMIC2", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANAMIC2, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 2050000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x10, + .update_val = 0x10, + }, + [AB8505_LDO_AUX8] = { + .desc = { + .name = "LDO-AUX8", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8505_LDO_AUX8, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 1800000, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x04, + .update_val = 0x04, + }, + /* + * Regulators with fixed voltage and normal/idle modes + */ + [AB8505_LDO_ANA] = { + .desc = { + .name = "LDO-ANA", + .ops = &ab8500_regulator_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANA, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .fixed_uV = 1200000, + .load_lp_uA = 1000, + .update_bank = 0x04, + .update_reg = 0x06, + .update_mask = 0x0c, + .update_val = 0x04, + .update_val_idle = 0x0c, + .update_val_normal = 0x04, + }, +}; + /* AB9540 regulator information */ static struct ab8500_regulator_info ab9540_regulator_info[AB9540_NUM_REGULATORS] = { @@ -1031,6 +1353,276 @@ static struct ab8500_reg_init ab8500_reg_init[] = { REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16), }; +/* AB8505 register init */ +static struct ab8500_reg_init ab8505_reg_init[] = { + /* + * 0x03, VarmRequestCtrl + * 0x0c, VsmpsCRequestCtrl + * 0x30, VsmpsARequestCtrl + * 0xc0, VsmpsBRequestCtrl + */ + REG_INIT(AB8505_REGUREQUESTCTRL1, 0x03, 0x03, 0xff), + /* + * 0x03, VsafeRequestCtrl + * 0x0c, VpllRequestCtrl + * 0x30, VanaRequestCtrl + */ + REG_INIT(AB8505_REGUREQUESTCTRL2, 0x03, 0x04, 0x3f), + /* + * 0x30, Vaux1RequestCtrl + * 0xc0, Vaux2RequestCtrl + */ + REG_INIT(AB8505_REGUREQUESTCTRL3, 0x03, 0x05, 0xf0), + /* + * 0x03, Vaux3RequestCtrl + * 0x04, SwHPReq + */ + REG_INIT(AB8505_REGUREQUESTCTRL4, 0x03, 0x06, 0x07), + /* + * 0x01, VsmpsASysClkReq1HPValid + * 0x02, VsmpsBSysClkReq1HPValid + * 0x04, VsafeSysClkReq1HPValid + * 0x08, VanaSysClkReq1HPValid + * 0x10, VpllSysClkReq1HPValid + * 0x20, Vaux1SysClkReq1HPValid + * 0x40, Vaux2SysClkReq1HPValid + * 0x80, Vaux3SysClkReq1HPValid + */ + REG_INIT(AB8505_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), + /* + * 0x01, VsmpsCSysClkReq1HPValid + * 0x02, VarmSysClkReq1HPValid + * 0x04, VbbSysClkReq1HPValid + * 0x08, VsmpsMSysClkReq1HPValid + */ + REG_INIT(AB8505_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x0f), + /* + * 0x01, VsmpsAHwHPReq1Valid + * 0x02, VsmpsBHwHPReq1Valid + * 0x04, VsafeHwHPReq1Valid + * 0x08, VanaHwHPReq1Valid + * 0x10, VpllHwHPReq1Valid + * 0x20, Vaux1HwHPReq1Valid + * 0x40, Vaux2HwHPReq1Valid + * 0x80, Vaux3HwHPReq1Valid + */ + REG_INIT(AB8505_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff), + /* + * 0x08, VsmpsMHwHPReq1Valid + */ + REG_INIT(AB8505_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x08), + /* + * 0x01, VsmpsAHwHPReq2Valid + * 0x02, VsmpsBHwHPReq2Valid + * 0x04, VsafeHwHPReq2Valid + * 0x08, VanaHwHPReq2Valid + * 0x10, VpllHwHPReq2Valid + * 0x20, Vaux1HwHPReq2Valid + * 0x40, Vaux2HwHPReq2Valid + * 0x80, Vaux3HwHPReq2Valid + */ + REG_INIT(AB8505_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff), + /* + * 0x08, VsmpsMHwHPReq2Valid + */ + REG_INIT(AB8505_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x08), + /* + * 0x01, VsmpsCSwHPReqValid + * 0x02, VarmSwHPReqValid + * 0x04, VsmpsASwHPReqValid + * 0x08, VsmpsBSwHPReqValid + * 0x10, VsafeSwHPReqValid + * 0x20, VanaSwHPReqValid + * 0x40, VpllSwHPReqValid + * 0x80, Vaux1SwHPReqValid + */ + REG_INIT(AB8505_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff), + /* + * 0x01, Vaux2SwHPReqValid + * 0x02, Vaux3SwHPReqValid + * 0x20, VsmpsMSwHPReqValid + */ + REG_INIT(AB8505_REGUSWHPREQVALID2, 0x03, 0x0e, 0x23), + /* + * 0x02, SysClkReq2Valid1 + * 0x04, SysClkReq3Valid1 + * 0x08, SysClkReq4Valid1 + */ + REG_INIT(AB8505_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0x0e), + /* + * 0x02, SysClkReq2Valid2 + * 0x04, SysClkReq3Valid2 + * 0x08, SysClkReq4Valid2 + */ + REG_INIT(AB8505_REGUSYSCLKREQVALID2, 0x03, 0x10, 0x0e), + /* + * 0x01, Vaux4SwHPReqValid + * 0x02, Vaux4HwHPReq2Valid + * 0x04, Vaux4HwHPReq1Valid + * 0x08, Vaux4SysClkReq1HPValid + */ + REG_INIT(AB8505_REGUVAUX4REQVALID, 0x03, 0x11, 0x0f), + /* + * 0x02, VadcEna + * 0x04, VintCore12Ena + * 0x38, VintCore12Sel + * 0x40, VintCore12LP + * 0x80, VadcLP + */ + REG_INIT(AB8505_REGUMISC1, 0x03, 0x80, 0xfe), + /* + * 0x02, VaudioEna + * 0x04, VdmicEna + * 0x08, Vamic1Ena + * 0x10, Vamic2Ena + */ + REG_INIT(AB8505_VAUDIOSUPPLY, 0x03, 0x83, 0x1e), + /* + * 0x01, Vamic1_dzout + * 0x02, Vamic2_dzout + */ + REG_INIT(AB8505_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), + /* + * 0x03, VsmpsARegu + * 0x0c, VsmpsASelCtrl + * 0x10, VsmpsAAutoMode + * 0x20, VsmpsAPWMMode + */ + REG_INIT(AB8505_VSMPSAREGU, 0x04, 0x03, 0x3f), + /* + * 0x03, VsmpsBRegu + * 0x0c, VsmpsBSelCtrl + * 0x10, VsmpsBAutoMode + * 0x20, VsmpsBPWMMode + */ + REG_INIT(AB8505_VSMPSBREGU, 0x04, 0x04, 0x3f), + /* + * 0x03, VsafeRegu + * 0x0c, VsafeSelCtrl + * 0x10, VsafeAutoMode + * 0x20, VsafePWMMode + */ + REG_INIT(AB8505_VSAFEREGU, 0x04, 0x05, 0x3f), + /* + * 0x03, VpllRegu (NOTE! PRCMU register bits) + * 0x0c, VanaRegu + */ + REG_INIT(AB8505_VPLLVANAREGU, 0x04, 0x06, 0x0f), + /* + * 0x03, VextSupply1Regu + * 0x0c, VextSupply2Regu + * 0x30, VextSupply3Regu + * 0x40, ExtSupply2Bypass + * 0x80, ExtSupply3Bypass + */ + REG_INIT(AB8505_EXTSUPPLYREGU, 0x04, 0x08, 0xff), + /* + * 0x03, Vaux1Regu + * 0x0c, Vaux2Regu + */ + REG_INIT(AB8505_VAUX12REGU, 0x04, 0x09, 0x0f), + /* + * 0x0f, Vaux3Regu + */ + REG_INIT(AB8505_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f), + /* + * 0x3f, VsmpsASel1 + */ + REG_INIT(AB8505_VSMPSASEL1, 0x04, 0x13, 0x3f), + /* + * 0x3f, VsmpsASel2 + */ + REG_INIT(AB8505_VSMPSASEL2, 0x04, 0x14, 0x3f), + /* + * 0x3f, VsmpsASel3 + */ + REG_INIT(AB8505_VSMPSASEL3, 0x04, 0x15, 0x3f), + /* + * 0x3f, VsmpsBSel1 + */ + REG_INIT(AB8505_VSMPSBSEL1, 0x04, 0x17, 0x3f), + /* + * 0x3f, VsmpsBSel2 + */ + REG_INIT(AB8505_VSMPSBSEL2, 0x04, 0x18, 0x3f), + /* + * 0x3f, VsmpsBSel3 + */ + REG_INIT(AB8505_VSMPSBSEL3, 0x04, 0x19, 0x3f), + /* + * 0x7f, VsafeSel1 + */ + REG_INIT(AB8505_VSAFESEL1, 0x04, 0x1b, 0x7f), + /* + * 0x3f, VsafeSel2 + */ + REG_INIT(AB8505_VSAFESEL2, 0x04, 0x1c, 0x7f), + /* + * 0x3f, VsafeSel3 + */ + REG_INIT(AB8505_VSAFESEL3, 0x04, 0x1d, 0x7f), + /* + * 0x0f, Vaux1Sel + */ + REG_INIT(AB8505_VAUX1SEL, 0x04, 0x1f, 0x0f), + /* + * 0x0f, Vaux2Sel + */ + REG_INIT(AB8505_VAUX2SEL, 0x04, 0x20, 0x0f), + /* + * 0x07, Vaux3Sel + * 0x30, VRF1Sel + */ + REG_INIT(AB8505_VRF1VAUX3SEL, 0x04, 0x21, 0x37), + /* + * 0x03, Vaux4RequestCtrl + */ + REG_INIT(AB8505_VAUX4REQCTRL, 0x04, 0x2d, 0x03), + /* + * 0x03, Vaux4Regu + */ + REG_INIT(AB8505_VAUX4REGU, 0x04, 0x2e, 0x03), + /* + * 0x0f, Vaux4Sel + */ + REG_INIT(AB8505_VAUX4SEL, 0x04, 0x2f, 0x0f), + /* + * 0x04, Vaux1Disch + * 0x08, Vaux2Disch + * 0x10, Vaux3Disch + * 0x20, Vintcore12Disch + * 0x40, VTVoutDisch + * 0x80, VaudioDisch + */ + REG_INIT(AB8505_REGUCTRLDISCH, 0x04, 0x43, 0xfc), + /* + * 0x02, VanaDisch + * 0x04, VdmicPullDownEna + * 0x10, VdmicDisch + */ + REG_INIT(AB8505_REGUCTRLDISCH2, 0x04, 0x44, 0x16), + /* + * 0x01, Vaux4Disch + */ + REG_INIT(AB8505_REGUCTRLDISCH3, 0x04, 0x48, 0x01), + /* + * 0x07, Vaux5Sel + * 0x08, Vaux5LP + * 0x10, Vaux5Ena + * 0x20, Vaux5Disch + * 0x40, Vaux5DisSfst + * 0x80, Vaux5DisPulld + */ + REG_INIT(AB8505_CTRLVAUX5, 0x01, 0x55, 0xff), + /* + * 0x07, Vaux6Sel + * 0x08, Vaux6LP + * 0x10, Vaux6Ena + * 0x80, Vaux6DisPulld + */ + REG_INIT(AB8505_CTRLVAUX6, 0x01, 0x56, 0x9f), +}; + /* AB9540 register init */ static struct ab8500_reg_init ab9540_reg_init[] = { /* @@ -1396,6 +1988,22 @@ static struct of_regulator_match ab8500_regulator_match[] = { { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, }, }; +static struct of_regulator_match ab8505_regulator_match[] = { + { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8505_LDO_AUX1, }, + { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8505_LDO_AUX2, }, + { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8505_LDO_AUX3, }, + { .name = "ab8500_ldo_aux4", .driver_data = (void *) AB8505_LDO_AUX4, }, + { .name = "ab8500_ldo_aux5", .driver_data = (void *) AB8505_LDO_AUX5, }, + { .name = "ab8500_ldo_aux6", .driver_data = (void *) AB8505_LDO_AUX6, }, + { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8505_LDO_INTCORE, }, + { .name = "ab8500_ldo_adc", .driver_data = (void *) AB8505_LDO_ADC, }, + { .name = "ab8500_ldo_audio", .driver_data = (void *) AB8505_LDO_AUDIO, }, + { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB8505_LDO_ANAMIC1, }, + { .name = "ab8500_ldo_amamic2", .driver_data = (void *) AB8505_LDO_ANAMIC2, }, + { .name = "ab8500_ldo_aux8", .driver_data = (void *) AB8505_LDO_AUX8, }, + { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8505_LDO_ANA, }, +}; + static struct of_regulator_match ab9540_regulator_match[] = { { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB9540_LDO_AUX1, }, { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB9540_LDO_AUX2, }, @@ -1450,6 +2058,11 @@ static int ab8500_regulator_probe(struct platform_device *pdev) reg_init_size = AB9540_NUM_REGULATOR_REGISTERS; match = ab9540_regulator_match; match_size = ARRAY_SIZE(ab9540_regulator_match) + } else if (is_ab8505(ab8500)) { + regulator_info = ab8505_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8505_regulator_info); + reg_init = ab8505_reg_init; + reg_init_size = AB8505_NUM_REGULATOR_REGISTERS; } else { regulator_info = ab8500_regulator_info; regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); @@ -1543,6 +2156,9 @@ static int ab8500_regulator_remove(struct platform_device *pdev) if (is_ab9540(ab8500)) { regulator_info = ab9540_regulator_info; regulator_info_size = ARRAY_SIZE(ab9540_regulator_info); + } else if (is_ab8505(ab8500)) { + regulator_info = ab8505_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8505_regulator_info); } else { regulator_info = ab8500_regulator_info; regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); @@ -1601,5 +2217,6 @@ module_exit(ab8500_regulator_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Sundar Iyer "); MODULE_AUTHOR("Bengt Jonsson "); +MODULE_AUTHOR("Daniel Willerud "); MODULE_DESCRIPTION("Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC"); MODULE_ALIAS("platform:ab8500-regulator"); diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 592a3f3994c0..9a7cf97e5040 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -5,6 +5,7 @@ * * Authors: Sundar Iyer for ST-Ericsson * Bengt Jonsson for ST-Ericsson + * Daniel Willerud for ST-Ericsson */ #ifndef __LINUX_MFD_AB8500_REGULATOR_H @@ -27,7 +28,28 @@ enum ab8500_regulator_id { AB8500_NUM_REGULATORS, }; -/* AB9450 regulators */ +/* AB8505 regulators */ +enum ab8505_regulator_id { + AB8505_LDO_AUX1, + AB8505_LDO_AUX2, + AB8505_LDO_AUX3, + AB8505_LDO_AUX4, + AB8505_LDO_AUX5, + AB8505_LDO_AUX6, + AB8505_LDO_INTCORE, + AB8505_LDO_ADC, + AB8505_LDO_USB, + AB8505_LDO_AUDIO, + AB8505_LDO_ANAMIC1, + AB8505_LDO_ANAMIC2, + AB8505_LDO_AUX8, + AB8505_LDO_ANA, + AB8505_SYSCLKREQ_2, + AB8505_SYSCLKREQ_4, + AB8505_NUM_REGULATORS, +}; + +/* AB9540 regulators */ enum ab9540_regulator_id { AB9540_LDO_AUX1, AB9540_LDO_AUX2, @@ -46,7 +68,7 @@ enum ab9540_regulator_id { AB9540_NUM_REGULATORS, }; -/* AB8500 and AB9540 register initialization */ +/* AB8500, AB8505, and AB9540 register initialization */ struct ab8500_regulator_reg_init { int id; u8 mask; @@ -92,6 +114,55 @@ enum ab8500_regulator_reg { AB8500_NUM_REGULATOR_REGISTERS, }; +/* AB8505 registers */ +enum ab8505_regulator_reg { + AB8505_REGUREQUESTCTRL1, + AB8505_REGUREQUESTCTRL2, + AB8505_REGUREQUESTCTRL3, + AB8505_REGUREQUESTCTRL4, + AB8505_REGUSYSCLKREQ1HPVALID1, + AB8505_REGUSYSCLKREQ1HPVALID2, + AB8505_REGUHWHPREQ1VALID1, + AB8505_REGUHWHPREQ1VALID2, + AB8505_REGUHWHPREQ2VALID1, + AB8505_REGUHWHPREQ2VALID2, + AB8505_REGUSWHPREQVALID1, + AB8505_REGUSWHPREQVALID2, + AB8505_REGUSYSCLKREQVALID1, + AB8505_REGUSYSCLKREQVALID2, + AB8505_REGUVAUX4REQVALID, + AB8505_REGUMISC1, + AB8505_VAUDIOSUPPLY, + AB8505_REGUCTRL1VAMIC, + AB8505_VSMPSAREGU, + AB8505_VSMPSBREGU, + AB8505_VSAFEREGU, /* NOTE! PRCMU register */ + AB8505_VPLLVANAREGU, + AB8505_EXTSUPPLYREGU, + AB8505_VAUX12REGU, + AB8505_VRF1VAUX3REGU, + AB8505_VSMPSASEL1, + AB8505_VSMPSASEL2, + AB8505_VSMPSASEL3, + AB8505_VSMPSBSEL1, + AB8505_VSMPSBSEL2, + AB8505_VSMPSBSEL3, + AB8505_VSAFESEL1, /* NOTE! PRCMU register */ + AB8505_VSAFESEL2, /* NOTE! PRCMU register */ + AB8505_VSAFESEL3, /* NOTE! PRCMU register */ + AB8505_VAUX1SEL, + AB8505_VAUX2SEL, + AB8505_VRF1VAUX3SEL, + AB8505_VAUX4REQCTRL, + AB8505_VAUX4REGU, + AB8505_VAUX4SEL, + AB8505_REGUCTRLDISCH, + AB8505_REGUCTRLDISCH2, + AB8505_REGUCTRLDISCH3, + AB8505_CTRLVAUX5, + AB8505_CTRLVAUX6, + AB8505_NUM_REGULATOR_REGISTERS, +}; /* AB9540 registers */ enum ab9540_regulator_reg { -- cgit v1.2.3 From ae0a9a3efce22e77b5f0f2b266646431f492f7ed Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:16 +0000 Subject: regulator: ab8500: Add support for the ab8540 To obtain full AB8540 regulator support, the AB8500 regulator driver first needs to know its register layout and their initialisation values for each. That information is provided via a couple of large data structures which we provide here. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 686 ++++++++++++++++++++++++++++++++++++++- include/linux/regulator/ab8500.h | 86 +++++ 2 files changed, 764 insertions(+), 8 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 1ab0f8a7c862..ec609ab747ae 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -107,6 +107,18 @@ static const int ldo_vaux56_voltages[] = { 2790000, }; +static const int ldo_vaux3_ab8540_voltages[] = { + 1200000, + 1500000, + 1800000, + 2100000, + 2500000, + 2750000, + 2790000, + 2910000, + 3050000, +}; + static const unsigned int ldo_vintcore_voltages[] = { 1200000, 1225000, @@ -117,6 +129,17 @@ static const unsigned int ldo_vintcore_voltages[] = { 1350000, }; +static const int ldo_sdio_voltages[] = { + 1160000, + 1050000, + 1100000, + 1500000, + 1800000, + 2200000, + 2910000, + 3050000, +}; + static int ab8500_regulator_enable(struct regulator_dev *rdev) { int ret; @@ -726,10 +749,10 @@ static struct ab8500_regulator_info /* values for CtrlVaux5 register */ .update_bank = 0x01, .update_reg = 0x55, - .update_mask = 0x08, - .update_val = 0x00, - .update_val_idle = 0x01, - .update_val_normal = 0x00, + .update_mask = 0x18, + .update_val = 0x10, + .update_val_idle = 0x18, + .update_val_normal = 0x10, .voltage_bank = 0x01, .voltage_reg = 0x55, .voltage_mask = 0x07, @@ -751,10 +774,10 @@ static struct ab8500_regulator_info /* values for CtrlVaux6 register */ .update_bank = 0x01, .update_reg = 0x56, - .update_mask = 0x08, - .update_val = 0x00, - .update_val_idle = 0x01, - .update_val_normal = 0x00, + .update_mask = 0x18, + .update_val = 0x10, + .update_val_idle = 0x18, + .update_val_normal = 0x10, .voltage_bank = 0x01, .voltage_reg = 0x56, .voltage_mask = 0x07, @@ -1169,6 +1192,255 @@ static struct ab8500_regulator_info }, }; +/* AB8540 regulator information */ +static struct ab8500_regulator_info + ab8540_regulator_info[AB8540_NUM_REGULATORS] = { + /* + * Variable Voltage Regulators + * name, min mV, max mV, + * update bank, reg, mask, enable val + * volt bank, reg, mask, table, table length + */ + [AB8540_LDO_AUX1] = { + .desc = { + .name = "LDO-AUX1", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX1, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x09, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x1f, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB8540_LDO_AUX2] = { + .desc = { + .name = "LDO-AUX2", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX2, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x09, + .update_mask = 0x0c, + .update_val = 0x04, + .update_val_idle = 0x0c, + .update_val_normal = 0x04, + .voltage_bank = 0x04, + .voltage_reg = 0x20, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB8540_LDO_AUX3] = { + .desc = { + .name = "LDO-AUX3", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUX3, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vaux3_ab8540_voltages), + }, + .load_lp_uA = 5000, + .update_bank = 0x04, + .update_reg = 0x0a, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + .voltage_bank = 0x04, + .voltage_reg = 0x21, + .voltage_mask = 0x07, + .voltages = ldo_vaux3_ab8540_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaux3_ab8540_voltages), + }, + [AB8540_LDO_AUX4] = { + .desc = { + .name = "LDO-AUX4", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB9540_LDO_AUX4, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + }, + .load_lp_uA = 5000, + /* values for Vaux4Regu register */ + .update_bank = 0x04, + .update_reg = 0x2e, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + /* values for Vaux4SEL register */ + .voltage_bank = 0x04, + .voltage_reg = 0x2f, + .voltage_mask = 0x0f, + .voltages = ldo_vauxn_voltages, + .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), + }, + [AB8540_LDO_INTCORE] = { + .desc = { + .name = "LDO-INTCORE", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_INTCORE, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), + }, + .load_lp_uA = 5000, + .update_bank = 0x03, + .update_reg = 0x80, + .update_mask = 0x44, + .update_val = 0x44, + .update_val_idle = 0x44, + .update_val_normal = 0x04, + .voltage_bank = 0x03, + .voltage_reg = 0x80, + .voltage_mask = 0x38, + .voltages = ldo_vintcore_voltages, + .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), + .voltage_shift = 3, + }, + + /* + * Fixed Voltage Regulators + * name, fixed mV, + * update bank, reg, mask, enable val + */ + [AB8540_LDO_TVOUT] = { + .desc = { + .name = "LDO-TVOUT", + .ops = &ab8500_regulator_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_TVOUT, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .delay = 10000, + .load_lp_uA = 1000, + .update_bank = 0x03, + .update_reg = 0x80, + .update_mask = 0x82, + .update_val = 0x02, + .update_val_idle = 0x82, + .update_val_normal = 0x02, + }, + [AB8540_LDO_AUDIO] = { + .desc = { + .name = "LDO-AUDIO", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_AUDIO, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x02, + .update_val = 0x02, + }, + [AB8540_LDO_ANAMIC1] = { + .desc = { + .name = "LDO-ANAMIC1", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANAMIC1, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x08, + .update_val = 0x08, + }, + [AB8540_LDO_ANAMIC2] = { + .desc = { + .name = "LDO-ANAMIC2", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANAMIC2, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x10, + .update_val = 0x10, + }, + [AB8540_LDO_DMIC] = { + .desc = { + .name = "LDO-DMIC", + .ops = &ab8500_regulator_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_DMIC, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .update_bank = 0x03, + .update_reg = 0x83, + .update_mask = 0x04, + .update_val = 0x04, + }, + + /* + * Regulators with fixed voltage and normal/idle modes + */ + [AB8540_LDO_ANA] = { + .desc = { + .name = "LDO-ANA", + .ops = &ab8500_regulator_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8500_LDO_ANA, + .owner = THIS_MODULE, + .n_voltages = 1, + }, + .load_lp_uA = 1000, + .update_bank = 0x04, + .update_reg = 0x06, + .update_mask = 0x0c, + .update_val = 0x04, + .update_val_idle = 0x0c, + .update_val_normal = 0x04, + }, + [AB8540_LDO_SDIO] = { + .desc = { + .name = "LDO-SDIO", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8540_LDO_SDIO, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_sdio_voltages), + }, + .min_uV = 1050000, + .max_uV = 3050000, + .load_lp_uA = 5000, + .update_bank = 0x03, + .update_reg = 0x88, + .update_mask = 0x30, + .update_val = 0x10, + .update_val_idle = 0x30, + .update_val_normal = 0x10, + .voltage_bank = 0x03, + .voltage_reg = 0x88, + .voltage_mask = 0x07, + .voltages = ldo_sdio_voltages, + .voltages_len = ARRAY_SIZE(ldo_sdio_voltages), + }, +}; + struct ab8500_reg_init { u8 bank; u8 addr; @@ -1898,6 +2170,384 @@ static struct ab8500_reg_init ab9540_reg_init[] = { REG_INIT(AB9540_REGUCTRLDISCH3, 0x04, 0x48, 0x01), }; +/* AB8540 register init */ +static struct ab8500_reg_init ab8540_reg_init[] = { + /* + * 0x01, VSimSycClkReq1Valid + * 0x02, VSimSycClkReq2Valid + * 0x04, VSimSycClkReq3Valid + * 0x08, VSimSycClkReq4Valid + * 0x10, VSimSycClkReq5Valid + * 0x20, VSimSycClkReq6Valid + * 0x40, VSimSycClkReq7Valid + * 0x80, VSimSycClkReq8Valid + */ + REG_INIT(AB8540_VSIMSYSCLKCTRL, 0x02, 0x33, 0xff), + /* + * 0x03, VarmRequestCtrl + * 0x0c, VapeRequestCtrl + * 0x30, Vsmps1RequestCtrl + * 0xc0, Vsmps2RequestCtrl + */ + REG_INIT(AB8540_REGUREQUESTCTRL1, 0x03, 0x03, 0xff), + /* + * 0x03, Vsmps3RequestCtrl + * 0x0c, VpllRequestCtrl + * 0x30, VanaRequestCtrl + * 0xc0, VextSupply1RequestCtrl + */ + REG_INIT(AB8540_REGUREQUESTCTRL2, 0x03, 0x04, 0xff), + /* + * 0x03, VextSupply2RequestCtrl + * 0x0c, VextSupply3RequestCtrl + * 0x30, Vaux1RequestCtrl + * 0xc0, Vaux2RequestCtrl + */ + REG_INIT(AB8540_REGUREQUESTCTRL3, 0x03, 0x05, 0xff), + /* + * 0x03, Vaux3RequestCtrl + * 0x04, SwHPReq + */ + REG_INIT(AB8540_REGUREQUESTCTRL4, 0x03, 0x06, 0x07), + /* + * 0x01, Vsmps1SysClkReq1HPValid + * 0x02, Vsmps2SysClkReq1HPValid + * 0x04, Vsmps3SysClkReq1HPValid + * 0x08, VanaSysClkReq1HPValid + * 0x10, VpllSysClkReq1HPValid + * 0x20, Vaux1SysClkReq1HPValid + * 0x40, Vaux2SysClkReq1HPValid + * 0x80, Vaux3SysClkReq1HPValid + */ + REG_INIT(AB8540_REGUSYSCLKREQ1HPVALID1, 0x03, 0x07, 0xff), + /* + * 0x01, VapeSysClkReq1HPValid + * 0x02, VarmSysClkReq1HPValid + * 0x04, VbbSysClkReq1HPValid + * 0x10, VextSupply1SysClkReq1HPValid + * 0x20, VextSupply2SysClkReq1HPValid + * 0x40, VextSupply3SysClkReq1HPValid + */ + REG_INIT(AB8540_REGUSYSCLKREQ1HPVALID2, 0x03, 0x08, 0x77), + /* + * 0x01, Vsmps1HwHPReq1Valid + * 0x02, Vsmps2HwHPReq1Valid + * 0x04, Vsmps3HwHPReq1Valid + * 0x08, VanaHwHPReq1Valid + * 0x10, VpllHwHPReq1Valid + * 0x20, Vaux1HwHPReq1Valid + * 0x40, Vaux2HwHPReq1Valid + * 0x80, Vaux3HwHPReq1Valid + */ + REG_INIT(AB8540_REGUHWHPREQ1VALID1, 0x03, 0x09, 0xff), + /* + * 0x01, VextSupply1HwHPReq1Valid + * 0x02, VextSupply2HwHPReq1Valid + * 0x04, VextSupply3HwHPReq1Valid + */ + REG_INIT(AB8540_REGUHWHPREQ1VALID2, 0x03, 0x0a, 0x07), + /* + * 0x01, Vsmps1HwHPReq2Valid + * 0x02, Vsmps2HwHPReq2Valid + * 0x03, Vsmps3HwHPReq2Valid + * 0x08, VanaHwHPReq2Valid + * 0x10, VpllHwHPReq2Valid + * 0x20, Vaux1HwHPReq2Valid + * 0x40, Vaux2HwHPReq2Valid + * 0x80, Vaux3HwHPReq2Valid + */ + REG_INIT(AB8540_REGUHWHPREQ2VALID1, 0x03, 0x0b, 0xff), + /* + * 0x01, VextSupply1HwHPReq2Valid + * 0x02, VextSupply2HwHPReq2Valid + * 0x04, VextSupply3HwHPReq2Valid + */ + REG_INIT(AB8540_REGUHWHPREQ2VALID2, 0x03, 0x0c, 0x07), + /* + * 0x01, VapeSwHPReqValid + * 0x02, VarmSwHPReqValid + * 0x04, Vsmps1SwHPReqValid + * 0x08, Vsmps2SwHPReqValid + * 0x10, Vsmps3SwHPReqValid + * 0x20, VanaSwHPReqValid + * 0x40, VpllSwHPReqValid + * 0x80, Vaux1SwHPReqValid + */ + REG_INIT(AB8540_REGUSWHPREQVALID1, 0x03, 0x0d, 0xff), + /* + * 0x01, Vaux2SwHPReqValid + * 0x02, Vaux3SwHPReqValid + * 0x04, VextSupply1SwHPReqValid + * 0x08, VextSupply2SwHPReqValid + * 0x10, VextSupply3SwHPReqValid + */ + REG_INIT(AB8540_REGUSWHPREQVALID2, 0x03, 0x0e, 0x1f), + /* + * 0x02, SysClkReq2Valid1 + * ... + * 0x80, SysClkReq8Valid1 + */ + REG_INIT(AB8540_REGUSYSCLKREQVALID1, 0x03, 0x0f, 0xff), + /* + * 0x02, SysClkReq2Valid2 + * ... + * 0x80, SysClkReq8Valid2 + */ + REG_INIT(AB8540_REGUSYSCLKREQVALID2, 0x03, 0x10, 0xff), + /* + * 0x01, Vaux4SwHPReqValid + * 0x02, Vaux4HwHPReq2Valid + * 0x04, Vaux4HwHPReq1Valid + * 0x08, Vaux4SysClkReq1HPValid + */ + REG_INIT(AB8540_REGUVAUX4REQVALID, 0x03, 0x11, 0x0f), + /* + * 0x01, Vaux5SwHPReqValid + * 0x02, Vaux5HwHPReq2Valid + * 0x04, Vaux5HwHPReq1Valid + * 0x08, Vaux5SysClkReq1HPValid + */ + REG_INIT(AB8540_REGUVAUX5REQVALID, 0x03, 0x12, 0x0f), + /* + * 0x01, Vaux6SwHPReqValid + * 0x02, Vaux6HwHPReq2Valid + * 0x04, Vaux6HwHPReq1Valid + * 0x08, Vaux6SysClkReq1HPValid + */ + REG_INIT(AB8540_REGUVAUX6REQVALID, 0x03, 0x13, 0x0f), + /* + * 0x01, VclkbSwHPReqValid + * 0x02, VclkbHwHPReq2Valid + * 0x04, VclkbHwHPReq1Valid + * 0x08, VclkbSysClkReq1HPValid + */ + REG_INIT(AB8540_REGUVCLKBREQVALID, 0x03, 0x14, 0x0f), + /* + * 0x01, Vrf1SwHPReqValid + * 0x02, Vrf1HwHPReq2Valid + * 0x04, Vrf1HwHPReq1Valid + * 0x08, Vrf1SysClkReq1HPValid + */ + REG_INIT(AB8540_REGUVRF1REQVALID, 0x03, 0x15, 0x0f), + /* + * 0x02, VTVoutEna + * 0x04, Vintcore12Ena + * 0x38, Vintcore12Sel + * 0x40, Vintcore12LP + * 0x80, VTVoutLP + */ + REG_INIT(AB8540_REGUMISC1, 0x03, 0x80, 0xfe), + /* + * 0x02, VaudioEna + * 0x04, VdmicEna + * 0x08, Vamic1Ena + * 0x10, Vamic2Ena + * 0x20, Vamic12LP + * 0xC0, VdmicSel + */ + REG_INIT(AB8540_VAUDIOSUPPLY, 0x03, 0x83, 0xfe), + /* + * 0x01, Vamic1_dzout + * 0x02, Vamic2_dzout + */ + REG_INIT(AB8540_REGUCTRL1VAMIC, 0x03, 0x84, 0x03), + /* + * 0x07, VHSICSel + * 0x08, VHSICOffState + * 0x10, VHSIEna + * 0x20, VHSICLP + */ + REG_INIT(AB8540_VHSIC, 0x03, 0x87, 0x3f), + /* + * 0x07, VSDIOSel + * 0x08, VSDIOOffState + * 0x10, VSDIOEna + * 0x20, VSDIOLP + */ + REG_INIT(AB8540_VSDIO, 0x03, 0x88, 0x3f), + /* + * 0x03, Vsmps1Regu + * 0x0c, Vsmps1SelCtrl + * 0x10, Vsmps1AutoMode + * 0x20, Vsmps1PWMMode + */ + REG_INIT(AB8540_VSMPS1REGU, 0x04, 0x03, 0x3f), + /* + * 0x03, Vsmps2Regu + * 0x0c, Vsmps2SelCtrl + * 0x10, Vsmps2AutoMode + * 0x20, Vsmps2PWMMode + */ + REG_INIT(AB8540_VSMPS2REGU, 0x04, 0x04, 0x3f), + /* + * 0x03, Vsmps3Regu + * 0x0c, Vsmps3SelCtrl + * 0x10, Vsmps3AutoMode + * 0x20, Vsmps3PWMMode + * NOTE! PRCMU register + */ + REG_INIT(AB8540_VSMPS3REGU, 0x04, 0x05, 0x0f), + /* + * 0x03, VpllRegu + * 0x0c, VanaRegu + */ + REG_INIT(AB8540_VPLLVANAREGU, 0x04, 0x06, 0x0f), + /* + * 0x03, VextSupply1Regu + * 0x0c, VextSupply2Regu + * 0x30, VextSupply3Regu + * 0x40, ExtSupply2Bypass + * 0x80, ExtSupply3Bypass + */ + REG_INIT(AB8540_EXTSUPPLYREGU, 0x04, 0x08, 0xff), + /* + * 0x03, Vaux1Regu + * 0x0c, Vaux2Regu + */ + REG_INIT(AB8540_VAUX12REGU, 0x04, 0x09, 0x0f), + /* + * 0x0c, VRF1Regu + * 0x03, Vaux3Regu + */ + REG_INIT(AB8540_VRF1VAUX3REGU, 0x04, 0x0a, 0x0f), + /* + * 0x3f, Vsmps1Sel1 + */ + REG_INIT(AB8540_VSMPS1SEL1, 0x04, 0x13, 0x3f), + /* + * 0x3f, Vsmps1Sel2 + */ + REG_INIT(AB8540_VSMPS1SEL2, 0x04, 0x14, 0x3f), + /* + * 0x3f, Vsmps1Sel3 + */ + REG_INIT(AB8540_VSMPS1SEL3, 0x04, 0x15, 0x3f), + /* + * 0x3f, Vsmps2Sel1 + */ + REG_INIT(AB8540_VSMPS2SEL1, 0x04, 0x17, 0x3f), + /* + * 0x3f, Vsmps2Sel2 + */ + REG_INIT(AB8540_VSMPS2SEL2, 0x04, 0x18, 0x3f), + /* + * 0x3f, Vsmps2Sel3 + */ + REG_INIT(AB8540_VSMPS2SEL3, 0x04, 0x19, 0x3f), + /* + * 0x7f, Vsmps3Sel1 + * NOTE! PRCMU register + */ + REG_INIT(AB8540_VSMPS3SEL1, 0x04, 0x1b, 0x7f), + /* + * 0x7f, Vsmps3Sel2 + * NOTE! PRCMU register + */ + REG_INIT(AB8540_VSMPS3SEL2, 0x04, 0x1c, 0x7f), + /* + * 0x0f, Vaux1Sel + */ + REG_INIT(AB8540_VAUX1SEL, 0x04, 0x1f, 0x0f), + /* + * 0x0f, Vaux2Sel + */ + REG_INIT(AB8540_VAUX2SEL, 0x04, 0x20, 0x0f), + /* + * 0x07, Vaux3Sel + * 0x70, Vrf1Sel + */ + REG_INIT(AB8540_VRF1VAUX3SEL, 0x04, 0x21, 0x77), + /* + * 0x01, VextSupply12LP + */ + REG_INIT(AB8540_REGUCTRL2SPARE, 0x04, 0x22, 0x01), + /* + * 0x07, Vanasel + * 0x30, Vpllsel + */ + REG_INIT(AB8540_VANAVPLLSEL, 0x04, 0x29, 0x37), + /* + * 0x03, Vaux4RequestCtrl + */ + REG_INIT(AB8540_VAUX4REQCTRL, 0x04, 0x2d, 0x03), + /* + * 0x03, Vaux4Regu + */ + REG_INIT(AB8540_VAUX4REGU, 0x04, 0x2e, 0x03), + /* + * 0x0f, Vaux4Sel + */ + REG_INIT(AB8540_VAUX4SEL, 0x04, 0x2f, 0x0f), + /* + * 0x03, Vaux5RequestCtrl + */ + REG_INIT(AB8540_VAUX5REQCTRL, 0x04, 0x31, 0x03), + /* + * 0x03, Vaux5Regu + */ + REG_INIT(AB8540_VAUX5REGU, 0x04, 0x32, 0x03), + /* + * 0x3f, Vaux5Sel + */ + REG_INIT(AB8540_VAUX5SEL, 0x04, 0x33, 0x3f), + /* + * 0x03, Vaux6RequestCtrl + */ + REG_INIT(AB8540_VAUX6REQCTRL, 0x04, 0x34, 0x03), + /* + * 0x03, Vaux6Regu + */ + REG_INIT(AB8540_VAUX6REGU, 0x04, 0x35, 0x03), + /* + * 0x3f, Vaux6Sel + */ + REG_INIT(AB8540_VAUX6SEL, 0x04, 0x36, 0x3f), + /* + * 0x03, VCLKBRequestCtrl + */ + REG_INIT(AB8540_VCLKBREQCTRL, 0x04, 0x37, 0x03), + /* + * 0x03, VCLKBRegu + */ + REG_INIT(AB8540_VCLKBREGU, 0x04, 0x38, 0x03), + /* + * 0x07, VCLKBSel + */ + REG_INIT(AB8540_VCLKBSEL, 0x04, 0x39, 0x07), + /* + * 0x03, Vrf1RequestCtrl + */ + REG_INIT(AB8540_VRF1REQCTRL, 0x04, 0x3a, 0x03), + /* + * 0x01, VpllDisch + * 0x02, Vrf1Disch + * 0x04, Vaux1Disch + * 0x08, Vaux2Disch + * 0x10, Vaux3Disch + * 0x20, Vintcore12Disch + * 0x40, VTVoutDisch + * 0x80, VaudioDisch + */ + REG_INIT(AB8540_REGUCTRLDISCH, 0x04, 0x43, 0xff), + /* + * 0x02, VanaDisch + * 0x04, VdmicPullDownEna + * 0x08, VpllPullDownEna + * 0x10, VdmicDisch + */ + REG_INIT(AB8540_REGUCTRLDISCH2, 0x04, 0x44, 0x1e), + /* + * 0x01, Vaux4Disch + */ + REG_INIT(AB8540_REGUCTRLDISCH3, 0x04, 0x48, 0x01), + /* + * 0x01, Vaux5Disch + * 0x02, Vaux6Disch + * 0x04, VCLKBDisch + */ + REG_INIT(AB8540_REGUCTRLDISCH4, 0x04, 0x49, 0x07), +}; + static int ab8500_regulator_init_registers(struct platform_device *pdev, struct ab8500_reg_init *reg_init, int id, int mask, int value) @@ -2004,6 +2654,21 @@ static struct of_regulator_match ab8505_regulator_match[] = { { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8505_LDO_ANA, }, }; +static struct of_regulator_match ab8540_regulator_match[] = { + { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8540_LDO_AUX1, }, + { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8540_LDO_AUX2, }, + { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8540_LDO_AUX3, }, + { .name = "ab8500_ldo_aux4", .driver_data = (void *) AB8540_LDO_AUX4, }, + { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8540_LDO_INTCORE, }, + { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB8540_LDO_TVOUT, }, + { .name = "ab8500_ldo_audio", .driver_data = (void *) AB8540_LDO_AUDIO, }, + { .name = "ab8500_ldo_anamic1", .driver_data = (void *) AB8540_LDO_ANAMIC1, }, + { .name = "ab8500_ldo_amamic2", .driver_data = (void *) AB8540_LDO_ANAMIC2, }, + { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8540_LDO_DMIC, }, + { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8540_LDO_ANA, }, + { .name = "ab8500_ldo_sdio", .driver_data = (void *) AB8540_LDO_SDIO, }, +}; + static struct of_regulator_match ab9540_regulator_match[] = { { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB9540_LDO_AUX1, }, { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB9540_LDO_AUX2, }, @@ -2063,6 +2728,11 @@ static int ab8500_regulator_probe(struct platform_device *pdev) regulator_info_size = ARRAY_SIZE(ab8505_regulator_info); reg_init = ab8505_reg_init; reg_init_size = AB8505_NUM_REGULATOR_REGISTERS; + } else if (is_ab8540(ab8500)) { + regulator_info = ab8540_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8540_regulator_info); + reg_init = ab8540_reg_init; + reg_init_size = AB8540_NUM_REGULATOR_REGISTERS; } else { regulator_info = ab8500_regulator_info; regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 9a7cf97e5040..bb0140c9d4f4 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -68,6 +68,25 @@ enum ab9540_regulator_id { AB9540_NUM_REGULATORS, }; +/* AB8540 regulators */ +enum ab8540_regulator_id { + AB8540_LDO_AUX1, + AB8540_LDO_AUX2, + AB8540_LDO_AUX3, + AB8540_LDO_AUX4, + AB8540_LDO_INTCORE, + AB8540_LDO_TVOUT, + AB8540_LDO_AUDIO, + AB8540_LDO_ANAMIC1, + AB8540_LDO_ANAMIC2, + AB8540_LDO_DMIC, + AB8540_LDO_ANA, + AB8540_LDO_SDIO, + AB8540_SYSCLKREQ_2, + AB8540_SYSCLKREQ_4, + AB8540_NUM_REGULATORS, +}; + /* AB8500, AB8505, and AB9540 register initialization */ struct ab8500_regulator_reg_init { int id; @@ -212,6 +231,73 @@ enum ab9540_regulator_reg { AB9540_NUM_REGULATOR_REGISTERS, }; +/* AB8540 registers */ +enum ab8540_regulator_reg { + AB8540_REGUREQUESTCTRL1, + AB8540_REGUREQUESTCTRL2, + AB8540_REGUREQUESTCTRL3, + AB8540_REGUREQUESTCTRL4, + AB8540_REGUSYSCLKREQ1HPVALID1, + AB8540_REGUSYSCLKREQ1HPVALID2, + AB8540_REGUHWHPREQ1VALID1, + AB8540_REGUHWHPREQ1VALID2, + AB8540_REGUHWHPREQ2VALID1, + AB8540_REGUHWHPREQ2VALID2, + AB8540_REGUSWHPREQVALID1, + AB8540_REGUSWHPREQVALID2, + AB8540_REGUSYSCLKREQVALID1, + AB8540_REGUSYSCLKREQVALID2, + AB8540_REGUVAUX4REQVALID, + AB8540_REGUVAUX5REQVALID, + AB8540_REGUVAUX6REQVALID, + AB8540_REGUVCLKBREQVALID, + AB8540_REGUVRF1REQVALID, + AB8540_REGUMISC1, + AB8540_VAUDIOSUPPLY, + AB8540_REGUCTRL1VAMIC, + AB8540_VHSIC, + AB8540_VSDIO, + AB8540_VSMPS1REGU, + AB8540_VSMPS2REGU, + AB8540_VSMPS3REGU, + AB8540_VPLLVANAREGU, + AB8540_EXTSUPPLYREGU, + AB8540_VAUX12REGU, + AB8540_VRF1VAUX3REGU, + AB8540_VSMPS1SEL1, + AB8540_VSMPS1SEL2, + AB8540_VSMPS1SEL3, + AB8540_VSMPS2SEL1, + AB8540_VSMPS2SEL2, + AB8540_VSMPS2SEL3, + AB8540_VSMPS3SEL1, + AB8540_VSMPS3SEL2, + AB8540_VAUX1SEL, + AB8540_VAUX2SEL, + AB8540_VRF1VAUX3SEL, + AB8540_REGUCTRL2SPARE, + AB8540_VAUX4REQCTRL, + AB8540_VAUX4REGU, + AB8540_VAUX4SEL, + AB8540_VAUX5REQCTRL, + AB8540_VAUX5REGU, + AB8540_VAUX5SEL, + AB8540_VAUX6REQCTRL, + AB8540_VAUX6REGU, + AB8540_VAUX6SEL, + AB8540_VCLKBREQCTRL, + AB8540_VCLKBREGU, + AB8540_VCLKBSEL, + AB8540_VRF1REQCTRL, + AB8540_REGUCTRLDISCH, + AB8540_REGUCTRLDISCH2, + AB8540_REGUCTRLDISCH3, + AB8540_REGUCTRLDISCH4, + AB8540_VSIMSYSCLKCTRL, + AB8540_VANAVPLLSEL, + AB8540_NUM_REGULATOR_REGISTERS, +}; + /* AB8500 external regulators */ struct ab8500_ext_regulator_cfg { bool hwreq; /* requires hw mode or high power mode */ -- cgit v1.2.3 From b080c78a4e447e9c212c207f725999d4e32c5f19 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:17 +0000 Subject: regulator: ab8500: Update voltage handling for fixed voltage regulators There are a few over-lapping methods for voltage selection operating in the AB8500 regulator driver currently. This patch removes unused, unnecessary variables from the regulator_info structures and provides voltage tables for those regulators which have fixed voltages. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 92 ++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 48 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index ec609ab747ae..bade3e2a510d 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -140,6 +140,26 @@ static const int ldo_sdio_voltages[] = { 3050000, }; +static const unsigned int fixed_1200000_voltage[] = { + 1200000, +}; + +static const unsigned int fixed_1800000_voltage[] = { + 1800000, +}; + +static const unsigned int fixed_2000000_voltage[] = { + 2000000, +}; + +static const unsigned int fixed_2050000_voltage[] = { + 2050000, +}; + +static const unsigned int fixed_3300000_voltage[] = { + 3300000, +}; + static int ab8500_regulator_enable(struct regulator_dev *rdev) { int ret; @@ -403,7 +423,6 @@ static struct regulator_ops ab8500_regulator_mode_ops = { .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_linear, }; @@ -411,7 +430,6 @@ 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_linear, }; @@ -527,7 +545,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_TVOUT, .owner = THIS_MODULE, .n_voltages = 1, - .min_uV = 2000000, + .volt_table = fixed_2000000_voltage, .enable_time = 500, }, .load_lp_uA = 1000, @@ -546,8 +564,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, - .min_uV = 2000000, .enable_time = 140, + .volt_table = fixed_2000000_voltage, }, .update_bank = 0x03, .update_reg = 0x83, @@ -562,8 +580,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, - .min_uV = 2050000, .enable_time = 500, + .volt_table = fixed_2050000_voltage, }, .update_bank = 0x03, .update_reg = 0x83, @@ -578,8 +596,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, - .min_uV = 2050000, .enable_time = 500, + .volt_table = fixed_2050000_voltage, }, .update_bank = 0x03, .update_reg = 0x83, @@ -594,8 +612,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_DMIC, .owner = THIS_MODULE, .n_voltages = 1, - .min_uV = 1800000, .enable_time = 420, + .volt_table = fixed_1800000_voltage, }, .update_bank = 0x03, .update_reg = 0x83, @@ -614,8 +632,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, - .min_uV = 1200000, .enable_time = 140, + .volt_table = fixed_1200000_voltage, }, .load_lp_uA = 1000, .update_bank = 0x04, @@ -645,8 +663,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x09, @@ -669,8 +685,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x09, @@ -693,8 +707,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x0a, @@ -717,8 +729,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, /* values for Vaux4Regu register */ .update_bank = 0x04, @@ -743,8 +753,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux56_voltages), }, - .min_uV = 1050000, - .max_uV = 2790000, .load_lp_uA = 2000, /* values for CtrlVaux5 register */ .update_bank = 0x01, @@ -768,8 +776,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux56_voltages), }, - .min_uV = 1050000, - .max_uV = 2790000, .load_lp_uA = 2000, /* values for CtrlVaux6 register */ .update_bank = 0x01, @@ -793,8 +799,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x03, .update_reg = 0x80, @@ -823,9 +827,9 @@ static struct ab8500_regulator_info .id = AB8505_LDO_ADC, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2000000_voltage, }, .delay = 10000, - .fixed_uV = 2000000, .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x80, @@ -842,8 +846,8 @@ static struct ab8500_regulator_info .id = AB9540_LDO_USB, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_3300000_voltage, }, - .fixed_uV = 3300000, .update_bank = 0x03, .update_reg = 0x82, .update_mask = 0x03, @@ -859,8 +863,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2000000_voltage, }, - .fixed_uV = 2000000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x02, @@ -874,8 +878,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2050000_voltage, }, - .fixed_uV = 2050000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x08, @@ -889,8 +893,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2050000_voltage, }, - .fixed_uV = 2050000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x10, @@ -904,8 +908,8 @@ static struct ab8500_regulator_info .id = AB8505_LDO_AUX8, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_1800000_voltage, }, - .fixed_uV = 1800000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x04, @@ -922,8 +926,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_1200000_voltage, }, - .fixed_uV = 1200000, .load_lp_uA = 1000, .update_bank = 0x04, .update_reg = 0x06, @@ -952,8 +956,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x09, @@ -976,8 +978,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x09, @@ -1000,8 +1000,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x04, .update_reg = 0x0a, @@ -1024,8 +1022,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, /* values for Vaux4Regu register */ .update_bank = 0x04, @@ -1050,8 +1046,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), }, - .min_uV = 1100000, - .max_uV = 3300000, .load_lp_uA = 5000, .update_bank = 0x03, .update_reg = 0x80, @@ -1080,9 +1074,9 @@ static struct ab8500_regulator_info .id = AB8500_LDO_TVOUT, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2000000_voltage, }, .delay = 10000, - .fixed_uV = 2000000, .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x80, @@ -1099,8 +1093,8 @@ static struct ab8500_regulator_info .id = AB9540_LDO_USB, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_3300000_voltage, }, - .fixed_uV = 3300000, .update_bank = 0x03, .update_reg = 0x82, .update_mask = 0x03, @@ -1116,8 +1110,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2000000_voltage, }, - .fixed_uV = 2000000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x02, @@ -1131,8 +1125,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2050000_voltage, }, - .fixed_uV = 2050000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x08, @@ -1146,8 +1140,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2050000_voltage, }, - .fixed_uV = 2050000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x10, @@ -1161,8 +1155,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_DMIC, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_1800000_voltage, }, - .fixed_uV = 1800000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x04, @@ -1180,8 +1174,8 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_1200000_voltage, }, - .fixed_uV = 1200000, .load_lp_uA = 1000, .update_bank = 0x04, .update_reg = 0x06, @@ -1346,6 +1340,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2000000_voltage, }, .update_bank = 0x03, .update_reg = 0x83, @@ -1360,6 +1355,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2050000_voltage, }, .update_bank = 0x03, .update_reg = 0x83, @@ -1374,6 +1370,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2050000_voltage, }, .update_bank = 0x03, .update_reg = 0x83, @@ -1406,6 +1403,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_1200000_voltage, }, .load_lp_uA = 1000, .update_bank = 0x04, @@ -1424,8 +1422,6 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_sdio_voltages), }, - .min_uV = 1050000, - .max_uV = 3050000, .load_lp_uA = 5000, .update_bank = 0x03, .update_reg = 0x88, -- cgit v1.2.3 From 62ab4111113cf0d54c2b264730533fb53a04cc30 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 28 Mar 2013 16:11:18 +0000 Subject: regulator: ab8500: Use regulator_list_voltage_table() Following a recent move to regulator_list_voltage_table() for all previous abx500 related platforms this converts all recent platform updates over too. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 62 ++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 40 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index bade3e2a510d..16f5cf7ec13b 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -96,7 +96,7 @@ static const unsigned int ldo_vaux3_voltages[] = { 2910000, }; -static const int ldo_vaux56_voltages[] = { +static const unsigned int ldo_vaux56_voltages[] = { 1800000, 1050000, 1100000, @@ -107,7 +107,7 @@ static const int ldo_vaux56_voltages[] = { 2790000, }; -static const int ldo_vaux3_ab8540_voltages[] = { +static const unsigned int ldo_vaux3_ab8540_voltages[] = { 1200000, 1500000, 1800000, @@ -129,7 +129,7 @@ static const unsigned int ldo_vintcore_voltages[] = { 1350000, }; -static const int ldo_sdio_voltages[] = { +static const unsigned int ldo_sdio_voltages[] = { 1160000, 1050000, 1100000, @@ -662,6 +662,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -673,8 +674,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x1f, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8505_LDO_AUX2] = { .desc = { @@ -684,6 +683,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -695,8 +695,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x20, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8505_LDO_AUX3] = { .desc = { @@ -706,6 +704,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), + .volt_table = ldo_vaux3_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -717,8 +716,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x21, .voltage_mask = 0x07, - .voltages = ldo_vaux3_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux3_voltages), }, [AB8505_LDO_AUX4] = { .desc = { @@ -728,6 +725,7 @@ static struct ab8500_regulator_info .id = AB9540_LDO_AUX4, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, /* values for Vaux4Regu register */ @@ -741,8 +739,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x2f, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8505_LDO_AUX5] = { .desc = { @@ -752,6 +748,7 @@ static struct ab8500_regulator_info .id = AB8505_LDO_AUX5, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux56_voltages), + .volt_table = ldo_vaux56_voltages, }, .load_lp_uA = 2000, /* values for CtrlVaux5 register */ @@ -764,8 +761,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x01, .voltage_reg = 0x55, .voltage_mask = 0x07, - .voltages = ldo_vaux56_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux56_voltages), }, [AB8505_LDO_AUX6] = { .desc = { @@ -775,6 +770,7 @@ static struct ab8500_regulator_info .id = AB8505_LDO_AUX6, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux56_voltages), + .volt_table = ldo_vaux56_voltages, }, .load_lp_uA = 2000, /* values for CtrlVaux6 register */ @@ -787,8 +783,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x01, .voltage_reg = 0x56, .voltage_mask = 0x07, - .voltages = ldo_vaux56_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux56_voltages), }, [AB8505_LDO_INTCORE] = { .desc = { @@ -798,6 +792,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), + .volt_table = ldo_vintcore_voltages, }, .load_lp_uA = 5000, .update_bank = 0x03, @@ -809,8 +804,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltages = ldo_vintcore_voltages, - .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), .voltage_shift = 3, }, @@ -955,6 +948,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -966,8 +960,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x1f, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB9540_LDO_AUX2] = { .desc = { @@ -977,6 +969,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -988,8 +981,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x20, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB9540_LDO_AUX3] = { .desc = { @@ -999,6 +990,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), + .volt_table = ldo_vaux3_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -1010,8 +1002,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x21, .voltage_mask = 0x07, - .voltages = ldo_vaux3_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux3_voltages), }, [AB9540_LDO_AUX4] = { .desc = { @@ -1021,6 +1011,7 @@ static struct ab8500_regulator_info .id = AB9540_LDO_AUX4, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, /* values for Vaux4Regu register */ @@ -1034,8 +1025,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x2f, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB9540_LDO_INTCORE] = { .desc = { @@ -1045,6 +1034,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), + .volt_table = ldo_vintcore_voltages, }, .load_lp_uA = 5000, .update_bank = 0x03, @@ -1056,8 +1046,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltages = ldo_vintcore_voltages, - .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), .voltage_shift = 3, }, @@ -1203,6 +1191,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -1214,8 +1203,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x1f, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8540_LDO_AUX2] = { .desc = { @@ -1225,6 +1212,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -1236,8 +1224,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x20, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8540_LDO_AUX3] = { .desc = { @@ -1247,6 +1233,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_ab8540_voltages), + .volt_table = ldo_vaux3_ab8540_voltages, }, .load_lp_uA = 5000, .update_bank = 0x04, @@ -1258,8 +1245,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x21, .voltage_mask = 0x07, - .voltages = ldo_vaux3_ab8540_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux3_ab8540_voltages), }, [AB8540_LDO_AUX4] = { .desc = { @@ -1269,6 +1254,7 @@ static struct ab8500_regulator_info .id = AB9540_LDO_AUX4, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), + .volt_table = ldo_vauxn_voltages, }, .load_lp_uA = 5000, /* values for Vaux4Regu register */ @@ -1282,8 +1268,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x2f, .voltage_mask = 0x0f, - .voltages = ldo_vauxn_voltages, - .voltages_len = ARRAY_SIZE(ldo_vauxn_voltages), }, [AB8540_LDO_INTCORE] = { .desc = { @@ -1293,6 +1277,7 @@ static struct ab8500_regulator_info .id = AB8500_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), + .volt_table = ldo_vintcore_voltages, }, .load_lp_uA = 5000, .update_bank = 0x03, @@ -1304,8 +1289,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltages = ldo_vintcore_voltages, - .voltages_len = ARRAY_SIZE(ldo_vintcore_voltages), .voltage_shift = 3, }, @@ -1420,7 +1403,8 @@ static struct ab8500_regulator_info .type = REGULATOR_VOLTAGE, .id = AB8540_LDO_SDIO, .owner = THIS_MODULE, - .n_voltages = ARRAY_SIZE(ldo_sdio_voltages), + .n_voltages = ARRAY_SIZE(ldo_sdio_voltages), + .volt_table = ldo_sdio_voltages, }, .load_lp_uA = 5000, .update_bank = 0x03, @@ -1432,8 +1416,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x88, .voltage_mask = 0x07, - .voltages = ldo_sdio_voltages, - .voltages_len = ARRAY_SIZE(ldo_sdio_voltages), }, }; -- cgit v1.2.3 From 0fe17e20a6af5cbe4d0a7739300f7b818c79620f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:06 +0100 Subject: regulator: ab8500-ext: Add support for AB9540 regulators Add the support for ab9540 external regulators. Signed-off-by: Michel JAOUEN Signed-off-by: Lee Jones Reviewed-by: Jonas ABERG Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index debae34b9dd4..1e92e0103380 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -393,6 +393,12 @@ int ab8500_ext_regulator_init(struct platform_device *pdev) config.init_data = &pdata->ext_regulator[i]; config.driver_data = info; + if (is_ab9540(ab8500) && + ((info->desc.id == AB8500_EXT_SUPPLY1) || + (info->desc.id == AB8500_EXT_SUPPLY2) || + (info->desc.id == AB8500_EXT_SUPPLY3))) + info->desc.ops = &ab8500_ext_regulator_ops; + /* register regulator with framework */ info->rdev = regulator_register(&info->desc, &config); -- cgit v1.2.3 From 0b94641126f217f01695d8cc40749bf70e4e0bb6 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:07 +0100 Subject: regulator: ab8500: Supply platform specific regulator id values The regulator ID in the regulator info array should be the same values as the position of the element within the array. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 16f5cf7ec13b..f89a17a66433 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -659,7 +659,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX1", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX1, + .id = AB8505_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -680,7 +680,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX2", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX2, + .id = AB8505_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -701,7 +701,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX3", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX3, + .id = AB8505_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), .volt_table = ldo_vaux3_voltages, @@ -722,7 +722,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX4", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_AUX4, + .id = AB8505_LDO_AUX4, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -789,7 +789,7 @@ static struct ab8500_regulator_info .name = "LDO-INTCORE", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_INTCORE, + .id = AB8505_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), .volt_table = ldo_vintcore_voltages, @@ -836,7 +836,7 @@ static struct ab8500_regulator_info .name = "LDO-USB", .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_USB, + .id = AB8505_LDO_USB, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_3300000_voltage, @@ -853,7 +853,7 @@ static struct ab8500_regulator_info .name = "LDO-AUDIO", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUDIO, + .id = AB8505_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2000000_voltage, @@ -868,7 +868,7 @@ static struct ab8500_regulator_info .name = "LDO-ANAMIC1", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANAMIC1, + .id = AB8505_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, @@ -883,7 +883,7 @@ static struct ab8500_regulator_info .name = "LDO-ANAMIC2", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANAMIC2, + .id = AB8505_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, @@ -916,7 +916,7 @@ static struct ab8500_regulator_info .name = "LDO-ANA", .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANA, + .id = AB8505_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_1200000_voltage, @@ -945,7 +945,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX1", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX1, + .id = AB9540_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -966,7 +966,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX2", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX2, + .id = AB9540_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -987,7 +987,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX3", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX3, + .id = AB9540_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_voltages), .volt_table = ldo_vaux3_voltages, @@ -1031,7 +1031,7 @@ static struct ab8500_regulator_info .name = "LDO-INTCORE", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_INTCORE, + .id = AB9540_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), .volt_table = ldo_vintcore_voltages, @@ -1059,7 +1059,7 @@ static struct ab8500_regulator_info .name = "LDO-TVOUT", .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_TVOUT, + .id = AB9540_LDO_TVOUT, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2000000_voltage, @@ -1095,7 +1095,7 @@ static struct ab8500_regulator_info .name = "LDO-AUDIO", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUDIO, + .id = AB9540_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2000000_voltage, @@ -1110,7 +1110,7 @@ static struct ab8500_regulator_info .name = "LDO-ANAMIC1", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANAMIC1, + .id = AB9540_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, @@ -1125,7 +1125,7 @@ static struct ab8500_regulator_info .name = "LDO-ANAMIC2", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANAMIC2, + .id = AB9540_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, @@ -1140,7 +1140,7 @@ static struct ab8500_regulator_info .name = "LDO-DMIC", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_DMIC, + .id = AB9540_LDO_DMIC, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_1800000_voltage, @@ -1159,7 +1159,7 @@ static struct ab8500_regulator_info .name = "LDO-ANA", .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANA, + .id = AB9540_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_1200000_voltage, @@ -1188,7 +1188,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX1", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX1, + .id = AB8540_LDO_AUX1, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -1209,7 +1209,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX2", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX2, + .id = AB8540_LDO_AUX2, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -1230,7 +1230,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX3", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUX3, + .id = AB8540_LDO_AUX3, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux3_ab8540_voltages), .volt_table = ldo_vaux3_ab8540_voltages, @@ -1251,7 +1251,7 @@ static struct ab8500_regulator_info .name = "LDO-AUX4", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB9540_LDO_AUX4, + .id = AB8540_LDO_AUX4, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vauxn_voltages), .volt_table = ldo_vauxn_voltages, @@ -1274,7 +1274,7 @@ static struct ab8500_regulator_info .name = "LDO-INTCORE", .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_INTCORE, + .id = AB8540_LDO_INTCORE, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vintcore_voltages), .volt_table = ldo_vintcore_voltages, @@ -1302,7 +1302,7 @@ static struct ab8500_regulator_info .name = "LDO-TVOUT", .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_TVOUT, + .id = AB8540_LDO_TVOUT, .owner = THIS_MODULE, .n_voltages = 1, }, @@ -1320,7 +1320,7 @@ static struct ab8500_regulator_info .name = "LDO-AUDIO", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_AUDIO, + .id = AB8540_LDO_AUDIO, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2000000_voltage, @@ -1335,7 +1335,7 @@ static struct ab8500_regulator_info .name = "LDO-ANAMIC1", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANAMIC1, + .id = AB8540_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, @@ -1350,7 +1350,7 @@ static struct ab8500_regulator_info .name = "LDO-ANAMIC2", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANAMIC2, + .id = AB8540_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, @@ -1365,7 +1365,7 @@ static struct ab8500_regulator_info .name = "LDO-DMIC", .ops = &ab8500_regulator_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_DMIC, + .id = AB8540_LDO_DMIC, .owner = THIS_MODULE, .n_voltages = 1, }, @@ -1383,7 +1383,7 @@ static struct ab8500_regulator_info .name = "LDO-ANA", .ops = &ab8500_regulator_mode_ops, .type = REGULATOR_VOLTAGE, - .id = AB8500_LDO_ANA, + .id = AB8540_LDO_ANA, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_1200000_voltage, -- cgit v1.2.3 From f7eae37fcc6e4bdc404692a3e94fc9c51e9c5cb2 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 2 Apr 2013 13:24:08 +0100 Subject: regulator: ab8500: Don't register external regulators on AB8505 ExtSupply regulators are not included on AB8505 based platforms. Signed-off-by: Rabin Vincent Signed-off-by: Lee Jones Tested-by: Marcus COOPER Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index f89a17a66433..65f9365885a8 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -2777,10 +2777,12 @@ static int ab8500_regulator_probe(struct platform_device *pdev) return err; } - /* register external regulators (before Vaux1, 2 and 3) */ - err = ab8500_ext_regulator_init(pdev); - if (err) - return err; + if (!is_ab8505(ab8500)) { + /* register external regulators (before Vaux1, 2 and 3) */ + err = ab8500_ext_regulator_init(pdev); + if (err) + return err; + } /* register all regulators */ for (i = 0; i < regulator_info_size; i++) { @@ -2822,10 +2824,12 @@ static int ab8500_regulator_remove(struct platform_device *pdev) regulator_unregister(info->regulator); } - /* remove external regulators (after Vaux1, 2 and 3) */ - err = ab8500_ext_regulator_exit(pdev); - if (err) - return err; + if (!is_ab8505(ab8500)) { + /* remove external regulators (after Vaux1, 2 and 3) */ + err = ab8500_ext_regulator_exit(pdev); + if (err) + return err; + } /* remove regulator debug */ err = ab8500_regulator_debug_exit(pdev); -- cgit v1.2.3 From 8a3b1b8703fed16c6b796e87c34e2bc0311fe305 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:09 +0100 Subject: regulator: ab8500: Add voltage selection for AUDIO and ANA on AB8505 Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 55 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 65f9365885a8..bf9139784670 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -160,6 +160,28 @@ static const unsigned int fixed_3300000_voltage[] = { 3300000, }; +static const unsigned int ldo_vana_voltages[] = { + 1050000, + 1075000, + 1100000, + 1125000, + 1150000, + 1175000, + 1200000, + 1225000, +}; + +static const unsigned int ldo_vaudio_voltages[] = { + 2000000, + 2100000, + 2200000, + 2300000, + 2400000, + 2500000, + 2600000, + 2600000, /* Duplicated in Vaudio and IsoUicc Control register. */ +}; + static int ab8500_regulator_enable(struct regulator_dev *rdev) { int ret; @@ -416,6 +438,16 @@ static struct regulator_ops ab8500_regulator_volt_mode_ops = { .list_voltage = regulator_list_voltage_table, }; +static struct regulator_ops ab8500_regulator_volt_ops = { + .enable = ab8500_regulator_enable, + .disable = ab8500_regulator_disable, + .is_enabled = ab8500_regulator_is_enabled, + .get_voltage_sel = ab8500_regulator_get_voltage_sel, + .set_voltage_sel = ab8500_regulator_set_voltage_sel, + .list_voltage = regulator_list_voltage_table, + .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, +}; + static struct regulator_ops ab8500_regulator_mode_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -851,17 +883,23 @@ static struct ab8500_regulator_info [AB8505_LDO_AUDIO] = { .desc = { .name = "LDO-AUDIO", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_volt_ops, .type = REGULATOR_VOLTAGE, .id = AB8505_LDO_AUDIO, .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_2000000_voltage, + .n_voltages = ARRAY_SIZE(ldo_vaudio_voltages), + .volt_table = ldo_vaudio_voltages, }, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x02, .update_val = 0x02, + .voltage_bank = 0x01, + .voltage_reg = 0x57, + .voltage_mask = 0x7, + .voltage_shift = 4, + .voltages = ldo_vaudio_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaudio_voltages), }, [AB8505_LDO_ANAMIC1] = { .desc = { @@ -914,12 +952,12 @@ static struct ab8500_regulator_info [AB8505_LDO_ANA] = { .desc = { .name = "LDO-ANA", - .ops = &ab8500_regulator_mode_ops, + .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8505_LDO_ANA, .owner = THIS_MODULE, - .n_voltages = 1, - .volt_table = fixed_1200000_voltage, + .n_voltages = ARRAY_SIZE(ldo_vana_voltages), + .volt_table = ldo_vana_voltages, }, .load_lp_uA = 1000, .update_bank = 0x04, @@ -928,6 +966,11 @@ static struct ab8500_regulator_info .update_val = 0x04, .update_val_idle = 0x0c, .update_val_normal = 0x04, + .voltage_bank = 0x04, + .voltage_reg = 0x29, + .voltage_mask = 0x7, + .voltages = ldo_vana_voltages, + .voltages_len = ARRAY_SIZE(ldo_vana_voltages), }, }; -- cgit v1.2.3 From bd44e2cb4a21d9297b84efbb2e26961f6ece0423 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:10 +0100 Subject: regulator: ab8500: Also check for AB8505 based platforms Ensure we initialise AB8505 external supply regulators. Signed-off-by: Alexandre Torgue Signed-off-by: Lee Jones Reviewed-by: Philippe LANGLAIS Tested-by: Xiao Mei ZHANG Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 2 +- drivers/regulator/ab8500.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 1e92e0103380..c24372e96922 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -393,7 +393,7 @@ int ab8500_ext_regulator_init(struct platform_device *pdev) config.init_data = &pdata->ext_regulator[i]; config.driver_data = info; - if (is_ab9540(ab8500) && + if ((is_ab9540(ab8500) || is_ab8540(ab8500)) && ((info->desc.id == AB8500_EXT_SUPPLY1) || (info->desc.id == AB8500_EXT_SUPPLY2) || (info->desc.id == AB8500_EXT_SUPPLY3))) diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index bf9139784670..e8d07f667448 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -2852,6 +2852,9 @@ static int ab8500_regulator_remove(struct platform_device *pdev) } else if (is_ab8505(ab8500)) { regulator_info = ab8505_regulator_info; regulator_info_size = ARRAY_SIZE(ab8505_regulator_info); + } else if (is_ab8540(ab8500)) { + regulator_info = ab8540_regulator_info; + regulator_info_size = ARRAY_SIZE(ab8540_regulator_info); } else { regulator_info = ab8500_regulator_info; regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); -- cgit v1.2.3 From d7607baf32160a64a2610552868d348b6644b5ef Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:11 +0100 Subject: regulator: ab8500: Add new operations for Vaux3 In former functions, only can set Vaux3 to 2.91V, because the highest bit of Vaux3 register is put into another register. So add new expanded functions for Vaux3's operation. Signed-off-by: zhang xiaomei Signed-off-by: Lee Jones Reviewed-by: Philippe LANGLAIS Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 129 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index e8d07f667448..6dae5dfb9fde 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -63,6 +63,13 @@ struct ab8500_regulator_info { u8 voltage_reg; u8 voltage_mask; u8 voltage_shift; + struct { + u8 voltage_limit; + u8 voltage_bank; + u8 voltage_reg; + u8 voltage_mask; + u8 voltage_shift; + } expand_register; }; /* voltage tables for the vauxn/vintcore supplies */ @@ -396,6 +403,57 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) return val >> info->voltage_shift; } +static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev) +{ + int ret, val; + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval, regval_expand; + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + ret = abx500_get_register_interruptible(info->dev, + info->voltage_bank, info->voltage_reg, ®val); + + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't read voltage reg for regulator\n"); + return ret; + } + + ret = abx500_get_register_interruptible(info->dev, + info->expand_register.voltage_bank, + info->expand_register.voltage_reg, ®val_expand); + + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't read voltage reg for regulator\n"); + return ret; + } + + dev_vdbg(rdev_get_dev(rdev), + "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," + " 0x%x\n", + info->desc.name, info->voltage_bank, info->voltage_reg, + info->voltage_mask, regval); + dev_vdbg(rdev_get_dev(rdev), + "%s-get_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," + " 0x%x\n", + info->desc.name, info->expand_register.voltage_bank, + info->expand_register.voltage_reg, + info->expand_register.voltage_mask, regval_expand); + + if (regval_expand&(info->expand_register.voltage_mask)) + /* Vaux3 has a different layout */ + val = info->expand_register.voltage_limit; + else + val = (regval & info->voltage_mask) >> info->voltage_shift; + + return val; +} + static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { @@ -426,6 +484,55 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } +static int ab8540_aux3_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned selector) +{ + int ret; + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + if (selector >= info->expand_register.voltage_limit) { + /* Vaux3 bit4 has different layout */ + regval = (u8)selector << info->expand_register.voltage_shift; + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->expand_register.voltage_bank, + info->expand_register.voltage_reg, + info->expand_register.voltage_mask, + regval); + } else { + /* set the registers for the request */ + regval = (u8)selector << info->voltage_shift; + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->voltage_bank, info->voltage_reg, + info->voltage_mask, regval); + } + if (ret < 0) + dev_err(rdev_get_dev(rdev), + "couldn't set voltage reg for regulator\n"); + + dev_vdbg(rdev_get_dev(rdev), + "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," + " 0x%x\n", + info->desc.name, info->voltage_bank, info->voltage_reg, + info->voltage_mask, regval); + + return ret; +} + +static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_sel, + unsigned int new_sel) +{ + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + + return info->delay; +} + static struct regulator_ops ab8500_regulator_volt_mode_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -438,6 +545,19 @@ static struct regulator_ops ab8500_regulator_volt_mode_ops = { .list_voltage = regulator_list_voltage_table, }; +static struct regulator_ops ab8540_aux3_regulator_volt_mode_ops = { + .enable = ab8500_regulator_enable, + .disable = ab8500_regulator_disable, + .get_optimum_mode = ab8500_regulator_get_optimum_mode, + .set_mode = ab8500_regulator_set_mode, + .get_mode = ab8500_regulator_get_mode, + .is_enabled = ab8500_regulator_is_enabled, + .get_voltage_sel = ab8540_aux3_regulator_get_voltage_sel, + .set_voltage_sel = ab8540_aux3_regulator_set_voltage_sel, + .list_voltage = regulator_list_voltage_table, + .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, +}; + static struct regulator_ops ab8500_regulator_volt_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -1271,7 +1391,7 @@ static struct ab8500_regulator_info [AB8540_LDO_AUX3] = { .desc = { .name = "LDO-AUX3", - .ops = &ab8500_regulator_volt_mode_ops, + .ops = &ab8540_aux3_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8540_LDO_AUX3, .owner = THIS_MODULE, @@ -1288,6 +1408,13 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x21, .voltage_mask = 0x07, + .expand_register = { + .voltage_limit = 8, + .voltage_bank = 0x04, + .voltage_reg = 0x01, + .voltage_mask = 0x10, + .voltage_shift = 1, + } }, [AB8540_LDO_AUX4] = { .desc = { -- cgit v1.2.3 From 3fe52289105823867226355e8e957119af50e3a1 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:12 +0100 Subject: regulator: ab8500: Add mode operation for v-amic v-amic1 and v-amic2 regulators have dedicated mode registers and share the same mode bit. This patch adds special handling for those regulators. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- arch/arm/mach-ux500/board-mop500-regulators.c | 10 +- drivers/regulator/ab8500.c | 193 +++++++++++++++++++++----- 2 files changed, 169 insertions(+), 34 deletions(-) (limited to 'drivers/regulator') diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index 62b4aa4cbfb3..832966311c29 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -877,7 +877,10 @@ struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = { [AB8505_LDO_ANAMIC1] = { .constraints = { .name = "V-AMIC1", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers), .consumer_supplies = ab8500_vamic1_consumers, @@ -886,7 +889,10 @@ struct regulator_init_data ab8505_regulators[AB8505_NUM_REGULATORS] = { [AB8505_LDO_ANAMIC2] = { .constraints = { .name = "V-AMIC2", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, + .valid_ops_mask = REGULATOR_CHANGE_STATUS | + REGULATOR_CHANGE_MODE, + .valid_modes_mask = REGULATOR_MODE_NORMAL | + REGULATOR_MODE_IDLE, }, .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers), .consumer_supplies = ab8500_vamic2_consumers, diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 6dae5dfb9fde..ac89439a4f9a 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -29,11 +29,23 @@ #include #include +/** + * struct ab8500_shared_mode - is used when mode is shared between + * two regulators. + * @shared_regulator: pointer to the other sharing regulator + * @lp_mode_req: low power mode requested by this regulator + */ +struct ab8500_shared_mode { + struct ab8500_regulator_info *shared_regulator; + bool lp_mode_req; +}; + /** * struct ab8500_regulator_info - ab8500 regulator information * @dev: device pointer * @desc: regulator description * @regulator_dev: regulator device + * @shared_mode: used when mode is shared between two regulators * @is_enabled: status of regulator (on/off) * @load_lp_uA: maximum load in idle (low power) mode * @update_bank: bank to control on/off @@ -42,6 +54,11 @@ * @update_val: bits holding the regulator current mode * @update_val_idle: bits to enable the regulator in idle (low power) mode * @update_val_normal: bits to enable the regulator in normal (high power) mode + * @mode_bank: bank with location of mode register + * @mode_reg: mode register + * @mode_mask: mask for setting mode + * @mode_val_idle: mode setting for low power + * @mode_val_normal: mode setting for normal power * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage @@ -51,6 +68,7 @@ struct ab8500_regulator_info { struct device *dev; struct regulator_desc desc; struct regulator_dev *regulator; + struct ab8500_shared_mode *shared_mode; bool is_enabled; int load_lp_uA; u8 update_bank; @@ -59,6 +77,11 @@ struct ab8500_regulator_info { u8 update_val; u8 update_val_idle; u8 update_val_normal; + u8 mode_bank; + u8 mode_reg; + u8 mode_mask; + u8 mode_val_idle; + u8 mode_val_normal; u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; @@ -189,6 +212,10 @@ static const unsigned int ldo_vaudio_voltages[] = { 2600000, /* Duplicated in Vaudio and IsoUicc Control register. */ }; +static DEFINE_MUTEX(shared_mode_mutex); +static struct ab8500_shared_mode ldo_anamic1_shared; +static struct ab8500_shared_mode ldo_anamic2_shared; + static int ab8500_regulator_enable(struct regulator_dev *rdev) { int ret; @@ -271,8 +298,12 @@ static unsigned int ab8500_regulator_get_optimum_mode( static int ab8500_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { - int ret; - u8 update_val; + int ret = 0; + u8 bank; + u8 reg; + u8 mask; + u8 val; + bool dmr = false; /* Dedicated mode register */ struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); if (info == NULL) { @@ -280,59 +311,128 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, return -EINVAL; } - switch (mode) { - case REGULATOR_MODE_NORMAL: - update_val = info->update_val_normal; - break; - case REGULATOR_MODE_IDLE: - update_val = info->update_val_idle; - break; - default: - return -EINVAL; + if (info->shared_mode) { + /* + * Special case where mode is shared between two regulators. + */ + struct ab8500_shared_mode *sm = info->shared_mode; + mutex_lock(&shared_mode_mutex); + + if (mode == REGULATOR_MODE_IDLE) { + sm->lp_mode_req = true; /* Low power mode requested */ + if (!((sm->shared_regulator)-> + shared_mode->lp_mode_req)) { + mutex_unlock(&shared_mode_mutex); + return 0; /* Other regulator prevent LP mode */ + } + } else { + sm->lp_mode_req = false; + } } - /* ab8500 regulators share mode and enable in the same register bits. - off = 0b00 - low power mode= 0b11 - full powermode = 0b01 - (HW control mode = 0b10) - Thus we don't write to the register when regulator is disabled. - */ - if (info->is_enabled) { + if (info->mode_mask) { + /* Dedicated register for handling mode */ + + dmr = true; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = info->mode_val_normal; + break; + case REGULATOR_MODE_IDLE: + val = info->mode_val_idle; + break; + default: + if (info->shared_mode) + mutex_unlock(&shared_mode_mutex); + return -EINVAL; + } + + bank = info->mode_bank; + reg = info->mode_reg; + mask = info->mode_mask; + } else { + /* Mode register same as enable register */ + + switch (mode) { + case REGULATOR_MODE_NORMAL: + info->update_val = info->update_val_normal; + val = info->update_val_normal; + break; + case REGULATOR_MODE_IDLE: + info->update_val = info->update_val_idle; + val = info->update_val_idle; + break; + default: + if (info->shared_mode) + mutex_unlock(&shared_mode_mutex); + return -EINVAL; + } + + bank = info->update_bank; + reg = info->update_reg; + mask = info->update_mask; + } + + if (info->is_enabled || dmr) { ret = abx500_mask_and_set_register_interruptible(info->dev, - info->update_bank, info->update_reg, - info->update_mask, update_val); - if (ret < 0) { + bank, reg, mask, val); + if (ret < 0) dev_err(rdev_get_dev(rdev), "couldn't set regulator mode\n"); - return ret; - } 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, update_val); + info->desc.name, bank, reg, + mask, val); } - info->update_val = update_val; + if (info->shared_mode) + mutex_unlock(&shared_mode_mutex); - return 0; + return ret; } static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) { struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); int ret; + u8 val; + u8 val_normal; + u8 val_idle; if (info == NULL) { dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); return -EINVAL; } - if (info->update_val == info->update_val_normal) + /* Need special handling for shared mode */ + if (info->shared_mode) { + if (info->shared_mode->lp_mode_req) + return REGULATOR_MODE_IDLE; + else + return REGULATOR_MODE_NORMAL; + } + + if (info->mode_mask) { + /* Dedicated register for handling mode */ + ret = abx500_get_register_interruptible(info->dev, + info->mode_bank, info->mode_reg, &val); + val = val & info->mode_mask; + + val_normal = info->mode_val_normal; + val_idle = info->mode_val_idle; + } else { + /* Mode register same as enable register */ + val = info->update_val; + val_normal = info->update_val_normal; + val_idle = info->update_val_idle; + } + + if (val == val_normal) ret = REGULATOR_MODE_NORMAL; - else if (info->update_val == info->update_val_idle) + else if (val == val_idle) ret = REGULATOR_MODE_IDLE; else ret = -EINVAL; @@ -585,6 +685,15 @@ static struct regulator_ops ab8500_regulator_ops = { .list_voltage = regulator_list_voltage_linear, }; +static struct regulator_ops ab8500_regulator_anamic_mode_ops = { + .enable = ab8500_regulator_enable, + .disable = ab8500_regulator_disable, + .is_enabled = ab8500_regulator_is_enabled, + .set_mode = ab8500_regulator_set_mode, + .get_mode = ab8500_regulator_get_mode, + .list_voltage = regulator_list_voltage_table, +}; + /* AB8500 regulator information */ static struct ab8500_regulator_info ab8500_regulator_info[AB8500_NUM_REGULATORS] = { @@ -1024,32 +1133,44 @@ static struct ab8500_regulator_info [AB8505_LDO_ANAMIC1] = { .desc = { .name = "LDO-ANAMIC1", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_anamic_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8505_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, }, + .shared_mode = &ldo_anamic1_shared, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x08, .update_val = 0x08, + .mode_bank = 0x01, + .mode_reg = 0x54, + .mode_mask = 0x04, + .mode_val_idle = 0x04, + .mode_val_normal = 0x00, }, [AB8505_LDO_ANAMIC2] = { .desc = { .name = "LDO-ANAMIC2", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_anamic_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8505_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, }, + .shared_mode = &ldo_anamic2_shared, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x10, .update_val = 0x10, + .mode_bank = 0x01, + .mode_reg = 0x54, + .mode_mask = 0x04, + .mode_val_idle = 0x04, + .mode_val_normal = 0x00, }, [AB8505_LDO_AUX8] = { .desc = { @@ -1589,6 +1710,14 @@ static struct ab8500_regulator_info }, }; +static struct ab8500_shared_mode ldo_anamic1_shared = { + .shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC2], +}; + +static struct ab8500_shared_mode ldo_anamic2_shared = { + .shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC1], +}; + struct ab8500_reg_init { u8 bank; u8 addr; -- cgit v1.2.3 From 4c84b4ddd4e3ce4ab475da96ba5531d4ce0741a4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:13 +0100 Subject: regulator: ab8500: Update vdmic, vamic[1|2] parameters for AB8540 Add voltage setting for vdmic; add LP mode setting for vamic1,2. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index ac89439a4f9a..ef12d3d79bdf 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -212,9 +212,18 @@ static const unsigned int ldo_vaudio_voltages[] = { 2600000, /* Duplicated in Vaudio and IsoUicc Control register. */ }; +static const unsigned int ldo_vdmic_voltages[] = { + 1800000, + 1900000, + 2000000, + 2850000, +}; + static DEFINE_MUTEX(shared_mode_mutex); static struct ab8500_shared_mode ldo_anamic1_shared; static struct ab8500_shared_mode ldo_anamic2_shared; +static struct ab8500_shared_mode ab8540_ldo_anamic1_shared; +static struct ab8500_shared_mode ab8540_ldo_anamic2_shared; static int ab8500_regulator_enable(struct regulator_dev *rdev) { @@ -1140,7 +1149,7 @@ static struct ab8500_regulator_info .n_voltages = 1, .volt_table = fixed_2050000_voltage, }, - .shared_mode = &ldo_anamic1_shared, + .shared_mode = &ldo_anamic1_shared, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x08, @@ -1624,46 +1633,64 @@ static struct ab8500_regulator_info [AB8540_LDO_ANAMIC1] = { .desc = { .name = "LDO-ANAMIC1", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_anamic_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8540_LDO_ANAMIC1, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, }, + .shared_mode = &ab8540_ldo_anamic1_shared, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x08, .update_val = 0x08, + .mode_bank = 0x03, + .mode_reg = 0x83, + .mode_mask = 0x20, + .mode_val_idle = 0x20, + .mode_val_normal = 0x00, }, [AB8540_LDO_ANAMIC2] = { .desc = { .name = "LDO-ANAMIC2", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_anamic_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8540_LDO_ANAMIC2, .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2050000_voltage, }, + .shared_mode = &ab8540_ldo_anamic2_shared, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x10, .update_val = 0x10, + .mode_bank = 0x03, + .mode_reg = 0x83, + .mode_mask = 0x20, + .mode_val_idle = 0x20, + .mode_val_normal = 0x00, }, [AB8540_LDO_DMIC] = { .desc = { .name = "LDO-DMIC", - .ops = &ab8500_regulator_ops, + .ops = &ab8500_regulator_volt_mode_ops, .type = REGULATOR_VOLTAGE, .id = AB8540_LDO_DMIC, .owner = THIS_MODULE, - .n_voltages = 1, + .n_voltages = ARRAY_SIZE(ldo_vdmic_voltages), }, + .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x83, .update_mask = 0x04, .update_val = 0x04, + .voltage_bank = 0x03, + .voltage_reg = 0x83, + .voltage_mask = 0xc0, + .voltages = ldo_vdmic_voltages, + .voltages_len = ARRAY_SIZE(ldo_vdmic_voltages), }, /* @@ -1718,6 +1745,14 @@ static struct ab8500_shared_mode ldo_anamic2_shared = { .shared_regulator = &ab8505_regulator_info[AB8505_LDO_ANAMIC1], }; +static struct ab8500_shared_mode ab8540_ldo_anamic1_shared = { + .shared_regulator = &ab8540_regulator_info[AB8540_LDO_ANAMIC2], +}; + +static struct ab8500_shared_mode ab8540_ldo_anamic2_shared = { + .shared_regulator = &ab8540_regulator_info[AB8540_LDO_ANAMIC1], +}; + struct ab8500_reg_init { u8 bank; u8 addr; -- cgit v1.2.3 From 1ec990c0020496ad32bf35726f7c033d09c2fce7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Apr 2013 21:08:24 +0800 Subject: regulator: dbx500-prcmu: Remove operating_point from struct dbx500_regulator_info operating_point is not used since the initial commit of db8500-prcmu driver, remove it. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/dbx500-prcmu.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/dbx500-prcmu.h b/drivers/regulator/dbx500-prcmu.h index e763883a44f4..c8e51ace9f06 100644 --- a/drivers/regulator/dbx500-prcmu.h +++ b/drivers/regulator/dbx500-prcmu.h @@ -21,7 +21,6 @@ * @is_enabled: status of the regulator * @epod_id: id for EPOD (power domain) * @is_ramret: RAM retention switch for EPOD (power domain) - * @operating_point: operating point (only for vape, to be removed) * */ struct dbx500_regulator_info { @@ -32,7 +31,6 @@ struct dbx500_regulator_info { u16 epod_id; bool is_ramret; bool exclude_from_power_state; - unsigned int operating_point; }; void power_state_active_enable(void); -- cgit v1.2.3 From 37daa8aed1af2e09abfdb66e8da9074eb9b9e1a1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Apr 2013 20:56:16 +0800 Subject: regulator: ab8500-ext: Don't update info->is_enabled if write to register fails Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index c24372e96922..57d43a10e6b0 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -72,9 +72,11 @@ static int enable(struct ab8500_ext_regulator_info *info, u8 *regval) ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, info->update_mask, *regval); - if (ret < 0) + if (ret < 0) { dev_err(rdev_get_dev(info->rdev), "couldn't set enable bits for regulator\n"); + return ret; + } info->is_enabled = true; @@ -117,9 +119,11 @@ static int disable(struct ab8500_ext_regulator_info *info, u8 *regval) ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, info->update_mask, *regval); - if (ret < 0) + if (ret < 0) { dev_err(rdev_get_dev(info->rdev), "couldn't set disable bits for regulator\n"); + return ret; + } info->is_enabled = false; -- cgit v1.2.3 From 33aeb49e247ff6b0d51301b92681a304f097c263 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:14 +0100 Subject: regulator: ab8500: Use a struct to select the good regulator configuration At the probe use a structure to select the good regulator array from from ab9540, ab8505, ab8540 or ab8500 configuration. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 135 +++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 71 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index ef12d3d79bdf..9cb634807ff8 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -2860,10 +2860,19 @@ static struct ab8500_reg_init ab8540_reg_init[] = { REG_INIT(AB8540_REGUCTRLDISCH4, 0x04, 0x49, 0x07), }; +static struct { + struct ab8500_regulator_info *info; + int info_size; + struct ab8500_reg_init *init; + int init_size; + struct of_regulator_match *match; + int match_size; +} abx500_regulator; + static int ab8500_regulator_init_registers(struct platform_device *pdev, - struct ab8500_reg_init *reg_init, int id, int mask, int value) { + struct ab8500_reg_init *reg_init = abx500_regulator.init; int err; BUG_ON(value & ~mask); @@ -2893,7 +2902,6 @@ static int ab8500_regulator_init_registers(struct platform_device *pdev, static int ab8500_regulator_register(struct platform_device *pdev, struct regulator_init_data *init_data, - struct ab8500_regulator_info *regulator_info, int id, struct device_node *np) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); @@ -2902,7 +2910,7 @@ static int ab8500_regulator_register(struct platform_device *pdev, int err; /* assign per-regulator data */ - info = ®ulator_info[id]; + info = &abx500_regulator.info[id]; info->dev = &pdev->dev; config.dev = &pdev->dev; @@ -2928,7 +2936,7 @@ static int ab8500_regulator_register(struct platform_device *pdev, info->desc.name); /* when we fail, un-register all earlier regulators */ while (--id >= 0) { - info = ®ulator_info[id]; + info = &abx500_regulator.info[id]; regulator_unregister(info->regulator); } return err; @@ -2995,19 +3003,49 @@ static struct of_regulator_match ab9540_regulator_match[] = { { .name = "ab8500_ldo_ana", .driver_data = (void *) AB9540_LDO_ANA, }, }; +static void abx500_get_regulator_info(struct ab8500 *ab8500) +{ + if (is_ab9540(ab8500)) { + abx500_regulator.info = ab9540_regulator_info; + abx500_regulator.info_size = ARRAY_SIZE(ab9540_regulator_info); + abx500_regulator.init = ab9540_reg_init; + abx500_regulator.init_size = AB9540_NUM_REGULATOR_REGISTERS; + abx500_regulator.match = ab9540_regulator_match; + abx500_regulator.match_size = ARRAY_SIZE(ab9540_regulator_match); + } else if (is_ab8505(ab8500)) { + abx500_regulator.info = ab8505_regulator_info; + abx500_regulator.info_size = ARRAY_SIZE(ab8505_regulator_info); + abx500_regulator.init = ab8505_reg_init; + abx500_regulator.init_size = AB8505_NUM_REGULATOR_REGISTERS; + abx500_regulator.match = ab8505_regulator_match; + abx500_regulator.match_size = ARRAY_SIZE(ab8505_regulator_match); + } else if (is_ab8540(ab8500)) { + abx500_regulator.info = ab8540_regulator_info; + abx500_regulator.info_size = ARRAY_SIZE(ab8540_regulator_info); + abx500_regulator.init = ab8540_reg_init; + abx500_regulator.init_size = AB8540_NUM_REGULATOR_REGISTERS; + abx500_regulator.match = ab8540_regulator_match; + abx500_regulator.match_size = ARRAY_SIZE(ab8540_regulator_match); + } else { + abx500_regulator.info = ab8500_regulator_info; + abx500_regulator.info_size = ARRAY_SIZE(ab8500_regulator_info); + abx500_regulator.init = ab8500_reg_init; + abx500_regulator.init_size = AB8500_NUM_REGULATOR_REGISTERS; + abx500_regulator.match = ab8500_regulator_match; + abx500_regulator.match_size = ARRAY_SIZE(ab8500_regulator_match); + } +} + static int ab8500_regulator_of_probe(struct platform_device *pdev, - struct ab8500_regulator_info *regulator_info, - int regulator_info_size, - struct of_regulator_match *match, struct device_node *np) { + struct of_regulator_match *match = abx500_regulator.match; int err, i; - for (i = 0; i < regulator_info_size; i++) { + for (i = 0; i < abx500_regulator.info_size; i++) { err = ab8500_regulator_register( - pdev, match[i].init_data, regulator_info, - i, match[i].of_node); + pdev, match[i].init_data, i, match[i].of_node); if (err) return err; } @@ -3019,59 +3057,31 @@ static int ab8500_regulator_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct device_node *np = pdev->dev.of_node; - struct of_regulator_match *match; struct ab8500_platform_data *ppdata; struct ab8500_regulator_platform_data *pdata; int i, err; - struct ab8500_regulator_info *regulator_info; - int regulator_info_size; - struct ab8500_reg_init *reg_init; - int reg_init_size; - if (is_ab9540(ab8500)) { - regulator_info = ab9540_regulator_info; - regulator_info_size = ARRAY_SIZE(ab9540_regulator_info); - reg_init = ab9540_reg_init; - reg_init_size = AB9540_NUM_REGULATOR_REGISTERS; - match = ab9540_regulator_match; - match_size = ARRAY_SIZE(ab9540_regulator_match) - } else if (is_ab8505(ab8500)) { - regulator_info = ab8505_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8505_regulator_info); - reg_init = ab8505_reg_init; - reg_init_size = AB8505_NUM_REGULATOR_REGISTERS; - } else if (is_ab8540(ab8500)) { - regulator_info = ab8540_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8540_regulator_info); - reg_init = ab8540_reg_init; - reg_init_size = AB8540_NUM_REGULATOR_REGISTERS; - } else { - regulator_info = ab8500_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); - reg_init = ab8500_reg_init; - reg_init_size = AB8500_NUM_REGULATOR_REGISTERS; - match = ab8500_regulator_match; - match_size = ARRAY_SIZE(ab8500_regulator_match) + if (!ab8500) { + dev_err(&pdev->dev, "null mfd parent\n"); + return -EINVAL; } + abx500_get_regulator_info(ab8500); + if (np) { - err = of_regulator_match(&pdev->dev, np, match, match_size); + err = of_regulator_match(&pdev->dev, np, + abx500_regulator.match, + abx500_regulator.match_size); if (err < 0) { dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", err); return err; } - err = ab8500_regulator_of_probe(pdev, regulator_info, - regulator_info_size, match, np); + err = ab8500_regulator_of_probe(pdev, np); return err; } - if (!ab8500) { - dev_err(&pdev->dev, "null mfd parent\n"); - return -EINVAL; - } - ppdata = dev_get_platdata(ab8500->dev); if (!ppdata) { dev_err(&pdev->dev, "null parent pdata\n"); @@ -3085,7 +3095,7 @@ static int ab8500_regulator_probe(struct platform_device *pdev) } /* make sure the platform data has the correct size */ - if (pdata->num_regulator != regulator_info_size) { + if (pdata->num_regulator != abx500_regulator.info_size) { dev_err(&pdev->dev, "Configuration error: size mismatch.\n"); return -EINVAL; } @@ -3104,9 +3114,9 @@ static int ab8500_regulator_probe(struct platform_device *pdev) value = pdata->reg_init[i].value; /* check for configuration errors */ - BUG_ON(id >= AB8500_NUM_REGULATOR_REGISTERS); + BUG_ON(id >= abx500_regulator.init_size); - err = ab8500_regulator_init_registers(pdev, reg_init, id, mask, value); + err = ab8500_regulator_init_registers(pdev, id, mask, value); if (err < 0) return err; } @@ -3119,9 +3129,9 @@ static int ab8500_regulator_probe(struct platform_device *pdev) } /* register all regulators */ - for (i = 0; i < regulator_info_size; i++) { + for (i = 0; i < abx500_regulator.info_size; i++) { err = ab8500_regulator_register(pdev, &pdata->regulator[i], - regulator_info, i, NULL); + i, NULL); if (err < 0) return err; } @@ -3133,27 +3143,10 @@ static int ab8500_regulator_remove(struct platform_device *pdev) { int i, err; struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); - struct ab8500_regulator_info *regulator_info; - int regulator_info_size; - - - if (is_ab9540(ab8500)) { - regulator_info = ab9540_regulator_info; - regulator_info_size = ARRAY_SIZE(ab9540_regulator_info); - } else if (is_ab8505(ab8500)) { - regulator_info = ab8505_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8505_regulator_info); - } else if (is_ab8540(ab8500)) { - regulator_info = ab8540_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8540_regulator_info); - } else { - regulator_info = ab8500_regulator_info; - regulator_info_size = ARRAY_SIZE(ab8500_regulator_info); - } - for (i = 0; i < regulator_info_size; i++) { + for (i = 0; i < abx500_regulator.info_size; i++) { struct ab8500_regulator_info *info = NULL; - info = ®ulator_info[i]; + info = &abx500_regulator.info[i]; dev_vdbg(rdev_get_dev(info->regulator), "%s-remove\n", info->desc.name); -- cgit v1.2.3 From 684d5ce4afafddb2ad08f36ea30ca7d7adc88ebe Mon Sep 17 00:00:00 2001 From: Zhenhua HUANG Date: Tue, 2 Apr 2013 13:24:15 +0100 Subject: regulator: ab8500: Introduce aux5, aux6 regulators for AB8540 Introduce aux5, aux6 into ab8540 regulator framework. Signed-off-by: Zhenhua HUANG Signed-off-by: Lee Jones Reviewed-by: Maxime COQUELIN Reviewed-by: David PARIS Reviewed-by: Philippe LANGLAIS Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 65 ++++++++++++++++++++++++++++++++++++++++ include/linux/regulator/ab8500.h | 2 ++ 2 files changed, 67 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 9cb634807ff8..433cac4396df 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -149,6 +149,21 @@ static const unsigned int ldo_vaux3_ab8540_voltages[] = { 3050000, }; +static const unsigned int ldo_vaux56_ab8540_voltages[] = { + 750000, 760000, 770000, 780000, 790000, 800000, + 810000, 820000, 830000, 840000, 850000, 860000, + 870000, 880000, 890000, 900000, 910000, 920000, + 930000, 940000, 950000, 960000, 970000, 980000, + 990000, 1000000, 1010000, 1020000, 1030000, + 1040000, 1050000, 1060000, 1070000, 1080000, + 1090000, 1100000, 1110000, 1120000, 1130000, + 1140000, 1150000, 1160000, 1170000, 1180000, + 1190000, 1200000, 1210000, 1220000, 1230000, + 1240000, 1250000, 1260000, 1270000, 1280000, + 1290000, 1300000, 1310000, 1320000, 1330000, + 1340000, 1350000, 1360000, 1800000, 2790000, +}; + static const unsigned int ldo_vintcore_voltages[] = { 1200000, 1225000, @@ -1569,6 +1584,54 @@ static struct ab8500_regulator_info .voltage_reg = 0x2f, .voltage_mask = 0x0f, }, + [AB8540_LDO_AUX5] = { + .desc = { + .name = "LDO-AUX5", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8540_LDO_AUX5, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), + }, + .load_lp_uA = 20000, + /* values for Vaux5Regu register */ + .update_bank = 0x04, + .update_reg = 0x32, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + /* values for Vaux5SEL register */ + .voltage_bank = 0x04, + .voltage_reg = 0x33, + .voltage_mask = 0x3f, + .voltages = ldo_vaux56_ab8540_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), + }, + [AB8540_LDO_AUX6] = { + .desc = { + .name = "LDO-AUX6", + .ops = &ab8500_regulator_volt_mode_ops, + .type = REGULATOR_VOLTAGE, + .id = AB8540_LDO_AUX6, + .owner = THIS_MODULE, + .n_voltages = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), + }, + .load_lp_uA = 20000, + /* values for Vaux6Regu register */ + .update_bank = 0x04, + .update_reg = 0x35, + .update_mask = 0x03, + .update_val = 0x01, + .update_val_idle = 0x03, + .update_val_normal = 0x01, + /* values for Vaux6SEL register */ + .voltage_bank = 0x04, + .voltage_reg = 0x36, + .voltage_mask = 0x3f, + .voltages = ldo_vaux56_ab8540_voltages, + .voltages_len = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), + }, [AB8540_LDO_INTCORE] = { .desc = { .name = "LDO-INTCORE", @@ -2979,6 +3042,8 @@ static struct of_regulator_match ab8540_regulator_match[] = { { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8540_LDO_AUX2, }, { .name = "ab8500_ldo_aux3", .driver_data = (void *) AB8540_LDO_AUX3, }, { .name = "ab8500_ldo_aux4", .driver_data = (void *) AB8540_LDO_AUX4, }, + { .name = "ab8500_ldo_aux5", .driver_data = (void *) AB8540_LDO_AUX5, }, + { .name = "ab8500_ldo_aux6", .driver_data = (void *) AB8540_LDO_AUX6, }, { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8540_LDO_INTCORE, }, { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB8540_LDO_TVOUT, }, { .name = "ab8500_ldo_audio", .driver_data = (void *) AB8540_LDO_AUDIO, }, diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 44f67e8f1a6d..90b8b5ae9a4e 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -74,6 +74,8 @@ enum ab8540_regulator_id { AB8540_LDO_AUX2, AB8540_LDO_AUX3, AB8540_LDO_AUX4, + AB8540_LDO_AUX5, + AB8540_LDO_AUX6, AB8540_LDO_INTCORE, AB8540_LDO_TVOUT, AB8540_LDO_AUDIO, -- cgit v1.2.3 From a4d68468ca6b24786ba0541bca27871f47e135b1 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:16 +0100 Subject: regulator: ab8500: Set enable enable_time in regulator_desc Allow the regulator framework to directly access the time it takes any given regulator to settle. This saves time and code because without it we would have to implement a dedication function to read the value from elsewhere. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 433cac4396df..8a9cd45eac02 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -1106,6 +1106,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2000000_voltage, + .enable_time = 10000, }, .delay = 10000, .load_lp_uA = 1000, @@ -1371,6 +1372,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .volt_table = fixed_2000000_voltage, + .enable_time = 10000, }, .delay = 10000, .load_lp_uA = 1000, @@ -1668,6 +1670,7 @@ static struct ab8500_regulator_info .id = AB8540_LDO_TVOUT, .owner = THIS_MODULE, .n_voltages = 1, + .enable_time = 10000, }, .delay = 10000, .load_lp_uA = 1000, -- cgit v1.2.3 From 5fc9da6d372cc2a75beef7c65b7559fcd1a2716e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:17 +0100 Subject: regulator: ab8500: Remove the need for a 'delay' property The regulator framework now has provisions to read a regulator's start-up time via the 'enable_time' attribute. So let's remove all 'enable_time'/'delay' duplication and just stick with 'enable_time' from now on. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 8a9cd45eac02..7892a516d074 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -654,7 +654,7 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, { struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - return info->delay; + return info->desc.enable_time; } static struct regulator_ops ab8500_regulator_volt_mode_ops = { @@ -1108,7 +1108,6 @@ static struct ab8500_regulator_info .volt_table = fixed_2000000_voltage, .enable_time = 10000, }, - .delay = 10000, .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x80, @@ -1374,7 +1373,6 @@ static struct ab8500_regulator_info .volt_table = fixed_2000000_voltage, .enable_time = 10000, }, - .delay = 10000, .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x80, @@ -1672,7 +1670,6 @@ static struct ab8500_regulator_info .n_voltages = 1, .enable_time = 10000, }, - .delay = 10000, .load_lp_uA = 1000, .update_bank = 0x03, .update_reg = 0x80, -- cgit v1.2.3 From d319310395bdaf3d99fdd221d7adcdb7270fb3cc Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:18 +0100 Subject: regulator: ab8500: Use regulator_list_voltage_table() to look-up voltages The regulator framework offers a generic regulator_list_voltage_table() function which can directly look-up a regulator's voltage capabilities using a table provided through the desc structure. This patch ensures that information is available. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 7892a516d074..bb574bfaac30 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -937,7 +937,7 @@ static struct ab8500_regulator_info * Variable Voltage Regulators * name, min mV, max mV, * update bank, reg, mask, enable val - * volt bank, reg, mask, table, table length + * volt bank, reg, mask */ [AB8505_LDO_AUX1] = { .desc = { @@ -1151,8 +1151,6 @@ static struct ab8500_regulator_info .voltage_reg = 0x57, .voltage_mask = 0x7, .voltage_shift = 4, - .voltages = ldo_vaudio_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaudio_voltages), }, [AB8505_LDO_ANAMIC1] = { .desc = { @@ -1234,8 +1232,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x29, .voltage_mask = 0x7, - .voltages = ldo_vana_voltages, - .voltages_len = ARRAY_SIZE(ldo_vana_voltages), }, }; @@ -1246,7 +1242,7 @@ static struct ab8500_regulator_info * Variable Voltage Regulators * name, min mV, max mV, * update bank, reg, mask, enable val - * volt bank, reg, mask, table, table length + * volt bank, reg, mask */ [AB9540_LDO_AUX1] = { .desc = { @@ -1489,7 +1485,7 @@ static struct ab8500_regulator_info * Variable Voltage Regulators * name, min mV, max mV, * update bank, reg, mask, enable val - * volt bank, reg, mask, table, table length + * volt bank, reg, mask */ [AB8540_LDO_AUX1] = { .desc = { @@ -1592,6 +1588,7 @@ static struct ab8500_regulator_info .id = AB8540_LDO_AUX5, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), + .volt_table = ldo_vaux56_ab8540_voltages, }, .load_lp_uA = 20000, /* values for Vaux5Regu register */ @@ -1605,8 +1602,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x33, .voltage_mask = 0x3f, - .voltages = ldo_vaux56_ab8540_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), }, [AB8540_LDO_AUX6] = { .desc = { @@ -1616,6 +1611,7 @@ static struct ab8500_regulator_info .id = AB8540_LDO_AUX6, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), + .volt_table = ldo_vaux56_ab8540_voltages, }, .load_lp_uA = 20000, /* values for Vaux6Regu register */ @@ -1629,8 +1625,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x36, .voltage_mask = 0x3f, - .voltages = ldo_vaux56_ab8540_voltages, - .voltages_len = ARRAY_SIZE(ldo_vaux56_ab8540_voltages), }, [AB8540_LDO_INTCORE] = { .desc = { @@ -1743,6 +1737,7 @@ static struct ab8500_regulator_info .id = AB8540_LDO_DMIC, .owner = THIS_MODULE, .n_voltages = ARRAY_SIZE(ldo_vdmic_voltages), + .volt_table = ldo_vdmic_voltages, }, .load_lp_uA = 1000, .update_bank = 0x03, @@ -1752,8 +1747,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x83, .voltage_mask = 0xc0, - .voltages = ldo_vdmic_voltages, - .voltages_len = ARRAY_SIZE(ldo_vdmic_voltages), }, /* -- cgit v1.2.3 From da45edc7f8e6930eb32e316bed3936bd05deeedd Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 2 Apr 2013 13:24:20 +0100 Subject: regulator: ab8500: Shuffle init functions into a more logical order The ab*_match[] arrays should be moved out of the way, instead of bunched in the middle of the initialisation functions. This patch moves all initialisation code which currently resides above these arrays down to be grouped with the others. This makes the whole thing slightly easier to read. Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 170 ++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 85 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index bb574bfaac30..535a94f6a4f1 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -2916,91 +2916,6 @@ static struct ab8500_reg_init ab8540_reg_init[] = { REG_INIT(AB8540_REGUCTRLDISCH4, 0x04, 0x49, 0x07), }; -static struct { - struct ab8500_regulator_info *info; - int info_size; - struct ab8500_reg_init *init; - int init_size; - struct of_regulator_match *match; - int match_size; -} abx500_regulator; - -static int ab8500_regulator_init_registers(struct platform_device *pdev, - int id, int mask, int value) -{ - struct ab8500_reg_init *reg_init = abx500_regulator.init; - int err; - - BUG_ON(value & ~mask); - BUG_ON(mask & ~reg_init[id].mask); - - /* initialize register */ - err = abx500_mask_and_set_register_interruptible( - &pdev->dev, - reg_init[id].bank, - reg_init[id].addr, - mask, value); - if (err < 0) { - dev_err(&pdev->dev, - "Failed to initialize 0x%02x, 0x%02x.\n", - reg_init[id].bank, - reg_init[id].addr); - return err; - } - dev_vdbg(&pdev->dev, - " init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - reg_init[id].bank, - reg_init[id].addr, - mask, value); - - return 0; -} - -static int ab8500_regulator_register(struct platform_device *pdev, - struct regulator_init_data *init_data, - int id, struct device_node *np) -{ - struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); - struct ab8500_regulator_info *info = NULL; - struct regulator_config config = { }; - int err; - - /* assign per-regulator data */ - info = &abx500_regulator.info[id]; - info->dev = &pdev->dev; - - config.dev = &pdev->dev; - config.init_data = init_data; - config.driver_data = info; - config.of_node = np; - - /* fix for hardware before ab8500v2.0 */ - if (is_ab8500_1p1_or_earlier(ab8500)) { - if (info->desc.id == AB8500_LDO_AUX3) { - info->desc.n_voltages = - ARRAY_SIZE(ldo_vauxn_voltages); - info->desc.volt_table = ldo_vauxn_voltages; - info->voltage_mask = 0xf; - } - } - - /* register regulator with framework */ - info->regulator = regulator_register(&info->desc, &config); - if (IS_ERR(info->regulator)) { - err = PTR_ERR(info->regulator); - dev_err(&pdev->dev, "failed to register regulator %s\n", - info->desc.name); - /* when we fail, un-register all earlier regulators */ - while (--id >= 0) { - info = &abx500_regulator.info[id]; - regulator_unregister(info->regulator); - } - return err; - } - - return 0; -} - static struct of_regulator_match ab8500_regulator_match[] = { { .name = "ab8500_ldo_aux1", .driver_data = (void *) AB8500_LDO_AUX1, }, { .name = "ab8500_ldo_aux2", .driver_data = (void *) AB8500_LDO_AUX2, }, @@ -3061,6 +2976,15 @@ static struct of_regulator_match ab9540_regulator_match[] = { { .name = "ab8500_ldo_ana", .driver_data = (void *) AB9540_LDO_ANA, }, }; +static struct { + struct ab8500_regulator_info *info; + int info_size; + struct ab8500_reg_init *init; + int init_size; + struct of_regulator_match *match; + int match_size; +} abx500_regulator; + static void abx500_get_regulator_info(struct ab8500 *ab8500) { if (is_ab9540(ab8500)) { @@ -3094,6 +3018,82 @@ static void abx500_get_regulator_info(struct ab8500 *ab8500) } } +static int ab8500_regulator_init_registers(struct platform_device *pdev, + int id, int mask, int value) +{ + struct ab8500_reg_init *reg_init = abx500_regulator.init; + int err; + + BUG_ON(value & ~mask); + BUG_ON(mask & ~reg_init[id].mask); + + /* initialize register */ + err = abx500_mask_and_set_register_interruptible( + &pdev->dev, + reg_init[id].bank, + reg_init[id].addr, + mask, value); + if (err < 0) { + dev_err(&pdev->dev, + "Failed to initialize 0x%02x, 0x%02x.\n", + reg_init[id].bank, + reg_init[id].addr); + return err; + } + dev_vdbg(&pdev->dev, + " init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + reg_init[id].bank, + reg_init[id].addr, + mask, value); + + return 0; +} + +static int ab8500_regulator_register(struct platform_device *pdev, + struct regulator_init_data *init_data, + int id, struct device_node *np) +{ + struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); + struct ab8500_regulator_info *info = NULL; + struct regulator_config config = { }; + int err; + + /* assign per-regulator data */ + info = &abx500_regulator.info[id]; + info->dev = &pdev->dev; + + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = info; + config.of_node = np; + + /* fix for hardware before ab8500v2.0 */ + if (is_ab8500_1p1_or_earlier(ab8500)) { + if (info->desc.id == AB8500_LDO_AUX3) { + info->desc.n_voltages = + ARRAY_SIZE(ldo_vauxn_voltages); + info->desc.volt_table = ldo_vauxn_voltages; + info->voltage_mask = 0xf; + } + } + + /* register regulator with framework */ + info->regulator = regulator_register(&info->desc, &config); + if (IS_ERR(info->regulator)) { + err = PTR_ERR(info->regulator); + dev_err(&pdev->dev, "failed to register regulator %s\n", + info->desc.name); + /* when we fail, un-register all earlier regulators */ + while (--id >= 0) { + info = &abx500_regulator.info[id]; + regulator_unregister(info->regulator); + } + return err; + } + + return 0; +} + static int ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np) -- cgit v1.2.3 From d7816ab09b4e8c6cbae1ec006558ca7f8c21f4e1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Apr 2013 13:24:22 +0100 Subject: regulator: ab8500: Fix list_voltage for fixed voltage regulators commit b080c78a4e447e9c212c207f725999d4e32c5f19 "regulator: ab8500: Update voltage handling for fixed voltage regulators" removes min_uV settings and sets volt_table for all fixed voltages, thus we can not use regulator_list_voltage_linear now. Use regulator_list_voltage_table instead. Signed-off-by: Axel Lin Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 535a94f6a4f1..d851c84bfa8c 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -699,14 +699,14 @@ static struct regulator_ops ab8500_regulator_mode_ops = { .get_optimum_mode = ab8500_regulator_get_optimum_mode, .set_mode = ab8500_regulator_set_mode, .get_mode = ab8500_regulator_get_mode, - .list_voltage = regulator_list_voltage_linear, + .list_voltage = regulator_list_voltage_table, }; static struct regulator_ops ab8500_regulator_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, - .list_voltage = regulator_list_voltage_linear, + .list_voltage = regulator_list_voltage_table, }; static struct regulator_ops ab8500_regulator_anamic_mode_ops = { -- cgit v1.2.3 From aca45e9e2fe90c496f238d87c3f27e294e99399a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 2 Apr 2013 13:24:23 +0100 Subject: regulator: ab8500: Add missing volt_table setting for AB8540_LDO_TVOUT This is required for regulator_list_voltage_table() to properly work. Signed-off-by: Axel Lin Signed-off-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index d851c84bfa8c..a8552a582ae7 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -1662,6 +1662,7 @@ static struct ab8500_regulator_info .id = AB8540_LDO_TVOUT, .owner = THIS_MODULE, .n_voltages = 1, + .volt_table = fixed_2000000_voltage, .enable_time = 10000, }, .load_lp_uA = 1000, -- cgit v1.2.3 From cd2a55d2eb8b58672d2805388aa4a8e354381c96 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 4 Apr 2013 06:05:17 +0800 Subject: regulator: ab8500: Remove ab8500_regulator_set_voltage_time_sel All users of ab8500_regulator_volt_mode_ops and ab8500_regulator_volt_ops do not set info->desc.enable_time, thus set_voltage_time_sel() always returns 0. Remove it. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index a8552a582ae7..517305e20126 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -648,15 +648,6 @@ static int ab8540_aux3_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } -static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, - unsigned int old_sel, - unsigned int new_sel) -{ - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - - return info->desc.enable_time; -} - static struct regulator_ops ab8500_regulator_volt_mode_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, @@ -679,7 +670,6 @@ static struct regulator_ops ab8540_aux3_regulator_volt_mode_ops = { .get_voltage_sel = ab8540_aux3_regulator_get_voltage_sel, .set_voltage_sel = ab8540_aux3_regulator_set_voltage_sel, .list_voltage = regulator_list_voltage_table, - .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; static struct regulator_ops ab8500_regulator_volt_ops = { @@ -689,7 +679,6 @@ static struct regulator_ops ab8500_regulator_volt_ops = { .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, .list_voltage = regulator_list_voltage_table, - .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; static struct regulator_ops ab8500_regulator_mode_ops = { -- cgit v1.2.3 From 438e695b87e03953fc4ba1aff59feab33c9c79a7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 7 Apr 2013 23:12:28 +0800 Subject: regulator: ab8500: Get rid of is_enabled from struct ab8500_regulator_info The intention of this patch is to simplify the code. Maintain the is_enabled flag is not trivial, it not only needs to set/clear the flag in disable()/enable() but also needs to set the flag in is_enable() to get initial status. The only benefit of keeping is_enabled flag is just save a register read when set_mode(). Remove is_enabled flag makes the code simpler. This patch also moves ab8500_regulator_is_enabled() close to ab8500_regulator_[en|dis]able functions. This is required to avoid a forward declaration because now we call ab8500_regulator_is_enabled() in ab8500_regulator_set_mode(). This change also makes the code better in readability by moving similar functions to one place. Signed-off-by: Axel Lin Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 72 +++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 40 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 517305e20126..9ebd131b2ec6 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -46,7 +46,6 @@ struct ab8500_shared_mode { * @desc: regulator description * @regulator_dev: regulator device * @shared_mode: used when mode is shared between two regulators - * @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_reg: register to control on/off @@ -69,7 +68,6 @@ struct ab8500_regulator_info { struct regulator_desc desc; struct regulator_dev *regulator; struct ab8500_shared_mode *shared_mode; - bool is_enabled; int load_lp_uA; u8 update_bank; u8 update_reg; @@ -259,8 +257,6 @@ static int ab8500_regulator_enable(struct regulator_dev *rdev) return ret; } - info->is_enabled = true; - dev_vdbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", info->desc.name, info->update_bank, info->update_reg, @@ -288,8 +284,6 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) return ret; } - info->is_enabled = false; - dev_vdbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", info->desc.name, info->update_bank, info->update_reg, @@ -298,6 +292,37 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev) return ret; } +static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) +{ + int ret; + struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; + + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } + + ret = abx500_get_register_interruptible(info->dev, + info->update_bank, info->update_reg, ®val); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't read 0x%x register\n", info->update_reg); + return ret; + } + + dev_vdbg(rdev_get_dev(rdev), + "%s-is_enabled (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, regval); + + if (regval & info->update_mask) + return 1; + else + return 0; +} + static unsigned int ab8500_regulator_get_optimum_mode( struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA) @@ -398,7 +423,7 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, mask = info->update_mask; } - if (info->is_enabled || dmr) { + if (dmr || ab8500_regulator_is_enabled(rdev)) { ret = abx500_mask_and_set_register_interruptible(info->dev, bank, reg, mask, val); if (ret < 0) @@ -464,39 +489,6 @@ static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) return ret; } -static int ab8500_regulator_is_enabled(struct regulator_dev *rdev) -{ - int ret; - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - u8 regval; - - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } - - ret = abx500_get_register_interruptible(info->dev, - info->update_bank, info->update_reg, ®val); - if (ret < 0) { - dev_err(rdev_get_dev(rdev), - "couldn't read 0x%x register\n", info->update_reg); - return ret; - } - - dev_vdbg(rdev_get_dev(rdev), - "%s-is_enabled (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, regval); - - if (regval & info->update_mask) - info->is_enabled = true; - else - info->is_enabled = false; - - return info->is_enabled; -} - static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) { int ret, val; -- cgit v1.2.3 From 9ab51a0eb46a1cd894b1bc784e7775f7c29918c0 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 7 Apr 2013 23:13:39 +0800 Subject: regulator: ab8500-ext: Get rid of is_enabled from struct ab8500_ext_regulator_info The intention of this patch is to simplify the code. Maintain the is_enabled flag is not trivial, it not only needs to set/clear the flag in disable()/enable() but also needs to set the flag in is_enable() to get initial status. The only benefit of keeping is_enabled flag is just save a register read when set_mode(). Remove is_enabled flag makes the code simpler. Signed-off-by: Axel Lin Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 57d43a10e6b0..5e604a2ad7cd 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -29,7 +29,6 @@ * @desc: regulator description * @rdev: regulator device * @cfg: regulator configuration (extension of regulator FW configuration) - * @is_enabled: status of regulator (on/off) * @update_bank: bank to control on/off * @update_reg: register to control on/off * @update_mask: mask to enable/disable and set mode of regulator @@ -46,7 +45,6 @@ struct ab8500_ext_regulator_info { struct regulator_desc desc; struct regulator_dev *rdev; struct ab8500_ext_regulator_cfg *cfg; - bool is_enabled; u8 update_bank; u8 update_reg; u8 update_mask; @@ -78,8 +76,6 @@ static int enable(struct ab8500_ext_regulator_info *info, u8 *regval) return ret; } - info->is_enabled = true; - return ret; } @@ -125,8 +121,6 @@ static int disable(struct ab8500_ext_regulator_info *info, u8 *regval) return ret; } - info->is_enabled = false; - return ret; } @@ -177,11 +171,9 @@ static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev) if (((regval & info->update_mask) == info->update_val_lp) || ((regval & info->update_mask) == info->update_val_hp)) - info->is_enabled = true; + return 1; else - info->is_enabled = false; - - return info->is_enabled; + return 0; } static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev, @@ -207,7 +199,7 @@ static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev, return -EINVAL; } - if (info->is_enabled) { + if (ab8500_ext_regulator_is_enabled(rdev)) { u8 regval; ret = enable(info, ®val); -- cgit v1.2.3 From bcbba9de0f66d30621a489dc8af07350f8d477fd Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 7 Apr 2013 23:15:24 +0800 Subject: regulator: ab8500-ext: Remove unnecessary checking for ab9540 and ab8540 This code was added by commit 0fe17e20a6 "regulator: ab8500-ext: Add support for AB9540 regulators" and commit bd44e2cb "regulator: ab8500: Also check for AB8505 based platforms" The original patch[1] is to set info->desc.ops = &ab9540_ext_regulator_ops. However, ab9540_ext_regulator_ops is identical to ab8500_ext_regulator_ops[2]. Thus we can complete remove the unnecessary checking for ab9540 and ab8540. [1] https://lkml.org/lkml/2013/3/28/333 [2] https://lkml.org/lkml/2013/4/1/178 Signed-off-by: Axel Lin Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 5e604a2ad7cd..c7896af4aaa8 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -389,15 +389,8 @@ int ab8500_ext_regulator_init(struct platform_device *pdev) config.init_data = &pdata->ext_regulator[i]; config.driver_data = info; - if ((is_ab9540(ab8500) || is_ab8540(ab8500)) && - ((info->desc.id == AB8500_EXT_SUPPLY1) || - (info->desc.id == AB8500_EXT_SUPPLY2) || - (info->desc.id == AB8500_EXT_SUPPLY3))) - info->desc.ops = &ab8500_ext_regulator_ops; - /* register regulator with framework */ info->rdev = regulator_register(&info->desc, &config); - if (IS_ERR(info->rdev)) { err = PTR_ERR(info->rdev); dev_err(&pdev->dev, "failed to register regulator %s\n", -- cgit v1.2.3 From e343ab08bddeb0ed83f0a85f06739569d3081e3a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 7 Apr 2013 23:17:50 +0800 Subject: regulator: ab8500-ext: Remove get_voltage to avoid duplicate implementation The implementation of ab8500_ext_fixed_get_voltage is identical to ab8500_ext_list_voltage. We can avoid the duplicate implementation by just remove get_voltage. For fixed regulator, regulator core will call list_voltage(rdev, 0) to get voltage if both get_voltage get_voltage_sel are not implemented. Signed-off-by: Axel Lin Acked-by: Lee Jones Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index c7896af4aaa8..9aee21cad379 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -237,21 +237,6 @@ static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev) return ret; } -static int ab8500_ext_fixed_get_voltage(struct regulator_dev *rdev) -{ - struct regulation_constraints *regu_constraints = rdev->constraints; - - if (regu_constraints == NULL) { - dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n"); - return -EINVAL; - } - if (regu_constraints->min_uV && regu_constraints->max_uV) { - if (regu_constraints->min_uV == regu_constraints->max_uV) - return regu_constraints->min_uV; - } - return -EINVAL; -} - static int ab8500_ext_list_voltage(struct regulator_dev *rdev, unsigned selector) { @@ -275,7 +260,6 @@ static struct regulator_ops ab8500_ext_regulator_ops = { .is_enabled = ab8500_ext_regulator_is_enabled, .set_mode = ab8500_ext_regulator_set_mode, .get_mode = ab8500_ext_regulator_get_mode, - .get_voltage = ab8500_ext_fixed_get_voltage, .list_voltage = ab8500_ext_list_voltage, }; -- cgit v1.2.3 From 3480c0cab6e1a25fdeb63147b0b643b7825a36fb Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 11 Apr 2013 12:04:18 +0800 Subject: regulator: ab8500-ext: Make the return type of ab8500_ext_regulator_exit() void ab8500_ext_regulator_exit() never fails. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 4 +--- drivers/regulator/ab8500.c | 9 +++------ include/linux/regulator/ab8500.h | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 9aee21cad379..20680f30a968 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -394,7 +394,7 @@ int ab8500_ext_regulator_init(struct platform_device *pdev) return 0; } -int ab8500_ext_regulator_exit(struct platform_device *pdev) +void ab8500_ext_regulator_exit(struct platform_device *pdev) { int i; @@ -407,8 +407,6 @@ int ab8500_ext_regulator_exit(struct platform_device *pdev) regulator_unregister(info->rdev); } - - return 0; } MODULE_LICENSE("GPL v2"); diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 9ebd131b2ec6..c200f8bb61db 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -3194,12 +3194,9 @@ static int ab8500_regulator_remove(struct platform_device *pdev) regulator_unregister(info->regulator); } - if (!is_ab8505(ab8500)) { - /* remove external regulators (after Vaux1, 2 and 3) */ - err = ab8500_ext_regulator_exit(pdev); - if (err) - return err; - } + /* remove external regulators (after Vaux1, 2 and 3) */ + if (!is_ab8505(ab8500)) + ab8500_ext_regulator_exit(pdev); /* remove regulator debug */ err = ab8500_regulator_debug_exit(pdev); diff --git a/include/linux/regulator/ab8500.h b/include/linux/regulator/ab8500.h index 90b8b5ae9a4e..7c5ff0c55773 100644 --- a/include/linux/regulator/ab8500.h +++ b/include/linux/regulator/ab8500.h @@ -338,6 +338,6 @@ static inline int ab8500_regulator_debug_exit(struct platform_device *pdev) /* AB8500 external regulator functions. */ int ab8500_ext_regulator_init(struct platform_device *pdev); -int ab8500_ext_regulator_exit(struct platform_device *pdev); +void ab8500_ext_regulator_exit(struct platform_device *pdev); #endif -- cgit v1.2.3 From 42e8c811bab682121cb57d58e9a37d8cb38e51ca Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 11 Apr 2013 12:05:43 +0800 Subject: regulator: ab8500: Unregister ab8500-ext regulators in probe() failure path Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index c200f8bb61db..ea182d3c23e6 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -3172,8 +3172,11 @@ static int ab8500_regulator_probe(struct platform_device *pdev) for (i = 0; i < abx500_regulator.info_size; i++) { err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL); - if (err < 0) + if (err < 0) { + if (!is_ab8505(ab8500)) + ab8500_ext_regulator_exit(pdev); return err; + } } return 0; -- cgit v1.2.3 From e4fc9d6d9fea5a1b05dcf5b60984bd6a19cc73d6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 12 Apr 2013 15:33:25 +0800 Subject: regulator: ab8500: Fix voltage_mask for AB8505_LDO_AUDIO The voltage_mask and voltage_shift settings of AB8505_LDO_AUDIO are not matched. It looks like a typo in the voltage_mask settings. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index ea182d3c23e6..b81ff04749c3 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -1130,7 +1130,7 @@ static struct ab8500_regulator_info .update_val = 0x02, .voltage_bank = 0x01, .voltage_reg = 0x57, - .voltage_mask = 0x7, + .voltage_mask = 0x70, .voltage_shift = 4, }, [AB8505_LDO_ANAMIC1] = { -- cgit v1.2.3 From 375dc9c141b4d62b92bb171817039ef764c61d9f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 15 Apr 2013 16:36:51 +0800 Subject: regulator: ab8500: Fix voltage_shift setting for AB8540_LDO_DMIC The voltage_mask is 0xc0, thus we need to set voltage_shift = 6 to get correct selector in get_voltage_sel and set_voltage_sel. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index b81ff04749c3..0a62ef942cfb 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -1729,6 +1729,7 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x83, .voltage_mask = 0xc0, + .voltage_shift = 6, }, /* -- cgit v1.2.3 From 241896ce8d112f10dae5538be41fad9eeb9e5e46 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 10 Apr 2013 14:46:20 +0800 Subject: regulator: ab8500: Optimize ab8540_aux3_regulator_get_voltage_sel We can save a register read operation in some case if read expand_register first. If info->expand_register.voltage_mask bit is set, no need to read voltage_reg. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 0a62ef942cfb..29a727ca399b 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -521,7 +521,7 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev) { - int ret, val; + int ret; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); u8 regval, regval_expand; @@ -531,18 +531,25 @@ static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev) } ret = abx500_get_register_interruptible(info->dev, - info->voltage_bank, info->voltage_reg, ®val); - + info->expand_register.voltage_bank, + info->expand_register.voltage_reg, ®val_expand); if (ret < 0) { dev_err(rdev_get_dev(rdev), - "couldn't read voltage reg for regulator\n"); + "couldn't read voltage expand reg for regulator\n"); return ret; } - ret = abx500_get_register_interruptible(info->dev, - info->expand_register.voltage_bank, - info->expand_register.voltage_reg, ®val_expand); + dev_vdbg(rdev_get_dev(rdev), + "%s-get_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", + info->desc.name, info->expand_register.voltage_bank, + info->expand_register.voltage_reg, + info->expand_register.voltage_mask, regval_expand); + if (regval_expand & info->expand_register.voltage_mask) + return info->expand_register.voltage_limit; + + ret = abx500_get_register_interruptible(info->dev, + info->voltage_bank, info->voltage_reg, ®val); if (ret < 0) { dev_err(rdev_get_dev(rdev), "couldn't read voltage reg for regulator\n"); @@ -550,24 +557,11 @@ static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev) } dev_vdbg(rdev_get_dev(rdev), - "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," - " 0x%x\n", - info->desc.name, info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); - dev_vdbg(rdev_get_dev(rdev), - "%s-get_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," - " 0x%x\n", - info->desc.name, info->expand_register.voltage_bank, - info->expand_register.voltage_reg, - info->expand_register.voltage_mask, regval_expand); - - if (regval_expand&(info->expand_register.voltage_mask)) - /* Vaux3 has a different layout */ - val = info->expand_register.voltage_limit; - else - val = (regval & info->voltage_mask) >> info->voltage_shift; + "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", + info->desc.name, info->voltage_bank, info->voltage_reg, + info->voltage_mask, regval); - return val; + return (regval & info->voltage_mask) >> info->voltage_shift; } static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, -- cgit v1.2.3 From f04adc5ab3b70ad9b7d17d6a6fc2113669134a4d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 9 Apr 2013 20:15:06 +0800 Subject: regulator: ab8500: Don't update info->update_val if write to register fails This patch ensures info->update_val is consistent with current register value. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 29a727ca399b..5fd3b34274cc 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -392,9 +392,8 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, val = info->mode_val_idle; break; default: - if (info->shared_mode) - mutex_unlock(&shared_mode_mutex); - return -EINVAL; + ret = -EINVAL; + goto out_unlock; } bank = info->mode_bank; @@ -405,17 +404,14 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_NORMAL: - info->update_val = info->update_val_normal; val = info->update_val_normal; break; case REGULATOR_MODE_IDLE: - info->update_val = info->update_val_idle; val = info->update_val_idle; break; default: - if (info->shared_mode) - mutex_unlock(&shared_mode_mutex); - return -EINVAL; + ret = -EINVAL; + goto out_unlock; } bank = info->update_bank; @@ -426,9 +422,11 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, if (dmr || ab8500_regulator_is_enabled(rdev)) { ret = abx500_mask_and_set_register_interruptible(info->dev, bank, reg, mask, val); - if (ret < 0) + if (ret < 0) { dev_err(rdev_get_dev(rdev), "couldn't set regulator mode\n"); + goto out_unlock; + } dev_vdbg(rdev_get_dev(rdev), "%s-set_mode (bank, reg, mask, value): " @@ -437,6 +435,10 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, mask, val); } + if (!dmr) + info->update_val = val; + +out_unlock: if (info->shared_mode) mutex_unlock(&shared_mode_mutex); -- cgit v1.2.3 From 0b665062a1dde470d69ff3bd435b090a119991ab Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 9 Apr 2013 20:17:15 +0800 Subject: regulator: ab8500: Don't update lp_mode_req flag in set_mode() error paths Currently, set invalid mode setting for shared mode regulators may change sm->lp_mode_req flag. This patch ensures we don't set lp_mode_req flag to wrong status if set_mode() fails. This patch includes some clean up, and these changes makes this patch looks like code refactor. The clean up is mainly to avoid adding ugly code to handle failure paths. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 98 ++++++++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 55 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 5fd3b34274cc..109ce3dcf533 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -348,11 +348,8 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { int ret = 0; - u8 bank; - u8 reg; - u8 mask; - u8 val; - bool dmr = false; /* Dedicated mode register */ + u8 bank, reg, mask, val; + bool lp_mode_req = false; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); if (info == NULL) { @@ -360,66 +357,54 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, return -EINVAL; } - if (info->shared_mode) { - /* - * Special case where mode is shared between two regulators. - */ - struct ab8500_shared_mode *sm = info->shared_mode; - mutex_lock(&shared_mode_mutex); - - if (mode == REGULATOR_MODE_IDLE) { - sm->lp_mode_req = true; /* Low power mode requested */ - if (!((sm->shared_regulator)-> - shared_mode->lp_mode_req)) { - mutex_unlock(&shared_mode_mutex); - return 0; /* Other regulator prevent LP mode */ - } - } else { - sm->lp_mode_req = false; - } - } - if (info->mode_mask) { - /* Dedicated register for handling mode */ - - dmr = true; - - switch (mode) { - case REGULATOR_MODE_NORMAL: - val = info->mode_val_normal; - break; - case REGULATOR_MODE_IDLE: - val = info->mode_val_idle; - break; - default: - ret = -EINVAL; - goto out_unlock; - } - bank = info->mode_bank; reg = info->mode_reg; mask = info->mode_mask; } else { - /* Mode register same as enable register */ + bank = info->update_bank; + reg = info->update_reg; + mask = info->update_mask; + } + + if (info->shared_mode) + mutex_lock(&shared_mode_mutex); + + switch (mode) { + case REGULATOR_MODE_NORMAL: + if (info->shared_mode) + lp_mode_req = false; - switch (mode) { - case REGULATOR_MODE_NORMAL: + if (info->mode_mask) + val = info->mode_val_normal; + else val = info->update_val_normal; - break; - case REGULATOR_MODE_IDLE: - val = info->update_val_idle; - break; - default: - ret = -EINVAL; - goto out_unlock; + break; + case REGULATOR_MODE_IDLE: + if (info->shared_mode) { + struct ab8500_regulator_info *shared_regulator; + + shared_regulator = info->shared_mode->shared_regulator; + if (!shared_regulator->shared_mode->lp_mode_req) { + /* Other regulator prevent LP mode */ + info->shared_mode->lp_mode_req = true; + goto out_unlock; + } + + lp_mode_req = true; } - bank = info->update_bank; - reg = info->update_reg; - mask = info->update_mask; + if (info->mode_mask) + val = info->mode_val_idle; + else + val = info->update_val_idle; + break; + default: + ret = -EINVAL; + goto out_unlock; } - if (dmr || ab8500_regulator_is_enabled(rdev)) { + if (info->mode_mask || ab8500_regulator_is_enabled(rdev)) { ret = abx500_mask_and_set_register_interruptible(info->dev, bank, reg, mask, val); if (ret < 0) { @@ -435,9 +420,12 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev, mask, val); } - if (!dmr) + if (!info->mode_mask) info->update_val = val; + if (info->shared_mode) + info->shared_mode->lp_mode_req = lp_mode_req; + out_unlock: if (info->shared_mode) mutex_unlock(&shared_mode_mutex); -- cgit v1.2.3 From 66511fa4a7902fb9ffdffc8c153f1758817fb8a4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 16 Apr 2013 23:29:12 +0800 Subject: regulator: ab8500-ext: Don't update info->update_val if set_mode() fails This ensures info->update_val status is still correct if set_mode() call fails. Otherwise, get_mode() may return wrong status if a set_mode() call fails. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 20680f30a968..03faf9c698c4 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -181,6 +181,7 @@ static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev, { int ret = 0; struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; if (info == NULL) { dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); @@ -189,23 +190,30 @@ static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev, switch (mode) { case REGULATOR_MODE_NORMAL: - info->update_val = info->update_val_hp; + regval = info->update_val_hp; break; case REGULATOR_MODE_IDLE: - info->update_val = info->update_val_lp; + regval = info->update_val_lp; break; default: return -EINVAL; } - if (ab8500_ext_regulator_is_enabled(rdev)) { - u8 regval; - - ret = enable(info, ®val); - if (ret < 0) + /* If regulator is enabled and info->cfg->hwreq is set, the regulator + must be on in high power, so we don't need to write the register with + the same value. + */ + if (ab8500_ext_regulator_is_enabled(rdev) && + !(info->cfg && info->cfg->hwreq)) { + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->update_bank, info->update_reg, + info->update_mask, regval); + if (ret < 0) { dev_err(rdev_get_dev(rdev), "Could not set regulator mode.\n"); + return ret; + } dev_dbg(rdev_get_dev(rdev), "%s-set_mode (bank, reg, mask, value): " @@ -214,7 +222,9 @@ static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev, info->update_mask, regval); } - return ret; + info->update_val = regval; + + return 0; } static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev) -- cgit v1.2.3 From 7384744d2de1638b5aa9cbe9f743e9067cb6a44a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 16 Apr 2013 23:33:00 +0800 Subject: regulator: ab8500-ext: Remove enable() and disable() functions Both enable() and disable() functions have only one caller, thus remove them. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500-ext.c | 64 +++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 41 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c index 03faf9c698c4..b4d45472aae6 100644 --- a/drivers/regulator/ab8500-ext.c +++ b/drivers/regulator/ab8500-ext.c @@ -54,32 +54,44 @@ struct ab8500_ext_regulator_info { u8 update_val_hw; }; -static int enable(struct ab8500_ext_regulator_info *info, u8 *regval) +static int ab8500_ext_regulator_enable(struct regulator_dev *rdev) { int ret; + struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); + u8 regval; - *regval = info->update_val; + if (info == NULL) { + dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); + return -EINVAL; + } /* * To satisfy both HW high power request and SW request, the regulator * must be on in high power. */ if (info->cfg && info->cfg->hwreq) - *regval = info->update_val_hp; + regval = info->update_val_hp; + else + regval = info->update_val; ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, - info->update_mask, *regval); + info->update_mask, regval); if (ret < 0) { dev_err(rdev_get_dev(info->rdev), "couldn't set enable bits for regulator\n"); return ret; } - return ret; + dev_dbg(rdev_get_dev(rdev), + "%s-enable (bank, reg, mask, value): 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", + info->desc.name, info->update_bank, info->update_reg, + info->update_mask, regval); + + return 0; } -static int ab8500_ext_regulator_enable(struct regulator_dev *rdev) +static int ab8500_ext_regulator_disable(struct regulator_dev *rdev) { int ret; struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); @@ -90,59 +102,29 @@ static int ab8500_ext_regulator_enable(struct regulator_dev *rdev) return -EINVAL; } - ret = enable(info, ®val); - - dev_dbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value):" - " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", - info->desc.name, info->update_bank, info->update_reg, - info->update_mask, regval); - - return ret; -} - -static int disable(struct ab8500_ext_regulator_info *info, u8 *regval) -{ - int ret; - - *regval = 0x0; - /* * Set the regulator in HW request mode if configured */ if (info->cfg && info->cfg->hwreq) - *regval = info->update_val_hw; + regval = info->update_val_hw; + else + regval = 0; ret = abx500_mask_and_set_register_interruptible(info->dev, info->update_bank, info->update_reg, - info->update_mask, *regval); + info->update_mask, regval); if (ret < 0) { dev_err(rdev_get_dev(info->rdev), "couldn't set disable bits for regulator\n"); return ret; } - return ret; -} - -static int ab8500_ext_regulator_disable(struct regulator_dev *rdev) -{ - int ret; - struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev); - u8 regval; - - if (info == NULL) { - dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); - return -EINVAL; - } - - ret = disable(info, ®val); - dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):" " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", info->desc.name, info->update_bank, info->update_reg, info->update_mask, regval); - return ret; + return 0; } static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev) -- cgit v1.2.3 From b4d12a79295ca216008af7970f208c6051fd408d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 17 Apr 2013 00:50:20 +0800 Subject: regulator: ab8500: Fix set voltage for AB8540_LDO_AUX3 When setting voltage for AB8540_LDO_AUX3, current code only updates one of info->voltage_reg and info->expand_register registers which is wrong. To ensure we set to correct voltage, it always needs to clear or set expand_register.voltage_mask bit of expand_register. The function of the expand register bit is the following (from the user manual): 0: VAUX3 output voltage is determined by Vaux3Sel bit settings in register VldoCVaux3Sel 1: VAUX3 output voltage is set to 3.05V regardless of Vaux3Sel settings in register VldoCVaux3Sel (VldoCVaux3Sel is the register at 0x0421) So when going to 3.05V, set the expand register bit. When leaving 3.05V for another voltage, set the target voltage before clearing the expand register bit. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 53 +++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 109ce3dcf533..279793e26d94 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -589,39 +589,52 @@ static int ab8540_aux3_regulator_set_voltage_sel(struct regulator_dev *rdev, { int ret; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - u8 regval; + u8 regval, regval_expand; if (info == NULL) { dev_err(rdev_get_dev(rdev), "regulator info null pointer\n"); return -EINVAL; } - if (selector >= info->expand_register.voltage_limit) { - /* Vaux3 bit4 has different layout */ - regval = (u8)selector << info->expand_register.voltage_shift; - ret = abx500_mask_and_set_register_interruptible(info->dev, - info->expand_register.voltage_bank, - info->expand_register.voltage_reg, - info->expand_register.voltage_mask, - regval); - } else { - /* set the registers for the request */ + if (selector < info->expand_register.voltage_limit) { regval = (u8)selector << info->voltage_shift; ret = abx500_mask_and_set_register_interruptible(info->dev, - info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); + info->voltage_bank, info->voltage_reg, + info->voltage_mask, regval); + if (ret < 0) { + dev_err(rdev_get_dev(rdev), + "couldn't set voltage reg for regulator\n"); + return ret; + } + + dev_vdbg(rdev_get_dev(rdev), + "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", + info->desc.name, info->voltage_bank, info->voltage_reg, + info->voltage_mask, regval); + + regval_expand = 0; + } else { + regval_expand = info->expand_register.voltage_mask; } - if (ret < 0) + + ret = abx500_mask_and_set_register_interruptible(info->dev, + info->expand_register.voltage_bank, + info->expand_register.voltage_reg, + info->expand_register.voltage_mask, + regval_expand); + if (ret < 0) { dev_err(rdev_get_dev(rdev), - "couldn't set voltage reg for regulator\n"); + "couldn't set expand voltage reg for regulator\n"); + return ret; + } dev_vdbg(rdev_get_dev(rdev), - "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," - " 0x%x\n", - info->desc.name, info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); + "%s-set_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n", + info->desc.name, info->expand_register.voltage_bank, + info->expand_register.voltage_reg, + info->expand_register.voltage_mask, regval_expand); - return ret; + return 0; } static struct regulator_ops ab8500_regulator_volt_mode_ops = { -- cgit v1.2.3 From 9135d3bcec6c087fa2ef4fbde8b80ff8b27b34c7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 17 Apr 2013 22:54:00 +0800 Subject: regulator: ab8500: Remove unused voltage_shift field from struct expand_register The voltage_shift field of struct expand_register is not used now, remove it. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 279793e26d94..ece31a33aa2e 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -89,7 +89,6 @@ struct ab8500_regulator_info { u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; - u8 voltage_shift; } expand_register; }; @@ -1532,7 +1531,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x04, .voltage_reg = 0x01, .voltage_mask = 0x10, - .voltage_shift = 1, } }, [AB8540_LDO_AUX4] = { -- cgit v1.2.3 From 5d9de8b1216c60c15b02982c9f6b4875f757db02 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 17 Apr 2013 22:55:45 +0800 Subject: regulator: ab8500: Get rid of voltage_shift field from struct ab8500_regulator_info The voltage_shift can be calculated from voltage_mask. Let's remove voltage_shift fied from struct ab8500_regulator_info, this change can prevent missing voltage_shift setting issue. Signed-off-by: Axel Lin Acked-by: Bengt Jonsson Signed-off-by: Mark Brown --- drivers/regulator/ab8500.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers/regulator') diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index ece31a33aa2e..f6656b8c28b6 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -61,7 +61,6 @@ struct ab8500_shared_mode { * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage - * @voltage_shift: shift to control regulator voltage */ struct ab8500_regulator_info { struct device *dev; @@ -83,7 +82,6 @@ struct ab8500_regulator_info { u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; - u8 voltage_shift; struct { u8 voltage_limit; u8 voltage_bank; @@ -480,7 +478,7 @@ static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev) static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) { - int ret, val; + int ret, voltage_shift; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); u8 regval; @@ -489,6 +487,8 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) return -EINVAL; } + voltage_shift = ffs(info->voltage_mask) - 1; + ret = abx500_get_register_interruptible(info->dev, info->voltage_bank, info->voltage_reg, ®val); if (ret < 0) { @@ -502,15 +502,14 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) "0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", info->desc.name, info->voltage_bank, info->voltage_reg, info->voltage_mask, - info->voltage_shift, regval); + voltage_shift, regval); - val = regval & info->voltage_mask; - return val >> info->voltage_shift; + return (regval & info->voltage_mask) >> voltage_shift; } static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev) { - int ret; + int ret, voltage_shift; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); u8 regval, regval_expand; @@ -550,13 +549,15 @@ static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev) info->desc.name, info->voltage_bank, info->voltage_reg, info->voltage_mask, regval); - return (regval & info->voltage_mask) >> info->voltage_shift; + voltage_shift = ffs(info->voltage_mask) - 1; + + return (regval & info->voltage_mask) >> voltage_shift; } static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { - int ret; + int ret, voltage_shift; struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); u8 regval; @@ -565,8 +566,10 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, return -EINVAL; } + voltage_shift = ffs(info->voltage_mask) - 1; + /* set the registers for the request */ - regval = (u8)selector << info->voltage_shift; + regval = (u8)selector << voltage_shift; ret = abx500_mask_and_set_register_interruptible(info->dev, info->voltage_bank, info->voltage_reg, info->voltage_mask, regval); @@ -596,7 +599,9 @@ static int ab8540_aux3_regulator_set_voltage_sel(struct regulator_dev *rdev, } if (selector < info->expand_register.voltage_limit) { - regval = (u8)selector << info->voltage_shift; + int voltage_shift = ffs(info->voltage_mask) - 1; + + regval = (u8)selector << voltage_shift; ret = abx500_mask_and_set_register_interruptible(info->dev, info->voltage_bank, info->voltage_reg, info->voltage_mask, regval); @@ -791,7 +796,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltage_shift = 3, }, /* @@ -1066,7 +1070,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltage_shift = 3, }, /* @@ -1127,7 +1130,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x01, .voltage_reg = 0x57, .voltage_mask = 0x70, - .voltage_shift = 4, }, [AB8505_LDO_ANAMIC1] = { .desc = { @@ -1327,7 +1329,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltage_shift = 3, }, /* @@ -1622,7 +1623,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, - .voltage_shift = 3, }, /* @@ -1724,7 +1724,6 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x83, .voltage_mask = 0xc0, - .voltage_shift = 6, }, /* -- cgit v1.2.3