From: yadi.brar01@gmail.com
To: linux-kernel@vger.kernel.org
Cc: linux-samsung-soc@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Mark Brown <broonie@opensource.wolfsonmicro.com>,
Liam Girdwood <lrg@ti.com>,
Yadwinder Singh Brar <yadi.brar@samsung.com>
Subject: [PATCH v3 2/2] regulator: Add support for MAX77686.
Date: Tue, 22 May 2012 11:27:00 +0530 [thread overview]
Message-ID: <4fbb2ada.63de440a.589d.78e2@mx.google.com> (raw)
In-Reply-To: <y>
From: Yadwinder Singh Brar <yadi.brar@samsung.com>
Add support for PMIC/regulator portion of MAX77686 multifunction device.
MAX77686 provides LDOs[1-26] and BUCKs[1-9]. This is initial release of driv
which supports setting and getting the voltage of a regulator with I2C
interface.
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/max77686.c | 387 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 397 insertions(+), 0 deletions(-)
create mode 100644 drivers/regulator/max77686.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c86b886..e8f9417 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -195,6 +195,15 @@ config REGULATOR_MAX8998
via I2C bus. The provided regulator is suitable for S3C6410
and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
+config REGULATOR_MAX77686
+ tristate "Maxim 77686 regulator"
+ depends on MFD_MAX77686
+ help
+ This driver controls a Maxim 77686 voltage regulator via I2C
+ bus. The provided regulator is suitable for Exynos5 chips to
+ control VDD_ARM and VDD_INT voltages.It supports LDOs[1-26]
+ and BUCKs[1-9].
+
config REGULATOR_PCAP
tristate "Motorola PCAP2 regulator driver"
depends on EZX_PCAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 977fd46..d854453 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
+obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
new file mode 100644
index 0000000..98dbd50
--- /dev/null
+++ b/drivers/regulator/max77686.c
@@ -0,0 +1,387 @@
+/*
+ * max77686.c - Regulator driver for the Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electronics Co. Ltd.
+ * Chiwoong Byun <woong.byun@samsung.com>
+ * Yadwinder Singh Brar <yadi.brar@samsung.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/module.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+
+struct max77686_data {
+ struct device *dev;
+ struct max77686_dev *iodev;
+ int num_regulators;
+ struct regulator_dev **rdev;
+ int ramp_delay; /* index of ramp_delay */
+
+ /*GPIO-DVS feature is not enabled with the
+ *current version of MAX77686 driver.*/
+};
+
+static int max77686_voltage_dvs_buck_time_sel(struct regulator_dev *rdev,
+ unsigned int old_sel,
+ unsigned int new_sel)
+{
+ struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+ int ramp[] = {13, 27, 55, 100}; /* ramp_rate in mV/uS */
+
+ return DIV_ROUND_UP(rdev->desc->uV_step *
+ abs(new_sel - old_sel),
+ ramp[max77686->ramp_delay]);
+}
+
+static int max77686_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_sel,
+ unsigned int new_sel)
+{
+ return DIV_ROUND_UP(rdev->desc->uV_step *
+ abs(new_sel - old_sel),
+ 100);
+}
+
+static struct regulator_ops max77686_ops = {
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = max77686_voltage_time_sel,
+};
+
+static struct regulator_ops max77686_buck_ops = {
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = max77686_voltage_dvs_buck_time_sel,
+};
+
+#define regulator_desc_ldo(num) { \
+ .name = "LDO"#num, \
+ .id = MAX77686_LDO##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 800000, \
+ .uV_step = 50000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .enable_mask = 0x0c, \
+}
+#define regulator_desc_ldo_low_vol(num) { \
+ .name = "LDO"#num, \
+ .id = MAX77686_LDO##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 800000, \
+ .uV_step = 25000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .enable_mask = 0x0c, \
+}
+#define regulator_desc_buck(num) { \
+ .name = "BUCK"#num, \
+ .id = MAX77686_BUCK##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 750000, \
+ .uV_step = 50000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \
+ .enable_mask = 0x03, \
+}
+#define regulator_desc_buck1(num) { \
+ .name = "BUCK"#num, \
+ .id = MAX77686_BUCK##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 750000, \
+ .uV_step = 50000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_BUCK1OUT, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_BUCK1CTRL, \
+ .enable_mask = 0x03, \
+}
+#define regulator_desc_buck_dvs(num) { \
+ .name = "BUCK"#num, \
+ .id = MAX77686_BUCK##num, \
+ .ops = &max77686_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 600000, \
+ .uV_step = 12500, \
+ .n_voltages = 256, \
+ .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \
+ .vsel_mask = 0xff, \
+ .enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \
+ .enable_mask = 0x30, \
+}
+
+static struct regulator_desc regulators[] = {
+ regulator_desc_ldo_low_vol(1),
+ regulator_desc_ldo_low_vol(2),
+ regulator_desc_ldo(3),
+ regulator_desc_ldo(4),
+ regulator_desc_ldo(5),
+ regulator_desc_ldo_low_vol(6),
+ regulator_desc_ldo_low_vol(7),
+ regulator_desc_ldo_low_vol(8),
+ regulator_desc_ldo(9),
+ regulator_desc_ldo(10),
+ regulator_desc_ldo(11),
+ regulator_desc_ldo(12),
+ regulator_desc_ldo(13),
+ regulator_desc_ldo(14),
+ regulator_desc_ldo(15),
+ regulator_desc_ldo(16),
+ regulator_desc_ldo(17),
+ regulator_desc_ldo(18),
+ regulator_desc_ldo(19),
+ regulator_desc_ldo(20),
+ regulator_desc_ldo(21),
+ regulator_desc_ldo(22),
+ regulator_desc_ldo(23),
+ regulator_desc_ldo(24),
+ regulator_desc_ldo(25),
+ regulator_desc_ldo(26),
+ regulator_desc_buck1(1),
+ regulator_desc_buck_dvs(2),
+ regulator_desc_buck_dvs(3),
+ regulator_desc_buck_dvs(4),
+ regulator_desc_buck(5),
+ regulator_desc_buck(6),
+ regulator_desc_buck(7),
+ regulator_desc_buck(8),
+ regulator_desc_buck(9),
+};
+
+#ifdef CONFIG_OF
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+ struct max77686_platform_data *pdata)
+{
+ struct device_node *pmic_np, *regulators_np;
+ struct of_regulator_match *rdata;
+ unsigned int i, ret;
+
+ pmic_np = iodev->dev->of_node;
+ if (!pmic_np) {
+ dev_err(iodev->dev, "could not find pmic sub-node\n");
+ return -ENODEV;
+ }
+
+ regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");
+ if (!regulators_np) {
+ dev_err(iodev->dev, "could not find regulators sub-node\n");
+ return -EINVAL;
+ }
+
+ /* count the number of regulators to be supported in pmic */
+ pdata->num_regulators = ARRAY_SIZE(regulators);
+
+ rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+ (pdata->num_regulators), GFP_KERNEL);
+ if (!rdata) {
+ dev_err(iodev->dev,
+ "could not allocate memory for regulator data\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < pdata->num_regulators; i++)
+ rdata[i].name = regulators[i].name;
+
+ ret = of_regulator_match(iodev->dev, regulators_np, rdata,
+ pdata->num_regulators);
+
+ if (ret < 0)
+ dev_err(iodev->dev, "Parsing DT for regulators failed\n");
+ else
+ dev_info(iodev->dev, "regulators found in device tree : %d\n"
+ , ret);
+
+ pdata->regulators = rdata;
+
+ if (of_property_read_u32(pmic_np, "max77686,buck_ramp_delay", &i))
+ pdata->ramp_delay = i & 0xff;
+
+ return 0;
+}
+#else
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+ struct max77686_platform_data *pdata)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
+static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+{
+ struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct max77686_platform_data *pdata = iodev->pdata;
+ struct regulator_dev **rdev;
+ struct max77686_data *max77686;
+ struct i2c_client *i2c = iodev->i2c;
+ struct regulator_config config = { };
+ int i, ret, size;
+
+ if (iodev->dev->of_node) {
+ ret = max77686_pmic_dt_parse_pdata(iodev, pdata);
+ if (ret)
+ return ret;
+ } else { /* pdata from machine-setup file */
+ if (!pdata) {
+ dev_err(&pdev->dev, "platform data not found\n");
+ return -ENODEV;
+ } else {
+ if (pdata->num_regulators != ARRAY_SIZE(regulators)) {
+ dev_err(&pdev->dev,
+ "incomplete regulator list\n");
+ return -ENODEV;
+ }
+ }
+ }
+
+ max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
+ GFP_KERNEL);
+ if (!max77686)
+ return -ENOMEM;
+
+ size = sizeof(struct regulator_dev *) * pdata->num_regulators;
+ max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (!max77686->rdev) {
+ kfree(max77686);
+ return -ENOMEM;
+ }
+
+ rdev = max77686->rdev;
+
+ max77686->dev = &pdev->dev;
+ max77686->iodev = iodev;
+ max77686->num_regulators = pdata->num_regulators;
+
+ if (pdata->ramp_delay < MAX77686_RAMP_RATE_13MV ||
+ pdata->ramp_delay > MAX77686_RAMP_RATE_100MV)
+ pdata->ramp_delay = MAX77686_RAMP_RATE_27MV; /* default */
+
+ max77686->ramp_delay = pdata->ramp_delay - 1;
+ max77686_update_reg(i2c, MAX77686_REG_BUCK2CTRL1,
+ max77686->ramp_delay << 6, RAMP_MASK);
+ max77686_update_reg(i2c, MAX77686_REG_BUCK3CTRL1,
+ max77686->ramp_delay << 6, RAMP_MASK);
+ max77686_update_reg(i2c, MAX77686_REG_BUCK4CTRL1,
+ max77686->ramp_delay << 6, RAMP_MASK);
+
+ platform_set_drvdata(pdev, max77686);
+
+ for (i = 0; i < pdata->num_regulators; i++) {
+ config.dev = max77686->dev;
+ config.init_data = pdata->regulators[i].init_data;
+ config.driver_data = max77686;
+ config.regmap = iodev->regmap;
+
+ rdev[i] = regulator_register(®ulators[i], &config);
+ if (IS_ERR(rdev[i])) {
+ ret = PTR_ERR(rdev[i]);
+ dev_err(max77686->dev,
+ "regulator init failed for id : %d\n", i);
+ rdev[i] = NULL;
+ goto err;
+ }
+ }
+
+ return 0;
+ err:
+ for (i = 0; i < max77686->num_regulators; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+
+ return ret;
+}
+
+static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+{
+ struct max77686_data *max77686 = platform_get_drvdata(pdev);
+ struct regulator_dev **rdev = max77686->rdev;
+ int i;
+
+ for (i = 0; i < max77686->num_regulators; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+
+ return 0;
+}
+
+static const struct platform_device_id max77686_pmic_id[] = {
+ {"max77686-pmic", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
+
+static struct platform_driver max77686_pmic_driver = {
+ .driver = {
+ .name = "max77686-pmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = max77686_pmic_probe,
+ .remove = __devexit_p(max77686_pmic_remove),
+ .id_table = max77686_pmic_id,
+};
+
+static int __init max77686_pmic_init(void)
+{
+ return platform_driver_register(&max77686_pmic_driver);
+}
+subsys_initcall(max77686_pmic_init);
+
+static void __exit max77686_pmic_cleanup(void)
+{
+ platform_driver_unregister(&max77686_pmic_driver);
+}
+module_exit(max77686_pmic_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
+MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
+MODULE_AUTHOR("Yadwinder Singh Brar <yadi.brar@samsung.com>");
+MODULE_LICENSE("GPL");
--
1.7.0.4
WARNING: multiple messages have this Message-ID (diff)
From: yadi.brar01@gmail.com (yadi.brar01 at gmail.com)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 2/2] regulator: Add support for MAX77686.
Date: Tue, 22 May 2012 11:27:00 +0530 [thread overview]
Message-ID: <4fbb2ada.63de440a.589d.78e2@mx.google.com> (raw)
In-Reply-To: <y>
From: Yadwinder Singh Brar <yadi.brar@samsung.com>
Add support for PMIC/regulator portion of MAX77686 multifunction device.
MAX77686 provides LDOs[1-26] and BUCKs[1-9]. This is initial release of driv
which supports setting and getting the voltage of a regulator with I2C
interface.
Signed-off-by: Yadwinder Singh Brar <yadi.brar@samsung.com>
---
drivers/regulator/Kconfig | 9 +
drivers/regulator/Makefile | 1 +
drivers/regulator/max77686.c | 387 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 397 insertions(+), 0 deletions(-)
create mode 100644 drivers/regulator/max77686.c
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index c86b886..e8f9417 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -195,6 +195,15 @@ config REGULATOR_MAX8998
via I2C bus. The provided regulator is suitable for S3C6410
and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
+config REGULATOR_MAX77686
+ tristate "Maxim 77686 regulator"
+ depends on MFD_MAX77686
+ help
+ This driver controls a Maxim 77686 voltage regulator via I2C
+ bus. The provided regulator is suitable for Exynos5 chips to
+ control VDD_ARM and VDD_INT voltages.It supports LDOs[1-26]
+ and BUCKs[1-9].
+
config REGULATOR_PCAP
tristate "Motorola PCAP2 regulator driver"
depends on EZX_PCAP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 977fd46..d854453 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
+obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
new file mode 100644
index 0000000..98dbd50
--- /dev/null
+++ b/drivers/regulator/max77686.c
@@ -0,0 +1,387 @@
+/*
+ * max77686.c - Regulator driver for the Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electronics Co. Ltd.
+ * Chiwoong Byun <woong.byun@samsung.com>
+ * Yadwinder Singh Brar <yadi.brar@samsung.com>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/module.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+
+struct max77686_data {
+ struct device *dev;
+ struct max77686_dev *iodev;
+ int num_regulators;
+ struct regulator_dev **rdev;
+ int ramp_delay; /* index of ramp_delay */
+
+ /*GPIO-DVS feature is not enabled with the
+ *current version of MAX77686 driver.*/
+};
+
+static int max77686_voltage_dvs_buck_time_sel(struct regulator_dev *rdev,
+ unsigned int old_sel,
+ unsigned int new_sel)
+{
+ struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+ int ramp[] = {13, 27, 55, 100}; /* ramp_rate in mV/uS */
+
+ return DIV_ROUND_UP(rdev->desc->uV_step *
+ abs(new_sel - old_sel),
+ ramp[max77686->ramp_delay]);
+}
+
+static int max77686_voltage_time_sel(struct regulator_dev *rdev,
+ unsigned int old_sel,
+ unsigned int new_sel)
+{
+ return DIV_ROUND_UP(rdev->desc->uV_step *
+ abs(new_sel - old_sel),
+ 100);
+}
+
+static struct regulator_ops max77686_ops = {
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = max77686_voltage_time_sel,
+};
+
+static struct regulator_ops max77686_buck_ops = {
+ .map_voltage = regulator_map_voltage_linear,
+ .list_voltage = regulator_list_voltage_linear,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .set_voltage_time_sel = max77686_voltage_dvs_buck_time_sel,
+};
+
+#define regulator_desc_ldo(num) { \
+ .name = "LDO"#num, \
+ .id = MAX77686_LDO##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 800000, \
+ .uV_step = 50000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .enable_mask = 0x0c, \
+}
+#define regulator_desc_ldo_low_vol(num) { \
+ .name = "LDO"#num, \
+ .id = MAX77686_LDO##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 800000, \
+ .uV_step = 25000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
+ .enable_mask = 0x0c, \
+}
+#define regulator_desc_buck(num) { \
+ .name = "BUCK"#num, \
+ .id = MAX77686_BUCK##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 750000, \
+ .uV_step = 50000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \
+ .enable_mask = 0x03, \
+}
+#define regulator_desc_buck1(num) { \
+ .name = "BUCK"#num, \
+ .id = MAX77686_BUCK##num, \
+ .ops = &max77686_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 750000, \
+ .uV_step = 50000, \
+ .n_voltages = 64, \
+ .vsel_reg = MAX77686_REG_BUCK1OUT, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = MAX77686_REG_BUCK1CTRL, \
+ .enable_mask = 0x03, \
+}
+#define regulator_desc_buck_dvs(num) { \
+ .name = "BUCK"#num, \
+ .id = MAX77686_BUCK##num, \
+ .ops = &max77686_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = 600000, \
+ .uV_step = 12500, \
+ .n_voltages = 256, \
+ .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \
+ .vsel_mask = 0xff, \
+ .enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \
+ .enable_mask = 0x30, \
+}
+
+static struct regulator_desc regulators[] = {
+ regulator_desc_ldo_low_vol(1),
+ regulator_desc_ldo_low_vol(2),
+ regulator_desc_ldo(3),
+ regulator_desc_ldo(4),
+ regulator_desc_ldo(5),
+ regulator_desc_ldo_low_vol(6),
+ regulator_desc_ldo_low_vol(7),
+ regulator_desc_ldo_low_vol(8),
+ regulator_desc_ldo(9),
+ regulator_desc_ldo(10),
+ regulator_desc_ldo(11),
+ regulator_desc_ldo(12),
+ regulator_desc_ldo(13),
+ regulator_desc_ldo(14),
+ regulator_desc_ldo(15),
+ regulator_desc_ldo(16),
+ regulator_desc_ldo(17),
+ regulator_desc_ldo(18),
+ regulator_desc_ldo(19),
+ regulator_desc_ldo(20),
+ regulator_desc_ldo(21),
+ regulator_desc_ldo(22),
+ regulator_desc_ldo(23),
+ regulator_desc_ldo(24),
+ regulator_desc_ldo(25),
+ regulator_desc_ldo(26),
+ regulator_desc_buck1(1),
+ regulator_desc_buck_dvs(2),
+ regulator_desc_buck_dvs(3),
+ regulator_desc_buck_dvs(4),
+ regulator_desc_buck(5),
+ regulator_desc_buck(6),
+ regulator_desc_buck(7),
+ regulator_desc_buck(8),
+ regulator_desc_buck(9),
+};
+
+#ifdef CONFIG_OF
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+ struct max77686_platform_data *pdata)
+{
+ struct device_node *pmic_np, *regulators_np;
+ struct of_regulator_match *rdata;
+ unsigned int i, ret;
+
+ pmic_np = iodev->dev->of_node;
+ if (!pmic_np) {
+ dev_err(iodev->dev, "could not find pmic sub-node\n");
+ return -ENODEV;
+ }
+
+ regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");
+ if (!regulators_np) {
+ dev_err(iodev->dev, "could not find regulators sub-node\n");
+ return -EINVAL;
+ }
+
+ /* count the number of regulators to be supported in pmic */
+ pdata->num_regulators = ARRAY_SIZE(regulators);
+
+ rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+ (pdata->num_regulators), GFP_KERNEL);
+ if (!rdata) {
+ dev_err(iodev->dev,
+ "could not allocate memory for regulator data\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < pdata->num_regulators; i++)
+ rdata[i].name = regulators[i].name;
+
+ ret = of_regulator_match(iodev->dev, regulators_np, rdata,
+ pdata->num_regulators);
+
+ if (ret < 0)
+ dev_err(iodev->dev, "Parsing DT for regulators failed\n");
+ else
+ dev_info(iodev->dev, "regulators found in device tree : %d\n"
+ , ret);
+
+ pdata->regulators = rdata;
+
+ if (of_property_read_u32(pmic_np, "max77686,buck_ramp_delay", &i))
+ pdata->ramp_delay = i & 0xff;
+
+ return 0;
+}
+#else
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+ struct max77686_platform_data *pdata)
+{
+ return 0;
+}
+#endif /* CONFIG_OF */
+
+static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+{
+ struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+ struct max77686_platform_data *pdata = iodev->pdata;
+ struct regulator_dev **rdev;
+ struct max77686_data *max77686;
+ struct i2c_client *i2c = iodev->i2c;
+ struct regulator_config config = { };
+ int i, ret, size;
+
+ if (iodev->dev->of_node) {
+ ret = max77686_pmic_dt_parse_pdata(iodev, pdata);
+ if (ret)
+ return ret;
+ } else { /* pdata from machine-setup file */
+ if (!pdata) {
+ dev_err(&pdev->dev, "platform data not found\n");
+ return -ENODEV;
+ } else {
+ if (pdata->num_regulators != ARRAY_SIZE(regulators)) {
+ dev_err(&pdev->dev,
+ "incomplete regulator list\n");
+ return -ENODEV;
+ }
+ }
+ }
+
+ max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
+ GFP_KERNEL);
+ if (!max77686)
+ return -ENOMEM;
+
+ size = sizeof(struct regulator_dev *) * pdata->num_regulators;
+ max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+ if (!max77686->rdev) {
+ kfree(max77686);
+ return -ENOMEM;
+ }
+
+ rdev = max77686->rdev;
+
+ max77686->dev = &pdev->dev;
+ max77686->iodev = iodev;
+ max77686->num_regulators = pdata->num_regulators;
+
+ if (pdata->ramp_delay < MAX77686_RAMP_RATE_13MV ||
+ pdata->ramp_delay > MAX77686_RAMP_RATE_100MV)
+ pdata->ramp_delay = MAX77686_RAMP_RATE_27MV; /* default */
+
+ max77686->ramp_delay = pdata->ramp_delay - 1;
+ max77686_update_reg(i2c, MAX77686_REG_BUCK2CTRL1,
+ max77686->ramp_delay << 6, RAMP_MASK);
+ max77686_update_reg(i2c, MAX77686_REG_BUCK3CTRL1,
+ max77686->ramp_delay << 6, RAMP_MASK);
+ max77686_update_reg(i2c, MAX77686_REG_BUCK4CTRL1,
+ max77686->ramp_delay << 6, RAMP_MASK);
+
+ platform_set_drvdata(pdev, max77686);
+
+ for (i = 0; i < pdata->num_regulators; i++) {
+ config.dev = max77686->dev;
+ config.init_data = pdata->regulators[i].init_data;
+ config.driver_data = max77686;
+ config.regmap = iodev->regmap;
+
+ rdev[i] = regulator_register(®ulators[i], &config);
+ if (IS_ERR(rdev[i])) {
+ ret = PTR_ERR(rdev[i]);
+ dev_err(max77686->dev,
+ "regulator init failed for id : %d\n", i);
+ rdev[i] = NULL;
+ goto err;
+ }
+ }
+
+ return 0;
+ err:
+ for (i = 0; i < max77686->num_regulators; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+
+ return ret;
+}
+
+static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+{
+ struct max77686_data *max77686 = platform_get_drvdata(pdev);
+ struct regulator_dev **rdev = max77686->rdev;
+ int i;
+
+ for (i = 0; i < max77686->num_regulators; i++)
+ if (rdev[i])
+ regulator_unregister(rdev[i]);
+
+ return 0;
+}
+
+static const struct platform_device_id max77686_pmic_id[] = {
+ {"max77686-pmic", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
+
+static struct platform_driver max77686_pmic_driver = {
+ .driver = {
+ .name = "max77686-pmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = max77686_pmic_probe,
+ .remove = __devexit_p(max77686_pmic_remove),
+ .id_table = max77686_pmic_id,
+};
+
+static int __init max77686_pmic_init(void)
+{
+ return platform_driver_register(&max77686_pmic_driver);
+}
+subsys_initcall(max77686_pmic_init);
+
+static void __exit max77686_pmic_cleanup(void)
+{
+ platform_driver_unregister(&max77686_pmic_driver);
+}
+module_exit(max77686_pmic_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
+MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
+MODULE_AUTHOR("Yadwinder Singh Brar <yadi.brar@samsung.com>");
+MODULE_LICENSE("GPL");
--
1.7.0.4
next reply other threads:[~2012-05-22 5:57 UTC|newest]
Thread overview: 102+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <y@samsung.com>
2012-05-22 5:57 ` yadi.brar01 [this message]
2012-05-22 5:57 ` [PATCH v3 2/2] regulator: Add support for MAX77686 yadi.brar01 at gmail.com
2012-05-23 1:40 ` jonghwa3.lee
2012-05-23 1:40 ` jonghwa3.lee at samsung.com
2012-05-23 4:16 ` Yadwinder Singh Brar
2012-05-23 4:16 ` Yadwinder Singh Brar
2012-05-23 4:40 ` jonghwa3.lee
2012-05-23 4:40 ` jonghwa3.lee at samsung.com
2012-05-23 5:23 ` Yadwinder Singh Brar
2012-05-23 5:23 ` Yadwinder Singh Brar
2012-05-23 5:33 ` jonghwa3.lee
2012-05-23 5:33 ` jonghwa3.lee
2012-05-23 5:33 ` jonghwa3.lee at samsung.com
2012-05-23 10:18 ` Mark Brown
2012-05-23 10:18 ` Mark Brown
2012-05-23 13:02 ` Yadwinder Singh Brar
2012-05-23 13:02 ` Yadwinder Singh Brar
2012-05-23 6:08 ` Yadwinder Singh Brar
2012-05-23 6:08 ` Yadwinder Singh Brar
2012-05-23 1:50 ` jonghwa3.lee
2012-05-23 1:50 ` jonghwa3.lee at samsung.com
2012-05-23 4:17 ` Yadwinder Singh Brar
2012-05-23 4:17 ` Yadwinder Singh Brar
2014-07-23 1:40 ` [PATCH] extcon: Add missing REGMAP_I2C/REGMAP_IRQ dependency on extcon driver Chanwoo Choi
2014-07-23 8:20 ` Krzysztof Kozlowski
2014-07-25 8:39 ` Charles Keepax
2014-08-12 2:01 ` [PATCHv2 0/5] rtc: s3c: Refactoring s3c-rtc driver and support Exynos3250 RTC y
2014-08-12 2:01 ` [PATCHv2 1/5] rtc: s3c: Define s3c_rtc structure to remove global variables y
2014-08-22 20:42 ` Andrew Morton
2014-08-25 0:57 ` Chanwoo Choi
2014-08-26 21:31 ` Andrew Morton
2014-08-28 4:49 ` Chanwoo Choi
2014-08-12 2:01 ` [PATCHv2 2/5] rtc: s3c: Remove warning message when checking coding style with checkpatch script y
2014-08-12 2:01 ` [PATCHv2 3/5] rtc: s3c: Add s3c_rtc_data structure to use variant data instead of s3c_cpu_type y
2014-08-12 2:01 ` [PATCHv2 4/5] rtc: s3c: Add support for RTC of Exynos3250 SoC y
2014-08-12 2:01 ` [PATCHv2 5/5] ARM: dts: Fix wrong compatible string of Exynos3250 RTC dt node y
2015-12-01 9:13 ` [PATCH 3/6] net: thunderx: Increase transmit queue length Sunil Goutham
2015-12-01 9:13 ` Sunil Goutham
2015-12-01 14:40 ` Pavel Fedin
2015-12-01 14:40 ` Pavel Fedin
2015-12-01 15:33 ` Eric Dumazet
2015-12-01 15:33 ` Eric Dumazet
2015-12-01 16:30 ` Sunil Kovvuri
2015-12-01 16:30 ` Sunil Kovvuri
2015-12-01 19:30 ` David Miller
2015-12-01 19:30 ` David Miller
2015-12-02 5:48 ` Sunil Kovvuri
2015-12-02 5:48 ` Sunil Kovvuri
2015-12-02 13:25 ` Eric Dumazet
2015-12-02 13:25 ` Eric Dumazet
2015-12-02 16:50 ` Sunil Kovvuri
2015-12-02 16:50 ` Sunil Kovvuri
2015-12-02 16:59 ` Eric Dumazet
2015-12-02 16:59 ` Eric Dumazet
2015-12-02 17:31 ` David Miller
2015-12-02 17:31 ` David Miller
2015-12-02 9:05 ` Pavel Fedin
2015-12-02 9:05 ` Pavel Fedin
2015-12-02 10:31 ` Pavel Fedin
2015-12-02 10:31 ` Pavel Fedin
2015-12-02 12:29 ` Pavel Fedin
2015-12-02 12:29 ` Pavel Fedin
2015-12-02 12:57 ` Sunil Kovvuri
2015-12-02 12:57 ` Sunil Kovvuri
2015-12-02 13:22 ` Pavel Fedin
2015-12-02 13:22 ` Pavel Fedin
2015-12-02 8:09 ` Pavel Fedin
2015-12-02 8:09 ` Pavel Fedin
2015-12-01 9:13 ` [PATCH 5/6] net: thunderx: Switchon carrier only upon interface link up Sunil Goutham
2015-12-01 9:13 ` Sunil Goutham
2015-12-01 9:13 ` Sunil Goutham
2015-12-01 15:32 ` Pavel Fedin
2015-12-01 15:32 ` Pavel Fedin
2015-12-01 16:39 ` Sunil Kovvuri
2015-12-01 16:39 ` Sunil Kovvuri
2015-12-07 5:00 ` [PATCH 0/2] net: thunderx: Miscellaneous cleanups Sunil Goutham
2015-12-07 5:00 ` Sunil Goutham
2015-12-07 10:33 ` Pavel Fedin
2015-12-07 10:33 ` Pavel Fedin
2015-12-07 18:40 ` David Miller
2015-12-07 18:40 ` David Miller
2015-12-09 11:38 ` [PATCH 1/2] net: thunderx: HW TSO support for pass-2 hardware Sunil Goutham
2015-12-09 11:38 ` Sunil Goutham
2015-12-09 12:05 ` Pavel Fedin
2015-12-09 12:05 ` Pavel Fedin
2015-12-09 12:24 ` Sunil Kovvuri
2015-12-09 12:24 ` Sunil Kovvuri
2015-12-09 20:26 ` David Miller
2015-12-09 20:26 ` David Miller
2015-12-09 11:38 ` [PATCH 2/2] net: thunderx: Enable CQE count threshold interrupt Sunil Goutham
2015-12-09 11:38 ` Sunil Goutham
2015-12-09 12:07 ` Pavel Fedin
2015-12-09 12:07 ` Pavel Fedin
2015-12-09 12:26 ` Sunil Kovvuri
2015-12-09 12:26 ` Sunil Kovvuri
2015-12-10 7:55 ` [PATCH v2 0/2] net: thunderx: Support for pass-2 hw features Sunil Goutham
2015-12-10 7:55 ` Sunil Goutham
2015-12-10 7:55 ` Sunil Goutham
2015-12-10 8:52 ` Pavel Fedin
2015-12-10 8:52 ` Pavel Fedin
2015-12-12 4:38 ` David Miller
2015-12-12 4:38 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4fbb2ada.63de440a.589d.78e2@mx.google.com \
--to=yadi.brar01@gmail.com \
--cc=broonie@opensource.wolfsonmicro.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=lrg@ti.com \
--cc=yadi.brar@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.