aboutsummaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorBengt Jonsson <bengt.g.jonsson@stericsson.com>2010-09-07 09:52:20 +0200
committerMian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>2010-10-23 13:29:59 +0200
commit9e966b13b19d3dfa512d1e42084aac2cd50343c6 (patch)
treeeb821bf9a94b7c06530bd1cf041424ec10e7e0d8 /drivers/regulator
parent3c25db55f4a77e6b502fcfaf3e4f724771801aba (diff)
Regulators: Replaced ab8500 regulator driver from mainline.
Also added bugfixes, USB regulator, AB8500v2 support, U8500v1.0 support and verbose debug. MMC driver patched to support voltage levels for both AB8500v1 (AUX3 2.9 V) and AB8500v2 (AUX3 2.91 V). ST-Ericsson Id: AP 271209 Change-Id: I20b8dd846a5b29cf12e190e0f3f03aed0a034f41 Signed-off-by: Bengt Jonsson <bengt.g.jonsson@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/4940 Reviewed-by: Martin PERSSON <martin.persson@stericsson.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig1
-rw-r--r--drivers/regulator/ab8500.c454
2 files changed, 383 insertions, 72 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c9e2bf14680..33a702b4bba 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -67,6 +67,7 @@ config REGULATOR_USERSPACE_CONSUMER
config REGULATOR_AB8500
bool "ST-Ericsson AB8500 Power Regulators"
depends on AB8500_CORE
+ default y if AB8500_CORE
help
This driver supports the regulators found on the ST-Ericsson mixed
signal AB8500 PMIC
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index 4e261650d77..00702a65dd3 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -3,64 +3,74 @@
*
* License Terms: GNU General Public License v2
*
- * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
*
* AB8500 peripheral regulators
*
- * AB8500 supports the following regulators,
- * LDOs - VAUDIO, VANAMIC2/2, VDIGMIC, VINTCORE12, VTVOUT,
- * VAUX1/2/3, VANA
+ * AB8500 supports the following regulators:
+ * VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VANAMIC1/2, VDIGMIC, VANA
*
- * for DB8500 cut 1.0 and previous versions of the silicon, all accesses
- * to registers are through the DB8500 SPI. In cut 1.1 onwards, these
- * accesses are through the DB8500 PRCMU I2C
+ * For DB8500 cut 1.0 and previous versions of the silicon, all accesses
+ * to registers are done through the DB8500 SPI. Reading registers in bank 4
+ * does not work so special operations are used in this case. In cut 1.1
+ * onwards, these accesses are done through the DB8500 PRCMU I2C.
*
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
+#include <linux/delay.h>
#include <linux/platform_device.h>
-#include <linux/mfd/ab8500.h>
#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/ab8500.h>
+/* Used only for detecting old u8500v10 hardware */
+#include <mach/hardware.h>
+
/**
* struct ab8500_regulator_info - ab8500 regulator information
+ * @dev: device pointer
* @desc: regulator description
- * @ab8500: ab8500 parent
* @regulator_dev: regulator device
* @max_uV: maximum voltage (for variable voltage supplies)
* @min_uV: minimum voltage (for variable voltage supplies)
* @fixed_uV: typical voltage (for fixed voltage supplies)
- * @update_bank: bank to control on/off
+ * @update_bank: register bank to control on/off
* @update_reg: register to control on/off
* @mask: mask to enable/disable regulator
* @enable: bits to enable the regulator in normal(high power) mode
- * @voltage_bank: bank to control regulator voltage
+ * @voltage_bank: register bank to control regulator voltage
* @voltage_reg: register to control regulator voltage
* @voltage_mask: mask to control regulator voltage
* @supported_voltages: supported voltage table
* @voltages_len: number of supported voltages for the regulator
+ * @delay: startup delay in ms
+ * @is_enabled: status of the regulator (only used with v10 ops)
+ * @voltage_regval: status of the voltage register (only used with v10 ops)
*/
struct ab8500_regulator_info {
struct device *dev;
struct regulator_desc desc;
- struct ab8500 *ab8500;
struct regulator_dev *regulator;
int max_uV;
int min_uV;
int fixed_uV;
- u8 update_bank;
- u8 update_reg;
- u8 mask;
- u8 enable;
- u8 voltage_bank;
- u8 voltage_reg;
- u8 voltage_mask;
+ int update_bank;
+ int update_reg;
+ int mask;
+ int enable;
+ int voltage_bank;
+ int voltage_reg;
+ int voltage_mask;
int const *supported_voltages;
int voltages_len;
+ unsigned int delay;
+ bool is_enabled;
+ int voltage_regval;
};
/* voltage tables for the vauxn/vintcore supplies */
@@ -83,6 +93,17 @@ static const int ldo_vauxn_voltages[] = {
3300000,
};
+static const int ldo_vaux3_voltages[] = {
+ 1200000,
+ 1500000,
+ 1800000,
+ 2100000,
+ 2500000,
+ 2750000,
+ 2790000,
+ 2910000,
+};
+
static const int ldo_vintcore_voltages[] = {
1200000,
1225000,
@@ -103,10 +124,19 @@ static int ab8500_regulator_enable(struct regulator_dev *rdev)
return -EINVAL;
ret = abx500_mask_and_set_register_interruptible(info->dev,
- info->update_bank, info->update_reg, info->mask, info->enable);
+ info->update_bank, info->update_reg,
+ info->mask, info->enable);
if (ret < 0)
dev_err(rdev_get_dev(rdev),
"couldn't set enable bits for regulator\n");
+
+ msleep(info->delay);
+
+ 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->mask, info->enable);
+
return ret;
}
@@ -120,10 +150,19 @@ static int ab8500_regulator_disable(struct regulator_dev *rdev)
return -EINVAL;
ret = abx500_mask_and_set_register_interruptible(info->dev,
- info->update_bank, info->update_reg, info->mask, 0x0);
+ info->update_bank, info->update_reg,
+ info->mask, 0x0);
if (ret < 0)
dev_err(rdev_get_dev(rdev),
"couldn't set disable bits for regulator\n");
+
+ msleep(info->delay);
+
+ 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,
+ info->mask, 0x0);
+
return ret;
}
@@ -131,21 +170,28 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
{
int regulator_id, ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
- u8 value;
+ u8 regval;
regulator_id = rdev_get_id(rdev);
if (regulator_id >= AB8500_NUM_REGULATORS)
return -EINVAL;
ret = abx500_get_register_interruptible(info->dev,
- info->update_bank, info->update_reg, &value);
+ info->update_bank, info->update_reg, &regval);
+
if (ret < 0) {
dev_err(rdev_get_dev(rdev),
"couldn't read 0x%x register\n", info->update_reg);
return ret;
}
- if (value & info->mask)
+ 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->mask, regval);
+
+ if (regval & info->mask)
return true;
else
return false;
@@ -172,28 +218,34 @@ static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
static int ab8500_regulator_get_voltage(struct regulator_dev *rdev)
{
- int regulator_id, ret;
+ int regulator_id, ret, val;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
- u8 value;
+ u8 regval;
regulator_id = rdev_get_id(rdev);
if (regulator_id >= AB8500_NUM_REGULATORS)
return -EINVAL;
- ret = abx500_get_register_interruptible(info->dev, info->voltage_bank,
- info->voltage_reg, &value);
+ ret = abx500_get_register_interruptible(info->dev,
+ info->voltage_bank, info->voltage_reg, &regval);
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);
+
/* vintcore has a different layout */
- value &= info->voltage_mask;
+ val = regval & info->voltage_mask;
if (regulator_id == AB8500_LDO_INTCORE)
- ret = info->supported_voltages[value >> 0x3];
+ ret = info->supported_voltages[val >> 0x3];
else
- ret = info->supported_voltages[value];
+ ret = info->supported_voltages[val];
return ret;
}
@@ -219,6 +271,7 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
{
int regulator_id, ret;
struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+ u8 regval;
regulator_id = rdev_get_id(rdev);
if (regulator_id >= AB8500_NUM_REGULATORS)
@@ -233,13 +286,217 @@ static int ab8500_regulator_set_voltage(struct regulator_dev *rdev,
}
/* set the registers for the request */
+ regval = (u8)ret;
ret = abx500_mask_and_set_register_interruptible(info->dev,
- info->voltage_bank, info->voltage_reg,
- info->voltage_mask, (u8)ret);
+ 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");
+ msleep(info->delay);
+
+ 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 struct ab8500_regulator_info ab8500_regulator_info[];
+
+static int ab8500_v10_regulator_enable(struct regulator_dev *rdev)
+{
+ int regulator_id, ret;
+ struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+ int val;
+
+ regulator_id = rdev_get_id(rdev);
+ switch (regulator_id) {
+ case AB8500_LDO_AUX1:
+ info->is_enabled = true;
+ val = info->enable;
+ if (ab8500_regulator_info[AB8500_LDO_AUX2].is_enabled == true)
+ val |= ab8500_regulator_info[AB8500_LDO_AUX2].enable;
+ break;
+ case AB8500_LDO_AUX2:
+ info->is_enabled = true;
+ val = info->enable;
+ if (ab8500_regulator_info[AB8500_LDO_AUX1].is_enabled == true)
+ val |= ab8500_regulator_info[AB8500_LDO_AUX1].enable;
+ break;
+ case AB8500_LDO_AUX3:
+ info->is_enabled = true;
+ val = info->enable;
+ val |= 0x4; /* put VRF1 in HP mode */
+ break;
+ case AB8500_LDO_ANA:
+ info->is_enabled = true;
+ val = info->enable;
+ val |= 0x1; /* put VPLL in HP mode */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = abx500_set_register_interruptible(info->dev,
+ info->update_bank, info->update_reg,
+ val);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "couldn't enable %s\n", info->desc.name);
+ return ret;
+ }
+
+ msleep(info->delay);
+
+ dev_vdbg(rdev_get_dev(rdev),
+ "%s_v10-enable (bank, reg, value): 0x%x, 0x%x, 0x%x\n",
+ info->desc.name, info->update_bank, info->update_reg,
+ val);
+
+ return 0;
+}
+
+static int ab8500_v10_regulator_disable(struct regulator_dev *rdev)
+{
+ int regulator_id, ret;
+ struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+ int val;
+
+ regulator_id = rdev_get_id(rdev);
+ switch (regulator_id) {
+ case AB8500_LDO_AUX1:
+ info->is_enabled = false;
+ val = 0x0;
+ if (ab8500_regulator_info[AB8500_LDO_AUX2].is_enabled == true)
+ val |= ab8500_regulator_info[AB8500_LDO_AUX2].enable;
+ break;
+ case AB8500_LDO_AUX2:
+ info->is_enabled = false;
+ val = 0x0;
+ if (ab8500_regulator_info[AB8500_LDO_AUX1].is_enabled == true)
+ val |= ab8500_regulator_info[AB8500_LDO_AUX1].enable;
+ break;
+ case AB8500_LDO_AUX3:
+ info->is_enabled = false;
+ val = 0x4; /* put VRF1 in HP mode */
+ break;
+ case AB8500_LDO_ANA:
+ info->is_enabled = false;
+ val = 0x1; /* put VPLL in HP mode */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = abx500_set_register_interruptible(info->dev,
+ info->update_bank, info->update_reg,
+ val);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "couldn't disable %s\n", info->desc.name);
+ return ret;
+ }
+
+ msleep(info->delay);
+
+ dev_vdbg(rdev_get_dev(rdev),
+ "%s_v10-disable (bank, reg, value): 0x%x, 0x%x, 0x%x\n",
+ info->desc.name, info->update_bank, info->update_reg,
+ val);
+
+ return 0;
+}
+
+static int ab8500_v10_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ int regulator_id;
+ struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+ regulator_id = rdev_get_id(rdev);
+ switch (regulator_id) {
+ case AB8500_LDO_AUX1:
+ case AB8500_LDO_AUX2:
+ case AB8500_LDO_AUX3:
+ case AB8500_LDO_ANA:
+ printk(KERN_ALERT "regulator:"
+ "%s_v10-is_enabled (is_enabled): %i\n",
+ info->desc.name, info->is_enabled);
+ return info->is_enabled;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ab8500_v10_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ int regulator_id;
+ struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+ u8 regval;
+ int voltage;
+
+ regulator_id = rdev_get_id(rdev);
+ switch (regulator_id) {
+ case AB8500_LDO_AUX1:
+ case AB8500_LDO_AUX2:
+ case AB8500_LDO_AUX3:
+ regval = info->voltage_regval & info->voltage_mask;
+ voltage = info->supported_voltages[regval];
+ printk(KERN_ALERT "regulator:"
+ "%s_v10-get_voltage (regval, voltage): 0x%x, %i\n",
+ info->desc.name, regval, voltage);
+ return voltage;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ab8500_v10_regulator_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int regulator_id, ret;
+ struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+ regulator_id = rdev_get_id(rdev);
+ switch (regulator_id) {
+ case AB8500_LDO_AUX1:
+ case AB8500_LDO_AUX2:
+ ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "couldn't get best voltage for regulator\n");
+ return ret;
+ }
+ info->voltage_regval = ret;
+ break;
+ case AB8500_LDO_AUX3:
+ ret = ab8500_get_best_voltage_index(rdev, min_uV, max_uV);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "couldn't get best voltage for regulator\n");
+ return ret;
+ }
+ info->voltage_regval = ret;
+ info->voltage_regval |= 0x20; /* set VRF1 to 2.15 V */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = abx500_set_register_interruptible(info->dev,
+ info->voltage_bank, info->voltage_reg,
+ info->voltage_regval);
+
+ msleep(info->delay);
+
+ dev_vdbg(rdev_get_dev(rdev),
+ "%s_v10-set_voltage (bank, reg, value): 0x%x, 0x%x, 0x%x",
+ info->desc.name, info->voltage_bank, info->voltage_reg,
+ info->voltage_regval);
+
return ret;
}
@@ -252,6 +509,15 @@ static struct regulator_ops ab8500_regulator_ops = {
.list_voltage = ab8500_list_voltage,
};
+static struct regulator_ops ab8500_v10_regulator_ops = {
+ .enable = ab8500_v10_regulator_enable,
+ .disable = ab8500_v10_regulator_disable,
+ .is_enabled = ab8500_v10_regulator_is_enabled,
+ .get_voltage = ab8500_v10_regulator_get_voltage,
+ .set_voltage = ab8500_v10_regulator_set_voltage,
+ .list_voltage = ab8500_list_voltage,
+};
+
static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
{
int regulator_id;
@@ -272,6 +538,14 @@ static struct regulator_ops ab8500_ldo_fixed_ops = {
.list_voltage = ab8500_list_voltage,
};
+static struct regulator_ops ab8500_v10_ldo_fixed_ops = {
+ .enable = ab8500_v10_regulator_enable,
+ .disable = ab8500_v10_regulator_disable,
+ .is_enabled = ab8500_v10_regulator_is_enabled,
+ .get_voltage = ab8500_fixed_get_voltage,
+ .list_voltage = ab8500_list_voltage,
+};
+
#define AB8500_LDO(_id, dly, min, max, bank, reg, reg_mask, \
reg_enable, volt_bank, volt_reg, volt_mask, \
voltages, len_volts) \
@@ -298,49 +572,54 @@ static struct regulator_ops ab8500_ldo_fixed_ops = {
.fixed_uV = 0, \
}
-#define AB8500_FIXED_LDO(_id, fixed, bank, reg, \
- reg_mask, reg_enable) \
-{ \
- .desc = { \
- .name = "LDO-" #_id, \
- .ops = &ab8500_ldo_fixed_ops, \
- .type = REGULATOR_VOLTAGE, \
- .id = AB8500_LDO_##_id, \
- .owner = THIS_MODULE, \
- }, \
- .fixed_uV = fixed * 1000, \
- .update_bank = bank, \
- .update_reg = reg, \
- .mask = reg_mask, \
- .enable = reg_enable, \
+#define AB8500_FIXED_LDO(_id, dly, fixed, bank, reg, reg_mask, \
+ reg_enable) \
+{ \
+ .desc = { \
+ .name = "LDO-" #_id, \
+ .ops = &ab8500_ldo_fixed_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = AB8500_LDO_##_id, \
+ .owner = THIS_MODULE, \
+ }, \
+ .delay = dly, \
+ .fixed_uV = fixed * 1000, \
+ .update_bank = bank, \
+ .update_reg = reg, \
+ .mask = reg_mask, \
+ .enable = reg_enable, \
}
static struct ab8500_regulator_info ab8500_regulator_info[] = {
/*
* Variable Voltage LDOs
- * name, min uV, max uV, ctrl bank, ctrl reg, reg mask, enable mask,
- * volt ctrl bank, volt ctrl reg, volt ctrl mask, volt table,
- * num supported volts
+ * name, min uV, max uV, ctrl reg, enable mask, enable value,
+ * volt ctrl reg, volt ctrl mask, volt table, num supported volts
*/
- AB8500_LDO(AUX1, 1100, 3300, 0x04, 0x09, 0x3, 0x1, 0x04, 0x1f, 0xf,
- ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
- AB8500_LDO(AUX2, 1100, 3300, 0x04, 0x09, 0xc, 0x4, 0x04, 0x20, 0xf,
- ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
- AB8500_LDO(AUX3, 1100, 3300, 0x04, 0x0a, 0x3, 0x1, 0x04, 0x21, 0xf,
- ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
- AB8500_LDO(INTCORE, 1100, 3300, 0x03, 0x80, 0x4, 0x4, 0x03, 0x80, 0x38,
+ AB8500_LDO(AUX1, 0, 1100, 3300, 0x04, 0x09, 0x03, 0x01,
+ 0x04, 0x1f, 0x0f,
+ ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
+ AB8500_LDO(AUX2, 0, 1100, 3300, 0x04, 0x09, 0x0c, 0x04,
+ 0x04, 0x20, 0x0f,
+ ldo_vauxn_voltages, ARRAY_SIZE(ldo_vauxn_voltages)),
+ AB8500_LDO(AUX3, 0, 1100, 3300, 0x04, 0x0a, 0x03, 0x01,
+ 0x04, 0x21, 0x07,
+ ldo_vaux3_voltages, ARRAY_SIZE(ldo_vaux3_voltages)),
+ AB8500_LDO(INTCORE, 0, 1100, 3300, 0x03, 0x80, 0x44, 0x04,
+ 0x03, 0x80, 0x38,
ldo_vintcore_voltages, ARRAY_SIZE(ldo_vintcore_voltages)),
/*
* Fixed Voltage LDOs
- * name, o/p uV, ctrl bank, ctrl reg, enable, disable
+ * name, o/p uV, ctrl bank, ctrl reg, enable mask, enable value
*/
- AB8500_FIXED_LDO(TVOUT, 2000, 0x03, 0x80, 0x2, 0x2),
- AB8500_FIXED_LDO(AUDIO, 2000, 0x03, 0x83, 0x2, 0x2),
- AB8500_FIXED_LDO(ANAMIC1, 2050, 0x03, 0x83, 0x4, 0x4),
- AB8500_FIXED_LDO(ANAMIC2, 2050, 0x03, 0x83, 0x8, 0x8),
- AB8500_FIXED_LDO(DMIC, 1800, 0x03, 0x83, 0x10, 0x10),
- AB8500_FIXED_LDO(ANA, 1200, 0x03, 0x83, 0xc, 0x4),
+ AB8500_FIXED_LDO(TVOUT, 10, 2000, 0x03, 0x80, 0x82, 0x02),
+ AB8500_FIXED_LDO(USB, 0, 3300, 0x03, 0x82, 0x03, 0x01),
+ AB8500_FIXED_LDO(AUDIO, 0, 2000, 0x03, 0x83, 0x02, 0x02),
+ AB8500_FIXED_LDO(ANAMIC1, 0, 2050, 0x03, 0x83, 0x08, 0x08),
+ AB8500_FIXED_LDO(ANAMIC2, 0, 2050, 0x03, 0x83, 0x10, 0x10),
+ AB8500_FIXED_LDO(DMIC, 0, 1800, 0x03, 0x83, 0x04, 0x04),
+ AB8500_FIXED_LDO(ANA, 0, 1200, 0x04, 0x06, 0x0c, 0x04),
};
static inline struct ab8500_regulator_info *find_regulator_info(int id)
@@ -362,11 +641,6 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
struct ab8500_platform_data *pdata = dev_get_platdata(ab8500->dev);
int i, err;
- if (!ab8500) {
- dev_err(&pdev->dev, "null mfd parent\n");
- return -EINVAL;
- }
-
/* register all regulators */
for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
struct ab8500_regulator_info *info = NULL;
@@ -374,8 +648,35 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
/* assign per-regulator data */
info = &ab8500_regulator_info[i];
info->dev = &pdev->dev;
- info->ab8500 = ab8500;
+ /* fix for hardware before ab8500v2.0 */
+ if (abx500_get_chip_id(info->dev) < 0x20) {
+ if (info->desc.id == AB8500_LDO_AUX3) {
+ info->supported_voltages = ldo_vauxn_voltages;
+ info->voltages_len =
+ ARRAY_SIZE(ldo_vauxn_voltages);
+ info->voltage_mask = 0xf;
+ }
+ }
+
+ /* fix for u8500v1.0 */
+ if (cpu_is_u8500v10()) {
+ switch (info->desc.id) {
+ case AB8500_LDO_AUX1:
+ case AB8500_LDO_AUX2:
+ info->desc.ops = &ab8500_v10_regulator_ops;
+ break;
+ case AB8500_LDO_AUX3:
+ pdata->regulator[i]->constraints.always_on = 1;
+ info->desc.ops = &ab8500_v10_regulator_ops;
+ break;
+ case AB8500_LDO_ANA:
+ info->desc.ops = &ab8500_v10_ldo_fixed_ops;
+ break;
+ }
+ }
+
+ /* register with the regulator framework */
info->regulator = regulator_register(&info->desc, &pdev->dev,
pdata->regulator[i], info);
if (IS_ERR(info->regulator)) {
@@ -383,12 +684,17 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
/* when we fail, un-register all earlier regulators */
- while (--i >= 0) {
+ i--;
+ while (i > 0) {
info = &ab8500_regulator_info[i];
regulator_unregister(info->regulator);
+ i--;
}
return err;
}
+
+ dev_vdbg(rdev_get_dev(info->regulator),
+ "%s-probed\n", info->desc.name);
}
return 0;
@@ -401,6 +707,10 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
struct ab8500_regulator_info *info = NULL;
info = &ab8500_regulator_info[i];
+
+ dev_vdbg(rdev_get_dev(info->regulator),
+ "%s-removed\n", info->desc.name);
+
regulator_unregister(info->regulator);
}