* @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
* @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;
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;
u8 voltage_bank;
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;
};
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,
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,
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,
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)
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) {
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:
- 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 */
+ 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:
- info->update_val = info->update_val_normal;
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ if (info->shared_mode)
+ lp_mode_req = false;
+
+ if (info->mode_mask)
+ val = info->mode_val_normal;
+ else
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;
+ 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 (info->is_enabled || dmr) {
+ 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)
+ 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): "
mask, val);
}
+ 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);
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;
+ int ret, voltage_shift;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
u8 regval;
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) {
"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, val;
+ int ret, voltage_shift;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
u8 regval, regval_expand;
}
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");
}
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);
+ "%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);
- 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;
+ voltage_shift = ffs(info->voltage_mask) - 1;
- return val;
+ 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;
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);
{
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;
+ if (selector < info->expand_register.voltage_limit) {
+ int voltage_shift = ffs(info->voltage_mask) - 1;
+
+ regval = (u8)selector << 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);
+ 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 {
- /* 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);
+ 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);
-
- 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);
+ "%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 info->delay;
+ return 0;
}
static struct regulator_ops ab8500_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 = {
.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 = {
.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 = {
.voltage_bank = 0x03,
.voltage_reg = 0x80,
.voltage_mask = 0x38,
- .voltage_shift = 3,
},
/*
* 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 = {
.voltage_bank = 0x03,
.voltage_reg = 0x80,
.voltage_mask = 0x38,
- .voltage_shift = 3,
},
/*
.owner = THIS_MODULE,
.n_voltages = 1,
.volt_table = fixed_2000000_voltage,
+ .enable_time = 10000,
},
- .delay = 10000,
.load_lp_uA = 1000,
.update_bank = 0x03,
.update_reg = 0x80,
.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),
+ .voltage_mask = 0x70,
},
[AB8505_LDO_ANAMIC1] = {
.desc = {
.voltage_bank = 0x04,
.voltage_reg = 0x29,
.voltage_mask = 0x7,
- .voltages = ldo_vana_voltages,
- .voltages_len = ARRAY_SIZE(ldo_vana_voltages),
},
};
* 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 = {
.voltage_bank = 0x03,
.voltage_reg = 0x80,
.voltage_mask = 0x38,
- .voltage_shift = 3,
},
/*
.owner = THIS_MODULE,
.n_voltages = 1,
.volt_table = fixed_2000000_voltage,
+ .enable_time = 10000,
},
- .delay = 10000,
.load_lp_uA = 1000,
.update_bank = 0x03,
.update_reg = 0x80,
* 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 = {
.voltage_bank = 0x04,
.voltage_reg = 0x01,
.voltage_mask = 0x10,
- .voltage_shift = 1,
}
},
[AB8540_LDO_AUX4] = {
.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),
+ .volt_table = 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,
+ },
+ [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),
+ .volt_table = 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,
+ },
[AB8540_LDO_INTCORE] = {
.desc = {
.name = "LDO-INTCORE",
.voltage_bank = 0x03,
.voltage_reg = 0x80,
.voltage_mask = 0x38,
- .voltage_shift = 3,
},
/*
.id = AB8540_LDO_TVOUT,
.owner = THIS_MODULE,
.n_voltages = 1,
+ .volt_table = fixed_2000000_voltage,
+ .enable_time = 10000,
},
- .delay = 10000,
.load_lp_uA = 1000,
.update_bank = 0x03,
.update_reg = 0x80,
.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,
.voltage_bank = 0x03,
.voltage_reg = 0x83,
.voltage_mask = 0xc0,
- .voltages = ldo_vdmic_voltages,
- .voltages_len = ARRAY_SIZE(ldo_vdmic_voltages),
},
/*
REG_INIT(AB8540_REGUCTRLDISCH4, 0x04, 0x49, 0x07),
};
+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, },
+ { .name = "ab8500_ldo_intcore", .driver_data = (void *) AB8500_LDO_INTCORE, },
+ { .name = "ab8500_ldo_tvout", .driver_data = (void *) AB8500_LDO_TVOUT, },
+ { .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, },
+ { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8500_LDO_DMIC, },
+ { .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 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_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, },
+ { .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, },
+ { .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 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)) {
+ 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_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);
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);
int err;
/* assign per-regulator data */
- info = ®ulator_info[id];
+ info = &abx500_regulator.info[id];
info->dev = &pdev->dev;
config.dev = &pdev->dev;
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;
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, },
- { .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_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, },
- { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8500_LDO_DMIC, },
- { .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 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, },
- { .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,
- 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;
}
{
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");
}
/* 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;
}
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;
}
}
/* 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);
- if (err < 0)
+ i, NULL);
+ if (err < 0) {
+ if (!is_ab8505(ab8500))
+ ab8500_ext_regulator_exit(pdev);
return err;
+ }
}
return 0;
{
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);
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);