|
@@ -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 = {
|