All of lore.kernel.org
 help / color / mirror / Atom feed
From: Milo Kim <milo.kim@ti.com>
To: Lee Jones <lee.jones@linaro.org>,
	Jingoo Han <jg1.han@samsung.com>, Bryan Wu <cooloney@gmail.com>,
	Mark Brown <broonie@kernel.org>
Cc: <linux-kernel@vger.kernel.org>, <devicetree@vger.kernel.org>,
	Samuel Ortiz <sameo@linux.intel.com>, Milo Kim <milo.kim@ti.com>
Subject: [PATCH 09/10] regulator: Add LM3631 driver
Date: Fri, 14 Feb 2014 15:32:31 +0900	[thread overview]
Message-ID: <1392359551-7170-1-git-send-email-milo.kim@ti.com> (raw)

LM3631 regulator driver has 5 regulators.
One boost output and four LDOs are used for the display module.
Boost voltage is configurable but always on.
Supported operations for LDOs are enabled/disabled and voltage change.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Milo Kim <milo.kim@ti.com>
---
 drivers/regulator/Kconfig            |    8 +
 drivers/regulator/Makefile           |    1 +
 drivers/regulator/lm3631-regulator.c |  285 ++++++++++++++++++++++++++++++++++
 3 files changed, 294 insertions(+)
 create mode 100644 drivers/regulator/lm3631-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6a79328..9809d7b 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -221,6 +221,14 @@ config REGULATOR_ISL6271A
 	help
 	  This driver supports ISL6271A voltage regulator chip.
 
+config REGULATOR_LM3631
+	tristate "TI LM3631 voltage regulators"
+	depends on MFD_TI_LMU
+	help
+	  This driver supports LM3631 voltage regulators for the LCD bias.
+	  One boost output voltage is configurable and always on.
+	  Four LDOs are used for the display module.
+
 config REGULATOR_LP3971
 	tristate "National Semiconductors LP3971 PMIC regulator driver"
 	depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 979f9dd..b20070d 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
 obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
+obj-$(CONFIG_REGULATOR_LM3631) += lm3631-regulator.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
 obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
