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') 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