aboutsummaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/ab3100.c236
-rw-r--r--drivers/regulator/ab8500-ext.c407
-rw-r--r--drivers/regulator/ab8500.c2662
-rw-r--r--drivers/regulator/arizona-ldo1.c2
-rw-r--r--drivers/regulator/as3711-regulator.c67
-rw-r--r--drivers/regulator/core.c43
-rw-r--r--drivers/regulator/db8500-prcmu.c4
-rw-r--r--drivers/regulator/dbx500-prcmu.h2
-rw-r--r--drivers/regulator/lp3971.c2
-rw-r--r--drivers/regulator/lp3972.c2
-rw-r--r--drivers/regulator/lp872x.c3
-rw-r--r--drivers/regulator/lp8788-buck.c2
-rw-r--r--drivers/regulator/mc13783-regulator.c44
-rw-r--r--drivers/regulator/mc13892-regulator.c46
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c17
-rw-r--r--drivers/regulator/mc13xxx.h4
-rw-r--r--drivers/regulator/palmas-regulator.c3
-rw-r--r--drivers/regulator/tps65023-regulator.c17
-rw-r--r--drivers/regulator/tps6507x-regulator.c1
-rw-r--r--drivers/regulator/tps6524x-regulator.c1
-rw-r--r--drivers/regulator/tps6586x-regulator.c1
-rw-r--r--drivers/regulator/tps65910-regulator.c4
-rw-r--r--drivers/regulator/twl-regulator.c9
24 files changed, 3296 insertions, 285 deletions
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 6e8250382de..47a34ff88f9 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/ab3100.c b/drivers/regulator/ab3100.c
index 111ec69a3e9..3be9e46594a 100644
--- a/drivers/regulator/ab3100.c
+++ b/drivers/regulator/ab3100.c
@@ -17,6 +17,8 @@
#include <linux/regulator/driver.h>
#include <linux/mfd/ab3100.h>
#include <linux/mfd/abx500.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
/* LDO registers and some handy masking definitions for AB3100 */
#define AB3100_LDO_A 0x40
@@ -345,7 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
{
struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
- return abreg->plfdata->external_voltage;
+ if (abreg->plfdata)
+ return abreg->plfdata->external_voltage;
+ else
+ /* TODO: encode external voltage into device tree */
+ return 0;
}
static struct regulator_ops regulator_ops_fixed = {
@@ -488,16 +494,174 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
},
};
+static int ab3100_regulator_register(struct platform_device *pdev,
+ struct ab3100_platform_data *plfdata,
+ struct regulator_init_data *init_data,
+ struct device_node *np,
+ int id)
+{
+ struct regulator_desc *desc;
+ struct ab3100_regulator *reg;
+ struct regulator_dev *rdev;
+ struct regulator_config config = { };
+ int err, i;
+
+ for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
+ desc = &ab3100_regulator_desc[i];
+ if (desc->id == id)
+ break;
+ }
+ if (desc->id != id)
+ return -ENODEV;
+
+ /* Same index used for this array */
+ reg = &ab3100_regulators[i];
+
+ /*
+ * Initialize per-regulator struct.
+ * Inherit platform data, this comes down from the
+ * i2c boarddata, from the machine. So if you want to
+ * see what it looks like for a certain machine, go
+ * into the machine I2C setup.
+ */
+ reg->dev = &pdev->dev;
+ if (plfdata) {
+ reg->plfdata = plfdata;
+ config.init_data = &plfdata->reg_constraints[i];
+ } else if (np) {
+ config.of_node = np;
+ config.init_data = init_data;
+ }
+ config.dev = &pdev->dev;
+ config.driver_data = reg;
+
+ rdev = regulator_register(desc, &config);
+ if (IS_ERR(rdev)) {
+ err = PTR_ERR(rdev);
+ dev_err(&pdev->dev,
+ "%s: failed to register regulator %s err %d\n",
+ __func__, desc->name,
+ err);
+ return err;
+ }
+
+ /* Then set a pointer back to the registered regulator */
+ reg->rdev = rdev;
+ return 0;
+}
+
+static struct of_regulator_match ab3100_regulator_matches[] = {
+ { .name = "ab3100_ldo_a", .driver_data = (void *) AB3100_LDO_A, },
+ { .name = "ab3100_ldo_c", .driver_data = (void *) AB3100_LDO_C, },
+ { .name = "ab3100_ldo_d", .driver_data = (void *) AB3100_LDO_D, },
+ { .name = "ab3100_ldo_e", .driver_data = (void *) AB3100_LDO_E, },
+ { .name = "ab3100_ldo_f", .driver_data = (void *) AB3100_LDO_F },
+ { .name = "ab3100_ldo_g", .driver_data = (void *) AB3100_LDO_G },
+ { .name = "ab3100_ldo_h", .driver_data = (void *) AB3100_LDO_H },
+ { .name = "ab3100_ldo_k", .driver_data = (void *) AB3100_LDO_K },
+ { .name = "ab3100_ext", .driver_data = (void *) AB3100_LDO_EXT },
+ { .name = "ab3100_buck", .driver_data = (void *) AB3100_BUCK },
+};
+
/*
- * NOTE: the following functions are regulators pluralis - it is the
- * binding to the AB3100 core driver and the parent platform device
- * for all the different regulators.
+ * Initial settings of ab3100 registers.
+ * Common for below LDO regulator settings are that
+ * bit 7-5 controls voltage. Bit 4 turns regulator ON(1) or OFF(0).
+ * Bit 3-2 controls sleep enable and bit 1-0 controls sleep mode.
*/
+/* LDO_A 0x16: 2.75V, ON, SLEEP_A, SLEEP OFF GND */
+#define LDO_A_SETTING 0x16
+/* LDO_C 0x10: 2.65V, ON, SLEEP_A or B, SLEEP full power */
+#define LDO_C_SETTING 0x10
+/* LDO_D 0x10: 2.65V, ON, sleep mode not used */
+#define LDO_D_SETTING 0x10
+/* LDO_E 0x10: 1.8V, ON, SLEEP_A or B, SLEEP full power */
+#define LDO_E_SETTING 0x10
+/* LDO_E SLEEP 0x00: 1.8V, not used, SLEEP_A or B, not used */
+#define LDO_E_SLEEP_SETTING 0x00
+/* LDO_F 0xD0: 2.5V, ON, SLEEP_A or B, SLEEP full power */
+#define LDO_F_SETTING 0xD0
+/* LDO_G 0x00: 2.85V, OFF, SLEEP_A or B, SLEEP full power */
+#define LDO_G_SETTING 0x00
+/* LDO_H 0x18: 2.75V, ON, SLEEP_B, SLEEP full power */
+#define LDO_H_SETTING 0x18
+/* LDO_K 0x00: 2.75V, OFF, SLEEP_A or B, SLEEP full power */
+#define LDO_K_SETTING 0x00
+/* LDO_EXT 0x00: Voltage not set, OFF, not used, not used */
+#define LDO_EXT_SETTING 0x00
+/* BUCK 0x7D: 1.2V, ON, SLEEP_A and B, SLEEP low power */
+#define BUCK_SETTING 0x7D
+/* BUCK SLEEP 0xAC: 1.05V, Not used, SLEEP_A and B, Not used */
+#define BUCK_SLEEP_SETTING 0xAC
+
+static const u8 ab3100_reg_initvals[] = {
+ LDO_A_SETTING,
+ LDO_C_SETTING,
+ LDO_E_SETTING,
+ LDO_E_SLEEP_SETTING,
+ LDO_F_SETTING,
+ LDO_G_SETTING,
+ LDO_H_SETTING,
+ LDO_K_SETTING,
+ LDO_EXT_SETTING,
+ BUCK_SETTING,
+ BUCK_SLEEP_SETTING,
+ LDO_D_SETTING,
+};
+
+static int ab3100_regulators_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
+ struct ab3100_regulator *reg = &ab3100_regulators[i];
+
+ regulator_unregister(reg->rdev);
+ reg->rdev = NULL;
+ }
+ return 0;
+}
+
+static int
+ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
+{
+ int err, i;
+
+ /*
+ * Set up the regulator registers, as was previously done with
+ * platform data.
+ */
+ /* Set up regulators */
+ for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
+ err = abx500_set_register_interruptible(&pdev->dev, 0,
+ ab3100_reg_init_order[i],
+ ab3100_reg_initvals[i]);
+ if (err) {
+ dev_err(&pdev->dev, "regulator initialization failed with error %d\n",
+ err);
+ return err;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ab3100_regulator_matches); i++) {
+ err = ab3100_regulator_register(
+ pdev, NULL, ab3100_regulator_matches[i].init_data,
+ ab3100_regulator_matches[i].of_node,
+ (int) ab3100_regulator_matches[i].driver_data);
+ if (err) {
+ ab3100_regulators_remove(pdev);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
static int ab3100_regulators_probe(struct platform_device *pdev)
{
struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
- struct regulator_config config = { };
+ struct device_node *np = pdev->dev.of_node;
int err = 0;
u8 data;
int i;
@@ -516,6 +680,18 @@ static int ab3100_regulators_probe(struct platform_device *pdev)
dev_notice(&pdev->dev,
"chip is in inactive mode (Cold start)\n");
+ if (np) {
+ err = of_regulator_match(&pdev->dev, np,
+ ab3100_regulator_matches,
+ ARRAY_SIZE(ab3100_regulator_matches));
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "Error parsing regulator init data: %d\n", err);
+ return err;
+ }
+ return ab3100_regulator_of_probe(pdev, np);
+ }
+
/* Set up regulators */
for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) {
err = abx500_set_register_interruptible(&pdev->dev, 0,
@@ -530,59 +706,19 @@ static int ab3100_regulators_probe(struct platform_device *pdev)
/* Register the regulators */
for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
- struct ab3100_regulator *reg = &ab3100_regulators[i];
- struct regulator_dev *rdev;
-
- /*
- * Initialize per-regulator struct.
- * Inherit platform data, this comes down from the
- * i2c boarddata, from the machine. So if you want to
- * see what it looks like for a certain machine, go
- * into the machine I2C setup.
- */
- reg->dev = &pdev->dev;
- reg->plfdata = plfdata;
+ struct regulator_desc *desc = &ab3100_regulator_desc[i];
- config.dev = &pdev->dev;
- config.driver_data = reg;
- config.init_data = &plfdata->reg_constraints[i];
-
- /*
- * Register the regulator, pass around
- * the ab3100_regulator struct
- */
- rdev = regulator_register(&ab3100_regulator_desc[i], &config);
- if (IS_ERR(rdev)) {
- err = PTR_ERR(rdev);
- dev_err(&pdev->dev,
- "%s: failed to register regulator %s err %d\n",
- __func__, ab3100_regulator_desc[i].name,
- err);
- /* remove the already registered regulators */
- while (--i >= 0)
- regulator_unregister(ab3100_regulators[i].rdev);
+ err = ab3100_regulator_register(pdev, plfdata, NULL, NULL,
+ desc->id);
+ if (err) {
+ ab3100_regulators_remove(pdev);
return err;
}
-
- /* Then set a pointer back to the registered regulator */
- reg->rdev = rdev;
}
return 0;
}
-static int ab3100_regulators_remove(struct platform_device *pdev)
-{
- int i;
-
- for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
- struct ab3100_regulator *reg = &ab3100_regulators[i];
-
- regulator_unregister(reg->rdev);
- }
- return 0;
-}
-
static struct platform_driver ab3100_regulators_driver = {
.driver = {
.name = "ab3100-regulators",
diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c
new file mode 100644
index 00000000000..b4d45472aae
--- /dev/null
+++ b/drivers/regulator/ab8500-ext.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Authors: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
+ *
+ * This file is based on drivers/regulator/ab8500.c
+ *
+ * AB8500 external regulators
+ *
+ * ab8500-ext supports the following regulators:
+ * - VextSupply3
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/regulator/ab8500.h>
+
+/**
+ * struct ab8500_ext_regulator_info - ab8500 regulator information
+ * @dev: device pointer
+ * @desc: regulator description
+ * @rdev: regulator device
+ * @cfg: regulator configuration (extension of regulator FW configuration)
+ * @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_hp: bits to set EN pin active (LPn pin deactive)
+ * normally this means high power mode
+ * @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;
+ u8 update_bank;
+ u8 update_reg;
+ u8 update_mask;
+ u8 update_val;
+ u8 update_val_hp;
+ u8 update_val_lp;
+ u8 update_val_hw;
+};
+
+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;
+ }
+
+ /*
+ * 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;
+ else
+ regval = info->update_val;
+
+ 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(info->rdev),
+ "couldn't set enable bits for regulator\n");
+ 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_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;
+ }
+
+ /*
+ * Set the regulator in HW request mode if configured
+ */
+ if (info->cfg && info->cfg->hwreq)
+ 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);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(info->rdev),
+ "couldn't set disable bits for regulator\n");
+ return ret;
+ }
+
+ 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 0;
+}
+
+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, &regval);
+ 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->update_val_lp) ||
+ ((regval & info->update_mask) == info->update_val_hp))
+ return 1;
+ else
+ return 0;
+}
+
+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);
+ u8 regval;
+
+ if (info == NULL) {
+ dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
+ return -EINVAL;
+ }
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ regval = info->update_val_hp;
+ break;
+ case REGULATOR_MODE_IDLE:
+ regval = info->update_val_lp;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* 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): "
+ "0x%x, 0x%x, 0x%x, 0x%x\n",
+ info->desc.name, info->update_bank, info->update_reg,
+ info->update_mask, regval);
+ }
+
+ info->update_val = regval;
+
+ return 0;
+}
+
+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_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,
+ .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_hp = 0x10,
+ .update_val_lp = 0x30,
+ .update_val_hw = 0x20,
+ },
+};
+
+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 (is_ab8500_2p0_or_earlier(ab8500)) {
+ 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_hp = 0x30;
+ info->update_val_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;
+ info->cfg = (struct ab8500_ext_regulator_cfg *)
+ pdata->ext_regulator[i].driver_data;
+
+ 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;
+}
+
+void 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);
+ }
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
+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 09014f38a94..f6656b8c28b 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -5,11 +5,15 @@
*
* Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
* Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ * Daniel Willerud <daniel.willerud@stericsson.com> 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 <linux/init.h>
#include <linux/kernel.h>
@@ -26,33 +30,64 @@
#include <linux/slab.h>
/**
+ * 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
+ * @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 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
+ * @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
- * @voltage_shift: shift to control regulator voltage
- * @delay: startup/set voltage delay in us
*/
struct ab8500_regulator_info {
struct device *dev;
struct regulator_desc desc;
struct regulator_dev *regulator;
+ struct ab8500_shared_mode *shared_mode;
+ int load_lp_uA;
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 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;
- u8 voltage_shift;
- unsigned int delay;
+ struct {
+ u8 voltage_limit;
+ u8 voltage_bank;
+ u8 voltage_reg;
+ u8 voltage_mask;
+ } expand_register;
};
/* voltage tables for the vauxn/vintcore supplies */
@@ -86,6 +121,44 @@ static const unsigned int ldo_vaux3_voltages[] = {
2910000,
};
+static const unsigned int ldo_vaux56_voltages[] = {
+ 1800000,
+ 1050000,
+ 1100000,
+ 1200000,
+ 1500000,
+ 2200000,
+ 2500000,
+ 2790000,
+};
+
+static const unsigned int ldo_vaux3_ab8540_voltages[] = {
+ 1200000,
+ 1500000,
+ 1800000,
+ 2100000,
+ 2500000,
+ 2750000,
+ 2790000,
+ 2910000,
+ 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,
@@ -96,6 +169,72 @@ static const unsigned int ldo_vintcore_voltages[] = {
1350000,
};
+static const unsigned int ldo_sdio_voltages[] = {
+ 1160000,
+ 1050000,
+ 1100000,
+ 1500000,
+ 1800000,
+ 2200000,
+ 2910000,
+ 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 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 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)
{
int ret;
@@ -108,15 +247,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);
- if (ret < 0)
+ info->update_mask, info->update_val);
+ if (ret < 0) {
dev_err(rdev_get_dev(rdev),
"couldn't set enable bits for regulator\n");
+ return ret;
+ }
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;
}
@@ -134,9 +275,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;
+ }
dev_vdbg(rdev_get_dev(rdev),
"%s-disable (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
@@ -172,14 +315,170 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
info->update_mask, regval);
if (regval & info->update_mask)
- return true;
+ 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;
+
+ 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)
+{
+ int ret = 0;
+ u8 bank, reg, mask, val;
+ bool lp_mode_req = false;
+ 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 (info->mode_mask) {
+ bank = info->mode_bank;
+ reg = info->mode_reg;
+ mask = info->mode_mask;
+ } else {
+ 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;
+
+ if (info->mode_mask)
+ val = info->mode_val_normal;
+ else
+ val = info->update_val_normal;
+ 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;
+ }
+
+ if (info->mode_mask)
+ val = info->mode_val_idle;
+ else
+ val = info->update_val_idle;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ 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) {
+ 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): "
+ "0x%x, 0x%x, 0x%x, 0x%x\n",
+ info->desc.name, bank, reg,
+ 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 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;
+ }
+
+ /* 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 (val == val_idle)
+ ret = REGULATOR_MODE_IDLE;
else
- return false;
+ ret = -EINVAL;
+
+ return ret;
}
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;
@@ -188,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, &regval);
if (ret < 0) {
@@ -201,16 +502,62 @@ 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, voltage_shift;
+ 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->expand_register.voltage_bank,
+ info->expand_register.voltage_reg, &regval_expand);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "couldn't read voltage expand reg for regulator\n");
+ return ret;
+ }
+
+ 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, &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);
+
+ 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;
@@ -219,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);
@@ -237,32 +586,121 @@ 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)
+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, 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) {
+ 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);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "couldn't set voltage reg for regulator\n");
+ return ret;
+ }
- return 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);
+
+ regval_expand = 0;
+ } else {
+ regval_expand = info->expand_register.voltage_mask;
+ }
+
+ 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 expand voltage reg for regulator\n");
+ return ret;
+ }
+
+ dev_vdbg(rdev_get_dev(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 0;
}
-static struct regulator_ops ab8500_regulator_ops = {
+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,
+};
+
+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,
+};
+
+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_fixed_ops = {
+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,
+ .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_table,
+};
+
+static struct regulator_ops ab8500_regulator_anamic_mode_ops = {
.enable = ab8500_regulator_enable,
.disable = ab8500_regulator_disable,
.is_enabled = ab8500_regulator_is_enabled,
- .list_voltage = regulator_list_voltage_linear,
+ .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] = {
/*
@@ -274,17 +712,21 @@ 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,
+ .enable_time = 200,
},
+ .load_lp_uA = 5000,
.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,
@@ -292,17 +734,21 @@ 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,
+ .enable_time = 200,
},
+ .load_lp_uA = 5000,
.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,
@@ -310,17 +756,21 @@ 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,
+ .enable_time = 450,
},
+ .load_lp_uA = 5000,
.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,
@@ -328,21 +778,24 @@ 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,
+ .enable_time = 750,
},
+ .load_lp_uA = 5000,
.update_bank = 0x03,
.update_reg = 0x80,
.update_mask = 0x44,
- .update_val_enable = 0x04,
+ .update_val = 0x44,
+ .update_val_idle = 0x44,
+ .update_val_normal = 0x04,
.voltage_bank = 0x03,
.voltage_reg = 0x80,
.voltage_mask = 0x38,
- .voltage_shift = 3,
},
/*
@@ -353,112 +806,984 @@ 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,
.n_voltages = 1,
- .min_uV = 2000000,
+ .volt_table = fixed_2000000_voltage,
+ .enable_time = 500,
+ },
+ .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_AUDIO] = {
+ .desc = {
+ .name = "LDO-AUDIO",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_AUDIO,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .enable_time = 140,
+ .volt_table = fixed_2000000_voltage,
+ },
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x02,
+ .update_val = 0x02,
+ },
+ [AB8500_LDO_ANAMIC1] = {
+ .desc = {
+ .name = "LDO-ANAMIC1",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_ANAMIC1,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .enable_time = 500,
+ .volt_table = fixed_2050000_voltage,
+ },
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x08,
+ .update_val = 0x08,
+ },
+ [AB8500_LDO_ANAMIC2] = {
+ .desc = {
+ .name = "LDO-ANAMIC2",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_ANAMIC2,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .enable_time = 500,
+ .volt_table = fixed_2050000_voltage,
+ },
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x10,
+ .update_val = 0x10,
+ },
+ [AB8500_LDO_DMIC] = {
+ .desc = {
+ .name = "LDO-DMIC",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_DMIC,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .enable_time = 420,
+ .volt_table = fixed_1800000_voltage,
+ },
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x04,
+ .update_val = 0x04,
+ },
+
+ /*
+ * Regulators with fixed voltage and normal/idle modes
+ */
+ [AB8500_LDO_ANA] = {
+ .desc = {
+ .name = "LDO-ANA",
+ .ops = &ab8500_regulator_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8500_LDO_ANA,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .enable_time = 140,
+ .volt_table = fixed_1200000_voltage,
+ },
+ .load_lp_uA = 1000,
+ .update_bank = 0x04,
+ .update_reg = 0x06,
+ .update_mask = 0x0c,
+ .update_val = 0x04,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x04,
+ },
+};
+
+/* 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
+ */
+ [AB8505_LDO_AUX1] = {
+ .desc = {
+ .name = "LDO-AUX1",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_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,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x1f,
+ .voltage_mask = 0x0f,
+ },
+ [AB8505_LDO_AUX2] = {
+ .desc = {
+ .name = "LDO-AUX2",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_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,
+ .update_val = 0x04,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x20,
+ .voltage_mask = 0x0f,
+ },
+ [AB8505_LDO_AUX3] = {
+ .desc = {
+ .name = "LDO-AUX3",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_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,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x21,
+ .voltage_mask = 0x07,
+ },
+ [AB8505_LDO_AUX4] = {
+ .desc = {
+ .name = "LDO-AUX4",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_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 */
+ .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,
+ },
+ [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),
+ .volt_table = ldo_vaux56_voltages,
+ },
+ .load_lp_uA = 2000,
+ /* values for CtrlVaux5 register */
+ .update_bank = 0x01,
+ .update_reg = 0x55,
+ .update_mask = 0x18,
+ .update_val = 0x10,
+ .update_val_idle = 0x18,
+ .update_val_normal = 0x10,
+ .voltage_bank = 0x01,
+ .voltage_reg = 0x55,
+ .voltage_mask = 0x07,
+ },
+ [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),
+ .volt_table = ldo_vaux56_voltages,
+ },
+ .load_lp_uA = 2000,
+ /* values for CtrlVaux6 register */
+ .update_bank = 0x01,
+ .update_reg = 0x56,
+ .update_mask = 0x18,
+ .update_val = 0x10,
+ .update_val_idle = 0x18,
+ .update_val_normal = 0x10,
+ .voltage_bank = 0x01,
+ .voltage_reg = 0x56,
+ .voltage_mask = 0x07,
+ },
+ [AB8505_LDO_INTCORE] = {
+ .desc = {
+ .name = "LDO-INTCORE",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_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,
+ .update_val = 0x04,
+ .update_val_idle = 0x44,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x03,
+ .voltage_reg = 0x80,
+ .voltage_mask = 0x38,
+ },
+
+ /*
+ * 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,
+ .volt_table = fixed_2000000_voltage,
.enable_time = 10000,
},
- .delay = 10000,
+ .load_lp_uA = 1000,
.update_bank = 0x03,
.update_reg = 0x80,
.update_mask = 0x82,
- .update_val_enable = 0x02,
+ .update_val = 0x02,
+ .update_val_idle = 0x82,
+ .update_val_normal = 0x02,
},
- [AB8500_LDO_USB] = {
+ [AB8505_LDO_USB] = {
.desc = {
.name = "LDO-USB",
- .ops = &ab8500_regulator_fixed_ops,
+ .ops = &ab8500_regulator_mode_ops,
.type = REGULATOR_VOLTAGE,
- .id = AB8500_LDO_USB,
+ .id = AB8505_LDO_USB,
.owner = THIS_MODULE,
.n_voltages = 1,
- .min_uV = 3300000,
+ .volt_table = fixed_3300000_voltage,
},
.update_bank = 0x03,
.update_reg = 0x82,
.update_mask = 0x03,
- .update_val_enable = 0x01,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
},
- [AB8500_LDO_AUDIO] = {
+ [AB8505_LDO_AUDIO] = {
.desc = {
.name = "LDO-AUDIO",
- .ops = &ab8500_regulator_fixed_ops,
+ .ops = &ab8500_regulator_volt_ops,
.type = REGULATOR_VOLTAGE,
- .id = AB8500_LDO_AUDIO,
+ .id = AB8505_LDO_AUDIO,
+ .owner = THIS_MODULE,
+ .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 = 0x70,
+ },
+ [AB8505_LDO_ANAMIC1] = {
+ .desc = {
+ .name = "LDO-ANAMIC1",
+ .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_anamic_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_LDO_ANAMIC2,
.owner = THIS_MODULE,
.n_voltages = 1,
- .min_uV = 2000000,
+ .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 = {
+ .name = "LDO-AUX8",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_LDO_AUX8,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .volt_table = fixed_1800000_voltage,
+ },
+ .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_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8505_LDO_ANA,
+ .owner = THIS_MODULE,
+ .n_voltages = ARRAY_SIZE(ldo_vana_voltages),
+ .volt_table = ldo_vana_voltages,
+ },
+ .load_lp_uA = 1000,
+ .update_bank = 0x04,
+ .update_reg = 0x06,
+ .update_mask = 0x0c,
+ .update_val = 0x04,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x29,
+ .voltage_mask = 0x7,
+ },
+};
+
+/* 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
+ */
+ [AB9540_LDO_AUX1] = {
+ .desc = {
+ .name = "LDO-AUX1",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB9540_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,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x1f,
+ .voltage_mask = 0x0f,
+ },
+ [AB9540_LDO_AUX2] = {
+ .desc = {
+ .name = "LDO-AUX2",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB9540_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,
+ .update_val = 0x04,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x20,
+ .voltage_mask = 0x0f,
+ },
+ [AB9540_LDO_AUX3] = {
+ .desc = {
+ .name = "LDO-AUX3",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB9540_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,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x21,
+ .voltage_mask = 0x07,
+ },
+ [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),
+ .volt_table = 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,
+ },
+ [AB9540_LDO_INTCORE] = {
+ .desc = {
+ .name = "LDO-INTCORE",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB9540_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,
+ .update_val = 0x44,
+ .update_val_idle = 0x44,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x03,
+ .voltage_reg = 0x80,
+ .voltage_mask = 0x38,
+ },
+
+ /*
+ * 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 = AB9540_LDO_TVOUT,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .volt_table = fixed_2000000_voltage,
+ .enable_time = 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,
+ },
+ [AB9540_LDO_USB] = {
+ .desc = {
+ .name = "LDO-USB",
+ .ops = &ab8500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB9540_LDO_USB,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .volt_table = fixed_3300000_voltage,
+ },
+ .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 = AB9540_LDO_AUDIO,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .volt_table = fixed_2000000_voltage,
},
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x02,
- .update_val_enable = 0x02,
+ .update_val = 0x02,
},
- [AB8500_LDO_ANAMIC1] = {
+ [AB9540_LDO_ANAMIC1] = {
.desc = {
.name = "LDO-ANAMIC1",
- .ops = &ab8500_regulator_fixed_ops,
+ .ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
- .id = AB8500_LDO_ANAMIC1,
+ .id = AB9540_LDO_ANAMIC1,
.owner = THIS_MODULE,
.n_voltages = 1,
- .min_uV = 2050000,
+ .volt_table = fixed_2050000_voltage,
},
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x08,
- .update_val_enable = 0x08,
+ .update_val = 0x08,
},
- [AB8500_LDO_ANAMIC2] = {
+ [AB9540_LDO_ANAMIC2] = {
.desc = {
.name = "LDO-ANAMIC2",
- .ops = &ab8500_regulator_fixed_ops,
+ .ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
- .id = AB8500_LDO_ANAMIC2,
+ .id = AB9540_LDO_ANAMIC2,
.owner = THIS_MODULE,
.n_voltages = 1,
- .min_uV = 2050000,
+ .volt_table = fixed_2050000_voltage,
},
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x10,
- .update_val_enable = 0x10,
+ .update_val = 0x10,
},
- [AB8500_LDO_DMIC] = {
+ [AB9540_LDO_DMIC] = {
.desc = {
.name = "LDO-DMIC",
- .ops = &ab8500_regulator_fixed_ops,
+ .ops = &ab8500_regulator_ops,
.type = REGULATOR_VOLTAGE,
- .id = AB8500_LDO_DMIC,
+ .id = AB9540_LDO_DMIC,
.owner = THIS_MODULE,
.n_voltages = 1,
- .min_uV = 1800000,
+ .volt_table = fixed_1800000_voltage,
},
.update_bank = 0x03,
.update_reg = 0x83,
.update_mask = 0x04,
- .update_val_enable = 0x04,
+ .update_val = 0x04,
},
- [AB8500_LDO_ANA] = {
+
+ /*
+ * Regulators with fixed voltage and normal/idle modes
+ */
+ [AB9540_LDO_ANA] = {
.desc = {
.name = "LDO-ANA",
- .ops = &ab8500_regulator_fixed_ops,
+ .ops = &ab8500_regulator_mode_ops,
.type = REGULATOR_VOLTAGE,
- .id = AB8500_LDO_ANA,
+ .id = AB9540_LDO_ANA,
.owner = THIS_MODULE,
.n_voltages = 1,
- .min_uV = 1200000,
+ .volt_table = fixed_1200000_voltage,
},
+ .load_lp_uA = 1000,
.update_bank = 0x04,
.update_reg = 0x06,
.update_mask = 0x0c,
- .update_val_enable = 0x04,
+ .update_val = 0x08,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x08,
},
+};
+/* 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
+ */
+ [AB8540_LDO_AUX1] = {
+ .desc = {
+ .name = "LDO-AUX1",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8540_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,
+ .update_val = 0x01,
+ .update_val_idle = 0x03,
+ .update_val_normal = 0x01,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x1f,
+ .voltage_mask = 0x0f,
+ },
+ [AB8540_LDO_AUX2] = {
+ .desc = {
+ .name = "LDO-AUX2",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8540_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,
+ .update_val = 0x04,
+ .update_val_idle = 0x0c,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x20,
+ .voltage_mask = 0x0f,
+ },
+ [AB8540_LDO_AUX3] = {
+ .desc = {
+ .name = "LDO-AUX3",
+ .ops = &ab8540_aux3_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8540_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,
+ .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,
+ .expand_register = {
+ .voltage_limit = 8,
+ .voltage_bank = 0x04,
+ .voltage_reg = 0x01,
+ .voltage_mask = 0x10,
+ }
+ },
+ [AB8540_LDO_AUX4] = {
+ .desc = {
+ .name = "LDO-AUX4",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8540_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 */
+ .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,
+ },
+ [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",
+ .ops = &ab8500_regulator_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8540_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,
+ .update_val = 0x44,
+ .update_val_idle = 0x44,
+ .update_val_normal = 0x04,
+ .voltage_bank = 0x03,
+ .voltage_reg = 0x80,
+ .voltage_mask = 0x38,
+ },
+ /*
+ * 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 = AB8540_LDO_TVOUT,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .volt_table = fixed_2000000_voltage,
+ .enable_time = 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 = AB8540_LDO_AUDIO,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .volt_table = fixed_2000000_voltage,
+ },
+ .update_bank = 0x03,
+ .update_reg = 0x83,
+ .update_mask = 0x02,
+ .update_val = 0x02,
+ },
+ [AB8540_LDO_ANAMIC1] = {
+ .desc = {
+ .name = "LDO-ANAMIC1",
+ .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_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_volt_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .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,
+ .update_reg = 0x83,
+ .update_mask = 0x04,
+ .update_val = 0x04,
+ .voltage_bank = 0x03,
+ .voltage_reg = 0x83,
+ .voltage_mask = 0xc0,
+ },
+
+ /*
+ * Regulators with fixed voltage and normal/idle modes
+ */
+ [AB8540_LDO_ANA] = {
+ .desc = {
+ .name = "LDO-ANA",
+ .ops = &ab8500_regulator_mode_ops,
+ .type = REGULATOR_VOLTAGE,
+ .id = AB8540_LDO_ANA,
+ .owner = THIS_MODULE,
+ .n_voltages = 1,
+ .volt_table = fixed_1200000_voltage,
+ },
+ .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),
+ .volt_table = ldo_sdio_voltages,
+ },
+ .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,
+ },
+};
+
+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],
+};
+
+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 {
@@ -474,13 +1799,13 @@ struct ab8500_reg_init {
.mask = _mask, \
}
+/* AB8500 register init */
static struct ab8500_reg_init ab8500_reg_init[] = {
/*
* 0x30, VanaRequestCtrl
- * 0x0C, VpllRequestCtrl
* 0xc0, VextSupply1RequestCtrl
*/
- REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xfc),
+ REG_INIT(AB8500_REGUREQUESTCTRL2, 0x03, 0x04, 0xf0),
/*
* 0x03, VextSupply2RequestCtrl
* 0x0c, VextSupply3RequestCtrl
@@ -547,13 +1872,21 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
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),
@@ -578,8 +1911,8 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
*/
REG_INIT(AB8500_REGUCTRL1VAMIC, 0x03, 0x84, 0x03),
/*
+ * 0x03, VpllRegu (NOTE! PRCMU register bits)
* 0x0c, VanaRegu
- * 0x03, VpllRegu
*/
REG_INIT(AB8500_VPLLVANAREGU, 0x04, 0x06, 0x0f),
/*
@@ -605,10 +1938,6 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
*/
REG_INIT(AB8500_VRF1VAUX3REGU, 0x04, 0x0a, 0x03),
/*
- * 0x3f, Vsmps1Sel1
- */
- REG_INIT(AB8500_VSMPS1SEL1, 0x04, 0x13, 0x3f),
- /*
* 0x0f, Vaux1Sel
*/
REG_INIT(AB8500_VAUX1SEL, 0x04, 0x1f, 0x0f),
@@ -641,52 +1970,1073 @@ 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)
+/* 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[] = {
+ /*
+ * 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),
+};
+
+/* 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 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,
+ int id, int mask, int value)
{
+ struct ab8500_reg_init *reg_init = abx500_regulator.init;
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 & ~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);
+ 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,
- ab8500_reg_init[id].mask,
- value);
+ " 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 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 = &ab8500_regulator_info[id];
+ info = &abx500_regulator.info[id];
info->dev = &pdev->dev;
config.dev = &pdev->dev;
@@ -695,7 +3045,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);
@@ -712,7 +3062,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 = &abx500_regulator.info[id];
regulator_unregister(info->regulator);
}
return err;
@@ -721,29 +3071,16 @@ static int ab8500_regulator_register(struct platform_device *pdev,
return 0;
}
-static struct of_regulator_match ab8500_regulator_matches[] = {
- { .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_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, },
- { .name = "ab8500_ldo_dmic", .driver_data = (void *) AB8500_LDO_DMIC, },
- { .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, },
-};
-
static int
-ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
+ab8500_regulator_of_probe(struct platform_device *pdev,
+ struct device_node *np)
{
+ struct of_regulator_match *match = abx500_regulator.match;
int err, i;
- for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
+ for (i = 0; i < abx500_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, i, match[i].of_node);
if (err)
return err;
}
@@ -754,14 +3091,22 @@ 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 (!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,
- ab8500_regulator_matches,
- ARRAY_SIZE(ab8500_regulator_matches));
+ abx500_regulator.match,
+ abx500_regulator.match_size);
if (err < 0) {
dev_err(&pdev->dev,
"Error parsing regulator init data: %d\n", err);
@@ -772,46 +3117,61 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
return err;
}
- if (!ab8500) {
- dev_err(&pdev->dev, "null mfd parent\n");
+ ppdata = dev_get_platdata(ab8500->dev);
+ if (!ppdata) {
+ dev_err(&pdev->dev, "null parent pdata\n");
return -EINVAL;
}
- pdata = dev_get_platdata(ab8500->dev);
+
+ 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_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
+ if (pdata->num_regulator != abx500_regulator.info_size) {
dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
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_regulator_reg_init; i++) {
- int id, value;
+ for (i = 0; i < pdata->num_reg_init; i++) {
+ int id, mask, value;
- id = pdata->regulator_reg_init[i].id;
- 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 */
- if (id >= AB8500_NUM_REGULATOR_REGISTERS) {
- dev_err(&pdev->dev,
- "Configuration error: id outside range.\n");
- return -EINVAL;
- }
+ BUG_ON(id >= abx500_regulator.init_size);
- err = ab8500_regulator_init_registers(pdev, id, value);
+ err = ab8500_regulator_init_registers(pdev, id, mask, value);
if (err < 0)
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 < ARRAY_SIZE(ab8500_regulator_info); i++) {
- err = ab8500_regulator_register(pdev, &pdata->regulator[i], i, NULL);
- if (err < 0)
+ for (i = 0; i < abx500_regulator.info_size; i++) {
+ err = ab8500_regulator_register(pdev, &pdata->regulator[i],
+ i, NULL);
+ if (err < 0) {
+ if (!is_ab8505(ab8500))
+ ab8500_ext_regulator_exit(pdev);
return err;
+ }
}
return 0;
@@ -819,11 +3179,12 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
static int ab8500_regulator_remove(struct platform_device *pdev)
{
- int i;
+ int i, err;
+ struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
- for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
+ for (i = 0; i < abx500_regulator.info_size; i++) {
struct ab8500_regulator_info *info = NULL;
- info = &ab8500_regulator_info[i];
+ info = &abx500_regulator.info[i];
dev_vdbg(rdev_get_dev(info->regulator),
"%s-remove\n", info->desc.name);
@@ -831,6 +3192,15 @@ static int ab8500_regulator_remove(struct platform_device *pdev)
regulator_unregister(info->regulator);
}
+ /* 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);
+ if (err)
+ return err;
+
return 0;
}
@@ -863,5 +3233,7 @@ module_exit(ab8500_regulator_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
+MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
+MODULE_AUTHOR("Daniel Willerud <daniel.willerud@stericsson.com>");
MODULE_DESCRIPTION("Regulator Driver for ST-Ericsson AB8500 Mixed-Sig PMIC");
MODULE_ALIAS("platform:ab8500-regulator");
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
index ed7beec53af..81d8681c319 100644
--- a/drivers/regulator/arizona-ldo1.c
+++ b/drivers/regulator/arizona-ldo1.c
@@ -131,7 +131,7 @@ static const struct regulator_desc arizona_ldo1_hc = {
.min_uV = 900000,
.uV_step = 50000,
.n_voltages = 8,
- .enable_time = 500,
+ .enable_time = 1500,
.owner = THIS_MODULE,
};
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index f0ba8c4eefa..3da6bd6950c 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -13,9 +13,11 @@
#include <linux/init.h>
#include <linux/mfd/as3711.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/slab.h>
struct as3711_regulator_info {
@@ -276,6 +278,53 @@ static struct as3711_regulator_info as3711_reg_info[] = {
#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
+static struct of_regulator_match
+as3711_regulator_matches[AS3711_REGULATOR_NUM] = {
+ [AS3711_REGULATOR_SD_1] = { .name = "sd1" },
+ [AS3711_REGULATOR_SD_2] = { .name = "sd2" },
+ [AS3711_REGULATOR_SD_3] = { .name = "sd3" },
+ [AS3711_REGULATOR_SD_4] = { .name = "sd4" },
+ [AS3711_REGULATOR_LDO_1] = { .name = "ldo1" },
+ [AS3711_REGULATOR_LDO_2] = { .name = "ldo2" },
+ [AS3711_REGULATOR_LDO_3] = { .name = "ldo3" },
+ [AS3711_REGULATOR_LDO_4] = { .name = "ldo4" },
+ [AS3711_REGULATOR_LDO_5] = { .name = "ldo5" },
+ [AS3711_REGULATOR_LDO_6] = { .name = "ldo6" },
+ [AS3711_REGULATOR_LDO_7] = { .name = "ldo7" },
+ [AS3711_REGULATOR_LDO_8] = { .name = "ldo8" },
+};
+
+static int as3711_regulator_parse_dt(struct device *dev,
+ struct device_node **of_node, const int count)
+{
+ struct as3711_regulator_pdata *pdata = dev_get_platdata(dev);
+ struct device_node *regulators =
+ of_find_node_by_name(dev->parent->of_node, "regulators");
+ struct of_regulator_match *match;
+ int ret, i;
+
+ if (!regulators) {
+ dev_err(dev, "regulator node not found\n");
+ return -ENODEV;
+ }
+
+ ret = of_regulator_match(dev->parent, regulators,
+ as3711_regulator_matches, count);
+ of_node_put(regulators);
+ if (ret < 0) {
+ dev_err(dev, "Error parsing regulator init data: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0, match = as3711_regulator_matches; i < count; i++, match++)
+ if (match->of_node) {
+ pdata->init_data[i] = match->init_data;
+ of_node[i] = match->of_node;
+ }
+
+ return 0;
+}
+
static int as3711_regulator_probe(struct platform_device *pdev)
{
struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
@@ -284,13 +333,24 @@ static int as3711_regulator_probe(struct platform_device *pdev)
struct regulator_config config = {.dev = &pdev->dev,};
struct as3711_regulator *reg = NULL;
struct as3711_regulator *regs;
+ struct device_node *of_node[AS3711_REGULATOR_NUM] = {};
struct regulator_dev *rdev;
struct as3711_regulator_info *ri;
int ret;
int id;
- if (!pdata)
- dev_dbg(&pdev->dev, "No platform data...\n");
+ if (!pdata) {
+ dev_err(&pdev->dev, "No platform data...\n");
+ return -ENODEV;
+ }
+
+ if (pdev->dev.parent->of_node) {
+ ret = as3711_regulator_parse_dt(&pdev->dev, of_node, AS3711_REGULATOR_NUM);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "DT parsing failed: %d\n", ret);
+ return ret;
+ }
+ }
regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
sizeof(struct as3711_regulator), GFP_KERNEL);
@@ -300,7 +360,7 @@ static int as3711_regulator_probe(struct platform_device *pdev)
}
for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
- reg_data = pdata ? pdata->init_data[id] : NULL;
+ reg_data = pdata->init_data[id];
/* No need to register if there is no regulator data */
if (!reg_data)
@@ -312,6 +372,7 @@ static int as3711_regulator_probe(struct platform_device *pdev)
config.init_data = reg_data;
config.driver_data = reg;
config.regmap = as3711->regmap;
+ config.of_node = of_node[id];
rdev = regulator_register(&ri->desc, &config);
if (IS_ERR(rdev)) {
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 73edb0ef6e1..6437949849b 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2147,6 +2147,37 @@ int regulator_map_voltage_iterate(struct regulator_dev *rdev,
EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
/**
+ * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers that have ascendant voltage list can use this as their
+ * map_voltage() operation.
+ */
+int regulator_map_voltage_ascend(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ int i, ret;
+
+ for (i = 0; i < rdev->desc->n_voltages; i++) {
+ ret = rdev->desc->ops->list_voltage(rdev, i);
+ if (ret < 0)
+ continue;
+
+ if (ret > max_uV)
+ break;
+
+ if (ret >= min_uV && ret <= max_uV)
+ return i;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);
+
+/**
* regulator_map_voltage_linear - map_voltage() for simple linear mappings
*
* @rdev: Regulator to operate on
@@ -2839,7 +2870,7 @@ EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
* regulator_allow_bypass - allow the regulator to go into bypass mode
*
* @regulator: Regulator to configure
- * @allow: enable or disable bypass mode
+ * @enable: enable or disable bypass mode
*
* Allow the regulator to go into bypass mode if all other consumers
* for the regulator also enable bypass mode and the machine
@@ -3066,9 +3097,13 @@ int regulator_bulk_enable(int num_consumers,
return 0;
err:
- pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
- while (--i >= 0)
- regulator_disable(consumers[i].consumer);
+ for (i = 0; i < num_consumers; i++) {
+ if (consumers[i].ret < 0)
+ pr_err("Failed to enable %s: %d\n", consumers[i].supply,
+ consumers[i].ret);
+ else
+ regulator_disable(consumers[i].consumer);
+ }
return ret;
}
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c
index 219d162b651..a53c11a529d 100644
--- a/drivers/regulator/db8500-prcmu.c
+++ b/drivers/regulator/db8500-prcmu.c
@@ -528,7 +528,7 @@ static int db8500_regulator_probe(struct platform_device *pdev)
return 0;
}
-static int __exit db8500_regulator_remove(struct platform_device *pdev)
+static int db8500_regulator_remove(struct platform_device *pdev)
{
int i;
@@ -553,7 +553,7 @@ static struct platform_driver db8500_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = db8500_regulator_probe,
- .remove = __exit_p(db8500_regulator_remove),
+ .remove = db8500_regulator_remove,
};
static int __init db8500_regulator_init(void)
diff --git a/drivers/regulator/dbx500-prcmu.h b/drivers/regulator/dbx500-prcmu.h
index e763883a44f..c8e51ace9f0 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);
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index 9cb2c0f3451..d8af9e77331 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -163,6 +163,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
static struct regulator_ops lp3971_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3971_ldo_is_enabled,
.enable = lp3971_ldo_enable,
.disable = lp3971_ldo_disable,
@@ -236,6 +237,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
static struct regulator_ops lp3971_dcdc_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3971_dcdc_is_enabled,
.enable = lp3971_dcdc_enable,
.disable = lp3971_dcdc_disable,
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 0baabcfb578..61e4cf9edf6 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -309,6 +309,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
static struct regulator_ops lp3972_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3972_ldo_is_enabled,
.enable = lp3972_ldo_enable,
.disable = lp3972_ldo_disable,
@@ -389,6 +390,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev,
static struct regulator_ops lp3972_dcdc_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.is_enabled = lp3972_dcdc_is_enabled,
.enable = lp3972_dcdc_enable,
.disable = lp3972_dcdc_disable,
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index 8e3c7ae0047..f5fc4a142cd 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -478,6 +478,7 @@ static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
static struct regulator_ops lp872x_ldo_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
@@ -488,6 +489,7 @@ static struct regulator_ops lp872x_ldo_ops = {
static struct regulator_ops lp8720_buck_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp872x_buck_set_voltage_sel,
.get_voltage_sel = lp872x_buck_get_voltage_sel,
.enable = regulator_enable_regmap,
@@ -500,6 +502,7 @@ static struct regulator_ops lp8720_buck_ops = {
static struct regulator_ops lp8725_buck_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp872x_buck_set_voltage_sel,
.get_voltage_sel = lp872x_buck_get_voltage_sel,
.enable = regulator_enable_regmap,
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index 97891a7ea7b..eb1e1e88ae5 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -346,6 +346,7 @@ static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
static struct regulator_ops lp8788_buck12_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = lp8788_buck12_set_voltage_sel,
.get_voltage_sel = lp8788_buck12_get_voltage_sel,
.enable = regulator_enable_regmap,
@@ -358,6 +359,7 @@ static struct regulator_ops lp8788_buck12_ops = {
static struct regulator_ops lp8788_buck34_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
diff --git a/drivers/regulator/mc13783-regulator.c b/drivers/regulator/mc13783-regulator.c
index c46c6705cd7..fdf7f0a0909 100644
--- a/drivers/regulator/mc13783-regulator.c
+++ b/drivers/regulator/mc13783-regulator.c
@@ -398,33 +398,51 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
struct mc13xxx_regulator_platform_data *pdata =
dev_get_platdata(&pdev->dev);
- struct mc13xxx_regulator_init_data *init_data;
+ struct mc13xxx_regulator_init_data *mc13xxx_data;
struct regulator_config config = { };
- int i, ret;
+ int i, ret, num_regulators;
- dev_dbg(&pdev->dev, "%s id %d\n", __func__, pdev->id);
+ num_regulators = mc13xxx_get_num_regulators_dt(pdev);
- if (!pdata)
+ if (num_regulators <= 0 && pdata)
+ num_regulators = pdata->num_regulators;
+ if (num_regulators <= 0)
return -EINVAL;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv) +
- pdata->num_regulators * sizeof(priv->regulators[0]),
+ num_regulators * sizeof(priv->regulators[0]),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
+ priv->num_regulators = num_regulators;
priv->mc13xxx_regulators = mc13783_regulators;
priv->mc13xxx = mc13783;
+ platform_set_drvdata(pdev, priv);
- for (i = 0; i < pdata->num_regulators; i++) {
- struct regulator_desc *desc;
+ mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13783_regulators,
+ ARRAY_SIZE(mc13783_regulators));
- init_data = &pdata->regulators[i];
- desc = &mc13783_regulators[init_data->id].desc;
+ for (i = 0; i < priv->num_regulators; i++) {
+ struct regulator_init_data *init_data;
+ struct regulator_desc *desc;
+ struct device_node *node = NULL;
+ int id;
+
+ if (mc13xxx_data) {
+ id = mc13xxx_data[i].id;
+ init_data = mc13xxx_data[i].init_data;
+ node = mc13xxx_data[i].node;
+ } else {
+ id = pdata->regulators[i].id;
+ init_data = pdata->regulators[i].init_data;
+ }
+ desc = &mc13783_regulators[id].desc;
config.dev = &pdev->dev;
- config.init_data = init_data->init_data;
+ config.init_data = init_data;
config.driver_data = priv;
+ config.of_node = node;
priv->regulators[i] = regulator_register(desc, &config);
if (IS_ERR(priv->regulators[i])) {
@@ -435,8 +453,6 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
}
}
- platform_set_drvdata(pdev, priv);
-
return 0;
err:
while (--i >= 0)
@@ -448,13 +464,11 @@ err:
static int mc13783_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
- struct mc13xxx_regulator_platform_data *pdata =
- dev_get_platdata(&pdev->dev);
int i;
platform_set_drvdata(pdev, NULL);
- for (i = 0; i < pdata->num_regulators; i++)
+ for (i = 0; i < priv->num_regulators; i++)
regulator_unregister(priv->regulators[i]);
return 0;
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index 9891aec47b5..b716283a876 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -465,13 +465,13 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
*/
if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) {
+ mask |= MC13892_SWITCHERS0_SWxHI;
+
if (volt > 1375000) {
reg_value -= MC13892_SWxHI_SEL_OFFSET;
reg_value |= MC13892_SWITCHERS0_SWxHI;
- mask |= MC13892_SWITCHERS0_SWxHI;
- } else if (volt < 1100000) {
+ } else {
reg_value &= ~MC13892_SWITCHERS0_SWxHI;
- mask |= MC13892_SWITCHERS0_SWxHI;
}
}
@@ -485,6 +485,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
static struct regulator_ops mc13892_sw_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
.get_voltage_sel = mc13892_sw_regulator_get_voltage_sel,
};
@@ -535,7 +536,7 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
struct mc13xxx_regulator_init_data *mc13xxx_data;
struct regulator_config config = { };
int i, ret;
- int num_regulators = 0, num_parsed;
+ int num_regulators = 0;
u32 val;
num_regulators = mc13xxx_get_num_regulators_dt(pdev);
@@ -545,8 +546,6 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
if (num_regulators <= 0)
return -EINVAL;
- num_parsed = num_regulators;
-
priv = devm_kzalloc(&pdev->dev, sizeof(*priv) +
num_regulators * sizeof(priv->regulators[0]),
GFP_KERNEL);
@@ -589,40 +588,9 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
= mc13892_vcam_get_mode;
mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators,
- ARRAY_SIZE(mc13892_regulators),
- &num_parsed);
-
- /*
- * Perform a little sanity check on the regulator tree - if we found
- * a number of regulators from mc13xxx_get_num_regulators_dt and
- * then parsed a smaller number in mc13xxx_parse_regulators_dt then
- * there is a regulator defined in the regulators node which has
- * not matched any usable regulator in the driver. In this case,
- * there is one missing and what will happen is the first regulator
- * will get registered again.
- *
- * Fix this by basically making our number of registerable regulators
- * equal to the number of regulators we parsed. We are allocating
- * too much memory for priv, but this is unavoidable at this point.
- *
- * As an example of how this can happen, try making a typo in your
- * regulators node (vviohi {} instead of viohi {}) so that the name
- * does not match..
- *
- * The check will basically pass for platform data (non-DT) because
- * mc13xxx_parse_regulators_dt for !CONFIG_OF will not touch num_parsed.
- *
- */
- if (num_parsed != num_regulators) {
- dev_warn(&pdev->dev,
- "parsed %d != regulators %d - check your device tree!\n",
- num_parsed, num_regulators);
-
- num_regulators = num_parsed;
- priv->num_regulators = num_regulators;
- }
+ ARRAY_SIZE(mc13892_regulators));
- for (i = 0; i < num_regulators; i++) {
+ for (i = 0; i < priv->num_regulators; i++) {
struct regulator_init_data *init_data;
struct regulator_desc *desc;
struct device_node *node = NULL;
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 23cf9f9c383..da485928230 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -180,15 +180,13 @@ EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
- int num_regulators, int *num_parsed)
+ int num_regulators)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
struct mc13xxx_regulator_init_data *data, *p;
struct device_node *parent, *child;
int i, parsed = 0;
- *num_parsed = 0;
-
of_node_get(pdev->dev.parent->of_node);
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators");
if (!parent)
@@ -204,10 +202,13 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
p = data;
for_each_child_of_node(parent, child) {
+ int found = 0;
+
for (i = 0; i < num_regulators; i++) {
+ if (!regulators[i].desc.name)
+ continue;
if (!of_node_cmp(child->name,
regulators[i].desc.name)) {
-
p->id = i;
p->init_data = of_get_regulator_init_data(
&pdev->dev, child);
@@ -215,13 +216,19 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
p++;
parsed++;
+ found = 1;
break;
}
}
+
+ if (!found)
+ dev_warn(&pdev->dev,
+ "Unknown regulator: %s\n", child->name);
}
of_node_put(parent);
- *num_parsed = parsed;
+ priv->num_regulators = parsed;
+
return data;
}
EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt);
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h
index 007f83387fd..06c8903f182 100644
--- a/drivers/regulator/mc13xxx.h
+++ b/drivers/regulator/mc13xxx.h
@@ -39,7 +39,7 @@ extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev);
extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
- int num_regulators, int *num_parsed);
+ int num_regulators);
#else
static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
{
@@ -48,7 +48,7 @@ static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
- int num_regulators, int *num_parsed)
+ int num_regulators)
{
return NULL;
}
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c
index cde13bb5a8f..39cf1460678 100644
--- a/drivers/regulator/palmas-regulator.c
+++ b/drivers/regulator/palmas-regulator.c
@@ -4,6 +4,7 @@
* Copyright 2011-2012 Texas Instruments Inc.
*
* Author: Graeme Gregory <gg@slimlogic.co.uk>
+ * Author: Ian Lartey <ian@slimlogic.co.uk>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -156,7 +157,7 @@ static const struct regs_info palmas_regs_info[] = {
*
* So they are basically (maxV-minV)/stepV
*/
-#define PALMAS_SMPS_NUM_VOLTAGES 116
+#define PALMAS_SMPS_NUM_VOLTAGES 117
#define PALMAS_SMPS10_NUM_VOLTAGES 2
#define PALMAS_LDO_NUM_VOLTAGES 50
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index 9b9af6d889c..8d21cf3385e 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -107,12 +107,7 @@ static const unsigned int DCDC_FIXED_1800000_VSEL_table[] = {
};
/* Supported voltage values for LDO regulators for tps65020 */
-static const unsigned int TPS65020_LDO1_VSEL_table[] = {
- 1000000, 1050000, 1100000, 1300000,
- 1800000, 2500000, 3000000, 3300000,
-};
-
-static const unsigned int TPS65020_LDO2_VSEL_table[] = {
+static const unsigned int TPS65020_LDO_VSEL_table[] = {
1000000, 1050000, 1100000, 1300000,
1800000, 2500000, 3000000, 3300000,
};
@@ -202,6 +197,7 @@ static struct regulator_ops tps65023_dcdc_ops = {
.get_voltage_sel = tps65023_dcdc_get_voltage_sel,
.set_voltage_sel = tps65023_dcdc_set_voltage_sel,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
};
/* Operations permitted on LDOx */
@@ -212,6 +208,7 @@ static struct regulator_ops tps65023_ldo_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
};
static struct regmap_config tps65023_regmap_config = {
@@ -347,13 +344,13 @@ static const struct tps_info tps65020_regs[] = {
},
{
.name = "LDO1",
- .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
- .table = TPS65020_LDO1_VSEL_table,
+ .table_len = ARRAY_SIZE(TPS65020_LDO_VSEL_table),
+ .table = TPS65020_LDO_VSEL_table,
},
{
.name = "LDO2",
- .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
- .table = TPS65020_LDO2_VSEL_table,
+ .table_len = ARRAY_SIZE(TPS65020_LDO_VSEL_table),
+ .table = TPS65020_LDO_VSEL_table,
},
};
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c
index 54aa2da7283..4117ff52dba 100644
--- a/drivers/regulator/tps6507x-regulator.c
+++ b/drivers/regulator/tps6507x-regulator.c
@@ -356,6 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
.get_voltage_sel = tps6507x_pmic_get_voltage_sel,
.set_voltage_sel = tps6507x_pmic_set_voltage_sel,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
};
#ifdef CONFIG_OF
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 06e92761afd..1094393155e 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -572,6 +572,7 @@ static struct regulator_ops regulator_ops = {
.get_voltage_sel = get_voltage_sel,
.set_voltage_sel = set_voltage_sel,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.set_current_limit = set_current_limit,
.get_current_limit = get_current_limit,
};
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index e68382d0e1e..ac8a6cb6209 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -70,6 +70,7 @@ static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
static struct regulator_ops tps6586x_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 6ba6931ac85..45c16447744 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -748,6 +748,7 @@ static struct regulator_ops tps65910_ops_dcdc = {
.set_voltage_sel = tps65910_set_voltage_dcdc_sel,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.list_voltage = tps65910_list_voltage_dcdc,
+ .map_voltage = regulator_map_voltage_ascend,
};
static struct regulator_ops tps65910_ops_vdd3 = {
@@ -758,6 +759,7 @@ static struct regulator_ops tps65910_ops_vdd3 = {
.get_mode = tps65910_get_mode,
.get_voltage = tps65910_get_voltage_vdd3,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
};
static struct regulator_ops tps65910_ops = {
@@ -769,6 +771,7 @@ static struct regulator_ops tps65910_ops = {
.get_voltage_sel = tps65910_get_voltage_sel,
.set_voltage_sel = tps65910_set_voltage_sel,
.list_voltage = regulator_list_voltage_table,
+ .map_voltage = regulator_map_voltage_ascend,
};
static struct regulator_ops tps65911_ops = {
@@ -780,6 +783,7 @@ static struct regulator_ops tps65911_ops = {
.get_voltage_sel = tps65911_get_voltage_sel,
.set_voltage_sel = tps65911_set_voltage_sel,
.list_voltage = tps65911_list_voltage,
+ .map_voltage = regulator_map_voltage_ascend,
};
static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 74508cc62d6..f705d25b437 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -471,24 +471,23 @@ twl4030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
selector);
}
-static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
+static int twl4030ldo_get_voltage_sel(struct regulator_dev *rdev)
{
struct twlreg_info *info = rdev_get_drvdata(rdev);
- int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
- VREG_VOLTAGE);
+ int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
if (vsel < 0)
return vsel;
vsel &= info->table_len - 1;
- return LDO_MV(info->table[vsel]) * 1000;
+ return vsel;
}
static struct regulator_ops twl4030ldo_ops = {
.list_voltage = twl4030ldo_list_voltage,
.set_voltage_sel = twl4030ldo_set_voltage_sel,
- .get_voltage = twl4030ldo_get_voltage,
+ .get_voltage_sel = twl4030ldo_get_voltage_sel,
.enable = twl4030reg_enable,
.disable = twl4030reg_disable,