summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig37
-rw-r--r--drivers/regulator/Makefile13
-rw-r--r--drivers/regulator/core.c5
-rw-r--r--drivers/regulator/da9052-regulator.c547
-rw-r--r--drivers/regulator/ltc3589-regulator.c1052
-rw-r--r--drivers/regulator/max17135-regulator.c640
-rw-r--r--drivers/regulator/mxs-regulator.c302
-rw-r--r--drivers/regulator/reg-mc13783.c2662
-rw-r--r--drivers/regulator/reg-mc13892.c1956
-rw-r--r--drivers/regulator/reg-mc34704.c289
-rw-r--r--drivers/regulator/reg-mc9s08dz60.c236
11 files changed, 7738 insertions, 1 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 04f2e085116a..694c2e6e539d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -201,5 +201,42 @@ config REGULATOR_88PM8607
help
This driver supports 88PM8607 voltage regulator chips.
+config REGULATOR_MC13892
+ tristate "MC13892 Regulator Support"
+ depends on MXC_PMIC_MC13892
+ default y
+
+config REGULATOR_MC34704
+ tristate "MC34704 Regulator Support"
+ depends on MXC_PMIC_MC34704
+ default y
+
+config REGULATOR_LTC3589
+ tristate "LTC3589 Regulator Support"
+ depends on MFD_LTC3589_I2C
+ depends on REGULATOR
+ default n
+
+config REGULATOR_MXS
+ tristate "MXS Regulator Support"
+ depends on ARCH_MXS
+ default y
+
+config REGULATOR_MC9S08DZ60
+ tristate "mc9s08dz60 Regulator Support"
+ depends on MXC_PMIC_MC9S08DZ60
+ default y
+
+config REGULATOR_MAX17135
+ tristate "Maxim MAX17135 Regulator Support"
+ depends on MFD_MAX17135
+ default n
+
+config REGULATOR_DA9052
+ tristate "Dialog DA9052 regulators"
+ depends on PMIC_DA9052
+ help
+ Say y here to support the BUCKs and LDOs regulators found on
+ Dialog Semiconductor DA9052 PMIC.
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 4e7feece22d5..850fdd8d45fa 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -2,7 +2,6 @@
# Makefile for regulator drivers.
#
-
obj-$(CONFIG_REGULATOR) += core.o
obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
@@ -32,4 +31,16 @@ obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
+obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
+
+obj-$(CONFIG_REGULATOR_MAX17135) += max17135-regulator.o
+
+obj-$(CONFIG_REGULATOR_MC13892) += reg-mc13892.o
+obj-$(CONFIG_REGULATOR_MC34704) += reg-mc34704.o
+obj-$(CONFIG_REGULATOR_STMP3XXX) += stmp3xxx.o
+obj-$(CONFIG_REGULATOR_MXS) += mxs-regulator.o
+obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589-regulator.o
+
+obj-$(CONFIG_REGULATOR_MC9S08DZ60) += reg-mc9s08dz60.o
+
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2248087b9be2..af6ebc027884 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1108,6 +1108,11 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
goto found;
}
}
+ list_for_each_entry(rdev, &regulator_list, list) {
+ if (strcmp(rdev->desc->name, id) == 0) {
+ goto found;
+ }
+ }
#ifdef CONFIG_REGULATOR_DUMMY
if (!devname)
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c
new file mode 100644
index 000000000000..34452839570c
--- /dev/null
+++ b/drivers/regulator/da9052-regulator.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright(c) 2009 Dialog Semiconductor Ltd.
+ *
+ * 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 Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * da9052-regulator.c: Regulator driver for DA9052
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/reg.h>
+#include <linux/mfd/da9052/pm.h>
+
+static struct regulator_ops da9052_ldo_buck_ops;
+
+
+struct regulator {
+ struct device *dev;
+ struct list_head list;
+ int uA_load;
+ int min_uV;
+ int max_uV;
+ int enabled; /* client has called enabled */
+ char *supply_name;
+ struct device_attribute dev_attr;
+ struct regulator_dev *rdev;
+};
+
+
+
+
+#define DA9052_LDO(_id, max, min, step_v, reg, mbits, cbits) \
+{\
+ .reg_desc = {\
+ .name = #_id,\
+ .ops = &da9052_ldo_buck_ops,\
+ .type = REGULATOR_VOLTAGE,\
+ .id = _id,\
+ .owner = THIS_MODULE,\
+ },\
+ .reg_const = {\
+ .max_uV = (max) * 1000,\
+ .min_uV = (min) * 1000,\
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE\
+ | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE,\
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,\
+ },\
+ .step_uV = (step_v) * 1000,\
+ .reg_add = (reg),\
+ .mask_bits = (mbits),\
+ .en_bit_mask = (cbits),\
+}
+
+struct regulator_info {
+ struct regulator_desc reg_desc;
+ struct regulation_constraints reg_const;
+ int step_uV;
+ unsigned char reg_add;
+ unsigned char mask_bits;
+ unsigned char en_bit_mask;
+};
+
+struct da9052_regulator_priv {
+ struct da9052 *da9052;
+ struct regulator_dev *regulators[];
+};
+
+struct regulator_info da9052_regulators[] = {
+ /* LD01 - LDO10*/
+ DA9052_LDO(DA9052_LDO1, DA9052_LDO1_VOLT_UPPER, DA9052_LDO1_VOLT_LOWER,
+ DA9052_LDO1_VOLT_STEP, DA9052_LDO1_REG,
+ DA9052_LDO1_VLDO1, DA9052_LDO1_LDO1EN),
+
+ DA9052_LDO(DA9052_LDO2,
+ DA9052_LDO2_VOLT_UPPER, DA9052_LDO2_VOLT_LOWER,
+ DA9052_LDO2_VOLT_STEP, DA9052_LDO2_REG,
+ DA9052_LDO2_VLDO2,
+ DA9052_LDO2_LDO2EN),
+
+ DA9052_LDO(DA9052_LDO3, DA9052_LDO34_VOLT_UPPER,
+ DA9052_LDO34_VOLT_LOWER,
+ DA9052_LDO34_VOLT_STEP, DA9052_LDO3_REG,
+ DA9052_LDO3_VLDO3, DA9052_LDO3_LDO3EN),
+
+ DA9052_LDO(DA9052_LDO4, DA9052_LDO34_VOLT_UPPER,
+ DA9052_LDO34_VOLT_LOWER,
+ DA9052_LDO34_VOLT_STEP, DA9052_LDO4_REG,
+ DA9052_LDO4_VLDO4, DA9052_LDO4_LDO4EN),
+
+ DA9052_LDO(DA9052_LDO5, DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER,
+ DA9052_LDO567810_VOLT_STEP, DA9052_LDO5_REG,
+ DA9052_LDO5_VLDO5, DA9052_LDO5_LDO5EN),
+
+ DA9052_LDO(DA9052_LDO6, DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER,
+ DA9052_LDO567810_VOLT_STEP, DA9052_LDO6_REG,
+ DA9052_LDO6_VLDO6, DA9052_LDO6_LDO6EN),
+
+ DA9052_LDO(DA9052_LDO7, DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER,
+ DA9052_LDO567810_VOLT_STEP, DA9052_LDO7_REG,
+ DA9052_LDO7_VLDO7, DA9052_LDO7_LDO7EN),
+
+ DA9052_LDO(DA9052_LDO8, DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER,
+ DA9052_LDO567810_VOLT_STEP, DA9052_LDO8_REG,
+ DA9052_LDO8_VLDO8, DA9052_LDO8_LDO8EN),
+
+ DA9052_LDO(DA9052_LDO9, DA9052_LDO9_VOLT_UPPER,
+ DA9052_LDO9_VOLT_LOWER,
+ DA9052_LDO9_VOLT_STEP,
+ DA9052_LDO9_REG, DA9052_LDO9_VLDO9,
+ DA9052_LDO9_LDO9EN),
+
+ DA9052_LDO(DA9052_LDO10, DA9052_LDO567810_VOLT_UPPER,
+ DA9052_LDO567810_VOLT_LOWER,
+ DA9052_LDO567810_VOLT_STEP, DA9052_LDO10_REG,
+ DA9052_LDO10_VLDO10, DA9052_LDO10_LDO10EN),
+
+ /* BUCKS */
+ DA9052_LDO(DA9052_BUCK_CORE, DA9052_BUCK_CORE_PRO_VOLT_UPPER,
+ DA9052_BUCK_CORE_PRO_VOLT_LOWER,
+ DA9052_BUCK_CORE_PRO_STEP, DA9052_BUCKCORE_REG,
+ DA9052_BUCKCORE_VBCORE, DA9052_BUCKCORE_BCOREEN),
+
+ DA9052_LDO(DA9052_BUCK_PRO, DA9052_BUCK_CORE_PRO_VOLT_UPPER,
+ DA9052_BUCK_CORE_PRO_VOLT_LOWER,
+ DA9052_BUCK_CORE_PRO_STEP, DA9052_BUCKPRO_REG,
+ DA9052_BUCKPRO_VBPRO, DA9052_BUCKPRO_BPROEN),
+
+ DA9052_LDO(DA9052_BUCK_MEM, DA9052_BUCK_MEM_VOLT_UPPER,
+ DA9052_BUCK_MEM_VOLT_LOWER,
+ DA9052_BUCK_MEM_STEP, DA9052_BUCKMEM_REG,
+ DA9052_BUCKMEM_VBMEM, DA9052_BUCKMEM_BMEMEN),
+
+ DA9052_LDO(DA9052_BUCK_PERI, DA9052_BUCK_PERI_VOLT_UPPER,
+ DA9052_BUCK_PERI_VOLT_LOWER,
+ DA9052_BUCK_PERI_STEP_BELOW_3000, DA9052_BUCKPERI_REG,
+ DA9052_BUCKPERI_VBPERI, DA9052_BUCKPERI_BPERIEN),
+};
+
+int da9052_ldo_buck_enable(struct regulator_dev *rdev)
+{
+ struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ int ret = 0;
+ struct da9052_ssc_msg ssc_msg;
+
+ ssc_msg.addr = da9052_regulators[id].reg_add;
+ ssc_msg.data = 0;
+
+ da9052_lock(priv->da9052);
+ ret = priv->da9052->read(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ ssc_msg.data = (ssc_msg.data | da9052_regulators[id].en_bit_mask);
+
+ ret = priv->da9052->write(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+ da9052_unlock(priv->da9052);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(da9052_ldo_buck_enable);
+/* Code added by KPIT to support additional attribure in sysfs - changestate */
+
+
+
+int da9052_ldo_buck_disable(struct regulator_dev *rdev)
+{
+ struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ int ret;
+ struct da9052_ssc_msg ssc_msg;
+
+ ssc_msg.addr = da9052_regulators[id].reg_add;
+ ssc_msg.data = 0;
+
+ da9052_lock(priv->da9052);
+ ret = priv->da9052->read(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ ssc_msg.data = (ssc_msg.data & ~(da9052_regulators[id].en_bit_mask));
+
+ ret = priv->da9052->write(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+ da9052_unlock(priv->da9052);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(da9052_ldo_buck_disable);
+/* Code added by KPIT to support additional attribure in sysfs - changestate */
+
+static int da9052_ldo_buck_is_enabled(struct regulator_dev *rdev)
+{
+ struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
+ int id = rdev_get_id(rdev);
+ int ret;
+ struct da9052_ssc_msg ssc_msg;
+ ssc_msg.addr = da9052_regulators[id].reg_add;
+ ssc_msg.data = 0;
+
+ da9052_lock(priv->da9052);
+ ret = priv->da9052->read(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+ da9052_unlock(priv->da9052);
+ return (ssc_msg.data & da9052_regulators[id].en_bit_mask) != 0;
+}
+
+int da9052_ldo_buck_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
+ struct da9052_ssc_msg ssc_msg;
+ int id = rdev_get_id(rdev);
+ int ret;
+ int ldo_volt = 0;
+
+ /* KPIT - Below if condition is there for added setvoltage attribute
+ in sysfs */
+ if (0 == max_uV)
+ max_uV = da9052_regulators[id].reg_const.max_uV;
+
+ /* Compare voltage range */
+ if (min_uV > max_uV)
+ return -EINVAL;
+
+ /* Check Minimum/ Maximum voltage range */
+ if (min_uV < da9052_regulators[id].reg_const.min_uV ||
+ min_uV > da9052_regulators[id].reg_const.max_uV)
+ return -EINVAL;
+ if (max_uV < da9052_regulators[id].reg_const.min_uV ||
+ max_uV > da9052_regulators[id].reg_const.max_uV)
+ return -EINVAL;
+
+ /* Get the ldo register value */
+ /* Varying step size for BUCK PERI */
+ if ((da9052_regulators[id].reg_desc.id == DA9052_BUCK_PERI) &&
+ (min_uV >= DA9052_BUCK_PERI_VALUES_3000)) {
+ ldo_volt = (DA9052_BUCK_PERI_VALUES_3000 -
+ da9052_regulators[id].reg_const.min_uV)/
+ (da9052_regulators[id].step_uV);
+ ldo_volt += (min_uV - DA9052_BUCK_PERI_VALUES_3000)/
+ (DA9052_BUCK_PERI_STEP_ABOVE_3000);
+ } else{
+ ldo_volt = (min_uV - da9052_regulators[id].reg_const.min_uV)/
+ (da9052_regulators[id].step_uV);
+ /* Check for maximum value */
+ if ((ldo_volt * da9052_regulators[id].step_uV) +
+ da9052_regulators[id].reg_const.min_uV > max_uV)
+ return -EINVAL;
+ }
+
+ /* Configure LDO Voltage, CONF bits */
+ ssc_msg.addr = da9052_regulators[id].reg_add;
+ ssc_msg.data = 0;
+
+ /* Read register */
+ da9052_lock(priv->da9052);
+ ret = priv->da9052->read(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ ssc_msg.data = (ssc_msg.data & ~(da9052_regulators[id].mask_bits));
+ ssc_msg.data |= ldo_volt;
+
+ ret = priv->da9052->write(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ /* Set the GO LDO/BUCk bits so that the voltage changes */
+ ssc_msg.addr = DA9052_SUPPLY_REG;
+ ssc_msg.data = 0;
+
+ ret = priv->da9052->read(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ switch (id) {
+ case DA9052_LDO2:
+ ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VLDO2GO);
+ break;
+ case DA9052_LDO3:
+ ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VLDO3GO);
+ break;
+ case DA9052_BUCK_CORE:
+ ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VBCOREGO);
+ break;
+ case DA9052_BUCK_PRO:
+ ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VBPROGO);
+ break;
+ case DA9052_BUCK_MEM:
+ ssc_msg.data = (ssc_msg.data | DA9052_SUPPLY_VBMEMGO);
+ break;
+ default:
+ da9052_unlock(priv->da9052);
+ return -EINVAL;
+ }
+
+ ret = priv->da9052->write(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ da9052_unlock(priv->da9052);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(da9052_ldo_buck_set_voltage);
+/* Code added by KPIT to support additional attributes in sysfs - setvoltage */
+
+
+int da9052_ldo_buck_get_voltage(struct regulator_dev *rdev)
+{
+ struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
+ struct da9052_ssc_msg ssc_msg;
+ int id = rdev_get_id(rdev);
+ int ldo_volt = 0;
+ int ldo_volt_uV = 0;
+ int ret;
+
+ ssc_msg.addr = da9052_regulators[id].reg_add;
+ ssc_msg.data = 0;
+ /* Read register */
+ da9052_lock(priv->da9052);
+ ret = priv->da9052->read(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+ da9052_unlock(priv->da9052);
+
+ ldo_volt = ssc_msg.data & da9052_regulators[id].mask_bits;
+ if (da9052_regulators[id].reg_desc.id == DA9052_BUCK_PERI) {
+ if (ldo_volt >= DA9052_BUCK_PERI_VALUES_UPTO_3000) {
+ ldo_volt_uV = ((DA9052_BUCK_PERI_VALUES_UPTO_3000 *
+ da9052_regulators[id].step_uV)
+ + da9052_regulators[id].reg_const.min_uV);
+ ldo_volt_uV = (ldo_volt_uV +
+ (ldo_volt - DA9052_BUCK_PERI_VALUES_UPTO_3000)
+ * (DA9052_BUCK_PERI_STEP_ABOVE_3000));
+ } else {
+ ldo_volt_uV =
+ (ldo_volt * da9052_regulators[id].step_uV)
+ + da9052_regulators[id].reg_const.min_uV;
+ }
+ } else {
+ ldo_volt_uV = (ldo_volt * da9052_regulators[id].step_uV) +
+ da9052_regulators[id].reg_const.min_uV;
+ }
+ return ldo_volt_uV;
+}
+EXPORT_SYMBOL_GPL(da9052_ldo_buck_get_voltage);
+/* Code added by KPIT to support additional attributes in sysfs - setvoltage */
+
+static int da9052_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+ struct da9052_regulator_priv *priv = rdev_get_drvdata(rdev);
+ struct da9052_ssc_msg ssc_msg;
+ int id = rdev_get_id(rdev);
+ int ret;
+ int ldo_volt = 0;
+
+
+ /* Check Minimum/ Maximum voltage range */
+ if (uV < da9052_regulators[id].reg_const.min_uV ||
+ uV > da9052_regulators[id].reg_const.max_uV)
+ return -EINVAL;
+
+ /* Get the ldo register value */
+ /* Varying step size for BUCK PERI */
+ if ((da9052_regulators[id].reg_desc.id == DA9052_BUCK_PERI) &&
+ (uV >= DA9052_BUCK_PERI_VALUES_3000)) {
+ ldo_volt = (DA9052_BUCK_PERI_VALUES_3000 -
+ da9052_regulators[id].reg_const.min_uV)/
+ (da9052_regulators[id].step_uV);
+ ldo_volt += (uV - DA9052_BUCK_PERI_VALUES_3000)/
+ (DA9052_BUCK_PERI_STEP_ABOVE_3000);
+ } else{
+ ldo_volt = (uV - da9052_regulators[id].reg_const.min_uV)/
+ (da9052_regulators[id].step_uV);
+ }
+ ldo_volt |= 0x80;
+ dev_info(&rdev->dev, "preset to %d %x\n", uV, ldo_volt);
+
+ /* Configure LDO Voltage, CONF bits */
+ ssc_msg.addr = da9052_regulators[id].reg_add;
+ ssc_msg.data = 0;
+
+ /* Read register */
+ da9052_lock(priv->da9052);
+ ret = priv->da9052->read(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ ssc_msg.data = (ssc_msg.data & ~(da9052_regulators[id].mask_bits));
+ ssc_msg.data |= ldo_volt;
+
+ ret = priv->da9052->write(priv->da9052, &ssc_msg);
+ if (ret) {
+ da9052_unlock(priv->da9052);
+ return -EIO;
+ }
+
+ da9052_unlock(priv->da9052);
+
+ return 0;
+}
+
+static int da9052_ldo_buck_stby_enable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int da9052_ldo_buck_stby_disable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int da9052_ldo_buck_stby_set_mode(struct regulator_dev *reg,
+ unsigned int mode)
+{
+ return 0;
+}
+
+
+static struct regulator_ops da9052_ldo_buck_ops = {
+ .is_enabled = da9052_ldo_buck_is_enabled,
+ .enable = da9052_ldo_buck_enable,
+ .disable = da9052_ldo_buck_disable,
+ .get_voltage = da9052_ldo_buck_get_voltage,
+ .set_voltage = da9052_ldo_buck_set_voltage,
+ .set_suspend_voltage = da9052_set_suspend_voltage,
+ .set_suspend_enable = da9052_ldo_buck_stby_enable,
+ .set_suspend_disable = da9052_ldo_buck_stby_disable,
+ .set_suspend_mode = da9052_ldo_buck_stby_set_mode,
+};
+
+
+static int __devinit da9052_regulator_probe(struct platform_device *pdev)
+{
+ struct da9052_regulator_priv *priv;
+ struct da9052_regulator_platform_data *pdata =
+ (pdev->dev.platform_data);
+ struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent);
+ struct regulator_init_data *init_data;
+ int i, ret = 0;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ priv->da9052 = da9052;
+ for (i = 0; i < 14; i++) {
+
+ init_data = &pdata->regulators[i];
+ init_data->driver_data = da9052;
+ pdev->dev.platform_data = init_data;
+ priv->regulators[i] = regulator_register(
+ &da9052_regulators[i].reg_desc,
+ &pdev->dev, init_data,
+ priv);
+ if (IS_ERR(priv->regulators[i])) {
+ ret = PTR_ERR(priv->regulators[i]);
+ goto err;
+ }
+ }
+ platform_set_drvdata(pdev, priv);
+ return 0;
+err:
+ while (--i >= 0)
+ regulator_unregister(priv->regulators[i]);
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit da9052_regulator_remove(struct platform_device *pdev)
+{
+ struct da9052_regulator_priv *priv = platform_get_drvdata(pdev);
+ struct da9052_platform_data *pdata = pdev->dev.platform_data;
+ int i;
+
+ for (i = 0; i < pdata->num_regulators; i++)
+ regulator_unregister(priv->regulators[i]);
+
+ return 0;
+}
+
+static struct platform_driver da9052_regulator_driver = {
+ .probe = da9052_regulator_probe,
+ .remove = __devexit_p(da9052_regulator_remove),
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init da9052_regulator_init(void)
+{
+ return platform_driver_register(&da9052_regulator_driver);
+}
+subsys_initcall(da9052_regulator_init);
+
+static void __exit da9052_regulator_exit(void)
+{
+ platform_driver_unregister(&da9052_regulator_driver);
+}
+module_exit(da9052_regulator_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/regulator/ltc3589-regulator.c b/drivers/regulator/ltc3589-regulator.c
new file mode 100644
index 000000000000..b81552e94316
--- /dev/null
+++ b/drivers/regulator/ltc3589-regulator.c
@@ -0,0 +1,1052 @@
+ /*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/*!
+ * @file ltc3589-regulator.c
+ * @brief This is the main file for the Linear PMIC regulator driver. i2c
+ * should be providing the interface between the PMIC and the MCU.
+ *
+ * @ingroup PMIC_CORE
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/ltc3589.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/mfd/ltc3589/core.h>
+#include <mach/hardware.h>
+
+/* Register definitions */
+#define LTC3589_REG_IRSTAT 0x02
+#define LTC3589_REG_SCR1 0x07
+#define LTC3589_REG_OVEN 0x10
+#define LTC3589_REG_SCR2 0x12
+#define LTC3589_REG_PGSTAT 0x13
+#define LTC3589_REG_VCCR 0x20
+#define LTC3589_REG_CLIRQ 0x21
+#define LTC3589_REG_B1DTV1 0x23
+#define LTC3589_REG_B1DTV2 0x24
+#define LTC3589_REG_VRRCR 0x25
+#define LTC3589_REG_B2DTV1 0x26
+#define LTC3589_REG_B2DTV2 0x27
+#define LTC3589_REG_B3DTV1 0x29
+#define LTC3589_REG_B3DTV2 0x2A
+#define LTC3589_REG_L2DTV1 0x32
+#define LTC3589_REG_L2DTV2 0x33
+
+/* SCR1 bitfields */
+#define LTC3589_SCR1_ BIT(7)
+#define LTC3589_PGOODZ_LOWBATTZ BIT(6)
+#define LTC3589_PGOODZ_VDCDC1 BIT(5)
+#define LTC3589_PGOODZ_VDCDC2 BIT(4)
+#define LTC3589_PGOODZ_VDCDC3 BIT(3)
+#define LTC3589_PGOODZ_LDO2 BIT(2)
+#define LTC3589_PGOODZ_LDO1 BIT(1)
+
+/* MASK bitfields */
+#define LTC3589_MASK_PWRFAILZ BIT(7)
+#define LTC3589_MASK_LOWBATTZ BIT(6)
+#define LTC3589_MASK_VDCDC1 BIT(5)
+#define LTC3589_MASK_VDCDC2 BIT(4)
+#define LTC3589_MASK_VDCDC3 BIT(3)
+#define LTC3589_MASK_LDO2 BIT(2)
+#define LTC3589_MASK_LDO1 BIT(1)
+
+/* REG_CTRL bitfields */
+#define LTC3589_REG_CTRL_VDCDC1_EN BIT(5)
+#define LTC3589_REG_CTRL_VDCDC2_EN BIT(4)
+#define LTC3589_REG_CTRL_VDCDC3_EN BIT(3)
+#define LTC3589_REG_CTRL_LDO2_EN BIT(2)
+#define LTC3589_REG_CTRL_LDO1_EN BIT(1)
+
+/* LDO_CTRL bitfields */
+#define LTC3589_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4)
+#define LTC3589_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4))
+
+/* Number of step-down converters available */
+#define LTC3589_NUM_DCDC 4
+/* Number of LDO voltage regulators available */
+#define LTC3589_NUM_LDO 4
+/* Number of total regulators available */
+#define LTC3589_NUM_REGULATOR (LTC3589_NUM_DCDC + LTC3589_NUM_LDO)
+
+/* DCDCs */
+#define LTC3589_DCDC_1 0
+#define LTC3589_DCDC_2 1
+#define LTC3589_DCDC_3 2
+#define LTC3589_DCDC_4 3
+/* LDOs */
+#define LTC3589_LDO_1 4
+#define LTC3589_LDO_2 5
+#define LTC3589_LDO_3 6
+#define LTC3589_LDO_4 7
+/* Resistorss */
+#define LTC3589_LDO2_R1 180
+#define LTC3589_LDO2_R2_TO1 232
+#define LTC3589_LDO2_R2_TO2 191
+#define LTC3589_SW1_R1 100
+#define LTC3589_SW1_R2 180
+#define LTC3589_SW2_R1 180
+#define LTC3589_SW2_R2_TO1 232
+#define LTC3589_SW2_R2_TO2 191
+#define LTC3589_SW3_R1 270
+#define LTC3589_SW3_R2 100
+
+#define LTC3589_MAX_REG_ID LTC3589_LDO_4
+
+/* Supported voltage values for regulators */
+static const u16 LDO4_VSEL_table[] = {
+ 2800, 2500, 1800, 3300,
+};
+
+struct i2c_client *ltc3589_client;
+
+/* Regulator specific details */
+struct ltc_info {
+ const char *name;
+ unsigned min_uV;
+ unsigned max_uV;
+ bool fixed;
+ u8 table_len;
+ const u16 *table;
+};
+
+/* PMIC details */
+struct ltc_pmic {
+ struct regulator_desc desc[LTC3589_NUM_REGULATOR];
+ struct i2c_client *client;
+ struct regulator_dev *rdev[LTC3589_NUM_REGULATOR];
+ const struct ltc_info *info[LTC3589_NUM_REGULATOR];
+ struct mutex io_lock;
+};
+
+static int ltc3589_ldo2_r2;
+static int ltc3589_sw2_r2;
+
+/*
+ * LTC3589 Device IO
+ */
+static DEFINE_MUTEX(io_mutex);
+
+static int ltc_3589_set_bits(struct ltc3589 *ltc, u8 reg, u8 mask)
+{
+ int err, data;
+
+ mutex_lock(&io_mutex);
+
+ data = ltc->read_dev(ltc, reg);
+ if (data < 0) {
+ dev_err(&ltc->i2c_client->dev,
+ "Read from reg 0x%x failed\n", reg);
+ err = data;
+ goto out;
+ }
+
+ data |= mask;
+ err = ltc->write_dev(ltc, reg, data);
+ if (err)
+ dev_err(&ltc->i2c_client->dev,
+ "Write for reg 0x%x failed\n", reg);
+
+out:
+ mutex_unlock(&io_mutex);
+ return err;
+}
+
+static int ltc_3589_clear_bits(struct ltc3589 *ltc, u8 reg, u8 mask)
+{
+ int err, data;
+
+ mutex_lock(&io_mutex);
+
+ data = ltc->read_dev(ltc, reg);
+ if (data < 0) {
+ dev_err(&ltc->i2c_client->dev,
+ "Read from reg 0x%x failed\n", reg);
+ err = data;
+ goto out;
+ }
+
+ data &= ~mask;
+
+ err = ltc->write_dev(ltc, reg, data);
+ if (err)
+ dev_err(&ltc->i2c_client->dev,
+ "Write for reg 0x%x failed\n", reg);
+
+out:
+ mutex_unlock(&io_mutex);
+ return err;
+
+}
+
+static int ltc_3589_reg_read(struct ltc3589 *ltc, u8 reg)
+{
+ int data;
+
+ mutex_lock(&io_mutex);
+
+ data = ltc->read_dev(ltc, reg);
+ if (data < 0)
+ dev_err(&ltc->i2c_client->dev,
+ "Read from reg 0x%x failed\n", reg);
+
+ mutex_unlock(&io_mutex);
+ return data;
+}
+
+static int ltc_3589_reg_write(struct ltc3589 *ltc, u8 reg, u8 val)
+{
+ int err;
+
+ mutex_lock(&io_mutex);
+
+ err = ltc->write_dev(ltc, reg, val);
+ if (err < 0)
+ dev_err(&ltc->i2c_client->dev,
+ "Write for reg 0x%x failed\n", reg);
+
+ mutex_unlock(&io_mutex);
+ return err;
+}
+
+int ltc3589_set_slew_rate(struct regulator_dev *dev, int rate)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int data, dcdc = rdev_get_id(dev);
+
+ if (dcdc == LTC3589_DCDC_4 || dcdc == LTC3589_LDO_1 ||
+ dcdc == LTC3589_LDO_3 || dcdc == LTC3589_LDO_4)
+ return 0;
+
+ if (rate > 0x3)
+ return -EINVAL;
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_VRRCR);
+ if (data < 0)
+ return data;
+
+ if (dcdc == LTC3589_LDO_2)
+ dcdc = 3;
+
+ data &= ~(3 << (2 * dcdc));
+ data |= (3 << (2 * dcdc));
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_VRRCR, data);
+
+ return 0;
+}
+
+static int ltc3589_dcdc_is_enabled(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int data, dcdc = rdev_get_id(dev);
+ u8 shift;
+
+ if (dcdc < LTC3589_DCDC_1 || dcdc > LTC3589_DCDC_4)
+ return -EINVAL;
+
+ shift = dcdc;
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_OVEN);
+
+ if (data < 0)
+ return data;
+ else
+ return (data & 1<<shift) ? 1 : 0;
+}
+
+static int ltc3589_ldo_is_enabled(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int data, ldo = rdev_get_id(dev);
+ u8 shift;
+
+ if (ldo < LTC3589_LDO_1 || ldo > LTC3589_LDO_4)
+ return -EINVAL;
+
+ if (ldo == LTC3589_LDO_1)
+ return 1;
+
+ shift = ldo - 1;
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_OVEN);
+
+ if (data < 0)
+ return data;
+ else
+ return (data & 1<<shift) ? 1 : 0;
+}
+
+static int ltc3589_dcdc_enable(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int dcdc = rdev_get_id(dev);
+ u8 shift;
+
+ if (dcdc < LTC3589_DCDC_1 || dcdc > LTC3589_DCDC_4)
+ return -EINVAL;
+
+ shift = dcdc;
+ return ltc_3589_set_bits(ltc, LTC3589_REG_OVEN, 1 << shift);
+}
+
+static int ltc3589_dcdc_disable(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int dcdc = rdev_get_id(dev);
+ u8 shift;
+
+ if (dcdc < LTC3589_DCDC_1 || dcdc > LTC3589_DCDC_4)
+ return -EINVAL;
+
+ shift = dcdc;
+ return ltc_3589_clear_bits(ltc, LTC3589_REG_OVEN, 1 << shift);
+}
+
+static int ltc3589_ldo_enable(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int ldo = rdev_get_id(dev);
+ u8 shift;
+
+ if (ldo < LTC3589_LDO_1 || ldo > LTC3589_LDO_4)
+ return -EINVAL;
+
+ if (ldo == LTC3589_LDO_1) {
+ printk(KERN_ERR "LDO1 is always enabled\n");
+ return 0;
+ }
+
+ shift = (ldo - 1);
+ return ltc_3589_set_bits(ltc, LTC3589_REG_OVEN, 1 << shift);
+}
+
+static int ltc3589_ldo_disable(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int ldo = rdev_get_id(dev);
+ u8 shift;
+
+ if (ldo < LTC3589_LDO_1 || ldo > LTC3589_LDO_4)
+ return -EINVAL;
+
+ if (ldo == LTC3589_LDO_1) {
+ printk(KERN_ERR "LDO1 can not be disabled\n");
+ return 0;
+ }
+
+ shift = (ldo - 1);
+ return ltc_3589_clear_bits(ltc, LTC3589_REG_OVEN, 1 << shift);
+}
+
+static int ltc3589_dcdc_set_mode(struct regulator_dev *dev,
+ unsigned int mode)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int dcdc = rdev_get_id(dev);
+ u16 val;
+ int data;
+
+ if (dcdc < LTC3589_DCDC_1 || dcdc > LTC3589_DCDC_4)
+ return -EINVAL;
+
+ val = 1 << (dcdc - LTC3589_DCDC_1);
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_SCR1);
+ if (data < 0)
+ return data;
+
+ data &= ~(3 << (2 * dcdc));
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ /* burst mode */
+ data |= (1 << (2 * dcdc));
+ break;
+ case REGULATOR_MODE_NORMAL:
+ /* active / pulse skipping */
+ data |= (0 << (2 * dcdc));
+ break;
+ case REGULATOR_MODE_IDLE:
+ case REGULATOR_MODE_STANDBY:
+ /* force continuous mode */
+ data |= (2 << (2 * dcdc));
+ }
+
+ return ltc_3589_reg_write(ltc, LTC3589_REG_SCR1, data);;
+}
+
+static unsigned int ltc3589_dcdc_get_mode(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int dcdc = rdev_get_id(dev);
+ int data;
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_VCCR);
+ if (data < 0)
+ return data;
+
+ if (dcdc == LTC3589_DCDC_4) {
+ data >>= (2 * dcdc);
+ data &= 0x01;
+
+ if (data == 1)
+ return REGULATOR_MODE_FAST;
+ else
+ return REGULATOR_MODE_NORMAL;
+ } else {
+ data >>= (2 * dcdc);
+ data &= 0x03;
+
+ switch (data) {
+ case 0:
+ return REGULATOR_MODE_NORMAL;
+ case 1:
+ return REGULATOR_MODE_FAST;
+ case 2:
+ return REGULATOR_MODE_IDLE;
+ }
+ }
+
+ return 0;
+}
+
+static int ltc3589_dcdc_get_voltage(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int volt_reg, data, dcdc = rdev_get_id(dev);
+ int shift, mask, r1, r2;
+ int uV;
+
+ r1 = 0;
+ r2 = 1;
+
+ if (dcdc < LTC3589_DCDC_1 || dcdc > LTC3589_DCDC_3)
+ return -EINVAL;
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_VCCR);
+ if (data < 0)
+ return data;
+
+ switch (dcdc) {
+ case LTC3589_DCDC_1:
+ r1 = LTC3589_SW1_R1;
+ r2 = LTC3589_SW1_R2;
+ shift = LTC3589_B1DTV2_REG1_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B1DTV2_REG1_REF_INPUT_V2_MASK;
+ if (data & LTC3589_VCCR_REG1_REF_SELECT)
+ volt_reg = LTC3589_REG_B1DTV2;
+ else
+ volt_reg = LTC3589_REG_B1DTV1;
+ break;
+ case LTC3589_DCDC_2:
+ r1 = LTC3589_SW2_R1;
+ r2 = ltc3589_sw2_r2;
+ shift = LTC3589_B2DTV2_REG2_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B2DTV2_REG2_REF_INPUT_V2_MASK;
+ if (data & LTC3589_VCCR_REG2_REF_SELECT)
+ volt_reg = LTC3589_REG_B2DTV2;
+ else
+ volt_reg = LTC3589_REG_B2DTV1;
+ break;
+ case LTC3589_DCDC_3:
+ r1 = LTC3589_SW3_R1;
+ r2 = LTC3589_SW3_R2;
+ shift = LTC3589_B3DTV2_REG3_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B3DTV2_REG3_REF_INPUT_V2_MASK;
+ if (data & LTC3589_VCCR_REG3_REF_SELECT)
+ volt_reg = LTC3589_REG_B3DTV2;
+ else
+ volt_reg = LTC3589_REG_B3DTV1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ data = ltc_3589_reg_read(ltc, volt_reg);
+ if (data < 0)
+ return data;
+
+ data >>= shift;
+ data &= mask;
+ uV = (((r1 + r2) * (362500 + data * 12500)) / r2);
+ return uV;
+}
+
+static int ltc3589_dcdc_set_voltage(struct regulator_dev *dev,
+ int min_uV, int max_uV)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int dcdc = rdev_get_id(dev);
+ int volt_reg1;
+ int volt_reg2;
+ int shift, mask;
+ int r1, r2;
+ int dac_vol, data, slew_val;
+
+ r1 = 0;
+ r2 = 1;
+ if (dcdc < LTC3589_DCDC_1 || dcdc > LTC3589_DCDC_3)
+ return -EINVAL;
+
+ switch (dcdc) {
+ case LTC3589_DCDC_1:
+ r1 = LTC3589_SW1_R1;
+ r2 = LTC3589_SW1_R2;
+ volt_reg1 = 0;
+ volt_reg2 = LTC3589_REG_B1DTV1;
+ slew_val = 1;
+ shift = LTC3589_B1DTV2_REG1_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B1DTV2_REG1_REF_INPUT_V2_MASK;
+ break;
+ case LTC3589_DCDC_2:
+ r1 = LTC3589_SW2_R1;
+ r2 = ltc3589_sw2_r2;
+ volt_reg1 = 0;
+ volt_reg2 = LTC3589_REG_B2DTV1;
+ slew_val = 1;
+ shift = LTC3589_B2DTV2_REG2_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B2DTV2_REG2_REF_INPUT_V2_MASK;
+ break;
+ case LTC3589_DCDC_3:
+ r1 = LTC3589_SW3_R1;
+ r2 = LTC3589_SW3_R2;
+ volt_reg1 = 0;
+ volt_reg2 = LTC3589_REG_B3DTV1;
+ slew_val = 1;
+ shift = LTC3589_B3DTV2_REG3_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B3DTV2_REG3_REF_INPUT_V2_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dac_vol = ((min_uV * r2 - 362500 * (r1 + r2)) / (12500 * (r1 + r2)));
+ if ((dac_vol > 0x1F) || (dac_vol < 0))
+ return -EINVAL;
+
+ /* Set voltage */
+ if (volt_reg1 != 0) {
+ data = ltc_3589_reg_read(ltc, volt_reg1);
+ if (data < 0)
+ return data;
+
+ data >>= shift;
+ data &= ~mask;
+ data |= dac_vol;
+ ltc_3589_reg_write(ltc, volt_reg1, data);
+ }
+
+ if (volt_reg2 != 0) {
+ data = ltc_3589_reg_read(ltc, volt_reg2);
+ if (data < 0)
+ return data;
+
+ data >>= shift;
+ data &= ~mask;
+ data |= dac_vol;
+ ltc_3589_reg_write(ltc, volt_reg2, data);
+ }
+
+ /* Set slew config */
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_VCCR);
+ if (data < 0)
+ return data;
+
+ data &= ~(3 << (2 * dcdc));
+ data |= (slew_val << (2 * dcdc));
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_VCCR, data);
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_SCR2);
+ if (data < 0)
+ return data;
+
+ data &= ~(1 << dcdc);
+ data |= (1 << dcdc);
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_SCR2, data);
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_OVEN);
+ if (data < 0)
+ return data;
+
+ data &= ~(1 << dcdc);
+ data |= (1 << dcdc);
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_OVEN, data);
+
+ mdelay(10);
+
+ return 0;
+}
+
+static int ltc3589_set_suspend_voltage(struct regulator_dev *dev,
+ int uV)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int dcdc = rdev_get_id(dev);
+ int volt_reg1;
+ int shift, mask;
+ int r1, r2;
+ int dac_vol, data;
+
+ r1 = 0;
+ r2 = 1;
+ if (dcdc < LTC3589_DCDC_1 || dcdc > LTC3589_DCDC_3)
+ return -EINVAL;
+
+ switch (dcdc) {
+ case LTC3589_DCDC_1:
+ r1 = LTC3589_SW1_R1;
+ r2 = LTC3589_SW1_R2;
+ volt_reg1 = LTC3589_REG_B1DTV2;
+ shift = LTC3589_B1DTV2_REG1_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B1DTV2_REG1_REF_INPUT_V2_MASK;
+ break;
+ case LTC3589_DCDC_2:
+ r1 = LTC3589_SW2_R1;
+ r2 = ltc3589_sw2_r2;
+ volt_reg1 = LTC3589_REG_B2DTV2;
+ shift = LTC3589_B2DTV2_REG2_REF_INPUT_V2_SHIFT;
+ mask = LTC3589_B2DTV2_REG2_REF_INPUT_V2_MASK;
+ break;
+ default:
+ return 0;
+ }
+
+ dac_vol = ((uV * r2 - 362500 * (r1 + r2)) / (12500 * (r1 + r2)));
+ if ((dac_vol > 0x1F) || (dac_vol < 0))
+ return -EINVAL;
+
+ data = ltc_3589_reg_read(ltc, volt_reg1);
+ if (data < 0)
+ return data;
+
+ data >>= shift;
+ data &= ~mask;
+ data |= dac_vol;
+ ltc_3589_reg_write(ltc, volt_reg1, data);
+ return 0;
+}
+
+static int ltc3589_set_suspend_enable(struct regulator_dev *rdev)
+{
+ return 0;
+}
+
+static int ltc3589_set_suspend_disable(struct regulator_dev *rdev)
+{
+ return 0;
+}
+
+static int ltc3589_set_suspend_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ return 0;
+}
+
+static int ltc3589_ldo_get_voltage(struct regulator_dev *dev)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int data, ldo = rdev_get_id(dev);
+ int uV;
+
+ if (ldo < LTC3589_LDO_1 || ldo > LTC3589_LDO_4)
+ return -EINVAL;
+
+ if (ldo == LTC3589_LDO_1 || ldo == LTC3589_LDO_3)
+ return -EINVAL;
+
+ if (ldo == LTC3589_LDO_4) {
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_L2DTV2);
+ if (data < 0)
+ return data;
+
+ data >>= LTC3589_L2DTV2_LDO4_OUTPUT_VOLTAGE_SHIFT;
+ data &= LTC3589_L2DTV2_LDO4_OUTPUT_VOLTAGE_MASK;
+ switch (data) {
+ case 0:
+ return 1800000;
+ case 1:
+ return 2500000;
+ case 2:
+ return 3000000;
+ case 3:
+ return 3300000;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_VCCR);
+ if (data < 0)
+ return data;
+
+ if (data & LTC3589_VCCR_LDO2_REF_SELECT)
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_L2DTV2);
+ else
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_L2DTV1);
+
+ if (data < 0)
+ return data;
+
+ data >>= LTC3589_L2DTV2_LDO2_REF_INPUT_V2_SHIFT;
+ data &= LTC3589_L2DTV2_LDO2_REF_INPUT_V2_MASK;
+ uV = (((LTC3589_LDO2_R1 + ltc3589_ldo2_r2)
+ * (362500 + data * 12500)) / ltc3589_ldo2_r2);
+ return uV;
+ }
+
+ return -EINVAL;
+}
+
+static int ltc3589_ldo_set_voltage(struct regulator_dev *dev,
+ int min_uV, int max_uV)
+{
+ struct ltc3589 *ltc = rdev_get_drvdata(dev);
+ int data, vsel, ldo = rdev_get_id(dev);
+
+ if (ldo < LTC3589_LDO_1 || ldo > LTC3589_LDO_4)
+ return -EINVAL;
+
+ if (ldo == LTC3589_LDO_1 || ldo == LTC3589_LDO_3)
+ return -EINVAL;
+
+ if (ldo == LTC3589_LDO_4) {
+ for (vsel = 0; vsel < 4; vsel++) {
+ int mV = LDO4_VSEL_table[vsel];
+ int uV = mV * 1000;
+
+ /* Break at the first in-range value */
+ if (min_uV <= uV && uV <= max_uV)
+ break;
+ }
+
+ if (vsel == 4)
+ return -EINVAL;
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_L2DTV2);
+ if (data < 0)
+ return data;
+
+ data &= ~(0x3 << LTC3589_L2DTV2_LDO4_OUTPUT_VOLTAGE_SHIFT);
+ data |= (vsel << LTC3589_L2DTV2_LDO4_OUTPUT_VOLTAGE_SHIFT);
+ data &= ~(1 << LTC3589_L2DTV2_LDO4_CONTROL_MODE_SHIFT);
+ data |= (1 << LTC3589_L2DTV2_LDO4_CONTROL_MODE_SHIFT);
+ ltc_3589_reg_write(ltc, LTC3589_REG_L2DTV2, data);
+
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_SCR2);
+ if (data < 0)
+ return data;
+
+ data &= ~(1 << LTC3589_SCR2_LDO4_STARTUP_SHIFT);
+ data |= (1 << LTC3589_SCR2_LDO4_STARTUP_SHIFT);
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_SCR2, data);
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_OVEN);
+ if (data < 0)
+ return data;
+
+ data &= ~(LTC3589_OVEN_EN_LDO4);
+ data |= LTC3589_OVEN_EN_LDO4;
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_OVEN, data);
+
+ mdelay(10);
+ } else {
+ int dac_vol;
+
+ dac_vol = ((min_uV * ltc3589_ldo2_r2 -
+ 362500 * (LTC3589_LDO2_R1 + ltc3589_ldo2_r2))
+ / (12500 * (LTC3589_LDO2_R1 + ltc3589_ldo2_r2)));
+ if ((dac_vol > 0x1F) || (dac_vol < 0))
+ return -EINVAL;
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_L2DTV1);
+ if (data < 0)
+ return data;
+
+ data &= ~LTC3589_L2DTV2_LDO2_REF_INPUT_V2_MASK;
+ data |= dac_vol;
+ ltc_3589_reg_write(ltc, LTC3589_REG_L2DTV1, data);
+
+ /* Set slew config */
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_VCCR);
+ if (data < 0)
+ return data;
+
+ data &= ~(LTC3589_VCCR_LDO2_SLEW |
+ LTC3589_VCCR_LDO2_REF_SELECT);
+ data |= LTC3589_VCCR_LDO2_SLEW;
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_VCCR, data);
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_SCR2);
+ if (data < 0)
+ return data;
+
+ data &= ~(1 << LTC3589_SCR2_LDO2_STARTUP_SHIFT);
+ data |= (1 << LTC3589_SCR2_LDO2_STARTUP_SHIFT);
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_SCR2, data);
+
+ data = ltc_3589_reg_read(ltc, LTC3589_REG_OVEN);
+ if (data < 0)
+ return data;
+
+ data &= ~(LTC3589_OVEN_EN_LDO2);
+ data |= (LTC3589_OVEN_EN_LDO2);
+
+ ltc_3589_reg_write(ltc, LTC3589_REG_OVEN, data);
+
+ mdelay(10);
+ }
+ return 0;
+}
+
+static int ltc3589_ldo4_list_voltage(struct regulator_dev *dev,
+ unsigned selector)
+{
+ int ldo = rdev_get_id(dev);
+
+ if (ldo != LTC3589_LDO_4)
+ return -EINVAL;
+
+ if (selector >= 4)
+ return -EINVAL;
+ else
+ return LDO4_VSEL_table[selector] * 1000;
+}
+
+/* Operations permitted on SWx */
+static struct regulator_ops ltc3589_sw_ops = {
+ .is_enabled = ltc3589_dcdc_is_enabled,
+ .enable = ltc3589_dcdc_enable,
+ .disable = ltc3589_dcdc_disable,
+ .get_mode = ltc3589_dcdc_get_mode,
+ .set_mode = ltc3589_dcdc_set_mode,
+ .get_voltage = ltc3589_dcdc_get_voltage,
+ .set_voltage = ltc3589_dcdc_set_voltage,
+ .set_suspend_voltage = ltc3589_set_suspend_voltage,
+ .set_suspend_enable = ltc3589_set_suspend_enable,
+ .set_suspend_disable = ltc3589_set_suspend_disable,
+ .set_suspend_mode = ltc3589_set_suspend_mode,
+};
+
+/* Operations permitted on SW4 Buck-Boost */
+static struct regulator_ops ltc3589_sw4_ops = {
+ .is_enabled = ltc3589_dcdc_is_enabled,
+ .enable = ltc3589_dcdc_enable,
+ .disable = ltc3589_dcdc_disable,
+ .get_mode = ltc3589_dcdc_get_mode,
+ .set_mode = ltc3589_dcdc_set_mode,
+};
+
+/* Operations permitted on LDO1_STBY, LDO3 */
+static struct regulator_ops ltc3589_ldo13_ops = {
+ .is_enabled = ltc3589_ldo_is_enabled,
+ .enable = ltc3589_ldo_enable,
+ .disable = ltc3589_ldo_disable,
+};
+
+/* Operations permitted on LDO2 */
+static struct regulator_ops ltc3589_ldo2_ops = {
+ .is_enabled = ltc3589_ldo_is_enabled,
+ .enable = ltc3589_ldo_enable,
+ .disable = ltc3589_ldo_disable,
+ .get_voltage = ltc3589_ldo_get_voltage,
+ .set_voltage = ltc3589_ldo_set_voltage,
+};
+
+/* Operations permitted on LDO4 */
+static struct regulator_ops ltc3589_ldo4_ops = {
+ .is_enabled = ltc3589_ldo_is_enabled,
+ .enable = ltc3589_ldo_enable,
+ .disable = ltc3589_ldo_disable,
+ .get_voltage = ltc3589_ldo_get_voltage,
+ .set_voltage = ltc3589_ldo_set_voltage,
+ .list_voltage = ltc3589_ldo4_list_voltage,
+};
+
+static struct regulator_desc ltc3589_reg[] = {
+ {
+ .name = "SW1",
+ .id = LTC3589_SW1,
+ .ops = &ltc3589_sw_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x1F + 1,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "SW2",
+ .id = LTC3589_SW2,
+ .ops = &ltc3589_sw_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x1F + 1,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "SW3",
+ .id = LTC3589_SW3,
+ .ops = &ltc3589_sw_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x1F + 1,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "SW4",
+ .id = LTC3589_SW4,
+ .ops = &ltc3589_sw4_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO1_STBY",
+ .id = LTC3589_LDO1,
+ .ops = &ltc3589_ldo13_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO2",
+ .id = LTC3589_LDO2,
+ .ops = &ltc3589_ldo2_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = 0x1F + 1,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO3",
+ .id = LTC3589_LDO3,
+ .ops = &ltc3589_ldo13_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ {
+ .name = "LDO4",
+ .id = LTC3589_LDO4,
+ .ops = &ltc3589_ldo4_ops,
+ .type = REGULATOR_VOLTAGE,
+ .n_voltages = ARRAY_SIZE(LDO4_VSEL_table),
+ .owner = THIS_MODULE,
+ },
+};
+
+static int ltc3589_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+
+ if (pdev->id < LTC3589_DCDC_1 || pdev->id > LTC3589_LDO4)
+ return -ENODEV;
+
+ if (cpu_is_mx53_rev(CHIP_REV_2_0) >= 1) {
+ ltc3589_ldo2_r2 = LTC3589_LDO2_R2_TO2;
+ ltc3589_sw2_r2 = LTC3589_SW2_R2_TO2;
+ } else {
+ ltc3589_ldo2_r2 = LTC3589_LDO2_R2_TO1;
+ ltc3589_sw2_r2 = LTC3589_SW2_R2_TO1;
+ }
+
+ /* register regulator */
+ rdev = regulator_register(&ltc3589_reg[pdev->id], &pdev->dev,
+ pdev->dev.platform_data,
+ dev_get_drvdata(&pdev->dev));
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ ltc3589_reg[pdev->id].name);
+ return PTR_ERR(rdev);
+ }
+
+ ltc3589_set_slew_rate(rdev, LTC3589_VRRCR_SLEW_RATE_7P00MV_US);
+
+ return 0;
+}
+
+static int ltc3589_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+int ltc3589_register_regulator(struct ltc3589 *ltc3589, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ if (ltc3589->pmic.pdev[reg])
+ return -EBUSY;
+ if (reg < LTC3589_DCDC_1 || reg > LTC3589_LDO_4)
+ return -ENODEV;
+ pdev = platform_device_alloc("ltc3589-regulator", reg);
+ if (!pdev)
+ return -ENOMEM;
+ ltc3589->pmic.pdev[reg] = pdev;
+
+ initdata->driver_data = ltc3589;
+
+ pdev->dev.platform_data = initdata;
+ pdev->dev.parent = ltc3589->dev;
+ platform_set_drvdata(pdev, ltc3589);
+
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ dev_err(ltc3589->dev, "Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ ltc3589->pmic.pdev[reg] = NULL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ltc3589_register_regulator);
+
+static struct platform_driver ltc3589_regulator_driver = {
+ .driver = {
+ .name = "ltc3589-regulator",
+ },
+ .probe = ltc3589_regulator_probe,
+ .remove = ltc3589_regulator_remove,
+};
+
+static int __init ltc3589_regulator_init(void)
+{
+ return platform_driver_register(&ltc3589_regulator_driver);
+
+}
+subsys_initcall_sync(ltc3589_regulator_init);
+
+static void __exit ltc3589_regulator_exit(void)
+{
+ platform_driver_unregister(&ltc3589_regulator_driver);
+}
+module_exit(ltc3589_regulator_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("LTC3589 Regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/max17135-regulator.c b/drivers/regulator/max17135-regulator.c
new file mode 100644
index 000000000000..2d4cbcc1667c
--- /dev/null
+++ b/drivers/regulator/max17135-regulator.c
@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/max17135.h>
+#include <linux/gpio.h>
+
+/*
+ * Regulator definitions
+ * *_MIN_uV - minimum microvolt for regulator
+ * *_MAX_uV - maximum microvolt for regulator
+ * *_STEP_uV - microvolts between regulator output levels
+ * *_MIN_VAL - minimum register field value for regulator
+ * *_MAX_VAL - maximum register field value for regulator
+ */
+#define MAX17135_HVINP_MIN_uV 5000000
+#define MAX17135_HVINP_MAX_uV 20000000
+#define MAX17135_HVINP_STEP_uV 1000000
+#define MAX17135_HVINP_MIN_VAL 0
+#define MAX17135_HVINP_MAX_VAL 1
+
+#define MAX17135_HVINN_MIN_uV 5000000
+#define MAX17135_HVINN_MAX_uV 20000000
+#define MAX17135_HVINN_STEP_uV 1000000
+#define MAX17135_HVINN_MIN_VAL 0
+#define MAX17135_HVINN_MAX_VAL 1
+
+#define MAX17135_GVDD_MIN_uV 5000000
+#define MAX17135_GVDD_MAX_uV 20000000
+#define MAX17135_GVDD_STEP_uV 1000000
+#define MAX17135_GVDD_MIN_VAL 0
+#define MAX17135_GVDD_MAX_VAL 1
+
+#define MAX17135_GVEE_MIN_uV 5000000
+#define MAX17135_GVEE_MAX_uV 20000000
+#define MAX17135_GVEE_STEP_uV 1000000
+#define MAX17135_GVEE_MIN_VAL 0
+#define MAX17135_GVEE_MAX_VAL 1
+
+#define MAX17135_VCOM_MIN_VAL 0
+#define MAX17135_VCOM_MAX_VAL 255
+
+#define MAX17135_VNEG_MIN_uV 5000000
+#define MAX17135_VNEG_MAX_uV 20000000
+#define MAX17135_VNEG_STEP_uV 1000000
+#define MAX17135_VNEG_MIN_VAL 0
+#define MAX17135_VNEG_MAX_VAL 1
+
+#define MAX17135_VPOS_MIN_uV 5000000
+#define MAX17135_VPOS_MAX_uV 20000000
+#define MAX17135_VPOS_STEP_uV 1000000
+#define MAX17135_VPOS_MIN_VAL 0
+#define MAX17135_VPOS_MAX_VAL 1
+
+struct max17135_vcom_programming_data {
+ int vcom_min_uV;
+ int vcom_max_uV;
+ int vcom_step_uV;
+};
+
+static int max17135_pass_num = { 1 };
+static int max17135_vcom = { -1250000 };
+
+struct max17135_vcom_programming_data vcom_data[2] = {
+ {
+ -4325000,
+ -500000,
+ 15000,
+ },
+ {
+ -3050000,
+ -500000,
+ 10000,
+ },
+};
+
+static int max17135_is_power_good(struct max17135 *max17135);
+
+/*
+ * Regulator operations
+ */
+static int max17135_hvinp_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int reg_val;
+ unsigned int fld_val;
+
+ if ((uV >= MAX17135_HVINP_MIN_uV) &&
+ (uV <= MAX17135_HVINP_MAX_uV))
+ fld_val = (uV - MAX17135_HVINP_MIN_uV) /
+ MAX17135_HVINP_STEP_uV;
+ else
+ return -EINVAL;
+
+ max17135_reg_read(REG_MAX17135_HVINP, &reg_val);
+
+ reg_val &= ~BITFMASK(HVINP);
+ reg_val |= BITFVAL(HVINP, fld_val); /* shift to correct bit */
+
+ return max17135_reg_write(REG_MAX17135_HVINP, reg_val);
+}
+
+static int max17135_hvinp_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int reg_val;
+ unsigned int fld_val;
+ int volt;
+
+ max17135_reg_read(REG_MAX17135_HVINP, &reg_val);
+
+ fld_val = (reg_val & BITFMASK(HVINP)) >> HVINP_LSH;
+
+ if ((fld_val >= MAX17135_HVINP_MIN_VAL) &&
+ (fld_val <= MAX17135_HVINP_MAX_VAL)) {
+ volt = (fld_val * MAX17135_HVINP_STEP_uV) +
+ MAX17135_HVINP_MIN_uV;
+ } else {
+ printk(KERN_ERR "MAX17135: HVINP voltage is out of range\n");
+ volt = 0;
+ }
+ return volt;
+}
+
+static int max17135_hvinp_enable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int max17135_hvinp_disable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+/* Convert uV to the VCOM register bitfield setting */
+static inline int vcom_uV_to_rs(int uV, int pass_num)
+{
+ return (vcom_data[pass_num].vcom_max_uV - uV)
+ / vcom_data[pass_num].vcom_step_uV;
+}
+
+/* Convert the VCOM register bitfield setting to uV */
+static inline int vcom_rs_to_uV(int rs, int pass_num)
+{
+ return vcom_data[pass_num].vcom_max_uV
+ - (vcom_data[pass_num].vcom_step_uV * rs);
+}
+
+static int max17135_vcom_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ unsigned int reg_val;
+ int vcom_read;
+
+ if ((uV < vcom_data[max17135->pass_num-1].vcom_min_uV)
+ || (uV > vcom_data[max17135->pass_num-1].vcom_max_uV))
+ return -EINVAL;
+
+ max17135_reg_read(REG_MAX17135_DVR, &reg_val);
+
+ /*
+ * Only program VCOM if it is not set to the desired value.
+ * Programming VCOM excessively degrades ability to keep
+ * DVR register value persistent.
+ */
+ vcom_read = vcom_rs_to_uV(reg_val, max17135->pass_num-1);
+ if (vcom_read != max17135->vcom_uV) {
+ reg_val &= ~BITFMASK(DVR);
+ reg_val |= BITFVAL(DVR, vcom_uV_to_rs(uV,
+ max17135->pass_num-1));
+ max17135_reg_write(REG_MAX17135_DVR, reg_val);
+
+ reg_val = BITFVAL(CTRL_DVR, true); /* shift to correct bit */
+ return max17135_reg_write(REG_MAX17135_PRGM_CTRL, reg_val);
+ }
+
+ return 0;
+}
+
+static int max17135_vcom_get_voltage(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_DVR, &reg_val);
+ return vcom_rs_to_uV(BITFEXT(reg_val, DVR), max17135->pass_num-1);
+}
+
+static int max17135_vcom_enable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ /*
+ * Check to see if we need to set the VCOM voltage.
+ * Should only be done one time. And, we can
+ * only change vcom voltage if we have been enabled.
+ */
+ if (!max17135->vcom_setup && max17135_is_power_good(max17135)) {
+ max17135_vcom_set_voltage(reg,
+ max17135->vcom_uV,
+ max17135->vcom_uV);
+ max17135->vcom_setup = true;
+ }
+
+ /* enable VCOM regulator output */
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 1);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(VCOM_ENABLE);
+ reg_val |= BITFVAL(VCOM_ENABLE, 1); /* shift to correct bit */
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ return 0;
+}
+
+static int max17135_vcom_disable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_vcom_ctrl, 0);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(VCOM_ENABLE);
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ return 0;
+}
+
+static int max17135_vcom_is_enabled(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ /* read VCOM regulator enable setting */
+ if (max17135->pass_num == 1) {
+ int gpio = gpio_get_value(max17135->gpio_pmic_vcom_ctrl);
+ if (gpio == 0)
+ return 0;
+ else
+ return 1;
+ } else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= BITFMASK(VCOM_ENABLE);
+ if (reg_val != 0)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+static int max17135_is_power_good(struct max17135 *max17135)
+{
+ /*
+ * XOR of polarity (starting value) and current
+ * value yields whether power is good.
+ */
+ return gpio_get_value(max17135->gpio_pmic_pwrgood) ^
+ max17135->pwrgood_polarity;
+}
+
+static int max17135_wait_power_good(struct max17135 *max17135)
+{
+ int i;
+
+ for (i = 0; i < max17135->max_wait * 3; i++) {
+ if (max17135_is_power_good(max17135))
+ return 0;
+
+ msleep(1);
+ }
+ return -ETIMEDOUT;
+}
+
+static int max17135_display_enable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ /* The Pass 1 parts cannot turn on the PMIC via I2C. */
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_wakeup, 1);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(ENABLE);
+ reg_val |= BITFVAL(ENABLE, 1);
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ return max17135_wait_power_good(max17135);
+}
+
+static int max17135_display_disable(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+
+ if (max17135->pass_num == 1)
+ gpio_set_value(max17135->gpio_pmic_wakeup, 0);
+ else {
+ unsigned int reg_val;
+
+ max17135_reg_read(REG_MAX17135_ENABLE, &reg_val);
+ reg_val &= ~BITFMASK(ENABLE);
+ max17135_reg_write(REG_MAX17135_ENABLE, reg_val);
+ }
+
+ msleep(max17135->max_wait);
+
+ return 0;
+}
+
+static int max17135_display_is_enabled(struct regulator_dev *reg)
+{
+ struct max17135 *max17135 = rdev_get_drvdata(reg);
+ int gpio = gpio_get_value(max17135->gpio_pmic_wakeup);
+
+ if (gpio == 0)
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * Regulator operations
+ */
+
+static struct regulator_ops max17135_display_ops = {
+ .enable = max17135_display_enable,
+ .disable = max17135_display_disable,
+ .is_enabled = max17135_display_is_enabled,
+};
+
+static struct regulator_ops max17135_gvdd_ops = {
+};
+
+static struct regulator_ops max17135_gvee_ops = {
+};
+
+static struct regulator_ops max17135_hvinn_ops = {
+};
+
+static struct regulator_ops max17135_hvinp_ops = {
+ .enable = max17135_hvinp_enable,
+ .disable = max17135_hvinp_disable,
+ .get_voltage = max17135_hvinp_get_voltage,
+ .set_voltage = max17135_hvinp_set_voltage,
+};
+
+static struct regulator_ops max17135_vcom_ops = {
+ .enable = max17135_vcom_enable,
+ .disable = max17135_vcom_disable,
+ .get_voltage = max17135_vcom_get_voltage,
+ .set_voltage = max17135_vcom_set_voltage,
+ .is_enabled = max17135_vcom_is_enabled,
+};
+
+static struct regulator_ops max17135_vneg_ops = {
+};
+
+static struct regulator_ops max17135_vpos_ops = {
+};
+
+/*
+ * Regulator descriptors
+ */
+static struct regulator_desc max17135_reg[MAX17135_NUM_REGULATORS] = {
+{
+ .name = "DISPLAY",
+ .id = MAX17135_DISPLAY,
+ .ops = &max17135_display_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "GVDD",
+ .id = MAX17135_GVDD,
+ .ops = &max17135_gvdd_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "GVEE",
+ .id = MAX17135_GVEE,
+ .ops = &max17135_gvee_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "HVINN",
+ .id = MAX17135_HVINN,
+ .ops = &max17135_hvinn_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "HVINP",
+ .id = MAX17135_HVINP,
+ .ops = &max17135_hvinp_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "VCOM",
+ .id = MAX17135_VCOM,
+ .ops = &max17135_vcom_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "VNEG",
+ .id = MAX17135_VNEG,
+ .ops = &max17135_vneg_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+{
+ .name = "VPOS",
+ .id = MAX17135_VPOS,
+ .ops = &max17135_vpos_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+},
+};
+
+static void max17135_setup_timings(struct max17135 *max17135)
+{
+ unsigned int reg_val;
+
+ int timing1, timing2, timing3, timing4,
+ timing5, timing6, timing7, timing8;
+
+ max17135_reg_read(REG_MAX17135_TIMING1, &timing1);
+ max17135_reg_read(REG_MAX17135_TIMING2, &timing2);
+ max17135_reg_read(REG_MAX17135_TIMING3, &timing3);
+ max17135_reg_read(REG_MAX17135_TIMING4, &timing4);
+ max17135_reg_read(REG_MAX17135_TIMING5, &timing5);
+ max17135_reg_read(REG_MAX17135_TIMING6, &timing6);
+ max17135_reg_read(REG_MAX17135_TIMING7, &timing7);
+ max17135_reg_read(REG_MAX17135_TIMING8, &timing8);
+
+ if ((timing1 != max17135->gvee_pwrup) ||
+ (timing2 != max17135->vneg_pwrup) ||
+ (timing3 != max17135->vpos_pwrup) ||
+ (timing4 != max17135->gvdd_pwrup) ||
+ (timing5 != max17135->gvdd_pwrdn) ||
+ (timing6 != max17135->vpos_pwrdn) ||
+ (timing7 != max17135->vneg_pwrdn) ||
+ (timing8 != max17135->gvee_pwrdn)) {
+ max17135_reg_write(REG_MAX17135_TIMING1, max17135->gvee_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING2, max17135->vneg_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING3, max17135->vpos_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING4, max17135->gvdd_pwrup);
+ max17135_reg_write(REG_MAX17135_TIMING5, max17135->gvdd_pwrdn);
+ max17135_reg_write(REG_MAX17135_TIMING6, max17135->vpos_pwrdn);
+ max17135_reg_write(REG_MAX17135_TIMING7, max17135->vneg_pwrdn);
+ max17135_reg_write(REG_MAX17135_TIMING8, max17135->gvee_pwrdn);
+
+ reg_val = BITFVAL(CTRL_TIMING, true); /* shift to correct bit */
+ max17135_reg_write(REG_MAX17135_PRGM_CTRL, reg_val);
+ }
+}
+
+
+/*
+ * Regulator init/probing/exit functions
+ */
+static int max17135_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+
+ rdev = regulator_register(&max17135_reg[pdev->id], &pdev->dev,
+ pdev->dev.platform_data,
+ dev_get_drvdata(&pdev->dev));
+
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ max17135_reg[pdev->id].name);
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+static int max17135_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ regulator_unregister(rdev);
+ return 0;
+}
+
+static struct platform_driver max17135_regulator_driver = {
+ .probe = max17135_regulator_probe,
+ .remove = max17135_regulator_remove,
+ .driver = {
+ .name = "max17135-reg",
+ },
+};
+
+int max17135_register_regulator(struct max17135 *max17135, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ struct i2c_client *client = max17135->i2c_client;
+ /* If we can't find PMIC via I2C, we should not register regulators */
+ if (i2c_smbus_read_byte_data(client,
+ REG_MAX17135_PRODUCT_REV) != 0) {
+ dev_err(max17135->dev,
+ "Max17135 PMIC not found!\n");
+ return -ENXIO;
+ }
+
+ if (max17135->pdev[reg])
+ return -EBUSY;
+
+ pdev = platform_device_alloc("max17135-reg", reg);
+ if (!pdev)
+ return -ENOMEM;
+
+ max17135->pdev[reg] = pdev;
+
+ initdata->driver_data = max17135;
+
+ pdev->dev.platform_data = initdata;
+ pdev->dev.parent = max17135->dev;
+ platform_set_drvdata(pdev, max17135);
+
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ dev_err(max17135->dev,
+ "Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ max17135->pdev[reg] = NULL;
+ }
+
+ if (!max17135->init_done) {
+ max17135->pass_num = max17135_pass_num;
+ max17135->vcom_uV = max17135_vcom;
+
+ /*
+ * Set up PMIC timing values.
+ * Should only be done one time! Timing values may only be
+ * changed a limited number of times according to spec.
+ */
+ max17135_setup_timings(max17135);
+
+ max17135->pwrgood_polarity =
+ gpio_get_value(max17135->gpio_pmic_pwrgood);
+
+ max17135->init_done = true;
+ }
+
+ return ret;
+}
+
+static int __init max17135_regulator_init(void)
+{
+ return platform_driver_register(&max17135_regulator_driver);
+}
+subsys_initcall(max17135_regulator_init);
+
+static void __exit max17135_regulator_exit(void)
+{
+ platform_driver_unregister(&max17135_regulator_driver);
+}
+module_exit(max17135_regulator_exit);
+
+
+/*
+ * Parse user specified options (`max17135:')
+ * example:
+ * max17135:pass=2,vcom=-1250000
+ */
+static int __init max17135_setup(char *options)
+{
+ int ret;
+ char *opt;
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
+ if (!strncmp(opt, "pass=", 5)) {
+ ret = strict_strtoul(opt + 5, 0, &max17135_pass_num);
+ if (ret < 0)
+ return ret;
+ }
+ if (!strncmp(opt, "vcom=", 5)) {
+ int offs = 5;
+ if (opt[5] == '-')
+ offs = 6;
+ ret = strict_strtoul(opt + offs, 0, &max17135_vcom);
+ if (ret < 0)
+ return ret;
+ max17135_vcom = -max17135_vcom;
+ }
+ }
+
+ return 1;
+}
+
+__setup("max17135:", max17135_setup);
+
+/* Module information */
+MODULE_DESCRIPTION("MAX17135 regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/mxs-regulator.c b/drivers/regulator/mxs-regulator.c
new file mode 100644
index 000000000000..34930776a90c
--- /dev/null
+++ b/drivers/regulator/mxs-regulator.c
@@ -0,0 +1,302 @@
+/*
+ * Freescale STMP378X voltage regulators
+ *
+ * Embedded Alley Solutions, Inc <source@embeddedalley.com>
+ *
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <mach/power.h>
+#include <mach/regulator.h>
+
+static int mxs_set_voltage(struct regulator_dev *reg, int MiniV, int uv)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ if (mxs_reg->rdata->set_voltage)
+ return mxs_reg->rdata->set_voltage(mxs_reg, uv);
+ else
+ return -ENOTSUPP;
+}
+
+
+static int mxs_get_voltage(struct regulator_dev *reg)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ if (mxs_reg->rdata->get_voltage)
+ return mxs_reg->rdata->get_voltage(mxs_reg);
+ else
+ return -ENOTSUPP;
+}
+
+static int mxs_set_current(struct regulator_dev *reg, int min_uA, int uA)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ if (mxs_reg->rdata->set_current)
+ return mxs_reg->rdata->set_current(mxs_reg, uA);
+ else
+ return -ENOTSUPP;
+}
+
+static int mxs_get_current(struct regulator_dev *reg)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ if (mxs_reg->rdata->get_current)
+ return mxs_reg->rdata->get_current(mxs_reg);
+ else
+ return -ENOTSUPP;
+}
+
+static int mxs_enable(struct regulator_dev *reg)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ return mxs_reg->rdata->enable(mxs_reg);
+}
+
+static int mxs_disable(struct regulator_dev *reg)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ return mxs_reg->rdata->disable(mxs_reg);
+}
+
+static int mxs_is_enabled(struct regulator_dev *reg)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ return mxs_reg->rdata->is_enabled(mxs_reg);
+}
+
+static int mxs_set_mode(struct regulator_dev *reg, unsigned int mode)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ return mxs_reg->rdata->set_mode(mxs_reg, mode);
+}
+
+static unsigned int mxs_get_mode(struct regulator_dev *reg)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ return mxs_reg->rdata->get_mode(mxs_reg);
+}
+
+static unsigned int mxs_get_optimum_mode(struct regulator_dev *reg,
+ int input_uV, int output_uV, int load_uA)
+{
+ struct mxs_regulator *mxs_reg = rdev_get_drvdata(reg);
+
+ if (mxs_reg->rdata->get_optimum_mode)
+ return mxs_reg->rdata->get_optimum_mode(mxs_reg, input_uV,
+ output_uV, load_uA);
+ else
+ return -ENOTSUPP;
+}
+
+static struct regulator_ops mxs_rops = {
+ .set_voltage = mxs_set_voltage,
+ .get_voltage = mxs_get_voltage,
+ .set_current_limit = mxs_set_current,
+ .get_current_limit = mxs_get_current,
+ .enable = mxs_enable,
+ .disable = mxs_disable,
+ .is_enabled = mxs_is_enabled,
+ .set_mode = mxs_set_mode,
+ .get_mode = mxs_get_mode,
+ .get_optimum_mode = mxs_get_optimum_mode,
+};
+
+static struct regulator_desc mxs_reg_desc[] = {
+ {
+ .name = "vddd",
+ .id = MXS_VDDD,
+ .ops = &mxs_rops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "vdda",
+ .id = MXS_VDDA,
+ .ops = &mxs_rops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "vddio",
+ .id = MXS_VDDIO,
+ .ops = &mxs_rops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "vddd_bo",
+ .id = MXS_VDDDBO,
+ .ops = &mxs_rops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "overall_current",
+ .id = MXS_OVERALL_CUR,
+ .ops = &mxs_rops,
+ .irq = 0,
+ .type = REGULATOR_CURRENT,
+ .owner = THIS_MODULE
+ },
+};
+
+static int reg_callback(struct notifier_block *self,
+ unsigned long event, void *data)
+{
+ unsigned long flags;
+ struct mxs_regulator *sreg =
+ container_of(self, struct mxs_regulator , nb);
+
+ switch (event) {
+ case MXS_REG5V_IS_USB:
+ spin_lock_irqsave(&sreg->lock, flags);
+ sreg->rdata->max_current = 500000;
+ spin_unlock_irqrestore(&sreg->lock, flags);
+ break;
+ case MXS_REG5V_NOT_USB:
+ spin_lock_irqsave(&sreg->lock, flags);
+ sreg->rdata->max_current = 0x7fffffff;
+ spin_unlock_irqrestore(&sreg->lock, flags);
+ break;
+ }
+
+ return 0;
+}
+
+int mxs_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_desc *rdesc;
+ struct regulator_dev *rdev;
+ struct mxs_regulator *sreg;
+ struct regulator_init_data *initdata;
+
+ sreg = platform_get_drvdata(pdev);
+ initdata = pdev->dev.platform_data;
+ sreg->cur_current = 0;
+ sreg->next_current = 0;
+ sreg->cur_voltage = 0;
+
+ init_waitqueue_head(&sreg->wait_q);
+ spin_lock_init(&sreg->lock);
+
+ if (pdev->id > MXS_OVERALL_CUR) {
+ rdesc = kzalloc(sizeof(struct regulator_desc), GFP_KERNEL);
+ memcpy(rdesc, &mxs_reg_desc[MXS_OVERALL_CUR],
+ sizeof(struct regulator_desc));
+ rdesc->name = kstrdup(sreg->rdata->name, GFP_KERNEL);
+ } else
+ rdesc = &mxs_reg_desc[pdev->id];
+
+ pr_debug("probing regulator %s %s %d\n",
+ sreg->rdata->name,
+ rdesc->name,
+ pdev->id);
+
+ /* register regulator */
+ rdev = regulator_register(rdesc, &pdev->dev,
+ initdata, sreg);
+
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ rdesc->name);
+ return PTR_ERR(rdev);
+ }
+
+ if (sreg->rdata->max_current) {
+ struct regulator *regu;
+ regu = regulator_get(NULL, sreg->rdata->name);
+ sreg->nb.notifier_call = reg_callback;
+ regulator_register_notifier(regu, &sreg->nb);
+ }
+
+ return 0;
+}
+
+
+int mxs_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+
+}
+
+int mxs_register_regulator(
+ struct mxs_regulator *reg_data, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ pdev = platform_device_alloc("mxs_reg", reg);
+ if (!pdev)
+ return -ENOMEM;
+
+ pdev->dev.platform_data = initdata;
+
+ platform_set_drvdata(pdev, reg_data);
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ pr_debug("Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ }
+ pr_debug("register regulator %s, %d: %d\n",
+ reg_data->rdata->name, reg, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mxs_register_regulator);
+
+struct platform_driver mxs_reg = {
+ .driver = {
+ .name = "mxs_reg",
+ },
+ .probe = mxs_regulator_probe,
+ .remove = mxs_regulator_remove,
+};
+
+int mxs_regulator_init(void)
+{
+ return platform_driver_register(&mxs_reg);
+}
+
+void mxs_regulator_exit(void)
+{
+ platform_driver_unregister(&mxs_reg);
+}
+
+postcore_initcall(mxs_regulator_init);
+module_exit(mxs_regulator_exit);
diff --git a/drivers/regulator/reg-mc13783.c b/drivers/regulator/reg-mc13783.c
new file mode 100644
index 000000000000..da20907ba087
--- /dev/null
+++ b/drivers/regulator/reg-mc13783.c
@@ -0,0 +1,2662 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/mc13783/core.h>
+#include <linux/platform_device.h>
+#include <linux/pmic_status.h>
+#include <linux/pmic_external.h>
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+/*!
+ * @enum regulator_voltage_sw
+ * @brief PMIC regulator SW output voltage.
+ */
+enum {
+ SW_0_9V = 0, /*!< 0.900 V */
+ SW_0_925V, /*!< 0.925 V */
+ SW_0_95V, /*!< 0.950 V */
+ SW_0_975V, /*!< 0.975 V */
+ SW_1V, /*!< 1.000 V */
+ SW_1_025V, /*!< 1.025 V */
+ SW_1_05V, /*!< 1.050 V */
+ SW_1_075V, /*!< 1.075 V */
+ SW_1_1V, /*!< 1.100 V */
+ SW_1_125V, /*!< 1.125 V */
+ SW_1_15V, /*!< 1.150 V */
+ SW_1_175V, /*!< 1.175 V */
+ SW_1_2V, /*!< 1.200 V */
+ SW_1_225V, /*!< 1.225 V */
+ SW_1_25V, /*!< 1.250 V */
+ SW_1_275V, /*!< 1.275 V */
+ SW_1_3V, /*!< 1.300 V */
+ SW_1_325V, /*!< 1.325 V */
+ SW_1_35V, /*!< 1.350 V */
+ SW_1_375V, /*!< 1.375 V */
+ SW_1_4V, /*!< 1.400 V */
+ SW_1_425V, /*!< 1.425 V */
+ SW_1_45V, /*!< 1.450 V */
+ SW_1_475V, /*!< 1.475 V */
+ SW_1_5V, /*!< 1.500 V */
+ SW_1_525V, /*!< 1.525 V */
+ SW_1_55V, /*!< 1.550 V */
+ SW_1_575V, /*!< 1.575 V */
+ SW_1_6V, /*!< 1.600 V */
+ SW_1_625V, /*!< 1.625 V */
+ SW_1_65V, /*!< 1.650 V */
+ SW_1_675V, /*!< 1.675 V */
+ SW_1_7V, /*!< 1.700 V */
+ SW_1_8V = 36, /*!< 1.800 V */
+ SW_1_85V = 40, /*!< 1.850 V */
+ SW_2V = 44, /*!< 2_000 V */
+ SW_2_1V = 48, /*!< 2_100 V */
+ SW_2_2V = 52, /*!< 2_200 V */
+} regulator_voltage_sw;
+
+/*!
+ * @enum regulator_voltage_violo
+ * @brief PMIC regulator VIOLO output voltage.
+ */
+enum {
+ VIOLO_1_2V = 0, /*!< 1.2 V */
+ VIOLO_1_3V, /*!< 1.3 V */
+ VIOLO_1_5V, /*!< 1.5 V */
+ VIOLO_1_8V, /*!< 1.8 V */
+} regulator_voltage_violo;
+
+/*!
+ * @enum regulator_voltage_vdig
+ * @brief PMIC regulator VDIG output voltage.
+ */
+enum {
+ VDIG_1_2V = 0, /*!< 1.2 V */
+ VDIG_1_3V, /*!< 1.3 V */
+ VDIG_1_5V, /*!< 1.5 V */
+ VDIG_1_8V, /*!< 1.8 V */
+} regulator_voltage_vdig;
+
+/*!
+ * @enum regulator_voltage_vgen
+ * @brief PMIC regulator VGEN output voltage.
+ */
+enum {
+ VGEN_1_2V = 0, /*!< 1.2 V */
+ VGEN_1_3V, /*!< 1.3 V */
+ VGEN_1_5V, /*!< 1.5 V */
+ VGEN_1_8V, /*!< 1.8 V */
+ VGEN_1_1V, /*!< 1.1 V */
+ VGEN_2V, /*!< 2 V */
+ VGEN_2_775V, /*!< 2.775 V */
+ VGEN_2_4V, /*!< 2.4 V */
+} regulator_voltage_vgen;
+
+/*!
+ * @enum regulator_voltage_vrfdig
+ * @brief PMIC regulator VRFDIG output voltage.
+ */
+enum {
+ VRFDIG_1_2V = 0, /*!< 1.2 V */
+ VRFDIG_1_5V, /*!< 1.5 V */
+ VRFDIG_1_8V, /*!< 1.8 V */
+ VRFDIG_1_875V, /*!< 1.875 V */
+} regulator_voltage_vrfdig;
+
+/*!
+ * @enum regulator_voltage_vrfref
+ * @brief PMIC regulator VRFREF output voltage.
+ */
+enum {
+ VRFREF_2_475V = 0, /*!< 2.475 V */
+ VRFREF_2_6V, /*!< 2.600 V */
+ VRFREF_2_7V, /*!< 2.700 V */
+ VRFREF_2_775V, /*!< 2.775 V */
+} regulator_voltage_vrfref;
+
+/*!
+ * @enum regulator_voltage_vrfcp
+ * @brief PMIC regulator VRFCP output voltage.
+ */
+enum {
+ VRFCP_2_7V = 0, /*!< 2.700 V */
+ VRFCP_2_775V, /*!< 2.775 V */
+} regulator_voltage_vrfcp;
+
+/*!
+ * @enum regulator_voltage_vsim
+ * @brief PMIC linear regulator VSIM output voltage.
+ */
+enum {
+ VSIM_1_8V = 0, /*!< 1.8 V */
+ VSIM_2_9V, /*!< 2.90 V */
+ VSIM_3V = 1, /*!< 3 V */
+} regulator_voltage_vsim;
+
+/*!
+ * @enum regulator_voltage_vesim
+ * @brief PMIC regulator VESIM output voltage.
+ */
+enum {
+ VESIM_1_8V = 0, /*!< 1.80 V */
+ VESIM_2_9V, /*!< 2.90 V */
+} regulator_voltage_vesim;
+
+/*!
+ * @enum regulator_voltage_vcam
+ * @brief PMIC regulator VCAM output voltage.
+ */
+enum {
+ VCAM_1_5V = 0, /*!< 1.50 V */
+ VCAM_1_8V, /*!< 1.80 V */
+ VCAM_2_5V, /*!< 2.50 V */
+ VCAM_2_55V, /*!< 2.55 V */
+ VCAM_2_6V, /*!< 2.60 V */
+ VCAM_2_75V, /*!< 2.75 V */
+ VCAM_2_8V, /*!< 2.80 V */
+ VCAM_3V, /*!< 3.00 V */
+} regulator_voltage_vcam;
+
+/*!
+ * @enum regulator_voltage_vvib
+ * @brief PMIC linear regulator V_VIB output voltage.
+ */
+enum {
+ VVIB_1_3V = 0, /*!< 1.30 V */
+ VVIB_1_8V, /*!< 1.80 V */
+ VVIB_2V, /*!< 2 V */
+ VVIB_3V, /*!< 3 V */
+} regulator_voltage_vvib;
+
+/*!
+ * @enum regulator_voltage_vmmc
+ * @brief MC13783 PMIC regulator VMMC output voltage.
+ */
+enum {
+ VMMC_1_6V = 0, /*!< 1.60 V */
+ VMMC_1_8V, /*!< 1.80 V */
+ VMMC_2V, /*!< 2.00 V */
+ VMMC_2_6V, /*!< 2.60 V */
+ VMMC_2_7V, /*!< 2.70 V */
+ VMMC_2_8V, /*!< 2.80 V */
+ VMMC_2_9V, /*!< 2.90 V */
+ VMMC_3V, /*!< 3.00 V */
+} regulator_voltage_vmmc;
+
+/*!
+ * @enum regulator_voltage_vrf
+ * @brief PMIC regulator VRF output voltage.
+ */
+enum {
+ VRF_1_5V = 0, /*!< 1.500 V */
+ VRF_1_875V, /*!< 1.875 V */
+ VRF_2_7V, /*!< 2.700 V */
+ VRF_2_775V, /*!< 2.775 V */
+} regulator_voltage_vrf;
+
+/*!
+ * @enum regulator_voltage_sw3
+ * @brief PMIC Switch mode regulator SW3 output voltages.
+ */
+enum {
+ SW3_5V = 0, /*!< 5.0 V */
+ SW3_5_5V = 3, /*!< 5.5 V */
+} regulator_voltage_sw3;
+
+/*!
+ * The \b TPmicDVSTransitionSpeed enum defines the rate with which the
+ * voltage transition occurs.
+ */
+enum {
+ ESysDependent,
+ E25mVEach4us,
+ E25mVEach8us,
+ E25mvEach16us
+} DVS_transition_speed;
+
+/*
+ * Reg Regulator Mode 0
+ */
+#define VAUDIO_EN_LSH 0
+#define VAUDIO_EN_WID 1
+#define VAUDIO_EN_ENABLE 1
+#define VAUDIO_EN_DISABLE 0
+#define VIOHI_EN_LSH 3
+#define VIOHI_EN_WID 1
+#define VIOHI_EN_ENABLE 1
+#define VIOHI_EN_DISABLE 0
+#define VIOLO_EN_LSH 6
+#define VIOLO_EN_WID 1
+#define VIOLO_EN_ENABLE 1
+#define VIOLO_EN_DISABLE 0
+#define VDIG_EN_LSH 9
+#define VDIG_EN_WID 1
+#define VDIG_EN_ENABLE 1
+#define VDIG_EN_DISABLE 0
+#define VGEN_EN_LSH 12
+#define VGEN_EN_WID 1
+#define VGEN_EN_ENABLE 1
+#define VGEN_EN_DISABLE 0
+#define VRFDIG_EN_LSH 15
+#define VRFDIG_EN_WID 1
+#define VRFDIG_EN_ENABLE 1
+#define VRFDIG_EN_DISABLE 0
+#define VRFREF_EN_LSH 18
+#define VRFREF_EN_WID 1
+#define VRFREF_EN_ENABLE 1
+#define VRFREF_EN_DISABLE 0
+#define VRFCP_EN_LSH 21
+#define VRFCP_EN_WID 1
+#define VRFCP_EN_ENABLE 1
+#define VRFCP_EN_DISABLE 0
+
+/*
+ * Reg Regulator Mode 1
+ */
+#define VSIM_EN_LSH 0
+#define VSIM_EN_WID 1
+#define VSIM_EN_ENABLE 1
+#define VSIM_EN_DISABLE 0
+#define VESIM_EN_LSH 3
+#define VESIM_EN_WID 1
+#define VESIM_EN_ENABLE 1
+#define VESIM_EN_DISABLE 0
+#define VCAM_EN_LSH 6
+#define VCAM_EN_WID 1
+#define VCAM_EN_ENABLE 1
+#define VCAM_EN_DISABLE 0
+#define VRFBG_EN_LSH 9
+#define VRFBG_EN_WID 1
+#define VRFBG_EN_ENABLE 1
+#define VRFBG_EN_DISABLE 0
+#define VVIB_EN_LSH 11
+#define VVIB_EN_WID 1
+#define VVIB_EN_ENABLE 1
+#define VVIB_EN_DISABLE 0
+#define VRF1_EN_LSH 12
+#define VRF1_EN_WID 1
+#define VRF1_EN_ENABLE 1
+#define VRF1_EN_DISABLE 0
+#define VRF2_EN_LSH 15
+#define VRF2_EN_WID 1
+#define VRF2_EN_ENABLE 1
+#define VRF2_EN_DISABLE 0
+#define VMMC1_EN_LSH 18
+#define VMMC1_EN_WID 1
+#define VMMC1_EN_ENABLE 1
+#define VMMC1_EN_DISABLE 0
+#define VMMC2_EN_LSH 21
+#define VMMC2_EN_WID 1
+#define VMMC2_EN_ENABLE 1
+#define VMMC2_EN_DISABLE 0
+
+/*
+ * Reg Regulator Setting 0
+ */
+#define VIOLO_LSH 2
+#define VIOLO_WID 2
+#define VDIG_LSH 4
+#define VDIG_WID 2
+#define VGEN_LSH 6
+#define VGEN_WID 3
+#define VRFDIG_LSH 9
+#define VRFDIG_WID 2
+#define VRFREF_LSH 11
+#define VRFREF_WID 2
+#define VRFCP_LSH 13
+#define VRFCP_WID 1
+#define VSIM_LSH 14
+#define VSIM_WID 1
+#define VESIM_LSH 15
+#define VESIM_WID 1
+#define VCAM_LSH 16
+#define VCAM_WID 3
+
+/*
+ * Reg Regulator Setting 1
+ */
+#define VVIB_LSH 0
+#define VVIB_WID 2
+#define VRF1_LSH 2
+#define VRF1_WID 2
+#define VRF2_LSH 4
+#define VRF2_WID 2
+#define VMMC1_LSH 6
+#define VMMC1_WID 3
+#define VMMC2_LSH 9
+#define VMMC2_WID 3
+
+/*
+ * Reg Switcher 0
+ */
+#define SW1A_LSH 0
+#define SW1A_WID 6
+#define SW1A_DVS_LSH 6
+#define SW1A_DVS_WID 6
+#define SW1A_STDBY_LSH 12
+#define SW1A_STDBY_WID 6
+
+/*
+ * Reg Switcher 1
+ */
+#define SW1B_LSH 0
+#define SW1B_WID 6
+#define SW1B_DVS_LSH 6
+#define SW1B_DVS_WID 6
+#define SW1B_STDBY_LSH 12
+#define SW1B_STDBY_WID 6
+
+/*
+ * Reg Switcher 2
+ */
+#define SW2A_LSH 0
+#define SW2A_WID 6
+#define SW2A_DVS_LSH 6
+#define SW2A_DVS_WID 6
+#define SW2A_STDBY_LSH 12
+#define SW2A_STDBY_WID 6
+
+/*
+ * Reg Switcher 3
+ */
+#define SW2B_LSH 0
+#define SW2B_WID 6
+#define SW2B_DVS_LSH 6
+#define SW2B_DVS_WID 6
+#define SW2B_STDBY_LSH 12
+#define SW2B_STDBY_WID 6
+
+/*
+ * Reg Switcher 4
+ */
+#define SW1A_MODE_LSH 0
+#define SW1A_MODE_WID 2
+#define SW1A_STBY_MODE_LSH 2
+#define SW1A_STBY_MODE_WID 2
+#define SW1A_DVS_SPEED_LSH 6
+#define SW1A_DVS_SPEED_WID 2
+#define SW1B_MODE_LSH 10
+#define SW1B_MODE_WID 2
+#define SW1B_STBY_MODE_LSH 12
+#define SW1B_STBY_MODE_WID 2
+#define SW1B_DVS_SPEED_LSH 14
+#define SW1B_DVS_SPEED_WID 2
+
+/*
+ * Reg Switcher 5
+ */
+#define SW2A_MODE_LSH 0
+#define SW2A_MODE_WID 2
+#define SW2A_STBY_MODE_LSH 2
+#define SW2A_STBY_MODE_WID 2
+#define SW2A_DVS_SPEED_LSH 6
+#define SW2A_DVS_SPEED_WID 2
+#define SW2B_MODE_LSH 10
+#define SW2B_MODE_WID 2
+#define SW2B_STBY_MODE_LSH 12
+#define SW2B_STBY_MODE_WID 2
+#define SW2B_DVS_SPEED_LSH 14
+#define SW2B_DVS_SPEED_WID 2
+#define SW3_LSH 18
+#define SW3_WID 2
+#define SW3_EN_LSH 20
+#define SW3_EN_WID 2
+#define SW3_EN_ENABLE 1
+#define SW3_EN_DISABLE 0
+
+/*
+ * Reg Regulator Misc.
+ */
+#define GPO1_EN_LSH 6
+#define GPO1_EN_WID 1
+#define GPO1_EN_ENABLE 1
+#define GPO1_EN_DISABLE 0
+#define GPO2_EN_LSH 8
+#define GPO2_EN_WID 1
+#define GPO2_EN_ENABLE 1
+#define GPO2_EN_DISABLE 0
+#define GPO3_EN_LSH 10
+#define GPO3_EN_WID 1
+#define GPO3_EN_ENABLE 1
+#define GPO3_EN_DISABLE 0
+#define GPO4_EN_LSH 12
+#define GPO4_EN_WID 1
+#define GPO4_EN_ENABLE 1
+#define GPO4_EN_DISABLE 0
+
+/*
+ * Switcher mode configuration
+ */
+#define SW_MODE_SYNC_RECT_EN 0
+#define SW_MODE_PULSE_NO_SKIP_EN 1
+#define SW_MODE_PULSE_SKIP_EN 2
+#define SW_MODE_LOW_POWER_EN 3
+
+#define dvs_speed E25mvEach16us
+
+static int mc13783_vaudio_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VAUDIO_EN, VAUDIO_EN_ENABLE);
+ register_mask = BITFMASK(VAUDIO_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vaudio_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VAUDIO_EN, VAUDIO_EN_DISABLE);
+ register_mask = BITFMASK(VAUDIO_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_viohi_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VIOHI_EN, VIOHI_EN_ENABLE);
+ register_mask = BITFMASK(VIOHI_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_viohi_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VIOHI_EN, VIOHI_EN_DISABLE);
+ register_mask = BITFMASK(VIOHI_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_violo_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0, register1 = 0;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1200) && (mV < 1300))
+ voltage = VIOLO_1_2V;
+ else if ((mV >= 1300) && (mV < 1500))
+ voltage = VIOLO_1_3V;
+ else if ((mV >= 1500) && (mV < 1800))
+ voltage = VIOLO_1_5V;
+ else
+ voltage = VIOLO_1_8V;
+
+ register_val = BITFVAL(VIOLO, voltage);
+ register_mask = BITFMASK(VIOLO);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_violo_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VIOLO);
+
+ switch (voltage) {
+ case VIOLO_1_2V:
+ mV = 1200;
+ break;
+ case VIOLO_1_3V:
+ mV = 1300;
+ break;
+ case VIOLO_1_5V:
+ mV = 1500;
+ break;
+ case VIOLO_1_8V:
+ mV = 1800;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_violo_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VIOLO_EN, VIOLO_EN_ENABLE);
+ register_mask = BITFMASK(VIOLO_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_violo_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VIOLO_EN, VIOLO_EN_DISABLE);
+ register_mask = BITFMASK(VIOLO_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vdig_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1200) && (mV < 1300))
+ voltage = VDIG_1_2V;
+ else if ((mV >= 1300) && (mV < 1500))
+ voltage = VDIG_1_3V;
+ else if ((mV >= 1500) && (mV < 1800))
+ voltage = VDIG_1_5V;
+ else
+ voltage = VDIG_1_8V;
+
+ register_val = BITFVAL(VDIG, voltage);
+ register_mask = BITFMASK(VDIG);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vdig_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VDIG);
+
+ switch (voltage) {
+ case VDIG_1_2V:
+ mV = 1200;
+ break;
+ case VDIG_1_3V:
+ mV = 1300;
+ break;
+ case VDIG_1_5V:
+ mV = 1500;
+ break;
+ case VDIG_1_8V:
+ mV = 1800;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vdig_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VDIG_EN, VDIG_EN_ENABLE);
+ register_mask = BITFMASK(VDIG_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vdig_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VDIG_EN, VDIG_EN_DISABLE);
+ register_mask = BITFMASK(VDIG_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vgen_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+ int vgenid = rdev_get_id(reg);
+
+ printk(KERN_INFO "VGEN ID is %d\n", vgenid);
+
+ if ((mV >= 1100) && (mV < 1200))
+ voltage = VGEN_1_1V;
+ else if ((mV >= 1200) && (mV < 1300))
+ voltage = VGEN_1_2V;
+ else if ((mV >= 1300) && (mV < 1500))
+ voltage = VGEN_1_3V;
+ else if ((mV >= 1500) && (mV < 1800))
+ voltage = VGEN_1_5V;
+ else if ((mV >= 1800) && (mV < 2000))
+ voltage = VGEN_1_8V;
+ else if ((mV >= 2000) && (mV < 2400))
+ voltage = VGEN_2V;
+ else if ((mV >= 2400) && (mV < 2775))
+ voltage = VGEN_2_4V;
+ else
+ voltage = VGEN_2_775V;
+
+ register_val = BITFVAL(VGEN, voltage);
+ register_mask = BITFMASK(VGEN);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vgen_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VGEN);
+
+ switch (voltage) {
+ case VGEN_1_2V:
+ mV = 1200;
+ break;
+ case VGEN_1_3V:
+ mV = 1300;
+ break;
+ case VGEN_1_5V:
+ mV = 1500;
+ break;
+ case VGEN_1_8V:
+ mV = 1800;
+ break;
+ case VGEN_1_1V:
+ mV = 1100;
+ break;
+ case VGEN_2V:
+ mV = 2000;
+ break;
+ case VGEN_2_775V:
+ mV = 2775;
+ break;
+ case VGEN_2_4V:
+ mV = 2400;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vgen_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN_EN, VGEN_EN_ENABLE);
+ register_mask = BITFMASK(VGEN_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vgen_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN_EN, VGEN_EN_DISABLE);
+ register_mask = BITFMASK(VGEN_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfdig_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1200) && (mV < 1500))
+ voltage = VRFDIG_1_2V;
+ else if ((mV >= 1500) && (mV < 1300))
+ voltage = VRFDIG_1_5V;
+ else if ((mV >= 1800) && (mV < 1875))
+ voltage = VRFDIG_1_8V;
+ else
+ voltage = VRFDIG_1_875V;
+
+ register_val = BITFVAL(VRFDIG, voltage);
+ register_mask = BITFMASK(VRFDIG);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfdig_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VRFDIG);
+
+ switch (voltage) {
+ case VRFDIG_1_2V:
+ mV = 1200;
+ break;
+ case VRFDIG_1_5V:
+ mV = 1500;
+ break;
+ case VRFDIG_1_8V:
+ mV = 1800;
+ break;
+ case VRFDIG_1_875V:
+ mV = 1875;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vrfdig_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VRFDIG_EN, VRFDIG_EN_ENABLE);
+ register_mask = BITFMASK(VRFDIG_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfdig_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VRFDIG_EN, VRFDIG_EN_DISABLE);
+ register_mask = BITFMASK(VRFDIG_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfref_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 2475) && (mV < 2600))
+ voltage = VRFREF_2_475V;
+ else if ((mV >= 2600) && (mV < 2700))
+ voltage = VRFREF_2_6V;
+ else if ((mV >= 2700) && (mV < 2775))
+ voltage = VRFREF_2_7V;
+ else
+ voltage = VRFREF_2_775V;
+
+ register_val = BITFVAL(VRFREF, voltage);
+ register_mask = BITFMASK(VRFREF);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfref_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VRFREF);
+
+ switch (voltage) {
+ case VRFREF_2_475V:
+ mV = 2475;
+ break;
+ case VRFREF_2_6V:
+ mV = 2600;
+ break;
+ case VRFREF_2_7V:
+ mV = 2700;
+ break;
+ case VRFREF_2_775V:
+ mV = 2775;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vrfref_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VRFREF_EN, VRFREF_EN_ENABLE);
+ register_mask = BITFMASK(VRFREF_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfref_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VRFREF_EN, VRFREF_EN_DISABLE);
+ register_mask = BITFMASK(VRFREF_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfcp_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 2700) && (mV < 2775))
+ voltage = VRFCP_2_7V;
+ else
+ voltage = VRFCP_2_775V;
+
+ register_val = BITFVAL(VRFCP, voltage);
+ register_mask = BITFMASK(VRFCP);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfcp_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VRFCP);
+
+ switch (voltage) {
+ case VRFCP_2_7V:
+ mV = 2700;
+ break;
+ case VRFCP_2_775V:
+ mV = 2775;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vrfcp_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VRFCP_EN, VRFCP_EN_ENABLE);
+ register_mask = BITFMASK(VRFCP_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrfcp_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VRFCP_EN, VRFCP_EN_DISABLE);
+ register_mask = BITFMASK(VRFCP_EN);
+ register1 = REG_REGULATOR_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vsim_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1800) && (mV < 2900))
+ voltage = VSIM_1_8V;
+ else
+ voltage = VSIM_2_9V;
+
+ register_val = BITFVAL(VSIM, voltage);
+ register_mask = BITFMASK(VSIM);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vsim_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VSIM);
+
+ switch (voltage) {
+ case VSIM_1_8V:
+ mV = 1800;
+ break;
+ case VSIM_2_9V:
+ mV = 1900;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vsim_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VSIM_EN, VSIM_EN_ENABLE);
+ register_mask = BITFMASK(VSIM_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vsim_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VSIM_EN, VSIM_EN_DISABLE);
+ register_mask = BITFMASK(VSIM_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vesim_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1800) && (mV < 2900))
+ voltage = VESIM_1_8V;
+ else
+ voltage = VESIM_2_9V;
+
+ register_val = BITFVAL(VESIM, voltage);
+ register_mask = BITFMASK(VESIM);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vesim_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VESIM);
+
+ switch (voltage) {
+ case VESIM_1_8V:
+ mV = 1800;
+ break;
+ case VESIM_2_9V:
+ mV = 1900;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vesim_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VESIM_EN, VESIM_EN_ENABLE);
+ register_mask = BITFMASK(VESIM_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vesim_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VESIM_EN, VESIM_EN_DISABLE);
+ register_mask = BITFMASK(VESIM_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vcam_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1500) && (mV < 1800))
+ voltage = VCAM_1_5V;
+ else if ((mV >= 1800) && (mV < 2500))
+ voltage = VCAM_1_8V;
+ else if ((mV >= 2500) && (mV < 2550))
+ voltage = VCAM_2_5V;
+ else if ((mV >= 2550) && (mV < 2600))
+ voltage = VCAM_2_55V;
+ if ((mV >= 2600) && (mV < 2750))
+ voltage = VCAM_2_6V;
+ else if ((mV >= 2750) && (mV < 2800))
+ voltage = VCAM_2_75V;
+ else if ((mV >= 2800) && (mV < 3000))
+ voltage = VCAM_2_8V;
+ else
+ voltage = VCAM_3V;
+
+ register_val = BITFVAL(VCAM, voltage);
+ register_mask = BITFMASK(VCAM);
+ register1 = REG_REGULATOR_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vcam_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VCAM);
+
+ switch (voltage) {
+ case VCAM_1_5V:
+ mV = 1500;
+ break;
+ case VCAM_1_8V:
+ mV = 1800;
+ break;
+ case VCAM_2_5V:
+ mV = 2500;
+ break;
+ case VCAM_2_55V:
+ mV = 2550;
+ break;
+ case VCAM_2_6V:
+ mV = 2600;
+ break;
+ case VCAM_2_75V:
+ mV = 2750;
+ break;
+ case VCAM_2_8V:
+ mV = 2800;
+ break;
+ case VCAM_3V:
+ mV = 3000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vcam_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VCAM_EN, VCAM_EN_ENABLE);
+ register_mask = BITFMASK(VCAM_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vcam_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VCAM_EN, VCAM_EN_DISABLE);
+ register_mask = BITFMASK(VCAM_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vvib_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1300) && (mV < 1800))
+ voltage = VVIB_1_3V;
+ else if ((mV >= 1800) && (mV < 2000))
+ voltage = VVIB_1_8V;
+ else if ((mV >= 2000) && (mV < 3000))
+ voltage = VVIB_2V;
+ else
+ voltage = VVIB_3V;
+
+ register_val = BITFVAL(VVIB, voltage);
+ register_mask = BITFMASK(VVIB);
+ register1 = REG_REGULATOR_SETTING_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vvib_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_1,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VVIB);
+
+ switch (voltage) {
+ case VVIB_1_3V:
+ mV = 1300;
+ break;
+ case VVIB_1_8V:
+ mV = 1800;
+ break;
+ case VVIB_2V:
+ mV = 2000;
+ break;
+ case VVIB_3V:
+ mV = 3000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vvib_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VVIB_EN, VVIB_EN_ENABLE);
+ register_mask = BITFMASK(VVIB_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vvib_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VVIB_EN, VVIB_EN_DISABLE);
+ register_mask = BITFMASK(VVIB_EN);
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrf_set_voltage(struct regulator_dev *reg, int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, rf = rdev_get_id(reg), mV = uV / 1000;
+
+ if ((mV >= 1500) && (mV < 1875))
+ voltage = VRF_1_5V;
+ else if ((mV >= 1875) && (mV < 2700))
+ voltage = VRF_1_875V;
+ else if ((mV >= 2700) && (mV < 2775))
+ voltage = VRF_2_7V;
+ else
+ voltage = VRF_2_775V;
+
+ switch (rf) {
+ case MC13783_VRF1:
+ register_val = BITFVAL(VRF1, voltage);
+ register_mask = BITFMASK(VRF1);
+ break;
+ case MC13783_VRF2:
+ register_val = BITFVAL(VRF2, voltage);
+ register_mask = BITFMASK(VRF2);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ register1 = REG_REGULATOR_SETTING_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrf_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, rf = rdev_get_id(reg), mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_1,
+ &register_val, PMIC_ALL_BITS));
+
+ switch (rf) {
+ case MC13783_VRF1:
+ voltage = BITFEXT(register_val, VRF1);
+ break;
+ case MC13783_VRF2:
+ voltage = BITFEXT(register_val, VRF2);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ switch (voltage) {
+ case VRF_1_5V:
+ mV = 1500;
+ break;
+ case VRF_1_875V:
+ mV = 1875;
+ break;
+ case VRF_2_7V:
+ mV = 2700;
+ break;
+ case VRF_2_775V:
+ mV = 2775;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vrf_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int vrf = rdev_get_id(reg);
+
+ switch (vrf) {
+ case MC13783_VRF1:
+ register_val = BITFVAL(VRF1_EN, VRF1_EN_ENABLE);
+ register_mask = BITFMASK(VRF1_EN);
+ break;
+ case MC13783_VRF2:
+ register_val = BITFVAL(VRF2_EN, VRF2_EN_ENABLE);
+ register_mask = BITFMASK(VRF2_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vrf_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int vrf = rdev_get_id(reg);
+
+ switch (vrf) {
+ case MC13783_VRF1:
+ register_val = BITFVAL(VRF1_EN, VRF1_EN_DISABLE);
+ register_mask = BITFMASK(VRF1_EN);
+ break;
+ case MC13783_VRF2:
+ register_val = BITFVAL(VRF2_EN, VRF2_EN_DISABLE);
+ register_mask = BITFMASK(VRF2_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vmmc_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mmc = rdev_get_id(reg), mV = uV / 1000;
+
+ printk(KERN_INFO "VMMC ID is %d\n", mmc);
+
+ if ((mV >= 1600) && (mV < 1800))
+ voltage = VMMC_1_6V;
+ else if ((mV >= 1800) && (mV < 2000))
+ voltage = VMMC_1_8V;
+ else if ((mV >= 2000) && (mV < 2600))
+ voltage = VMMC_2V;
+ else if ((mV >= 2600) && (mV < 2700))
+ voltage = VMMC_2_6V;
+ else if ((mV >= 2700) && (mV < 2800))
+ voltage = VMMC_2_7V;
+ else if ((mV >= 2800) && (mV < 2900))
+ voltage = VMMC_2_8V;
+ else if ((mV >= 2900) && (mV < 3000))
+ voltage = VMMC_2_9V;
+ else
+ voltage = VMMC_3V;
+
+ switch (mmc) {
+ case MC13783_VMMC1:
+ register_val = BITFVAL(VMMC1, voltage);
+ register_mask = BITFMASK(VMMC1);
+ break;
+ case MC13783_VMMC2:
+ register_val = BITFVAL(VMMC2, voltage);
+ register_mask = BITFMASK(VMMC2);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ register1 = REG_REGULATOR_SETTING_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vmmc_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mmc = rdev_get_id(reg), mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_REGULATOR_SETTING_1,
+ &register_val, PMIC_ALL_BITS));
+
+ switch (mmc) {
+ case MC13783_VMMC1:
+ voltage = BITFEXT(register_val, VMMC1);
+ break;
+ case MC13783_VMMC2:
+ voltage = BITFEXT(register_val, VMMC2);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (voltage) {
+ case VMMC_1_6V:
+ mV = 1600;
+ break;
+ case VMMC_1_8V:
+ mV = 1800;
+ break;
+ case VMMC_2V:
+ mV = 2000;
+ break;
+ case VMMC_2_6V:
+ mV = 2600;
+ break;
+ case VMMC_2_7V:
+ mV = 2700;
+ break;
+ case VMMC_2_8V:
+ mV = 2800;
+ break;
+ case VMMC_2_9V:
+ mV = 2900;
+ break;
+ case VMMC_3V:
+ mV = 3000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_vmmc_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int vmmc = rdev_get_id(reg);
+
+ switch (vmmc) {
+ case MC13783_VMMC1:
+ register_val = BITFVAL(VMMC1_EN, VMMC1_EN_ENABLE);
+ register_mask = BITFMASK(VMMC1_EN);
+ break;
+ case MC13783_VMMC2:
+ register_val = BITFVAL(VMMC2_EN, VMMC2_EN_ENABLE);
+ register_mask = BITFMASK(VMMC2_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_vmmc_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int vmmc = rdev_get_id(reg);
+
+ switch (vmmc) {
+ case MC13783_VMMC1:
+ register_val = BITFVAL(VMMC1_EN, VMMC1_EN_DISABLE);
+ register_mask = BITFMASK(VMMC1_EN);
+ break;
+ case MC13783_VMMC2:
+ register_val = BITFVAL(VMMC2_EN, VMMC2_EN_DISABLE);
+ register_mask = BITFMASK(VMMC2_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_REGULATOR_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_gpo_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int gpo = rdev_get_id(reg);
+
+ switch (gpo) {
+ case MC13783_GPO1:
+ register_val = BITFVAL(GPO1_EN, GPO1_EN_ENABLE);
+ register_mask = BITFMASK(GPO1_EN);
+ break;
+ case MC13783_GPO2:
+ register_val = BITFVAL(GPO2_EN, GPO2_EN_ENABLE);
+ register_mask = BITFMASK(GPO2_EN);
+ break;
+ case MC13783_GPO3:
+ register_val = BITFVAL(GPO3_EN, GPO3_EN_ENABLE);
+ register_mask = BITFMASK(GPO3_EN);
+ break;
+ case MC13783_GPO4:
+ register_val = BITFVAL(GPO4_EN, GPO4_EN_ENABLE);
+ register_mask = BITFMASK(GPO4_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_POWER_MISCELLANEOUS;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_gpo_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int gpo = rdev_get_id(reg);
+
+ switch (gpo) {
+ case MC13783_GPO1:
+ register_val = BITFVAL(GPO1_EN, GPO1_EN_DISABLE);
+ register_mask = BITFMASK(GPO1_EN);
+ break;
+ case MC13783_GPO2:
+ register_val = BITFVAL(GPO2_EN, GPO2_EN_DISABLE);
+ register_mask = BITFMASK(GPO2_EN);
+ break;
+ case MC13783_GPO3:
+ register_val = BITFVAL(GPO3_EN, GPO3_EN_DISABLE);
+ register_mask = BITFMASK(GPO3_EN);
+ break;
+ case MC13783_GPO4:
+ register_val = BITFVAL(GPO4_EN, GPO4_EN_DISABLE);
+ register_mask = BITFMASK(GPO4_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_POWER_MISCELLANEOUS;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_sw3_set_voltage(struct regulator_dev *reg, int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0, register1 = 0;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 5000) && (mV < 5500))
+ voltage = SW3_5V;
+ else
+ voltage = SW3_5_5V;
+
+ register_val = BITFVAL(SW3, voltage);
+ register_mask = BITFMASK(SW3);
+ register1 = REG_SWITCHERS_5;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_sw3_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SWITCHERS_5,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW3);
+
+ if (voltage == SW3_5_5V)
+ mV = 5500;
+ else
+ mV = 5000;
+
+ return mV * 1000;
+}
+
+static int mc13783_sw3_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(SW3_EN, SW3_EN_ENABLE);
+ register_mask = BITFMASK(SW3_EN);
+ register1 = REG_SWITCHERS_5;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_sw3_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(SW3_EN, SW3_EN_DISABLE);
+ register_mask = BITFMASK(SW3_EN);
+ register1 = REG_SWITCHERS_5;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_sw_set_normal_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1 = 0;
+ int voltage, sw = rdev_get_id(reg), mV = uV / 1000;
+
+ if ((mV >= 900) && (mV < 925))
+ voltage = SW_0_9V;
+ else if ((mV >= 925) && (mV < 950))
+ voltage = SW_0_925V;
+ else if ((mV >= 950) && (mV < 975))
+ voltage = SW_0_95V;
+ else if ((mV >= 975) && (mV < 1000))
+ voltage = SW_0_975V;
+ else if ((mV >= 1000) && (mV < 1025))
+ voltage = SW_1V;
+ else if ((mV >= 1025) && (mV < 1050))
+ voltage = SW_1_025V;
+ else if ((mV >= 1050) && (mV < 1075))
+ voltage = SW_1_05V;
+ else if ((mV >= 1075) && (mV < 1100))
+ voltage = SW_1_075V;
+ else if ((mV >= 1100) && (mV < 1125))
+ voltage = SW_1_1V;
+ else if ((mV >= 1125) && (mV < 1150))
+ voltage = SW_1_125V;
+ else if ((mV >= 1150) && (mV < 1175))
+ voltage = SW_1_15V;
+ else if ((mV >= 1175) && (mV < 1200))
+ voltage = SW_1_175V;
+ else if ((mV >= 1200) && (mV < 1225))
+ voltage = SW_1_2V;
+ else if ((mV >= 1225) && (mV < 1250))
+ voltage = SW_1_225V;
+ else if ((mV >= 1250) && (mV < 1275))
+ voltage = SW_1_25V;
+ else if ((mV >= 1275) && (mV < 1300))
+ voltage = SW_1_275V;
+ else if ((mV >= 1300) && (mV < 1325))
+ voltage = SW_1_3V;
+ else if ((mV >= 1325) && (mV < 1350))
+ voltage = SW_1_325V;
+ else if ((mV >= 1350) && (mV < 1375))
+ voltage = SW_1_35V;
+ else if ((mV >= 1375) && (mV < 1400))
+ voltage = SW_1_375V;
+ else if ((mV >= 1400) && (mV < 1425))
+ voltage = SW_1_4V;
+ else if ((mV >= 1425) && (mV < 1450))
+ voltage = SW_1_425V;
+ else if ((mV >= 1450) && (mV < 1475))
+ voltage = SW_1_45V;
+ else if ((mV >= 1475) && (mV < 1500))
+ voltage = SW_1_475V;
+ else if ((mV >= 1500) && (mV < 1525))
+ voltage = SW_1_5V;
+ else if ((mV >= 1525) && (mV < 1550))
+ voltage = SW_1_525V;
+ else if ((mV >= 1550) && (mV < 1575))
+ voltage = SW_1_55V;
+ else if ((mV >= 1575) && (mV < 1600))
+ voltage = SW_1_575V;
+ else if ((mV >= 1600) && (mV < 1625))
+ voltage = SW_1_6V;
+ else if ((mV >= 1625) && (mV < 1650))
+ voltage = SW_1_625V;
+ else if ((mV >= 1650) && (mV < 1675))
+ voltage = SW_1_65V;
+ else if ((mV >= 1675) && (mV < 1700))
+ voltage = SW_1_675V;
+ else if ((mV >= 1700) && (mV < 1800))
+ voltage = SW_1_7V;
+ else if ((mV >= 1800) && (mV < 1850))
+ voltage = SW_1_8V;
+ else if ((mV >= 1850) && (mV < 2000))
+ voltage = SW_1_85V;
+ else if ((mV >= 2000) && (mV < 2100))
+ voltage = SW_2V;
+ else if ((mV >= 2100) && (mV < 2200))
+ voltage = SW_2_1V;
+ else
+ voltage = SW_2_2V;
+
+ switch (sw) {
+ case MC13783_SW1A:
+ register1 = REG_SWITCHERS_0;
+ register_val = BITFVAL(SW1A, voltage);
+ register_mask = BITFMASK(SW1A);
+ break;
+ case MC13783_SW1B:
+ register1 = REG_SWITCHERS_1;
+ register_val = BITFVAL(SW1B, voltage);
+ register_mask = BITFMASK(SW1B);
+ break;
+ case MC13783_SW2A:
+ register1 = REG_SWITCHERS_2;
+ register_val = BITFVAL(SW2A, voltage);
+ register_mask = BITFMASK(SW2A);
+ break;
+ case MC13783_SW2B:
+ register1 = REG_SWITCHERS_3;
+ register_val = BITFVAL(SW2B, voltage);
+ register_mask = BITFMASK(SW2B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_sw_get_normal_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0, sw = rdev_get_id(reg);
+
+ switch (sw) {
+ case MC13783_SW1A:
+ CHECK_ERROR(pmic_read_reg(REG_SWITCHERS_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW1A);
+ break;
+ case MC13783_SW1B:
+ CHECK_ERROR(pmic_read_reg(REG_SWITCHERS_1,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW1B);
+ break;
+ case MC13783_SW2A:
+ CHECK_ERROR(pmic_read_reg(REG_SWITCHERS_2,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW2A);
+ break;
+ case MC13783_SW2B:
+ CHECK_ERROR(pmic_read_reg(REG_SWITCHERS_3,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW2B);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (voltage) {
+ case SW_0_9V:
+ mV = 900;
+ break;
+ case SW_0_925V:
+ mV = 925;
+ break;
+ case SW_0_95V:
+ mV = 950;
+ break;
+ case SW_0_975V:
+ mV = 975;
+ break;
+ case SW_1V:
+ mV = 1000;
+ break;
+ case SW_1_025V:
+ mV = 1025;
+ break;
+ case SW_1_05V:
+ mV = 1050;
+ break;
+ case SW_1_075V:
+ mV = 1075;
+ break;
+ case SW_1_1V:
+ mV = 1100;
+ break;
+ case SW_1_125V:
+ mV = 1125;
+ break;
+ case SW_1_15V:
+ mV = 1150;
+ break;
+ case SW_1_175V:
+ mV = 1175;
+ break;
+ case SW_1_2V:
+ mV = 1200;
+ break;
+ case SW_1_225V:
+ mV = 1225;
+ break;
+ case SW_1_25V:
+ mV = 1250;
+ break;
+ case SW_1_275V:
+ mV = 1275;
+ break;
+ case SW_1_3V:
+ mV = 1300;
+ break;
+ case SW_1_325V:
+ mV = 1325;
+ break;
+ case SW_1_35V:
+ mV = 1350;
+ break;
+ case SW_1_375V:
+ mV = 1375;
+ break;
+ case SW_1_4V:
+ mV = 1400;
+ break;
+ case SW_1_425V:
+ mV = 1425;
+ break;
+ case SW_1_45V:
+ mV = 1450;
+ break;
+ case SW_1_475V:
+ mV = 1475;
+ break;
+ case SW_1_5V:
+ mV = 1500;
+ break;
+ case SW_1_525V:
+ mV = 1525;
+ break;
+ case SW_1_55V:
+ mV = 1550;
+ break;
+ case SW_1_575V:
+ mV = 1575;
+ break;
+ case SW_1_6V:
+ mV = 1600;
+ break;
+ case SW_1_625V:
+ mV = 1625;
+ break;
+ case SW_1_65V:
+ mV = 1650;
+ break;
+ case SW_1_675V:
+ mV = 1675;
+ break;
+ case SW_1_7V:
+ mV = 1700;
+ break;
+ case SW_1_8V:
+ mV = 1800;
+ break;
+ case SW_1_85V:
+ mV = 1850;
+ break;
+ case SW_2V:
+ mV = 2000;
+ break;
+ case SW_2_1V:
+ mV = 2100;
+ break;
+ case SW_2_2V:
+ mV = 2200;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13783_sw_normal_enable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int mc13783_sw_normal_disable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int mc13783_sw_stby_enable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int mc13783_sw_stby_disable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int mc13783_sw_set_stby_voltage(struct regulator_dev *reg, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1 = 0;
+ int voltage, sw = rdev_get_id(reg), mV = uV / 1000;
+
+ if ((mV >= 900) && (mV < 925))
+ voltage = SW_0_9V;
+ else if ((mV >= 925) && (mV < 950))
+ voltage = SW_0_925V;
+ else if ((mV >= 950) && (mV < 975))
+ voltage = SW_0_95V;
+ else if ((mV >= 975) && (mV < 1000))
+ voltage = SW_0_975V;
+ else if ((mV >= 1000) && (mV < 1025))
+ voltage = SW_1V;
+ else if ((mV >= 1025) && (mV < 1050))
+ voltage = SW_1_025V;
+ else if ((mV >= 1050) && (mV < 1075))
+ voltage = SW_1_05V;
+ else if ((mV >= 1075) && (mV < 1100))
+ voltage = SW_1_075V;
+ else if ((mV >= 1100) && (mV < 1125))
+ voltage = SW_1_1V;
+ else if ((mV >= 1125) && (mV < 1150))
+ voltage = SW_1_125V;
+ else if ((mV >= 1150) && (mV < 1175))
+ voltage = SW_1_15V;
+ else if ((mV >= 1175) && (mV < 1200))
+ voltage = SW_1_175V;
+ else if ((mV >= 1200) && (mV < 1225))
+ voltage = SW_1_2V;
+ else if ((mV >= 1225) && (mV < 1250))
+ voltage = SW_1_225V;
+ else if ((mV >= 1250) && (mV < 1275))
+ voltage = SW_1_25V;
+ else if ((mV >= 1275) && (mV < 1300))
+ voltage = SW_1_275V;
+ else if ((mV >= 1300) && (mV < 1325))
+ voltage = SW_1_3V;
+ else if ((mV >= 1325) && (mV < 1350))
+ voltage = SW_1_325V;
+ else if ((mV >= 1350) && (mV < 1375))
+ voltage = SW_1_35V;
+ else if ((mV >= 1375) && (mV < 1400))
+ voltage = SW_1_375V;
+ else if ((mV >= 1400) && (mV < 1425))
+ voltage = SW_1_4V;
+ else if ((mV >= 1425) && (mV < 1450))
+ voltage = SW_1_425V;
+ else if ((mV >= 1450) && (mV < 1475))
+ voltage = SW_1_45V;
+ else if ((mV >= 1475) && (mV < 1500))
+ voltage = SW_1_475V;
+ else if ((mV >= 1500) && (mV < 1525))
+ voltage = SW_1_5V;
+ else if ((mV >= 1525) && (mV < 1550))
+ voltage = SW_1_525V;
+ else if ((mV >= 1550) && (mV < 1575))
+ voltage = SW_1_55V;
+ else if ((mV >= 1575) && (mV < 1600))
+ voltage = SW_1_575V;
+ else if ((mV >= 1600) && (mV < 1625))
+ voltage = SW_1_6V;
+ else if ((mV >= 1625) && (mV < 1650))
+ voltage = SW_1_625V;
+ else if ((mV >= 1650) && (mV < 1675))
+ voltage = SW_1_65V;
+ else if ((mV >= 1675) && (mV < 1700))
+ voltage = SW_1_675V;
+ else if ((mV >= 1700) && (mV < 1800))
+ voltage = SW_1_7V;
+ else if ((mV >= 1800) && (mV < 1850))
+ voltage = SW_1_8V;
+ else if ((mV >= 1850) && (mV < 2000))
+ voltage = SW_1_85V;
+ else if ((mV >= 2000) && (mV < 2100))
+ voltage = SW_2V;
+ else if ((mV >= 2100) && (mV < 2200))
+ voltage = SW_2_1V;
+ else
+ voltage = SW_2_2V;
+
+ switch (sw) {
+ case MC13783_SW1A:
+ register1 = REG_SWITCHERS_0;
+ register_val = BITFVAL(SW1A_STDBY, voltage);
+ register_mask = BITFMASK(SW1A_STDBY);
+ break;
+ case MC13783_SW1B:
+ register1 = REG_SWITCHERS_1;
+ register_val = BITFVAL(SW1B_STDBY, voltage);
+ register_mask = BITFMASK(SW1B_STDBY);
+ break;
+ case MC13783_SW2A:
+ register1 = REG_SWITCHERS_2;
+ register_val = BITFVAL(SW2A_STDBY, voltage);
+ register_mask = BITFMASK(SW2A_STDBY);
+ break;
+ case MC13783_SW2B:
+ register1 = REG_SWITCHERS_3;
+ register_val = BITFVAL(SW2B_STDBY, voltage);
+ register_mask = BITFMASK(SW2B_STDBY);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13783_sw_set_normal_mode(struct regulator_dev *reg,
+ unsigned int mode)
+{
+ unsigned int reg_val = 0, reg_mask = 0;
+ unsigned int register1 = 0;
+ unsigned int l_mode;
+ int sw = rdev_get_id(reg);
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ /* SYNC RECT mode */
+ l_mode = SW_MODE_SYNC_RECT_EN;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ /* PULSE SKIP mode */
+ l_mode = SW_MODE_PULSE_SKIP_EN;
+ break;
+ case REGULATOR_MODE_IDLE:
+ /* LOW POWER mode */
+ l_mode = SW_MODE_LOW_POWER_EN;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ /* NO PULSE SKIP mode */
+ l_mode = SW_MODE_PULSE_NO_SKIP_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (sw) {
+ case MC13783_SW1A:
+ reg_val = BITFVAL(SW1A_MODE, l_mode);
+ reg_mask = BITFMASK(SW1A_MODE);
+ register1 = REG_SWITCHERS_4;
+ break;
+ case MC13783_SW1B:
+ reg_val = BITFVAL(SW1B_MODE, l_mode);
+ reg_mask = BITFMASK(SW1B_MODE);
+ register1 = REG_SWITCHERS_4;
+ break;
+ case MC13783_SW2A:
+ reg_val = BITFVAL(SW2A_MODE, l_mode);
+ reg_mask = BITFMASK(SW2A_MODE);
+ register1 = REG_SWITCHERS_5;
+ break;
+ case MC13783_SW2B:
+ reg_val = BITFVAL(SW2B_MODE, l_mode);
+ reg_mask = BITFMASK(SW2B_MODE);
+ register1 = REG_SWITCHERS_5;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return pmic_write_reg(register1, reg_val, reg_mask);
+}
+
+static unsigned int mc13783_sw_get_normal_mode(struct regulator_dev *reg)
+{
+ unsigned int reg_val = 0, reg_mask = 0;
+ unsigned int register1 = 0;
+ unsigned int l_mode = 0;
+ int sw = rdev_get_id(reg);
+ int ret = 0;
+
+ switch (sw) {
+ case MC13783_SW1A:
+ reg_mask = BITFMASK(SW1A_MODE);
+ register1 = REG_SWITCHERS_4;
+ break;
+ case MC13783_SW1B:
+ reg_mask = BITFMASK(SW1B_MODE);
+ register1 = REG_SWITCHERS_4;
+ break;
+ case MC13783_SW2A:
+ reg_mask = BITFMASK(SW2A_MODE);
+ register1 = REG_SWITCHERS_5;
+ break;
+ case MC13783_SW2B:
+ reg_mask = BITFMASK(SW2B_MODE);
+ register1 = REG_SWITCHERS_5;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = pmic_read_reg(register1, &reg_val, reg_mask);
+ if (ret != 0)
+ return ret;
+
+ switch (sw) {
+ case MC13783_SW1A:
+ l_mode = BITFEXT(reg_val, SW1A_MODE);
+ break;
+ case MC13783_SW1B:
+ l_mode = BITFEXT(reg_val, SW1B_MODE);
+ break;
+ case MC13783_SW2A:
+ l_mode = BITFEXT(reg_val, SW2A_MODE);
+ break;
+ case MC13783_SW2B:
+ l_mode = BITFEXT(reg_val, SW2B_MODE);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (l_mode == SW_MODE_SYNC_RECT_EN) {
+ return REGULATOR_MODE_FAST;
+ } else if (l_mode == SW_MODE_PULSE_NO_SKIP_EN) {
+ return REGULATOR_MODE_STANDBY;
+ } else if (l_mode == SW_MODE_PULSE_SKIP_EN) {
+ return REGULATOR_MODE_NORMAL;
+ } else if (l_mode == SW_MODE_LOW_POWER_EN) {
+ return REGULATOR_MODE_IDLE;
+ } else {
+ return -EINVAL;
+ }
+}
+
+static int mc13783_sw_set_stby_mode(struct regulator_dev *reg,
+ unsigned int mode)
+{
+ unsigned int reg_val = 0, reg_mask = 0;
+ unsigned int register1 = 0;
+ unsigned int l_mode;
+ int sw = rdev_get_id(reg);
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ /* SYNC RECT mode */
+ l_mode = SW_MODE_SYNC_RECT_EN;
+ break;
+ case REGULATOR_MODE_NORMAL:
+ /* PULSE SKIP mode */
+ l_mode = SW_MODE_PULSE_SKIP_EN;
+ break;
+ case REGULATOR_MODE_IDLE:
+ /* LOW POWER mode */
+ l_mode = SW_MODE_LOW_POWER_EN;
+ break;
+ case REGULATOR_MODE_STANDBY:
+ /* NO PULSE SKIP mode */
+ l_mode = SW_MODE_PULSE_NO_SKIP_EN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (sw) {
+ case MC13783_SW1A:
+ reg_val = BITFVAL(SW1A_STBY_MODE, l_mode);
+ reg_mask = BITFMASK(SW1A_STBY_MODE);
+ register1 = REG_SWITCHERS_4;
+ break;
+ case MC13783_SW1B:
+ reg_val = BITFVAL(SW1B_STBY_MODE, l_mode);
+ reg_mask = BITFMASK(SW1B_STBY_MODE);
+ register1 = REG_SWITCHERS_4;
+ break;
+ case MC13783_SW2A:
+ reg_val = BITFVAL(SW2A_STBY_MODE, l_mode);
+ reg_mask = BITFMASK(SW2A_STBY_MODE);
+ register1 = REG_SWITCHERS_5;
+ break;
+ case MC13783_SW2B:
+ reg_val = BITFVAL(SW2B_STBY_MODE, l_mode);
+ reg_mask = BITFMASK(SW2B_STBY_MODE);
+ register1 = REG_SWITCHERS_5;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return pmic_write_reg(register1, reg_val, reg_mask);
+}
+
+static struct regulator_ops mc13783_vaudio_ops = {
+ .enable = mc13783_vaudio_enable,
+ .disable = mc13783_vaudio_disable,
+};
+
+static struct regulator_ops mc13783_viohi_ops = {
+ .enable = mc13783_viohi_enable,
+ .disable = mc13783_viohi_disable,
+};
+
+static struct regulator_ops mc13783_violo_ops = {
+ .set_voltage = mc13783_violo_set_voltage,
+ .get_voltage = mc13783_violo_get_voltage,
+ .enable = mc13783_violo_enable,
+ .disable = mc13783_violo_disable,
+};
+
+static struct regulator_ops mc13783_vdig_ops = {
+ .set_voltage = mc13783_vdig_set_voltage,
+ .get_voltage = mc13783_vdig_get_voltage,
+ .enable = mc13783_vdig_enable,
+ .disable = mc13783_vdig_disable,
+};
+
+static struct regulator_ops mc13783_vgen_ops = {
+ .set_voltage = mc13783_vgen_set_voltage,
+ .get_voltage = mc13783_vgen_get_voltage,
+ .enable = mc13783_vgen_enable,
+ .disable = mc13783_vgen_disable,
+};
+
+static struct regulator_ops mc13783_vrfdig_ops = {
+ .set_voltage = mc13783_vrfdig_set_voltage,
+ .get_voltage = mc13783_vrfdig_get_voltage,
+ .enable = mc13783_vrfdig_enable,
+ .disable = mc13783_vrfdig_disable,
+};
+
+static struct regulator_ops mc13783_vrfref_ops = {
+ .set_voltage = mc13783_vrfref_set_voltage,
+ .get_voltage = mc13783_vrfref_get_voltage,
+ .enable = mc13783_vrfref_enable,
+ .disable = mc13783_vrfref_disable,
+};
+
+static struct regulator_ops mc13783_vrfcp_ops = {
+ .set_voltage = mc13783_vrfcp_set_voltage,
+ .get_voltage = mc13783_vrfcp_get_voltage,
+ .enable = mc13783_vrfcp_enable,
+ .disable = mc13783_vrfcp_disable,
+};
+
+static struct regulator_ops mc13783_vsim_ops = {
+ .set_voltage = mc13783_vsim_set_voltage,
+ .get_voltage = mc13783_vsim_get_voltage,
+ .enable = mc13783_vsim_enable,
+ .disable = mc13783_vsim_disable,
+};
+
+static struct regulator_ops mc13783_vesim_ops = {
+ .set_voltage = mc13783_vesim_set_voltage,
+ .get_voltage = mc13783_vesim_get_voltage,
+ .enable = mc13783_vesim_enable,
+ .disable = mc13783_vesim_disable,
+};
+
+static struct regulator_ops mc13783_vcam_ops = {
+ .set_voltage = mc13783_vcam_set_voltage,
+ .get_voltage = mc13783_vcam_get_voltage,
+ .enable = mc13783_vcam_enable,
+ .disable = mc13783_vcam_disable,
+};
+
+static struct regulator_ops mc13783_vvib_ops = {
+ .set_voltage = mc13783_vvib_set_voltage,
+ .get_voltage = mc13783_vvib_get_voltage,
+ .enable = mc13783_vvib_enable,
+ .disable = mc13783_vvib_disable,
+};
+
+static struct regulator_ops mc13783_vrf_ops = {
+ .set_voltage = mc13783_vrf_set_voltage,
+ .get_voltage = mc13783_vrf_get_voltage,
+ .enable = mc13783_vrf_enable,
+ .disable = mc13783_vrf_disable,
+};
+
+static struct regulator_ops mc13783_vmmc_ops = {
+ .set_voltage = mc13783_vmmc_set_voltage,
+ .get_voltage = mc13783_vmmc_get_voltage,
+ .enable = mc13783_vmmc_enable,
+ .disable = mc13783_vmmc_disable,
+};
+
+static struct regulator_ops mc13783_gpo_ops = {
+ .enable = mc13783_gpo_enable,
+ .disable = mc13783_gpo_disable,
+};
+
+static struct regulator_ops mc13783_sw3_ops = {
+ .set_voltage = mc13783_sw3_set_voltage,
+ .get_voltage = mc13783_sw3_get_voltage,
+ .enable = mc13783_sw3_enable,
+ .disable = mc13783_sw3_disable,
+};
+
+static struct regulator_ops mc13783_sw1_ops = {
+ .set_voltage = mc13783_sw_set_normal_voltage,
+ .get_voltage = mc13783_sw_get_normal_voltage,
+ .get_mode = mc13783_sw_get_normal_mode,
+ .set_mode = mc13783_sw_set_normal_mode,
+ .set_suspend_voltage = mc13783_sw_set_stby_voltage,
+ .set_suspend_enable = mc13783_sw_stby_enable,
+ .set_suspend_disable = mc13783_sw_stby_disable,
+ .set_suspend_mode = mc13783_sw_set_stby_mode,
+};
+
+static struct regulator_ops mc13783_sw_normal_ops = {
+ .set_voltage = mc13783_sw_set_normal_voltage,
+ .get_voltage = mc13783_sw_get_normal_voltage,
+ .get_mode = mc13783_sw_get_normal_mode,
+ .set_mode = mc13783_sw_set_normal_mode,
+ .enable = mc13783_sw_normal_enable,
+ .disable = mc13783_sw_normal_disable,
+};
+
+static struct regulator_desc reg_mc13783[] = {
+ {
+ .name = "SW1A",
+ .id = MC13783_SW1A,
+ .ops = &mc13783_sw1_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SW1B",
+ .id = MC13783_SW1B,
+ .ops = &mc13783_sw_normal_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SW2A",
+ .id = MC13783_SW2A,
+ .ops = &mc13783_sw_normal_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SW2B",
+ .id = MC13783_SW2B,
+ .ops = &mc13783_sw_normal_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SW3",
+ .id = MC13783_SW3,
+ .ops = &mc13783_sw3_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VAUDIO",
+ .id = MC13783_VAUDIO,
+ .ops = &mc13783_vaudio_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VIOHI",
+ .id = MC13783_VIOHI,
+ .ops = &mc13783_viohi_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VIOLO",
+ .id = MC13783_VIOLO,
+ .ops = &mc13783_violo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VDIG",
+ .id = MC13783_VDIG,
+ .ops = &mc13783_vdig_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VGEN",
+ .id = MC13783_VGEN,
+ .ops = &mc13783_vgen_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VRFDIG",
+ .id = MC13783_VRFDIG,
+ .ops = &mc13783_vrfdig_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VRFREF",
+ .id = MC13783_VRFREF,
+ .ops = &mc13783_vrfref_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VRFCP",
+ .id = MC13783_VRFCP,
+ .ops = &mc13783_vrfcp_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VSIM",
+ .id = MC13783_VSIM,
+ .ops = &mc13783_vsim_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VESIM",
+ .id = MC13783_VESIM,
+ .ops = &mc13783_vesim_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VCAM",
+ .id = MC13783_VCAM,
+ .ops = &mc13783_vcam_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VRFBG",
+ .id = MC13783_VRFBG,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VVIB",
+ .id = MC13783_VVIB,
+ .ops = &mc13783_vvib_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VRF1",
+ .id = MC13783_VRF1,
+ .ops = &mc13783_vrf_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VRF2",
+ .id = MC13783_VRF2,
+ .ops = &mc13783_vrf_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VMMC1",
+ .id = MC13783_VMMC1,
+ .ops = &mc13783_vmmc_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VMMC2",
+ .id = MC13783_VMMC2,
+ .ops = &mc13783_vmmc_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO1",
+ .id = MC13783_GPO1,
+ .ops = &mc13783_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO2",
+ .id = MC13783_GPO2,
+ .ops = &mc13783_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO3",
+ .id = MC13783_GPO3,
+ .ops = &mc13783_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO4",
+ .id = MC13783_GPO4,
+ .ops = &mc13783_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+};
+
+/*
+ * Init and Exit
+ */
+
+static int reg_mc13783_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+
+ /* register regulator */
+ rdev = regulator_register(&reg_mc13783[pdev->id], &pdev->dev,
+ pdev->dev.platform_data,
+ dev_get_drvdata(&pdev->dev));
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ reg_mc13783[pdev->id].name);
+ return PTR_ERR(rdev);
+ }
+ platform_set_drvdata(pdev, rdev);
+
+ return 0;
+}
+
+static int mc13783_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+int mc13783_register_regulator(struct mc13783 *mc13783, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ if (mc13783->pmic.pdev[reg])
+ return -EBUSY;
+
+ pdev = platform_device_alloc("mc13783-regulatr", reg);
+ if (!pdev)
+ return -ENOMEM;
+
+ mc13783->pmic.pdev[reg] = pdev;
+
+ initdata->driver_data = mc13783;
+
+ pdev->dev.platform_data = initdata;
+ pdev->dev.parent = mc13783->dev;
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ dev_err(mc13783->dev, "Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ mc13783->pmic.pdev[reg] = NULL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mc13783_register_regulator);
+
+static struct platform_driver mc13783_regulator_driver = {
+ .probe = reg_mc13783_probe,
+ .remove = mc13783_regulator_remove,
+ .driver = {
+ .name = "mc13783-regulatr",
+ /* o left out due to string length */
+ },
+};
+
+static int __init mc13783_regulator_subsys_init(void)
+{
+ return platform_driver_register(&mc13783_regulator_driver);
+}
+subsys_initcall(mc13783_regulator_subsys_init);
+
+static void __exit mc13783_regulator_exit(void)
+{
+ platform_driver_unregister(&mc13783_regulator_driver);
+}
+module_exit(mc13783_regulator_exit);
+
+
+/* Module information */
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MC13783 Regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/reg-mc13892.c b/drivers/regulator/reg-mc13892.c
new file mode 100644
index 000000000000..e3c6ab36426d
--- /dev/null
+++ b/drivers/regulator/reg-mc13892.c
@@ -0,0 +1,1956 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/mc13892/core.h>
+#include <linux/platform_device.h>
+#include <linux/pmic_status.h>
+#include <linux/pmic_external.h>
+
+/*
+ * Convenience conversion.
+ * Here atm, maybe there is somewhere better for this.
+ */
+#define mV_to_uV(mV) (mV * 1000)
+#define uV_to_mV(uV) (uV / 1000)
+#define V_to_uV(V) (mV_to_uV(V * 1000))
+#define uV_to_V(uV) (uV_to_mV(uV) / 1000)
+
+enum {
+ VDIG_1_05V = 0,
+ VDIG_1_25V,
+ VDIG_1_65V,
+ VDIG_1_80V,
+} regulator_voltage_vdig;
+
+enum {
+ VPLL_1_05V = 0,
+ VPLL_1_25V,
+ VPLL_1_65V,
+ VPLL_1_80V,
+} regulator_voltage_vpll;
+
+enum {
+ VGEN1_1_2V = 0,
+ VGEN1_1_5V,
+ VGEN1_2_775V,
+ VGEN1_3_15V,
+} regulator_voltage_vgen1;
+
+enum {
+ VGEN2_1_2V = 0,
+ VGEN2_1_5V,
+ VGEN2_1_6V,
+ VGEN2_1_8V,
+ VGEN2_2_7V,
+ VGEN2_2_8V,
+ VGEN2_3_0V,
+ VGEN2_3_15V,
+} regulator_voltage_vgen2;
+
+enum {
+ VGEN3_1_8V = 0,
+ VGEN3_2_9V,
+} regulator_voltage_vgen3;
+
+enum {
+ VSD_1_8V = 0,
+ VSD_2_0V,
+ VSD_2_6V,
+ VSD_2_7V,
+ VSD_2_8V,
+ VSD_2_9V,
+ VSD_3_0V,
+ VSD_3_15V,
+} regulator_voltage_vsd;
+
+enum {
+ VCAM_2_5V,
+ VCAM_2_6V,
+ VCAM_2_75V,
+ VCAM_3_0V,
+} regulator_voltage_vcam;
+
+enum {
+ VAUDIO_2_3V,
+ VAUDIO_2_5V,
+ VAUDIO_2_775V,
+ VAUDIO_3V,
+} regulator_voltage_vaudio;
+
+enum {
+ VUSB2_2_4V,
+ VUSB2_2_6V,
+ VUSB2_2_7V,
+ VUSB2_2_775V,
+} regulator_voltage_vusb2;
+
+enum {
+ VVIDEO_2_7V,
+ VVIDEO_2_775V,
+ VVIDEO_2_5V,
+ VVIDEO_2_6V,
+} regulator_voltage_vvideo;
+
+#define VAUDIO_LSH 4
+#define VAUDIO_WID 2
+#define VAUDIO_EN_LSH 15
+#define VAUDIO_EN_WID 1
+#define VAUDIO_EN_ENABLE 1
+#define VAUDIO_EN_DISABLE 0
+
+#define VUSB2_LSH 11
+#define VUSB2_WID 2
+#define VUSB2_EN_LSH 18
+#define VUSB2_EN_WID 1
+#define VUSB2_EN_ENABLE 1
+#define VUSB2_EN_DISABLE 0
+
+#define VVIDEO_LSH 2
+#define VVIDEO_WID 2
+#define VVIDEO_EN_LSH 12
+#define VVIDEO_EN_WID 1
+#define VVIDEO_EN_ENABLE 1
+#define VVIDEO_EN_DISABLE 0
+
+#define SWBST_EN_LSH 20
+#define SWBST_EN_WID 1
+#define SWBST_EN_ENABLE 1
+#define SWBST_EN_DISABLE 0
+
+#define VIOHI_EN_LSH 3
+#define VIOHI_EN_WID 1
+#define VIOHI_EN_ENABLE 1
+#define VIOHI_EN_DISABLE 0
+
+#define VDIG_LSH 4
+#define VDIG_WID 2
+#define VDIG_EN_LSH 9
+#define VDIG_EN_WID 1
+#define VDIG_EN_ENABLE 1
+#define VDIG_EN_DISABLE 0
+
+#define VPLL_LSH 9
+#define VPLL_WID 2
+#define VPLL_EN_LSH 15
+#define VPLL_EN_WID 1
+#define VPLL_EN_ENABLE 1
+#define VPLL_EN_DISABLE 0
+
+#define VGEN1_LSH 0
+#define VGEN1_WID 2
+#define VGEN1_EN_LSH 0
+#define VGEN1_EN_WID 1
+#define VGEN1_EN_ENABLE 1
+#define VGEN1_EN_DISABLE 0
+
+#define VGEN2_LSH 6
+#define VGEN2_WID 3
+#define VGEN2_EN_LSH 12
+#define VGEN2_EN_WID 1
+#define VGEN2_EN_ENABLE 1
+#define VGEN2_EN_DISABLE 0
+
+#define VGEN3_LSH 14
+#define VGEN3_WID 1
+#define VGEN3_EN_LSH 0
+#define VGEN3_EN_WID 1
+#define VGEN3_EN_ENABLE 1
+#define VGEN3_EN_DISABLE 0
+
+#define VSD_LSH 6
+#define VSD_WID 3
+#define VSD_EN_LSH 18
+#define VSD_EN_WID 1
+#define VSD_EN_ENABLE 1
+#define VSD_EN_DISABLE 0
+
+#define VCAM_LSH 16
+#define VCAM_WID 2
+#define VCAM_EN_LSH 6
+#define VCAM_EN_WID 1
+#define VCAM_EN_ENABLE 1
+#define VCAM_EN_DISABLE 0
+#define VCAM_CONFIG_LSH 9
+#define VCAM_CONFIG_WID 1
+#define VCAM_CONFIG_EXT 1
+#define VCAM_CONFIG_INT 0
+
+#define SW1_LSH 0
+#define SW1_WID 5
+#define SW1_DVS_LSH 5
+#define SW1_DVS_WID 5
+#define SW1_STDBY_LSH 10
+#define SW1_STDBY_WID 5
+
+#define SW2_LSH 0
+#define SW2_WID 5
+#define SW2_DVS_LSH 5
+#define SW2_DVS_WID 5
+#define SW2_STDBY_LSH 10
+#define SW2_STDBY_WID 5
+
+#define SW3_LSH 0
+#define SW3_WID 5
+#define SW3_STDBY_LSH 10
+#define SW3_STDBY_WID 5
+
+#define SW4_LSH 0
+#define SW4_WID 5
+#define SW4_STDBY_LSH 10
+#define SW4_STDBY_WID 5
+
+#define VUSB_EN_LSH 3
+#define VUSB_EN_WID 1
+#define VUSB_EN_ENABLE 1
+#define VUSB_EN_DISABLE 0
+
+#define GPO1_EN_LSH 6
+#define GPO1_EN_WID 1
+#define GPO1_EN_ENABLE 1
+#define GPO1_EN_DISABLE 0
+
+#define GPO2_EN_LSH 8
+#define GPO2_EN_WID 1
+#define GPO2_EN_ENABLE 1
+#define GPO2_EN_DISABLE 0
+
+#define GPO3_EN_LSH 10
+#define GPO3_EN_WID 1
+#define GPO3_EN_ENABLE 1
+#define GPO3_EN_DISABLE 0
+
+#define GPO4_EN_LSH 12
+#define GPO4_EN_WID 1
+#define GPO4_EN_ENABLE 1
+#define GPO4_EN_DISABLE 0
+
+#define GPO4_ADIN_LSH 21
+#define GPO4_ADIN_WID 1
+#define GPO4_ADIN_ENABLE 1
+#define GPO4_ADIN_DISABLE 0
+
+#define PWGT1SPI_EN_LSH 15
+#define PWGT1SPI_EN_WID 1
+#define PWGT1SPI_EN_ENABLE 0
+#define PWGT1SPI_EN_DISABLE 1
+
+#define PWGT2SPI_EN_LSH 16
+#define PWGT2SPI_EN_WID 1
+#define PWGT2SPI_EN_ENABLE 0
+#define PWGT2SPI_EN_DISABLE 1
+
+#define SWXHI_LSH 23
+#define SWXHI_WID 1
+#define SWXHI_ON 1
+#define SWXHI_OFF 0
+
+static int mc13892_get_sw_hi_bit(int sw)
+{
+ unsigned int register_val = 0;
+ unsigned int reg = 0;
+
+ switch (sw) {
+ case MC13892_SW1:
+ reg = REG_SW_0;
+ break;
+ case MC13892_SW2:
+ reg = REG_SW_1;
+ break;
+ case MC13892_SW3:
+ reg = REG_SW_2;
+ break;
+ case MC13892_SW4:
+ reg = REG_SW_3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ CHECK_ERROR(pmic_read_reg(reg, &register_val, PMIC_ALL_BITS));
+ return (register_val & 0x800000) >> SWXHI_LSH;
+}
+
+static int mc13892_get_voltage_value(int *hi, int mV)
+{
+ int voltage;
+
+ if (mV < 600)
+ mV = 600;
+ if (mV > 1850)
+ mV = 1850;
+
+ if (mV > 1375)
+ *hi = 1;
+ if (mV < 1100)
+ *hi = 0;
+
+ if (*hi == 0)
+ voltage = (mV - 600) / 25;
+ else
+ voltage = (mV - 1100) / 25;
+
+ return voltage;
+}
+
+static int mc13892_get_voltage_mV(int hi, int voltage)
+{
+ int mV;
+
+ if (hi == 0)
+ mV = voltage * 25 + 600;
+ else
+ mV = voltage * 25 + 1100;
+
+ return mV;
+}
+
+static int mc13892_sw_set_voltage(struct regulator_dev *reg, int MiniV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1 = 0;
+ int voltage;
+ int sw = rdev_get_id(reg);
+ int mV = uV / 1000;
+ int hi;
+
+ hi = mc13892_get_sw_hi_bit(sw);
+ voltage = mc13892_get_voltage_value(&hi, mV);
+
+ switch (sw) {
+ case MC13892_SW1:
+ register1 = REG_SW_0;
+ register_val = BITFVAL(SW1, voltage);
+ register_mask = BITFMASK(SW1);
+ break;
+ case MC13892_SW2:
+ register1 = REG_SW_1;
+ register_val = BITFVAL(SW2, voltage);
+ register_mask = BITFMASK(SW2);
+ break;
+ case MC13892_SW3:
+ register1 = REG_SW_2;
+ register_val = BITFVAL(SW3, voltage);
+ register_mask = BITFMASK(SW3);
+ break;
+ case MC13892_SW4:
+ register1 = REG_SW_3;
+ register_val = BITFVAL(SW4, voltage);
+ register_mask = BITFMASK(SW4);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ register_val |= (hi << SWXHI_LSH);
+ register_mask |= (1 << SWXHI_LSH);
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_sw_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0;
+ int mV = 0;
+ int sw = rdev_get_id(reg);
+ int hi;
+
+ switch (sw) {
+ case MC13892_SW1:
+ CHECK_ERROR(pmic_read_reg(REG_SW_0,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW1);
+ break;
+ case MC13892_SW2:
+ CHECK_ERROR(pmic_read_reg(REG_SW_1,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW2);
+ break;
+ case MC13892_SW3:
+ CHECK_ERROR(pmic_read_reg(REG_SW_2,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW3);
+ break;
+ case MC13892_SW4:
+ CHECK_ERROR(pmic_read_reg(REG_SW_3,
+ &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, SW4);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ hi = mc13892_get_sw_hi_bit(sw);
+ mV = mc13892_get_voltage_mV(hi, voltage);
+
+ return mV * 1000;
+}
+
+static int mc13892_sw_stby_enable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int mc13892_sw_stby_disable(struct regulator_dev *reg)
+{
+ return 0;
+}
+
+static int mc13892_sw_stby_set_mode(struct regulator_dev *reg, unsigned int mode)
+{
+ return 0;
+}
+
+static int mc13892_sw_stby_set_voltage(struct regulator_dev *reg, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1 = 0;
+ int voltage, mV = uV / 1000, hi;
+ int sw = rdev_get_id(reg);
+
+ hi = mc13892_get_sw_hi_bit(sw);
+ voltage = mc13892_get_voltage_value(&hi, mV);
+
+ switch (sw) {
+ case MC13892_SW1:
+ register1 = REG_SW_0;
+ register_val = BITFVAL(SW1_STDBY, voltage);
+ register_mask = BITFMASK(SW1_STDBY);
+ break;
+ case MC13892_SW2:
+ register1 = REG_SW_1;
+ register_val = BITFVAL(SW2_STDBY, voltage);
+ register_mask = BITFMASK(SW2_STDBY);
+ break;
+ case MC13892_SW3:
+ register1 = REG_SW_2;
+ register_val = BITFVAL(SW3_STDBY, voltage);
+ register_mask = BITFMASK(SW3_STDBY);
+ break;
+ case MC13892_SW4:
+ register1 = REG_SW_3;
+ register_val = BITFVAL(SW4_STDBY, voltage);
+ register_mask = BITFMASK(SW4_STDBY);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ register_val |= (hi << SWXHI_LSH);
+ register_mask |= (1 << SWXHI_LSH);
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_swbst_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(SWBST_EN, SWBST_EN_ENABLE);
+ register_mask = BITFMASK(SWBST_EN);
+ register1 = REG_SW_5;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_swbst_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(SWBST_EN, SWBST_EN_DISABLE);
+ register_mask = BITFMASK(SWBST_EN);
+ register1 = REG_SW_5;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_viohi_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VIOHI_EN, VIOHI_EN_ENABLE);
+ register_mask = BITFMASK(VIOHI_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_viohi_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VIOHI_EN, VIOHI_EN_DISABLE);
+ register_mask = BITFMASK(VIOHI_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vusb_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VUSB_EN, VUSB_EN_ENABLE);
+ register_mask = BITFMASK(VUSB_EN);
+ register1 = REG_USB1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vusb_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VUSB_EN, VUSB_EN_DISABLE);
+ register_mask = BITFMASK(VUSB_EN);
+ register1 = REG_USB1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vdig_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1050) && (mV < 1250))
+ voltage = VDIG_1_05V;
+ else if ((mV >= 1250) && (mV < 1650))
+ voltage = VDIG_1_25V;
+ else if ((mV >= 1650) && (mV < 1800))
+ voltage = VDIG_1_65V;
+ else
+ voltage = VDIG_1_80V;
+
+ register_val = BITFVAL(VDIG, voltage);
+ register_mask = BITFMASK(VDIG);
+ register1 = REG_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vdig_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_0, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VDIG);
+
+ switch (voltage) {
+ case VDIG_1_05V:
+ mV = 1050;
+ break;
+ case VDIG_1_25V:
+ mV = 1250;
+ break;
+ case VDIG_1_65V:
+ mV = 1650;
+ break;
+ case VDIG_1_80V:
+ mV = 1800;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vdig_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VDIG_EN, VDIG_EN_ENABLE);
+ register_mask = BITFMASK(VDIG_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vdig_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VDIG_EN, VDIG_EN_DISABLE);
+ register_mask = BITFMASK(VDIG_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vpll_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1050) && (mV < 1250))
+ voltage = VPLL_1_05V;
+ else if ((mV >= 1250) && (mV < 1650))
+ voltage = VPLL_1_25V;
+ else if ((mV >= 1650) && (mV < 1800))
+ voltage = VPLL_1_65V;
+ else
+ voltage = VPLL_1_80V;
+
+ register_val = BITFVAL(VPLL, voltage);
+ register_mask = BITFMASK(VPLL);
+ register1 = REG_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vpll_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_0, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VPLL);
+
+ switch (voltage) {
+ case VPLL_1_05V:
+ mV = 1050;
+ break;
+ case VPLL_1_25V:
+ mV = 1250;
+ break;
+ case VPLL_1_65V:
+ mV = 1650;
+ break;
+ case VPLL_1_80V:
+ mV = 1800;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vpll_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VPLL_EN, VPLL_EN_ENABLE);
+ register_mask = BITFMASK(VPLL_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vpll_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VPLL_EN, VPLL_EN_DISABLE);
+ register_mask = BITFMASK(VPLL_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vaudio_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 2300) && (mV < 2500))
+ voltage = VAUDIO_2_3V;
+ else if ((mV >= 2500) && (mV < 2775))
+ voltage = VAUDIO_2_5V;
+ else if ((mV >= 2775) && (mV < 3000))
+ voltage = VAUDIO_2_775V;
+ else
+ voltage = VAUDIO_3V;
+
+ register_val = BITFVAL(VAUDIO, voltage);
+ register_mask = BITFMASK(VAUDIO);
+ register1 = REG_SETTING_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vaudio_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_1, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VAUDIO);
+
+ switch (voltage) {
+ case VAUDIO_2_3V:
+ mV = 2300;
+ break;
+ case VAUDIO_2_5V:
+ mV = 2500;
+ break;
+ case VAUDIO_2_775V:
+ mV = 2775;
+ break;
+ case VAUDIO_3V:
+ mV = 3000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vaudio_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VAUDIO_EN, VAUDIO_EN_ENABLE);
+ register_mask = BITFMASK(VAUDIO_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vaudio_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VAUDIO_EN, VAUDIO_EN_DISABLE);
+ register_mask = BITFMASK(VAUDIO_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vusb2_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 2400) && (mV < 2600))
+ voltage = VUSB2_2_4V;
+ else if ((mV >= 2600) && (mV < 2700))
+ voltage = VUSB2_2_6V;
+ else if ((mV >= 2700) && (mV < 2775))
+ voltage = VUSB2_2_7V;
+ else
+ voltage = VUSB2_2_775V;
+
+ register_val = BITFVAL(VUSB2, voltage);
+ register_mask = BITFMASK(VUSB2);
+ register1 = REG_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vusb2_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_0, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VUSB2);
+
+ switch (voltage) {
+ case VUSB2_2_4V:
+ mV = 2400;
+ break;
+ case VUSB2_2_6V:
+ mV = 2600;
+ break;
+ case VUSB2_2_7V:
+ mV = 2700;
+ break;
+ case VUSB2_2_775V:
+ mV = 2775;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vusb2_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VUSB2_EN, VUSB2_EN_ENABLE);
+ register_mask = BITFMASK(VUSB2_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vusb2_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VUSB2_EN, VUSB2_EN_DISABLE);
+ register_mask = BITFMASK(VUSB2_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vvideo_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 2500) && (mV < 2600))
+ voltage = VVIDEO_2_5V;
+ else if ((mV >= 2600) && (mV < 2700))
+ voltage = VVIDEO_2_6V;
+ else if ((mV >= 2700) && (mV < 2775))
+ voltage = VVIDEO_2_7V;
+ else
+ voltage = VVIDEO_2_775V;
+
+ register_val = BITFVAL(VVIDEO, voltage);
+ register_mask = BITFMASK(VVIDEO);
+ register1 = REG_SETTING_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vvideo_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_1, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VVIDEO);
+
+ switch (voltage) {
+ case VVIDEO_2_5V:
+ mV = 2500;
+ break;
+ case VVIDEO_2_6V:
+ mV = 2600;
+ break;
+ case VVIDEO_2_7V:
+ mV = 2700;
+ break;
+ case VVIDEO_2_775V:
+ mV = 2775;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vvideo_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VVIDEO_EN, VVIDEO_EN_ENABLE);
+ register_mask = BITFMASK(VVIDEO_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vvideo_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VVIDEO_EN, VVIDEO_EN_DISABLE);
+ register_mask = BITFMASK(VVIDEO_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vsd_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1800) && (mV < 2000))
+ voltage = VSD_1_8V;
+ else if ((mV >= 2000) && (mV < 2600))
+ voltage = VSD_2_0V;
+ else if ((mV >= 2600) && (mV < 2700))
+ voltage = VSD_2_6V;
+ else if ((mV >= 2700) && (mV < 2800))
+ voltage = VSD_2_7V;
+ else if ((mV >= 2800) && (mV < 2900))
+ voltage = VSD_2_8V;
+ else if ((mV >= 2900) && (mV < 3000))
+ voltage = VSD_2_9V;
+ else if ((mV >= 3000) && (mV < 3150))
+ voltage = VSD_3_0V;
+ else
+ voltage = VSD_3_15V;
+
+ register_val = BITFVAL(VSD, voltage);
+ register_mask = BITFMASK(VSD);
+ register1 = REG_SETTING_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vsd_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_1, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VSD);
+
+ switch (voltage) {
+ case VSD_1_8V:
+ mV = 1800;
+ break;
+ case VSD_2_0V:
+ mV = 2000;
+ break;
+ case VSD_2_6V:
+ mV = 2600;
+ break;
+ case VSD_2_7V:
+ mV = 2700;
+ break;
+ case VSD_2_8V:
+ mV = 2800;
+ break;
+ case VSD_2_9V:
+ mV = 2900;
+ break;
+ case VSD_3_0V:
+ mV = 3000;
+ break;
+ case VSD_3_15V:
+ mV = 3150;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vsd_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VSD_EN, VSD_EN_ENABLE);
+ register_mask = BITFMASK(VSD_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vsd_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VSD_EN, VSD_EN_DISABLE);
+ register_mask = BITFMASK(VSD_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vcam_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 2500) && (mV < 2600))
+ voltage = VCAM_2_5V;
+ else if ((mV >= 2600) && (mV < 2750))
+ voltage = VCAM_2_6V;
+ else if ((mV >= 2750) && (mV < 3000))
+ voltage = VCAM_2_75V;
+ else
+ voltage = VCAM_3_0V;
+
+ register_val = BITFVAL(VCAM, voltage);
+ register_mask = BITFMASK(VCAM);
+ register1 = REG_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vcam_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_0, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VCAM);
+
+ switch (voltage) {
+ case VCAM_2_5V:
+ mV = 2500;
+ break;
+ case VCAM_2_6V:
+ mV = 2600;
+ break;
+ case VCAM_2_75V:
+ mV = 2750;
+ break;
+ case VCAM_3_0V:
+ mV = 3000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vcam_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VCAM_EN, VCAM_EN_ENABLE);
+ register_mask = BITFMASK(VCAM_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vcam_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VCAM_EN, VCAM_EN_DISABLE);
+ register_mask = BITFMASK(VCAM_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vcam_set_mode(struct regulator_dev *reg, unsigned int mode)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ switch (mode) {
+ case REGULATOR_MODE_FAST:
+ register_val = BITFVAL(VCAM_CONFIG, VCAM_CONFIG_EXT);
+ break;
+ case REGULATOR_MODE_NORMAL:
+ register_val = BITFVAL(VCAM_CONFIG, VCAM_CONFIG_INT);
+ break;
+ default:
+ return -EINVAL;
+ }
+ register_mask = BITFMASK(VCAM_CONFIG);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+unsigned int mc13892_vcam_get_mode(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int config = 0, mode = VCAM_CONFIG_INT;
+
+ CHECK_ERROR(pmic_read_reg(REG_MODE_1, &register_val, PMIC_ALL_BITS));
+ config = BITFEXT(register_val, VCAM_CONFIG);
+
+ switch (config) {
+ case VCAM_CONFIG_EXT:
+ mode = REGULATOR_MODE_FAST;
+ break;
+ case VCAM_CONFIG_INT:
+ mode = REGULATOR_MODE_NORMAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return mode;
+}
+
+static int mc13892_vgen1_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1200) && (mV < 1500))
+ voltage = VGEN1_1_2V;
+ else if ((mV >= 1500) && (mV < 2775))
+ voltage = VGEN1_1_5V;
+ else if ((mV >= 2775) && (mV < 3150))
+ voltage = VGEN1_2_775V;
+ else
+ voltage = VGEN1_3_15V;
+
+ register_val = BITFVAL(VGEN1, voltage);
+ register_mask = BITFMASK(VGEN1);
+ register1 = REG_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen1_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_0, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VGEN1);
+
+ switch (voltage) {
+ case VGEN1_1_2V:
+ mV = 1200;
+ break;
+ case VGEN1_1_5V:
+ mV = 1500;
+ break;
+ case VGEN1_2_775V:
+ mV = 2775;
+ break;
+ case VGEN1_3_15V:
+ mV = 3150;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vgen1_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN1_EN, VGEN1_EN_ENABLE);
+ register_mask = BITFMASK(VGEN1_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen1_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN1_EN, VGEN1_EN_DISABLE);
+ register_mask = BITFMASK(VGEN1_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen2_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1200) && (mV < 1500))
+ voltage = VGEN2_1_2V;
+ else if ((mV >= 1500) && (mV < 1600))
+ voltage = VGEN2_1_5V;
+ else if ((mV >= 1600) && (mV < 1800))
+ voltage = VGEN2_1_6V;
+ else if ((mV >= 1800) && (mV < 2700))
+ voltage = VGEN2_1_8V;
+ else if ((mV >= 2700) && (mV < 2800))
+ voltage = VGEN2_2_7V;
+ else if ((mV >= 2800) && (mV < 3000))
+ voltage = VGEN2_2_8V;
+ else if ((mV >= 3000) && (mV < 3150))
+ voltage = VGEN2_3_0V;
+ else
+ voltage = VGEN2_3_15V;
+
+ register_val = BITFVAL(VGEN2, voltage);
+ register_mask = BITFMASK(VGEN2);
+ register1 = REG_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen2_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_0, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VGEN2);
+
+ switch (voltage) {
+ case VGEN2_1_2V:
+ mV = 1200;
+ break;
+ case VGEN2_1_5V:
+ mV = 1500;
+ break;
+ case VGEN2_1_6V:
+ mV = 1600;
+ break;
+ case VGEN2_1_8V:
+ mV = 1800;
+ break;
+ case VGEN2_2_7V:
+ mV = 2700;
+ break;
+ case VGEN2_2_8V:
+ mV = 2800;
+ break;
+ case VGEN2_3_0V:
+ mV = 3000;
+ break;
+ case VGEN2_3_15V:
+ mV = 3150;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vgen2_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN2_EN, VGEN2_EN_ENABLE);
+ register_mask = BITFMASK(VGEN2_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen2_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN2_EN, VGEN2_EN_DISABLE);
+ register_mask = BITFMASK(VGEN2_EN);
+ register1 = REG_MODE_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen3_set_voltage(struct regulator_dev *reg,
+ int minuV, int uV)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int voltage, mV = uV / 1000;
+
+ if ((mV >= 1800) && (mV < 2900))
+ voltage = VGEN3_1_8V;
+ else
+ voltage = VGEN3_2_9V;
+
+ register_val = BITFVAL(VGEN3, voltage);
+ register_mask = BITFMASK(VGEN3);
+ register1 = REG_SETTING_0;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen3_get_voltage(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0;
+ int voltage = 0, mV = 0;
+
+ CHECK_ERROR(pmic_read_reg(REG_SETTING_0, &register_val, PMIC_ALL_BITS));
+ voltage = BITFEXT(register_val, VGEN3);
+
+ switch (voltage) {
+ case VGEN3_1_8V:
+ mV = 1800;
+ break;
+ case VGEN3_2_9V:
+ mV = 2900;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mV * 1000;
+}
+
+static int mc13892_vgen3_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN3_EN, VGEN3_EN_ENABLE);
+ register_mask = BITFMASK(VGEN3_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_vgen3_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+
+ register_val = BITFVAL(VGEN3_EN, VGEN3_EN_DISABLE);
+ register_mask = BITFMASK(VGEN3_EN);
+ register1 = REG_MODE_1;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_gpo_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int gpo = rdev_get_id(reg);
+
+ switch (gpo) {
+ case MC13892_GPO1:
+ register_val = BITFVAL(GPO1_EN, GPO1_EN_ENABLE);
+ register_mask = BITFMASK(GPO1_EN);
+ break;
+ case MC13892_GPO2:
+ register_val = BITFVAL(GPO2_EN, GPO2_EN_ENABLE);
+ register_mask = BITFMASK(GPO2_EN);
+ break;
+ case MC13892_GPO3:
+ register_val = BITFVAL(GPO3_EN, GPO3_EN_ENABLE);
+ register_mask = BITFMASK(GPO3_EN);
+ break;
+ case MC13892_GPO4:
+ register_val = BITFVAL(GPO4_EN, GPO4_EN_ENABLE) +
+ BITFVAL(GPO4_ADIN, GPO4_ADIN_DISABLE);
+ register_mask = BITFMASK(GPO4_EN) + BITFMASK(GPO4_ADIN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_POWER_MISC;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_gpo_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int gpo = rdev_get_id(reg);
+
+ switch (gpo) {
+ case MC13892_GPO1:
+ register_val = BITFVAL(GPO1_EN, GPO1_EN_DISABLE);
+ register_mask = BITFMASK(GPO1_EN);
+ break;
+ case MC13892_GPO2:
+ register_val = BITFVAL(GPO2_EN, GPO2_EN_DISABLE);
+ register_mask = BITFMASK(GPO2_EN);
+ break;
+ case MC13892_GPO3:
+ register_val = BITFVAL(GPO3_EN, GPO3_EN_DISABLE);
+ register_mask = BITFMASK(GPO3_EN);
+ break;
+ case MC13892_GPO4:
+ register_val = BITFVAL(GPO4_EN, GPO4_EN_DISABLE);
+ register_mask = BITFMASK(GPO4_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_POWER_MISC;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_power_gating_enable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int gpo = rdev_get_id(reg);
+
+ switch (gpo) {
+ case MC13892_PWGT1:
+ register_val = BITFVAL(PWGT1SPI_EN, PWGT1SPI_EN_ENABLE);
+ register_mask = BITFMASK(PWGT1SPI_EN);
+ break;
+ case MC13892_PWGT2:
+ register_val = BITFVAL(PWGT2SPI_EN, PWGT2SPI_EN_ENABLE);
+ register_mask = BITFMASK(PWGT2SPI_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_POWER_MISC;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_power_gating_disable(struct regulator_dev *reg)
+{
+ unsigned int register_val = 0, register_mask = 0;
+ unsigned int register1;
+ int gpo = rdev_get_id(reg);
+
+ switch (gpo) {
+ case MC13892_PWGT1:
+ register_val = BITFVAL(PWGT1SPI_EN, PWGT1SPI_EN_DISABLE);
+ register_mask = BITFMASK(PWGT1SPI_EN);
+ break;
+ case MC13892_PWGT2:
+ register_val = BITFVAL(PWGT2SPI_EN, PWGT2SPI_EN_DISABLE);
+ register_mask = BITFMASK(PWGT2SPI_EN);
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ register1 = REG_POWER_MISC;
+
+ return pmic_write_reg(register1, register_val, register_mask);
+}
+
+static int mc13892_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ unsigned int register1;
+ unsigned int register_mask;
+ int id = rdev_get_id(rdev);
+ unsigned int register_val = 0;
+
+ switch (id) {
+ case MC13892_SWBST:
+ register_mask = BITFMASK(SWBST_EN);
+ register1 = REG_SW_5;
+ break;
+ case MC13892_VIOHI:
+ register_mask = BITFMASK(VIOHI_EN);
+ register1 = REG_MODE_0;
+ break;
+ case MC13892_VPLL:
+ register_mask = BITFMASK(VPLL_EN);
+ register1 = REG_MODE_0;
+ break;
+ case MC13892_VDIG:
+ register_mask = BITFMASK(VDIG_EN);
+ register1 = REG_MODE_0;
+ break;
+ case MC13892_VSD:
+ register_mask = BITFMASK(VSD_EN);
+ register1 = REG_MODE_1;
+ break;
+ case MC13892_VUSB2:
+ register_mask = BITFMASK(VUSB2_EN);
+ register1 = REG_MODE_0;
+ break;
+ case MC13892_VVIDEO:
+ register_mask = BITFMASK(VVIDEO_EN);
+ register1 = REG_MODE_1;
+ break;
+ case MC13892_VAUDIO:
+ register_mask = BITFMASK(VAUDIO_EN);
+ register1 = REG_MODE_1;
+ break;
+ case MC13892_VCAM:
+ register_mask = BITFMASK(VCAM_EN);
+ register1 = REG_MODE_1;
+ break;
+ case MC13892_VGEN1:
+ register_mask = BITFMASK(VGEN1_EN);
+ register1 = REG_MODE_0;
+ break;
+ case MC13892_VGEN2:
+ register_mask = BITFMASK(VGEN2_EN);
+ register1 = REG_MODE_0;
+ break;
+ case MC13892_VGEN3:
+ register_mask = BITFMASK(VGEN3_EN);
+ register1 = REG_MODE_1;
+ break;
+ case MC13892_VUSB:
+ register_mask = BITFMASK(VUSB_EN);
+ register1 = REG_USB1;
+ break;
+ case MC13892_GPO1:
+ register_mask = BITFMASK(GPO1_EN);
+ register1 = REG_POWER_MISC;
+ break;
+ case MC13892_GPO2:
+ register_mask = BITFMASK(GPO2_EN);
+ register1 = REG_POWER_MISC;
+ break;
+ case MC13892_GPO3:
+ register_mask = BITFMASK(GPO3_EN);
+ register1 = REG_POWER_MISC;
+ break;
+ case MC13892_GPO4:
+ register_mask = BITFMASK(GPO4_EN);
+ register1 = REG_POWER_MISC;
+ break;
+ case MC13892_PWGT1:
+ register_mask = BITFMASK(PWGT1SPI_EN);
+ register1 = REG_POWER_MISC;
+ break;
+ case MC13892_PWGT2:
+ register_mask = BITFMASK(PWGT2SPI_EN);
+ register1 = REG_POWER_MISC;
+ break;
+ default:
+ return 1;
+ }
+ CHECK_ERROR(pmic_read_reg(register1, &register_val, register_mask));
+ return (register_val != 0);
+}
+
+static struct regulator_ops mc13892_sw_ops = {
+ .enable = mc13892_sw_stby_enable,
+ .disable = mc13892_sw_stby_disable,
+ .set_voltage = mc13892_sw_set_voltage,
+ .get_voltage = mc13892_sw_get_voltage,
+ .set_suspend_voltage = mc13892_sw_stby_set_voltage,
+ .set_suspend_enable = mc13892_sw_stby_enable,
+ .set_suspend_disable = mc13892_sw_stby_disable,
+ .set_suspend_mode = mc13892_sw_stby_set_mode,
+};
+
+static struct regulator_ops mc13892_swbst_ops = {
+ .enable = mc13892_swbst_enable,
+ .disable = mc13892_swbst_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_viohi_ops = {
+ .enable = mc13892_viohi_enable,
+ .disable = mc13892_viohi_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vusb_ops = {
+ .enable = mc13892_vusb_enable,
+ .disable = mc13892_vusb_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vdig_ops = {
+ .set_voltage = mc13892_vdig_set_voltage,
+ .get_voltage = mc13892_vdig_get_voltage,
+ .enable = mc13892_vdig_enable,
+ .disable = mc13892_vdig_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vpll_ops = {
+ .set_voltage = mc13892_vpll_set_voltage,
+ .get_voltage = mc13892_vpll_get_voltage,
+ .enable = mc13892_vpll_enable,
+ .disable = mc13892_vpll_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vusb2_ops = {
+ .set_voltage = mc13892_vusb2_set_voltage,
+ .get_voltage = mc13892_vusb2_get_voltage,
+ .enable = mc13892_vusb2_enable,
+ .disable = mc13892_vusb2_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vvideo_ops = {
+ .set_voltage = mc13892_vvideo_set_voltage,
+ .get_voltage = mc13892_vvideo_get_voltage,
+ .enable = mc13892_vvideo_enable,
+ .disable = mc13892_vvideo_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vaudio_ops = {
+ .set_voltage = mc13892_vaudio_set_voltage,
+ .get_voltage = mc13892_vaudio_get_voltage,
+ .enable = mc13892_vaudio_enable,
+ .disable = mc13892_vaudio_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vsd_ops = {
+ .set_voltage = mc13892_vsd_set_voltage,
+ .get_voltage = mc13892_vsd_get_voltage,
+ .enable = mc13892_vsd_enable,
+ .disable = mc13892_vsd_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vcam_ops = {
+ .set_voltage = mc13892_vcam_set_voltage,
+ .get_voltage = mc13892_vcam_get_voltage,
+ .enable = mc13892_vcam_enable,
+ .disable = mc13892_vcam_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+ .set_mode = mc13892_vcam_set_mode,
+ .get_mode = mc13892_vcam_get_mode,
+};
+
+static struct regulator_ops mc13892_vgen1_ops = {
+ .set_voltage = mc13892_vgen1_set_voltage,
+ .get_voltage = mc13892_vgen1_get_voltage,
+ .enable = mc13892_vgen1_enable,
+ .disable = mc13892_vgen1_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vgen2_ops = {
+ .set_voltage = mc13892_vgen2_set_voltage,
+ .get_voltage = mc13892_vgen2_get_voltage,
+ .enable = mc13892_vgen2_enable,
+ .disable = mc13892_vgen2_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_vgen3_ops = {
+ .set_voltage = mc13892_vgen3_set_voltage,
+ .get_voltage = mc13892_vgen3_get_voltage,
+ .enable = mc13892_vgen3_enable,
+ .disable = mc13892_vgen3_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_gpo_ops = {
+ .enable = mc13892_gpo_enable,
+ .disable = mc13892_gpo_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+};
+
+static struct regulator_ops mc13892_power_gating_ops = {
+ .enable = mc13892_power_gating_enable,
+ .disable = mc13892_power_gating_disable,
+ .is_enabled = mc13892_regulator_is_enabled,
+
+};
+
+static struct regulator_desc mc13892_reg[] = {
+ {
+ .name = "SW1",
+ .id = MC13892_SW1,
+ .ops = &mc13892_sw_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SW2",
+ .id = MC13892_SW2,
+ .ops = &mc13892_sw_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SW3",
+ .id = MC13892_SW3,
+ .ops = &mc13892_sw_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SW4",
+ .id = MC13892_SW4,
+ .ops = &mc13892_sw_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SWBST",
+ .id = MC13892_SWBST,
+ .ops = &mc13892_swbst_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VIOHI",
+ .id = MC13892_VIOHI,
+ .ops = &mc13892_viohi_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VPLL",
+ .id = MC13892_VPLL,
+ .ops = &mc13892_vpll_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VDIG",
+ .id = MC13892_VDIG,
+ .ops = &mc13892_vdig_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VSD",
+ .id = MC13892_VSD,
+ .ops = &mc13892_vsd_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VUSB2",
+ .id = MC13892_VUSB2,
+ .ops = &mc13892_vusb2_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VVIDEO",
+ .id = MC13892_VVIDEO,
+ .ops = &mc13892_vvideo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VAUDIO",
+ .id = MC13892_VAUDIO,
+ .ops = &mc13892_vaudio_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VCAM",
+ .id = MC13892_VCAM,
+ .ops = &mc13892_vcam_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VGEN1",
+ .id = MC13892_VGEN1,
+ .ops = &mc13892_vgen1_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VGEN2",
+ .id = MC13892_VGEN2,
+ .ops = &mc13892_vgen2_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VGEN3",
+ .id = MC13892_VGEN3,
+ .ops = &mc13892_vgen3_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "VUSB",
+ .id = MC13892_VUSB,
+ .ops = &mc13892_vusb_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO1",
+ .id = MC13892_GPO1,
+ .ops = &mc13892_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO2",
+ .id = MC13892_GPO2,
+ .ops = &mc13892_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO3",
+ .id = MC13892_GPO3,
+ .ops = &mc13892_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPO4",
+ .id = MC13892_GPO4,
+ .ops = &mc13892_gpo_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "PWGT1",
+ .id = MC13892_PWGT1,
+ .ops = &mc13892_power_gating_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "PWGT2",
+ .id = MC13892_PWGT2,
+ .ops = &mc13892_power_gating_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+};
+
+static int mc13892_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+
+ /* register regulator */
+ rdev = regulator_register(&mc13892_reg[pdev->id], &pdev->dev,
+ pdev->dev.platform_data,
+ dev_get_drvdata(&pdev->dev));
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ mc13892_reg[pdev->id].name);
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+
+static int mc13892_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+int mc13892_register_regulator(struct mc13892 *mc13892, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ if (mc13892->pmic.pdev[reg])
+ return -EBUSY;
+
+ pdev = platform_device_alloc("mc13892-regulatr", reg);
+ if (!pdev)
+ return -ENOMEM;
+
+ mc13892->pmic.pdev[reg] = pdev;
+
+ initdata->driver_data = mc13892;
+
+ pdev->dev.platform_data = initdata;
+ pdev->dev.parent = mc13892->dev;
+ platform_set_drvdata(pdev, mc13892);
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ dev_err(mc13892->dev, "Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ mc13892->pmic.pdev[reg] = NULL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mc13892_register_regulator);
+
+static struct platform_driver mc13892_regulator_driver = {
+ .probe = mc13892_regulator_probe,
+ .remove = mc13892_regulator_remove,
+ .driver = {
+ .name = "mc13892-regulatr",
+ },
+};
+
+static int __init mc13892_regulator_init(void)
+{
+ return platform_driver_register(&mc13892_regulator_driver);
+}
+subsys_initcall(mc13892_regulator_init);
+
+static void __exit mc13892_regulator_exit(void)
+{
+ platform_driver_unregister(&mc13892_regulator_driver);
+}
+module_exit(mc13892_regulator_exit);
+
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MC13892 Regulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/reg-mc34704.c b/drivers/regulator/reg-mc34704.c
new file mode 100644
index 000000000000..7fb3732b9e03
--- /dev/null
+++ b/drivers/regulator/reg-mc34704.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/ioctl.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/mc34704/core.h>
+#include <linux/platform_device.h>
+#include <linux/pmic_status.h>
+#include <linux/pmic_external.h>
+
+#define MC34704_ONOFFA 0x8
+#define MC34704_ONOFFC 0x4
+#define MC34704_ONOFFD 0x2
+#define MC34704_ONOFFE 0x1
+
+/* Private data for MC34704 regulators */
+
+struct reg_mc34704_priv {
+ short enable; /* enable bit, if available */
+ short v_default; /* default regulator voltage in mV */
+ int dvs_min; /* minimum voltage change in units of 2.5% */
+ int dvs_max; /* maximum voltage change in units of 2.5% */
+ char i2c_dvs; /* i2c DVS register number */
+ char i2c_stat; /* i2c status register number */
+};
+struct reg_mc34704_priv mc34704_reg_priv[] = {
+ {
+ .v_default = REG1_V_MV,
+ .dvs_min = REG1_DVS_MIN_PCT / 2.5,
+ .dvs_max = REG1_DVS_MAX_PCT / 2.5,
+ .i2c_dvs = 0x4,
+ .i2c_stat = 0x5,
+ .enable = MC34704_ONOFFA,
+ },
+ {
+ .v_default = REG2_V_MV,
+ .dvs_min = REG2_DVS_MIN_PCT / 2.5,
+ .dvs_max = REG2_DVS_MAX_PCT / 2.5,
+ .i2c_dvs = 0x6,
+ .i2c_stat = 0x7,
+ },
+ {
+ .v_default = REG3_V_MV,
+ .dvs_min = REG3_DVS_MIN_PCT / 2.5,
+ .dvs_max = REG3_DVS_MAX_PCT / 2.5,
+ .i2c_dvs = 0x8,
+ .i2c_stat = 0x9,
+ },
+ {
+ .v_default = REG4_V_MV,
+ .dvs_min = REG4_DVS_MIN_PCT / 2.5,
+ .dvs_max = REG4_DVS_MAX_PCT / 2.5,
+ .i2c_dvs = 0xA,
+ .i2c_stat = 0xB,
+ },
+ {
+ .v_default = REG5_V_MV,
+ .dvs_min = REG5_DVS_MIN_PCT / 2.5,
+ .dvs_max = REG5_DVS_MAX_PCT / 2.5,
+ .i2c_dvs = 0xC,
+ .i2c_stat = 0xE,
+ .enable = MC34704_ONOFFE,
+ },
+};
+
+static int mc34704_set_voltage(struct regulator_dev *reg, int MiniV, int uV)
+{
+ struct reg_mc34704_priv *priv = rdev_get_drvdata(reg);
+ int mV = uV / 1000;
+ int dV = mV - priv->v_default;
+
+ /* compute dynamic voltage scaling value */
+ int dvs = 1000 * dV / priv->v_default / 25;
+
+ /* clip to regulator limits */
+ if (dvs > priv->dvs_max)
+ dvs = priv->dvs_max;
+ if (dvs < priv->dvs_min)
+ dvs = priv->dvs_min;
+
+ return pmic_write_reg(priv->i2c_dvs, dvs << 1, 0x1E);
+}
+
+static int mc34704_get_voltage(struct regulator_dev *reg)
+{
+ int mV;
+ struct reg_mc34704_priv *priv = rdev_get_drvdata(reg);
+ int val, dvs;
+
+ CHECK_ERROR(pmic_read_reg(priv->i2c_dvs, &val, 0xF));
+
+ dvs = (val >> 1) & 0xF;
+
+ /* dvs is 4-bit 2's complement; sign-extend it */
+ if (dvs & 8)
+ dvs |= -1 & ~0xF;
+
+ /* Regulator voltage is adjusted by (dvs * 2.5%) */
+ mV = priv->v_default * (1000 + 25 * dvs) / 1000;
+
+ return 1000 * mV;
+}
+
+static int mc34704_enable_reg(struct regulator_dev *reg)
+{
+ struct reg_mc34704_priv *priv = rdev_get_drvdata(reg);
+
+ if (priv->enable)
+ return pmic_write_reg(REG_MC34704_GENERAL2, -1, priv->enable);
+
+ return PMIC_ERROR;
+}
+
+static int mc34704_disable_reg(struct regulator_dev *reg)
+{
+ struct reg_mc34704_priv *priv = rdev_get_drvdata(reg);
+
+ if (priv->enable)
+ return pmic_write_reg(REG_MC34704_GENERAL2, 0, priv->enable);
+
+ return PMIC_ERROR;
+}
+
+static int mc34704_is_reg_enabled(struct regulator_dev *reg)
+{
+ struct reg_mc34704_priv *priv = rdev_get_drvdata(reg);
+ int val;
+
+ if (priv->enable) {
+ CHECK_ERROR(pmic_read_reg(REG_MC34704_GENERAL2, &val,
+ priv->enable));
+ return val ? 1 : 0;
+ } else {
+ return PMIC_ERROR;
+ }
+}
+
+static struct regulator_ops mc34704_full_ops = {
+ .set_voltage = mc34704_set_voltage,
+ .get_voltage = mc34704_get_voltage,
+ .enable = mc34704_enable_reg,
+ .disable = mc34704_disable_reg,
+ .is_enabled = mc34704_is_reg_enabled,
+};
+
+static struct regulator_ops mc34704_partial_ops = {
+ .set_voltage = mc34704_set_voltage,
+ .get_voltage = mc34704_get_voltage,
+};
+
+static struct regulator_desc reg_mc34704[] = {
+ {
+ .name = "REG1_BKLT",
+ .id = MC34704_BKLT,
+ .ops = &mc34704_full_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE},
+ {
+ .name = "REG2_CPU",
+ .id = MC34704_CPU,
+ .ops = &mc34704_partial_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE},
+ {
+ .name = "REG3_CORE",
+ .id = MC34704_CORE,
+ .ops = &mc34704_partial_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE},
+ {
+ .name = "REG4_DDR",
+ .id = MC34704_DDR,
+ .ops = &mc34704_partial_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE},
+ {
+ .name = "REG5_PERS",
+ .id = MC34704_PERS,
+ .ops = &mc34704_full_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE},
+};
+
+static int mc34704_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+
+ /* register regulator */
+ rdev = regulator_register(&reg_mc34704[pdev->id], &pdev->dev,
+ pdev->dev.platform_data,
+ (void *)&mc34704_reg_priv[pdev->id]);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ reg_mc34704[pdev->id].name);
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+static int mc34704_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+int mc34704_register_regulator(struct mc34704 *mc34704, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ if (mc34704->pmic.pdev[reg])
+ return -EBUSY;
+
+ pdev = platform_device_alloc("mc34704-regulatr", reg);
+ if (!pdev)
+ return -ENOMEM;
+
+ mc34704->pmic.pdev[reg] = pdev;
+
+ initdata->driver_data = mc34704;
+
+ pdev->dev.platform_data = initdata;
+
+ pdev->dev.parent = mc34704->dev;
+ platform_set_drvdata(pdev, mc34704);
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ dev_err(mc34704->dev, "Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ mc34704->pmic.pdev[reg] = NULL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mc34704_register_regulator);
+
+static struct platform_driver mc34704_regulator_driver = {
+ .probe = mc34704_regulator_probe,
+ .remove = mc34704_regulator_remove,
+ .driver = {
+ .name = "mc34704-regulatr",
+ },
+};
+
+static int __init mc34704_regulator_init(void)
+{
+ return platform_driver_register(&mc34704_regulator_driver);
+}
+subsys_initcall(mc34704_regulator_init);
+
+static void __exit mc34704_regulator_exit(void)
+{
+ platform_driver_unregister(&mc34704_regulator_driver);
+}
+module_exit(mc34704_regulator_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MC34704 Regulator Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/reg-mc9s08dz60.c b/drivers/regulator/reg-mc9s08dz60.c
new file mode 100644
index 000000000000..f2748e99fd80
--- /dev/null
+++ b/drivers/regulator/reg-mc9s08dz60.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/mc9s08dz60/core.h>
+#include <linux/mfd/mc9s08dz60/pmic.h>
+#include <linux/platform_device.h>
+#include <linux/pmic_status.h>
+
+/* lcd */
+static int mc9s08dz60_lcd_enable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 6, 1);
+}
+
+static int mc9s08dz60_lcd_disable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 6, 0);
+}
+
+static struct regulator_ops mc9s08dz60_lcd_ops = {
+ .enable = mc9s08dz60_lcd_enable,
+ .disable = mc9s08dz60_lcd_disable,
+};
+
+/* wifi */
+static int mc9s08dz60_wifi_enable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 5, 1);
+}
+
+static int mc9s08dz60_wifi_disable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 5, 0);
+}
+
+static struct regulator_ops mc9s08dz60_wifi_ops = {
+ .enable = mc9s08dz60_wifi_enable,
+ .disable = mc9s08dz60_wifi_disable,
+};
+
+/* hdd */
+static int mc9s08dz60_hdd_enable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 4, 1);
+}
+
+static int mc9s08dz60_hdd_disable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 4, 0);
+}
+
+static struct regulator_ops mc9s08dz60_hdd_ops = {
+ .enable = mc9s08dz60_hdd_enable,
+ .disable = mc9s08dz60_hdd_disable,
+};
+
+/* gps */
+static int mc9s08dz60_gps_enable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 0, 1);
+}
+
+static int mc9s08dz60_gps_disable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_2, 0, 0);
+}
+
+static struct regulator_ops mc9s08dz60_gps_ops = {
+ .enable = mc9s08dz60_gps_enable,
+ .disable = mc9s08dz60_gps_disable,
+};
+
+/* speaker */
+static int mc9s08dz60_speaker_enable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 0, 1);
+}
+
+static int mc9s08dz60_speaker_disable(struct regulator_dev *reg)
+{
+ return pmic_gpio_set_bit_val(MCU_GPIO_REG_GPIO_CONTROL_1, 0, 0);
+}
+
+static struct regulator_ops mc9s08dz60_speaker_ops = {
+ .enable = mc9s08dz60_speaker_enable,
+ .disable = mc9s08dz60_speaker_disable,
+};
+
+static struct regulator_desc mc9s08dz60_reg[] = {
+ {
+ .name = "LCD",
+ .id = MC9S08DZ60_LCD,
+ .ops = &mc9s08dz60_lcd_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "WIFI",
+ .id = MC9S08DZ60_WIFI,
+ .ops = &mc9s08dz60_wifi_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "HDD",
+ .id = MC9S08DZ60_HDD,
+ .ops = &mc9s08dz60_hdd_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "GPS",
+ .id = MC9S08DZ60_GPS,
+ .ops = &mc9s08dz60_gps_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+ {
+ .name = "SPKR",
+ .id = MC9S08DZ60_SPKR,
+ .ops = &mc9s08dz60_speaker_ops,
+ .irq = 0,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE
+ },
+
+};
+
+static int mc9s08dz60_regulator_probe(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev;
+
+ /* register regulator */
+ rdev = regulator_register(&mc9s08dz60_reg[pdev->id], &pdev->dev,
+ pdev->dev.platform_data,
+ dev_get_drvdata(&pdev->dev));
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register %s\n",
+ mc9s08dz60_reg[pdev->id].name);
+ return PTR_ERR(rdev);
+ }
+
+ return 0;
+}
+
+
+static int mc9s08dz60_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+
+ return 0;
+}
+
+int mc9s08dz60_register_regulator(struct mc9s08dz60 *mc9s08dz60, int reg,
+ struct regulator_init_data *initdata)
+{
+ struct platform_device *pdev;
+ int ret;
+
+ if (mc9s08dz60->pmic.pdev[reg])
+ return -EBUSY;
+
+ pdev = platform_device_alloc("mc9s08dz60-regu", reg);
+ if (!pdev)
+ return -ENOMEM;
+
+ mc9s08dz60->pmic.pdev[reg] = pdev;
+
+ initdata->driver_data = mc9s08dz60;
+
+ pdev->dev.platform_data = initdata;
+ pdev->dev.parent = mc9s08dz60->dev;
+ platform_set_drvdata(pdev, mc9s08dz60);
+ ret = platform_device_add(pdev);
+
+ if (ret != 0) {
+ dev_err(mc9s08dz60->dev,
+ "Failed to register regulator %d: %d\n",
+ reg, ret);
+ platform_device_del(pdev);
+ mc9s08dz60->pmic.pdev[reg] = NULL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mc9s08dz60_register_regulator);
+
+static struct platform_driver mc9s08dz60_regulator_driver = {
+ .probe = mc9s08dz60_regulator_probe,
+ .remove = mc9s08dz60_regulator_remove,
+ .driver = {
+ .name = "mc9s08dz60-regu",
+ },
+};
+
+static int __init mc9s08dz60_regulator_init(void)
+{
+ return platform_driver_register(&mc9s08dz60_regulator_driver);
+}
+subsys_initcall(mc9s08dz60_regulator_init);
+
+static void __exit mc9s08dz60_regulator_exit(void)
+{
+ platform_driver_unregister(&mc9s08dz60_regulator_driver);
+}
+module_exit(mc9s08dz60_regulator_exit);
+
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MC9S08DZ60 Regulator driver");
+MODULE_LICENSE("GPL");