diff --git a/drivers/regulator/lm3631-regulator.c b/drivers/regulator/lm3631-regulator.c
new file mode 100644
index 0000000..930bad4
--- /dev/null
+++ b/drivers/regulator/lm3631-regulator.c
@@ -0,0 +1,285 @@
+/*
+ * TI LM3631 Regulator Driver
+ *
+ * Copyright 2014 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/ti-lmu.h>
+#include <linux/mfd/ti-lmu-register.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+#define ENABLE_TIME_USEC		1000
+
+enum lm3631_regulator_id {
+	LM3631_BOOST,		/* Boost output */
+	LM3631_LDO_CONT,	/* Display panel controller */
+	LM3631_LDO_OREF,	/* Gamma reference */
+	LM3631_LDO_POS,		/* Positive display bias output */
+	LM3631_LDO_NEG,		/* Negative display bias output */
+};
+
+struct lm3631_regulator {
+	struct ti_lmu *lmu;
+	struct regulator_desc *desc;
+	struct regulator_dev *regulator;
+};
+
+static const int lm3631_boost_vtbl[] = {
+	4500000, 4550000, 4600000, 4650000, 4700000, 4750000, 4800000, 4850000,
+	4900000, 4950000, 5000000, 5050000, 5100000, 5150000, 5200000, 5250000,
+	5300000, 5350000, 5400000, 5450000, 5500000, 5550000, 5600000, 5650000,
+	5700000, 5750000, 5800000, 5850000, 5900000, 5950000, 6000000, 6050000,
+	6100000, 6150000, 6200000, 6250000, 6300000, 6350000,
+};
+
+static const int lm3631_ldo_cont_vtbl[] = {
+	1800000, 2300000, 2800000, 3300000,
+};
+
+static const int lm3631_ldo_target_vtbl[] = {
+	4000000, 4050000, 4100000, 4150000, 4200000, 4250000, 4300000, 4350000,
+	4400000, 4450000, 4500000, 4550000, 4600000, 4650000, 4700000, 4750000,
+	4800000, 4850000, 4900000, 4950000, 5000000, 5050000, 5100000, 5150000,
+	5200000, 5250000, 5300000, 5350000, 5400000, 5450000, 5500000, 5550000,
+	5600000, 5650000, 5700000, 5750000, 5800000, 5850000, 5900000, 5950000,
+	6000000,
+};
+
+const int ldo_cont_enable_time[] = {
+	0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
+};
+
+static int lm3631_regulator_enable_time(struct regulator_dev *rdev)
+{
+	struct lm3631_regulator *lm3631_regulator = rdev_get_drvdata(rdev);
+	enum lm3631_regulator_id id = rdev_get_id(rdev);
+	u8 val, addr, mask;
+
+	switch (id) {
+	case LM3631_LDO_CONT:
+		addr = LM3631_REG_ENTIME_VCONT;
+		mask = LM3631_ENTIME_CONT_MASK;
+		break;
+	case LM3631_LDO_OREF:
+		addr = LM3631_REG_ENTIME_VOREF;
+		mask = LM3631_ENTIME_MASK;
+		break;
+	case LM3631_LDO_POS:
+		addr = LM3631_REG_ENTIME_VPOS;
+		mask = LM3631_ENTIME_MASK;
+		break;
+	case LM3631_LDO_NEG:
+		addr = LM3631_REG_ENTIME_VNEG;
+		mask = LM3631_ENTIME_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ti_lmu_read_byte(lm3631_regulator->lmu, addr, &val))
+		return -EINVAL;
+
+	val = (val & mask) >> LM3631_ENTIME_SHIFT;
+
+	if (id == LM3631_LDO_CONT)
+		return ldo_cont_enable_time[val];
+	else
+		return ENABLE_TIME_USEC * val;
+}
+
+static struct regulator_ops lm3631_boost_voltage_table_ops = {
+	.list_voltage     = regulator_list_voltage_table,
+	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
+};
+
+static struct regulator_ops lm3631_regulator_voltage_table_ops = {
+	.list_voltage     = regulator_list_voltage_table,
+	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
+	.enable           = regulator_enable_regmap,
+	.disable          = regulator_disable_regmap,
+	.is_enabled       = regulator_is_enabled_regmap,
+	.enable_time      = lm3631_regulator_enable_time,
+};
+
+static struct regulator_desc lm3631_regulator_desc[] = {
+	{
+		.name           = "vboost",
+		.id             = LM3631_BOOST,
+		.ops            = &lm3631_boost_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_boost_vtbl),
+		.volt_table     = lm3631_boost_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_BOOST,
+		.vsel_mask      = LM3631_VOUT_MASK,
+	},
+	{
+		.name           = "ldo_cont",
+		.id             = LM3631_LDO_CONT,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_cont_vtbl),
+		.volt_table     = lm3631_ldo_cont_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_CONT,
+		.vsel_mask      = LM3631_VOUT_CONT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL2,
+		.enable_mask    = LM3631_EN_CONT_MASK,
+	},
+	{
+		.name           = "ldo_oref",
+		.id             = LM3631_LDO_OREF,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
+		.volt_table     = lm3631_ldo_target_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_OREF,
+		.vsel_mask      = LM3631_VOUT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL1,
+		.enable_mask    = LM3631_EN_OREF_MASK,
+	},
+	{
+		.name           = "ldo_vpos",
+		.id             = LM3631_LDO_POS,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
+		.volt_table     = lm3631_ldo_target_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_POS,
+		.vsel_mask      = LM3631_VOUT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL1,
+		.enable_mask    = LM3631_EN_VPOS_MASK,
+	},
+	{
+		.name           = "ldo_vneg",
+		.id             = LM3631_LDO_NEG,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
+		.volt_table     = lm3631_ldo_target_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_NEG,
+		.vsel_mask      = LM3631_VOUT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL1,
+		.enable_mask    = LM3631_EN_VNEG_MASK,
+	},
+};
+
+static struct of_regulator_match lm3631_regulator_matches[] = {
+	{ .name = "vboost", .driver_data = (void *)LM3631_BOOST, },
+	{ .name = "vcont",  .driver_data = (void *)LM3631_LDO_CONT, },
+	{ .name = "voref",  .driver_data = (void *)LM3631_LDO_OREF, },
+	{ .name = "vpos",   .driver_data = (void *)LM3631_LDO_POS,  },
+	{ .name = "vneg",   .driver_data = (void *)LM3631_LDO_NEG,  },
+};
+
+static struct regulator_init_data *
+lm3631_regulator_parse_dt(struct device *dev,
+			  struct lm3631_regulator *lm3631_regulator, int id)
+{
+	struct device_node *node = dev->of_node;
+	int count;
+
+	count = of_regulator_match(dev, node, &lm3631_regulator_matches[id], 1);
+	if (count <= 0)
+		return ERR_PTR(-ENODEV);
+
+	return lm3631_regulator_matches[id].init_data;
+}
+
+static int lm3631_regulator_probe(struct platform_device *pdev)
+{
+	struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
+	struct lm3631_regulator *lm3631_regulator;
+	struct regulator_init_data *init_data;
+	struct regulator_config cfg = { };
+	struct regulator_dev *rdev;
+	int id = pdev->id;
+	int ret;
+
+	lm3631_regulator = devm_kzalloc(&pdev->dev, sizeof(*lm3631_regulator),
+					GFP_KERNEL);
+	if (!lm3631_regulator)
+		return -ENOMEM;
+
+	lm3631_regulator->lmu = lmu;
+
+	init_data = lmu->pdata->regulator_data[id];
+	if (!init_data) {
+		if (IS_ENABLED(CONFIG_OF)) {
+			init_data = lm3631_regulator_parse_dt(&pdev->dev,
+							      lm3631_regulator,
+							      id);
+			if (IS_ERR(init_data))
+				return PTR_ERR(init_data);
+		}
+	}
+
+	cfg.dev = pdev->dev.parent;
+	cfg.init_data = init_data;
+	cfg.driver_data = lm3631_regulator;
+	cfg.regmap = lmu->regmap;
+
+	rdev = regulator_register(&lm3631_regulator_desc[id], &cfg);
+	if (IS_ERR(rdev)) {
+		ret = PTR_ERR(rdev);
+		dev_err(&pdev->dev, "[%d] regulator register err: %d\n",
+			id + 1, ret);
+		return ret;
+	}
+
+	lm3631_regulator->regulator = rdev;
+	platform_set_drvdata(pdev, lm3631_regulator);
+
+	return 0;
+}
+
+static int lm3631_regulator_remove(struct platform_device *pdev)
+{
+	struct lm3631_regulator *lm3631_regulator = platform_get_drvdata(pdev);
+
+	regulator_unregister(lm3631_regulator->regulator);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id lm3631_regulator_of_match[] = {
+	{ .compatible = "ti,lm3631-regulator", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lm3631_regulator_of_match);
+#endif
+
+static struct platform_driver lm3631_regulator_driver = {
+	.probe = lm3631_regulator_probe,
+	.remove = lm3631_regulator_remove,
+	.driver = {
+		.name = "lm3631-regulator",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(lm3631_regulator_of_match),
+	},
+};
+
+module_platform_driver(lm3631_regulator_driver);
+
+MODULE_DESCRIPTION("TI LM3631 Regulator Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lm3631-regulator");
-- 
1.7.9.5


WARNING: multiple messages have this Message-ID (diff)
From: Milo Kim <milo.kim@ti.com>
To: Lee Jones <lee.jones@linaro.org>,
	Jingoo Han <jg1.han@samsung.com>, Bryan Wu <cooloney@gmail.com>,
	Mark Brown <broonie@kernel.org>
Cc: linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
	Samuel Ortiz <sameo@linux.intel.com>, Milo Kim <milo.kim@ti.com>
Subject: [PATCH 09/10] regulator: Add LM3631 driver
Date: Fri, 14 Feb 2014 15:32:31 +0900	[thread overview]
Message-ID: <1392359551-7170-1-git-send-email-milo.kim@ti.com> (raw)

LM3631 regulator driver has 5 regulators.
One boost output and four LDOs are used for the display module.
Boost voltage is configurable but always on.
Supported operations for LDOs are enabled/disabled and voltage change.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Milo Kim <milo.kim@ti.com>
---
 drivers/regulator/Kconfig            |    8 +
 drivers/regulator/Makefile           |    1 +
 drivers/regulator/lm3631-regulator.c |  285 ++++++++++++++++++++++++++++++++++
 3 files changed, 294 insertions(+)
 create mode 100644 drivers/regulator/lm3631-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6a79328..9809d7b 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -221,6 +221,14 @@ config REGULATOR_ISL6271A
 	help
 	  This driver supports ISL6271A voltage regulator chip.
 
+config REGULATOR_LM3631
+	tristate "TI LM3631 voltage regulators"
+	depends on MFD_TI_LMU
+	help
+	  This driver supports LM3631 voltage regulators for the LCD bias.
+	  One boost output voltage is configurable and always on.
+	  Four LDOs are used for the display module.
+
 config REGULATOR_LP3971
 	tristate "National Semiconductors LP3971 PMIC regulator driver"
 	depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 979f9dd..b20070d 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
 obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
+obj-$(CONFIG_REGULATOR_LM3631) += lm3631-regulator.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
 obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
diff --git a/drivers/regulator/lm3631-regulator.c b/drivers/regulator/lm3631-regulator.c
new file mode 100644
index 0000000..930bad4
--- /dev/null
+++ b/drivers/regulator/lm3631-regulator.c
@@ -0,0 +1,285 @@
+/*
+ * TI LM3631 Regulator Driver
+ *
+ * Copyright 2014 Texas Instruments
+ *
+ * Author: Milo Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/ti-lmu.h>
+#include <linux/mfd/ti-lmu-register.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+#define ENABLE_TIME_USEC		1000
+
+enum lm3631_regulator_id {
+	LM3631_BOOST,		/* Boost output */
+	LM3631_LDO_CONT,	/* Display panel controller */
+	LM3631_LDO_OREF,	/* Gamma reference */
+	LM3631_LDO_POS,		/* Positive display bias output */
+	LM3631_LDO_NEG,		/* Negative display bias output */
+};
+
+struct lm3631_regulator {
+	struct ti_lmu *lmu;
+	struct regulator_desc *desc;
+	struct regulator_dev *regulator;
+};
+
+static const int lm3631_boost_vtbl[] = {
+	4500000, 4550000, 4600000, 4650000, 4700000, 4750000, 4800000, 4850000,
+	4900000, 4950000, 5000000, 5050000, 5100000, 5150000, 5200000, 5250000,
+	5300000, 5350000, 5400000, 5450000, 5500000, 5550000, 5600000, 5650000,
+	5700000, 5750000, 5800000, 5850000, 5900000, 5950000, 6000000, 6050000,
+	6100000, 6150000, 6200000, 6250000, 6300000, 6350000,
+};
+
+static const int lm3631_ldo_cont_vtbl[] = {
+	1800000, 2300000, 2800000, 3300000,
+};
+
+static const int lm3631_ldo_target_vtbl[] = {
+	4000000, 4050000, 4100000, 4150000, 4200000, 4250000, 4300000, 4350000,
+	4400000, 4450000, 4500000, 4550000, 4600000, 4650000, 4700000, 4750000,
+	4800000, 4850000, 4900000, 4950000, 5000000, 5050000, 5100000, 5150000,
+	5200000, 5250000, 5300000, 5350000, 5400000, 5450000, 5500000, 5550000,
+	5600000, 5650000, 5700000, 5750000, 5800000, 5850000, 5900000, 5950000,
+	6000000,
+};
+
+const int ldo_cont_enable_time[] = {
+	0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
+};
+
+static int lm3631_regulator_enable_time(struct regulator_dev *rdev)
+{
+	struct lm3631_regulator *lm3631_regulator = rdev_get_drvdata(rdev);
+	enum lm3631_regulator_id id = rdev_get_id(rdev);
+	u8 val, addr, mask;
+
+	switch (id) {
+	case LM3631_LDO_CONT:
+		addr = LM3631_REG_ENTIME_VCONT;
+		mask = LM3631_ENTIME_CONT_MASK;
+		break;
+	case LM3631_LDO_OREF:
+		addr = LM3631_REG_ENTIME_VOREF;
+		mask = LM3631_ENTIME_MASK;
+		break;
+	case LM3631_LDO_POS:
+		addr = LM3631_REG_ENTIME_VPOS;
+		mask = LM3631_ENTIME_MASK;
+		break;
+	case LM3631_LDO_NEG:
+		addr = LM3631_REG_ENTIME_VNEG;
+		mask = LM3631_ENTIME_MASK;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ti_lmu_read_byte(lm3631_regulator->lmu, addr, &val))
+		return -EINVAL;
+
+	val = (val & mask) >> LM3631_ENTIME_SHIFT;
+
+	if (id == LM3631_LDO_CONT)
+		return ldo_cont_enable_time[val];
+	else
+		return ENABLE_TIME_USEC * val;
+}
+
+static struct regulator_ops lm3631_boost_voltage_table_ops = {
+	.list_voltage     = regulator_list_voltage_table,
+	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
+};
+
+static struct regulator_ops lm3631_regulator_voltage_table_ops = {
+	.list_voltage     = regulator_list_voltage_table,
+	.set_voltage_sel  = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel  = regulator_get_voltage_sel_regmap,
+	.enable           = regulator_enable_regmap,
+	.disable          = regulator_disable_regmap,
+	.is_enabled       = regulator_is_enabled_regmap,
+	.enable_time      = lm3631_regulator_enable_time,
+};
+
+static struct regulator_desc lm3631_regulator_desc[] = {
+	{
+		.name           = "vboost",
+		.id             = LM3631_BOOST,
+		.ops            = &lm3631_boost_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_boost_vtbl),
+		.volt_table     = lm3631_boost_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_BOOST,
+		.vsel_mask      = LM3631_VOUT_MASK,
+	},
+	{
+		.name           = "ldo_cont",
+		.id             = LM3631_LDO_CONT,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_cont_vtbl),
+		.volt_table     = lm3631_ldo_cont_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_CONT,
+		.vsel_mask      = LM3631_VOUT_CONT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL2,
+		.enable_mask    = LM3631_EN_CONT_MASK,
+	},
+	{
+		.name           = "ldo_oref",
+		.id             = LM3631_LDO_OREF,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
+		.volt_table     = lm3631_ldo_target_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_OREF,
+		.vsel_mask      = LM3631_VOUT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL1,
+		.enable_mask    = LM3631_EN_OREF_MASK,
+	},
+	{
+		.name           = "ldo_vpos",
+		.id             = LM3631_LDO_POS,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
+		.volt_table     = lm3631_ldo_target_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_POS,
+		.vsel_mask      = LM3631_VOUT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL1,
+		.enable_mask    = LM3631_EN_VPOS_MASK,
+	},
+	{
+		.name           = "ldo_vneg",
+		.id             = LM3631_LDO_NEG,
+		.ops            = &lm3631_regulator_voltage_table_ops,
+		.n_voltages     = ARRAY_SIZE(lm3631_ldo_target_vtbl),
+		.volt_table     = lm3631_ldo_target_vtbl,
+		.type           = REGULATOR_VOLTAGE,
+		.owner          = THIS_MODULE,
+		.vsel_reg       = LM3631_REG_VOUT_NEG,
+		.vsel_mask      = LM3631_VOUT_MASK,
+		.enable_reg     = LM3631_REG_LDO_CTRL1,
+		.enable_mask    = LM3631_EN_VNEG_MASK,
+	},
+};
+
+static struct of_regulator_match lm3631_regulator_matches[] = {
+	{ .name = "vboost", .driver_data = (void *)LM3631_BOOST, },
+	{ .name = "vcont",  .driver_data = (void *)LM3631_LDO_CONT, },
+	{ .name = "voref",  .driver_data = (void *)LM3631_LDO_OREF, },
+	{ .name = "vpos",   .driver_data = (void *)LM3631_LDO_POS,  },
+	{ .name = "vneg",   .driver_data = (void *)LM3631_LDO_NEG,  },
+};
+
+static struct regulator_init_data *
+lm3631_regulator_parse_dt(struct device *dev,
+			  struct lm3631_regulator *lm3631_regulator, int id)
+{
+	struct device_node *node = dev->of_node;
+	int count;
+
+	count = of_regulator_match(dev, node, &lm3631_regulator_matches[id], 1);
+	if (count <= 0)
+		return ERR_PTR(-ENODEV);
+
+	return lm3631_regulator_matches[id].init_data;
+}
+
+static int lm3631_regulator_probe(struct platform_device *pdev)
+{
+	struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
+	struct lm3631_regulator *lm3631_regulator;
+	struct regulator_init_data *init_data;
+	struct regulator_config cfg = { };
+	struct regulator_dev *rdev;
+	int id = pdev->id;
+	int ret;
+
+	lm3631_regulator = devm_kzalloc(&pdev->dev, sizeof(*lm3631_regulator),
+					GFP_KERNEL);
+	if (!lm3631_regulator)
+		return -ENOMEM;
+
+	lm3631_regulator->lmu = lmu;
+
+	init_data = lmu->pdata->regulator_data[id];
+	if (!init_data) {
+		if (IS_ENABLED(CONFIG_OF)) {
+			init_data = lm3631_regulator_parse_dt(&pdev->dev,
+							      lm3631_regulator,
+							      id);
+			if (IS_ERR(init_data))
+				return PTR_ERR(init_data);
+		}
+	}
+
+	cfg.dev = pdev->dev.parent;
+	cfg.init_data = init_data;
+	cfg.driver_data = lm3631_regulator;
+	cfg.regmap = lmu->regmap;
+
+	rdev = regulator_register(&lm3631_regulator_desc[id], &cfg);
+	if (IS_ERR(rdev)) {
+		ret = PTR_ERR(rdev);
+		dev_err(&pdev->dev, "[%d] regulator register err: %d\n",
+			id + 1, ret);
+		return ret;
+	}
+
+	lm3631_regulator->regulator = rdev;
+	platform_set_drvdata(pdev, lm3631_regulator);
+
+	return 0;
+}
+
+static int lm3631_regulator_remove(struct platform_device *pdev)
+{
+	struct lm3631_regulator *lm3631_regulator = platform_get_drvdata(pdev);
+
+	regulator_unregister(lm3631_regulator->regulator);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id lm3631_regulator_of_match[] = {
+	{ .compatible = "ti,lm3631-regulator", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lm3631_regulator_of_match);
+#endif
+
+static struct platform_driver lm3631_regulator_driver = {
+	.probe = lm3631_regulator_probe,
+	.remove = lm3631_regulator_remove,
+	.driver = {
+		.name = "lm3631-regulator",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(lm3631_regulator_of_match),
+	},
+};
+
+module_platform_driver(lm3631_regulator_driver);
+
+MODULE_DESCRIPTION("TI LM3631 Regulator Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lm3631-regulator");
-- 
1.7.9.5

             reply	other threads:[~2014-02-14  6:32 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-14  6:32 Milo Kim [this message]
2014-02-14  6:32 ` [PATCH 09/10] regulator: Add LM3631 driver Milo Kim
2014-02-14 20:55 ` Mark Brown

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=1392359551-7170-1-git-send-email-milo.kim@ti.com \
    --to=milo.kim@ti.com \
    --cc=broonie@kernel.org \
    --cc=cooloney@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=jg1.han@samsung.com \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sameo@linux.intel.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.