[PATCH 3/7] regulator: MT6397: Add support for MT6397 regulator

Flora Fu flora.fu at mediatek.com
Sun Nov 16 23:40:23 PST 2014


This patch is MT6397 regulator driver.

signed-off-by: Flora Fu <flora.fu at mediatek.com>
---
 drivers/regulator/Kconfig                  |   6 +
 drivers/regulator/Makefile                 |   1 +
 drivers/regulator/mt6397-regulator.c       | 547 +++++++++++++++++++++++++++++
 include/linux/regulator/mt6397-regulator.h |  50 +++
 4 files changed, 604 insertions(+)
 create mode 100644 drivers/regulator/mt6397-regulator.c
 create mode 100644 include/linux/regulator/mt6397-regulator.h

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 55d7b7b..ced47af 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -725,5 +725,11 @@ config REGULATOR_WM8994
 	  This driver provides support for the voltage regulators on the
 	  WM8994 CODEC.
 
+config REGULATOR_MT6397
+	tristate "MediaTek MT6397 PMIC"
+	depends on MFD_MT6397
+	help
+	   This driver provides support for the voltage regulators on the MediaTek MT6397 PMIC.
+
 endif
 
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 1029ed3..3622ece 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
 obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
 obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
 obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
+obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
 
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c
new file mode 100644
index 0000000..6ff0c22
--- /dev/null
+++ b/drivers/regulator/mt6397-regulator.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora.Fu <flora.fu at mediatek.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.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/mt6397-regulator.h>
+#include <linux/mfd/mt6397/core.h>
+#include <linux/mfd/mt6397/registers.h>
+
+struct mt6397_buck_conf {
+	unsigned int vosel_reg;
+	unsigned int voselon_reg;
+	unsigned int nivosel_reg;
+	unsigned int vosel_mask;
+};
+
+struct mt6397_ldo_conf {
+	unsigned int is_fixed;
+	unsigned int vosel_reg;
+	unsigned int vosel_mask;
+	unsigned int vosel_shift;
+};
+
+struct mt6397_regulator_info {
+	struct regulator_desc desc;
+	struct mt6397_buck_conf buck_conf;
+	struct mt6397_ldo_conf ldo_conf;
+	unsigned int qi;
+	unsigned int qi_mask;
+};
+
+struct mt6397_regulator_data {
+	int id;
+	const char *name;
+	struct regulator_init_data *initdata;
+	struct device_node *reg_node;
+};
+
+struct mt6397_regulator_priv {
+	struct mt6397_regulator_data *regulators;
+	unsigned int num_regulators;
+};
+
+#define MT6397_BUCK(vreg, min, max, step, volt_ranges,		\
+		enreg, vosel, voselon, nivosel)			\
+[MT6397_ID_##vreg] = {						\
+	.desc = {						\
+		.name = #vreg,					\
+		.ops = &mt6397_volt_range_ops,			\
+		.type = REGULATOR_VOLTAGE,			\
+		.id = MT6397_ID_##vreg,				\
+		.owner = THIS_MODULE,				\
+		.n_voltages	= (max - min)/step + 1,		\
+		.linear_ranges = volt_ranges,			\
+		.n_linear_ranges = ARRAY_SIZE(volt_ranges),	\
+		.enable_reg = enreg,				\
+		.enable_mask = BIT(0),				\
+	},							\
+	.qi = enreg,						\
+	.qi_mask = BIT(13),					\
+	.buck_conf = {						\
+		.vosel_reg = vosel,				\
+		.voselon_reg = voselon,				\
+		.nivosel_reg = nivosel,				\
+		.vosel_mask = 0x7f,				\
+	},							\
+}
+
+#define MT6397_BUCK_TABLE(vreg, buck_volt_table,		\
+		enreg, vosel, voselon, nivosel)			\
+[MT6397_ID_##vreg] = {						\
+	.desc = {						\
+		.name = #vreg,					\
+		.ops = &mt6397_volt_table_ops,			\
+		.type = REGULATOR_VOLTAGE,			\
+		.id = MT6397_ID_##vreg,				\
+		.owner = THIS_MODULE,				\
+		.n_voltages = 1,				\
+		.volt_table = buck_volt_table,			\
+		.enable_reg = enreg,				\
+		.enable_mask = BIT(0),				\
+	},							\
+	.qi = enreg,						\
+	.qi_mask = BIT(13),					\
+	.buck_conf = {						\
+		.vosel_reg = vosel,				\
+		.voselon_reg = voselon,				\
+		.nivosel_reg = nivosel,				\
+		.vosel_mask = 0x1f,				\
+	},							\
+}
+
+#define MT6397_LDO(vreg, ldo_volt_table,			\
+		enreg, enbit, fixed, vosel, _vosel_mask,	\
+		_vosel_shift)					\
+[MT6397_ID_##vreg] = {						\
+	.desc = {						\
+		.name = #vreg,					\
+		.ops = &mt6397_volt_table_ops,			\
+		.type = REGULATOR_VOLTAGE,			\
+		.id = MT6397_ID_##vreg,				\
+		.owner = THIS_MODULE,				\
+		.n_voltages = ARRAY_SIZE(ldo_volt_table),	\
+		.volt_table = ldo_volt_table,			\
+		.enable_reg = enreg,				\
+		.enable_mask = BIT(enbit),			\
+	},							\
+	.qi = enreg,						\
+	.qi_mask = BIT(15),					\
+	.ldo_conf = {						\
+		.is_fixed = fixed,				\
+		.vosel_reg = vosel,				\
+		.vosel_mask = _vosel_mask,			\
+		.vosel_shift = _vosel_shift,			\
+	},							\
+}
+
+static const struct regulator_linear_range buck_volt_range1[] = {
+	REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
+};
+
+static const struct regulator_linear_range buck_volt_range2[] = {
+	REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),
+};
+
+static const unsigned int fixed_1800000_voltage[] = {
+	1800000,
+};
+
+static const unsigned int fixed_2800000_voltage[] = {
+	2800000,
+};
+
+static const unsigned int fixed_3300000_voltage[] = {
+	3300000,
+};
+
+static const unsigned int ldo_volt_table1[] = {
+	1500000, 1800000, 2500000, 2800000,
+};
+
+static const unsigned int ldo_volt_table2[] = {
+	1800000, 3300000,
+};
+
+static const unsigned int ldo_volt_table3[] = {
+	3000000, 3300000,
+};
+
+static const unsigned int ldo_volt_table4[] = {
+	1220000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static const unsigned int ldo_volt_table5[] = {
+	1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static const unsigned int ldo_volt_table5_v2[] = {
+	1200000, 1000000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static const unsigned int ldo_volt_table6[] = {
+	1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
+};
+
+static const unsigned int ldo_volt_table7[] = {
+	1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,
+};
+
+static int mt6397_buck_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
+{
+	int ret;
+	unsigned int vosel;
+	unsigned int voselon;
+	unsigned int vosel_mask;
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+
+	vosel = info->buck_conf.vosel_reg;
+	voselon = info->buck_conf.voselon_reg;
+	vosel_mask = info->buck_conf.vosel_mask;
+
+	ret = regmap_update_bits(rdev->regmap, vosel, vosel_mask, sel);
+	if (ret != 0) {
+		dev_err(&rdev->dev, "Failed to update vosel: %d\n", ret);
+		return ret;
+	}
+
+	ret = regmap_update_bits(rdev->regmap, voselon, vosel_mask, sel);
+	if (ret != 0) {
+		dev_err(&rdev->dev, "Failed to update vosel_on: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static int mt6397_buck_get_voltage_sel(struct regulator_dev *rdev)
+{
+	int ret;
+	unsigned int nivosel;
+	unsigned int vosel_mask;
+	unsigned int regval;
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+
+	nivosel = info->buck_conf.nivosel_reg;
+	vosel_mask = info->buck_conf.vosel_mask;
+
+	ret = regmap_read(rdev->regmap, nivosel, &regval);
+	if (ret != 0) {
+		dev_err(&rdev->dev, "Failed to get vosel: %d\n", ret);
+		return ret;
+	}
+
+	regval &= vosel_mask;
+	regval >>= ffs(vosel_mask) - 1;
+
+	return regval;
+}
+
+
+static int mt6397_ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned sel)
+{
+	int ret;
+	unsigned int is_fixed;
+	unsigned int vosel;
+	unsigned int vosel_mask;
+	unsigned int vosel_shift;
+
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+
+	is_fixed = info->ldo_conf.is_fixed;
+	vosel = info->ldo_conf.vosel_reg;
+	vosel_mask = info->ldo_conf.vosel_mask;
+	vosel_shift = info->ldo_conf.vosel_shift;
+
+	if (is_fixed)
+		return 0;
+
+	sel <<= vosel_shift;
+	ret = regmap_update_bits(rdev->regmap, vosel, vosel_mask, sel);
+	if (ret != 0) {
+		dev_err(&rdev->dev, "Failed to update vosel: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int mt6397_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+	int ret;
+	unsigned int vosel;
+	unsigned int vosel_mask;
+	unsigned int regval;
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+
+	vosel = info->ldo_conf.vosel_reg;
+	vosel_mask = info->ldo_conf.vosel_mask;
+
+	ret = regmap_read(rdev->regmap, vosel, &regval);
+	if (ret != 0) {
+		dev_err(&rdev->dev, "Failed to get vosel: %d\n", ret);
+		return ret;
+	}
+
+	regval &= vosel_mask;
+	regval >>= ffs(vosel_mask) - 1;
+
+	return regval;
+}
+
+static int mt6397_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	int ret;
+	unsigned int regaddr;
+	unsigned int regmask;
+	unsigned int regval;
+	struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);
+
+	regaddr = info->qi;
+	regmask = info->qi_mask;
+
+	ret = regmap_read(rdev->regmap, regaddr, &regval);
+	if (ret != 0) {
+		dev_err(&rdev->dev, "Failed to get vosel: %d\n", ret);
+		return ret;
+	}
+
+	return (regval & info->qi_mask) ? 1 : 0;
+}
+
+static struct regulator_ops mt6397_volt_range_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.map_voltage = regulator_map_voltage_linear_range,
+	.set_voltage_sel = mt6397_buck_set_voltage_sel,
+	.get_voltage_sel = mt6397_buck_get_voltage_sel,
+	.set_voltage_time_sel = regulator_set_voltage_time_sel,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = mt6397_regulator_is_enabled,
+};
+
+static struct regulator_ops mt6397_volt_table_ops = {
+	.list_voltage = regulator_list_voltage_table,
+	.map_voltage = regulator_map_voltage_iterate,
+	.set_voltage_sel = mt6397_ldo_set_voltage_sel,
+	.get_voltage_sel = mt6397_ldo_get_voltage_sel,
+	.set_voltage_time_sel = regulator_set_voltage_time_sel,
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = mt6397_regulator_is_enabled,
+};
+
+/* The array is indexed by id(MT6397_ID_XXX) */
+static struct mt6397_regulator_info mt6397_regulators[] = {
+	MT6397_BUCK(VPCA15, 700000, 1493750, 6250, buck_volt_range1,
+		MT6397_VCA15_CON7, MT6397_VCA15_CON9,
+		MT6397_VCA15_CON10, MT6397_VCA15_CON12),
+	MT6397_BUCK(VPCA7, 700000, 1493750, 6250, buck_volt_range1,
+		MT6397_VPCA7_CON7, MT6397_VPCA7_CON9,
+		MT6397_VPCA7_CON10, MT6397_VPCA7_CON12),
+	MT6397_BUCK(VSRAMCA15, 700000, 1493750, 6250, buck_volt_range1,
+		MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,
+		MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON12),
+	MT6397_BUCK(VSRAMCA7, 700000, 1493750, 6250, buck_volt_range1,
+		MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,
+		MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON12),
+	MT6397_BUCK(VCORE, 700000, 1493750, 6250, buck_volt_range1,
+		MT6397_VCORE_CON7, MT6397_VCORE_CON9,
+		MT6397_VCORE_CON10, MT6397_VCORE_CON12),
+	MT6397_BUCK(VGPU, 700000, 1493750, 6250, buck_volt_range1,
+		MT6397_VGPU_CON7, MT6397_VGPU_CON9,
+		MT6397_VGPU_CON10, MT6397_VCORE_CON12),
+	MT6397_BUCK(VDRM, 800000, 1593750, 6250, buck_volt_range2,
+		MT6397_VDRM_CON7, MT6397_VDRM_CON9,
+		MT6397_VDRM_CON10, MT6397_VDRM_CON12),
+	MT6397_BUCK_TABLE(VIO18, fixed_1800000_voltage,
+		MT6397_VIO18_CON7, MT6397_VIO18_CON9,
+		MT6397_VIO18_CON10, MT6397_VIO18_CON12),
+	MT6397_LDO(VTCXO, fixed_2800000_voltage,
+		MT6397_ANALDO_CON0, 10, 1, 0, 0, 0),
+	MT6397_LDO(VA28, fixed_2800000_voltage,
+		MT6397_ANALDO_CON1, 14, 1, 0, 0, 0),
+	MT6397_LDO(VCAMA, ldo_volt_table1,
+		MT6397_ANALDO_CON2, 15, 0, MT6397_ANALDO_CON6, 0xC0, 6),
+	MT6397_LDO(VIO28, fixed_2800000_voltage,
+		MT6397_DIGLDO_CON0, 14, 1, 0, 0, 0),
+	MT6397_LDO(USB, fixed_3300000_voltage,
+		MT6397_DIGLDO_CON1, 14, 1, 0, 0, 0),
+	MT6397_LDO(VMC, ldo_volt_table2,
+		MT6397_DIGLDO_CON2, 12, 0, MT6397_DIGLDO_CON29, 0x10, 4),
+	MT6397_LDO(VMCH, ldo_volt_table3,
+		MT6397_DIGLDO_CON3, 14, 0, MT6397_DIGLDO_CON17, 0x80, 7),
+	MT6397_LDO(VEMC3V3, ldo_volt_table3,
+		MT6397_DIGLDO_CON4, 14, 0, MT6397_DIGLDO_CON18, 0x10, 4),
+	MT6397_LDO(VCAMD, ldo_volt_table4,
+		MT6397_DIGLDO_CON5, 15, 0, MT6397_DIGLDO_CON19, 0xE0, 5),
+	MT6397_LDO(VCAMIO, ldo_volt_table5,
+		MT6397_DIGLDO_CON6, 15, 0, MT6397_DIGLDO_CON20, 0xE0, 5),
+	MT6397_LDO(VCAMAF, ldo_volt_table5,
+		MT6397_DIGLDO_CON7, 15, 0, MT6397_DIGLDO_CON21, 0xE0, 5),
+	MT6397_LDO(VGP4, ldo_volt_table5,
+		MT6397_DIGLDO_CON8, 15, 0, MT6397_DIGLDO_CON22, 0xE0, 5),
+	MT6397_LDO(VGP5, ldo_volt_table6,
+		MT6397_DIGLDO_CON9, 15, 0, MT6397_DIGLDO_CON23, 0xE0, 5),
+	MT6397_LDO(VGP6, ldo_volt_table5,
+		MT6397_DIGLDO_CON10, 15, 0, MT6397_DIGLDO_CON33, 0xE0, 5),
+	MT6397_LDO(VIBR, ldo_volt_table7,
+		MT6397_DIGLDO_CON24, 15, 0, MT6397_DIGLDO_CON25, 0xE00, 9),
+};
+
+#define MT6397_REGULATOR_OF_MATCH(_name, _id)			\
+[MT6397_ID_##_id] = {						\
+	.name = #_name,						\
+	.driver_data = &mt6397_regulators[MT6397_ID_##_id],	\
+}
+
+static struct of_regulator_match mt6397_regulator_matches[] = {
+	MT6397_REGULATOR_OF_MATCH(buck_vpca15, VPCA15),
+	MT6397_REGULATOR_OF_MATCH(buck_vpca7, VPCA7),
+	MT6397_REGULATOR_OF_MATCH(buck_vsramca15, VSRAMCA15),
+	MT6397_REGULATOR_OF_MATCH(buck_vsramca7, VSRAMCA7),
+	MT6397_REGULATOR_OF_MATCH(buck_vcore, VCORE),
+	MT6397_REGULATOR_OF_MATCH(buck_vgpu, VGPU),
+	MT6397_REGULATOR_OF_MATCH(buck_vdrm, VDRM),
+	MT6397_REGULATOR_OF_MATCH(buck_vio18, VIO18),
+	MT6397_REGULATOR_OF_MATCH(ldo_vtcxo, VTCXO),
+	MT6397_REGULATOR_OF_MATCH(ldo_va28, VA28),
+	MT6397_REGULATOR_OF_MATCH(ldo_vcama, VCAMA),
+	MT6397_REGULATOR_OF_MATCH(ldo_vio28, VIO28),
+	MT6397_REGULATOR_OF_MATCH(ldo_usb, USB),
+	MT6397_REGULATOR_OF_MATCH(ldo_vmc, VMC),
+	MT6397_REGULATOR_OF_MATCH(ldo_vmch, VMCH),
+	MT6397_REGULATOR_OF_MATCH(ldo_vemc3v3, VEMC3V3),
+	MT6397_REGULATOR_OF_MATCH(ldo_vcamd, VCAMD),
+	MT6397_REGULATOR_OF_MATCH(ldo_vcamio, VCAMIO),
+	MT6397_REGULATOR_OF_MATCH(ldo_vcamaf, VCAMAF),
+	MT6397_REGULATOR_OF_MATCH(ldo_vgp4, VGP4),
+	MT6397_REGULATOR_OF_MATCH(ldo_vgp5, VGP5),
+	MT6397_REGULATOR_OF_MATCH(ldo_vgp6, VGP6),
+	MT6397_REGULATOR_OF_MATCH(ldo_vibr, VIBR),
+};
+
+static int mt6397_regulator_dt_init(struct platform_device *pdev,
+			struct mt6397_regulator_priv *priv)
+{
+	struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
+	struct device_node *np, *regulators;
+	struct mt6397_regulator_data *rdata;
+	int matched, i, j, ret;
+	unsigned int reg_value;
+
+	if (!priv) {
+		dev_err(&pdev->dev, "regulator private data missing\n");
+		return -EINVAL;
+	}
+
+	np = of_node_get(pdev->dev.parent->of_node);
+	if (!np)
+		return -EINVAL;
+
+	regulators = of_get_child_by_name(np, "regulators");
+	if (!regulators) {
+		dev_err(&pdev->dev, "regulators node not found\n");
+		ret = -EINVAL;
+		goto out;
+	}
+	of_node_put(np);
+	matched = of_regulator_match(&pdev->dev, regulators,
+				mt6397_regulator_matches,
+				ARRAY_SIZE(mt6397_regulator_matches));
+	of_node_put(regulators);
+	if (matched < 0) {
+		dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
+			matched);
+		return matched;
+	}
+
+	priv->num_regulators = matched;
+	priv->regulators = devm_kzalloc(&pdev->dev,
+			(sizeof(struct mt6397_regulator_data) *
+			ARRAY_SIZE(mt6397_regulator_matches)), GFP_KERNEL);
+	if (!priv->regulators)
+		return -ENOMEM;
+
+	/* Read PMIC chip revision to update constraints and voltage table */
+	if (regmap_read(mt6397->regmap, MT6397_CID, &reg_value) < 0) {
+		dev_err(&pdev->dev, "Failed to read Chip ID\n");
+		return -EIO;
+	}
+	dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
+
+	if ((reg_value & 0xFF) == MT6397_REGULATOR_ID91) {
+		j = MT6397_ID_VCAMIO;
+		mt6397_regulator_matches[j].init_data->constraints.min_uV =
+		1000000;
+		mt6397_regulators[j].desc.volt_table = ldo_volt_table5_v2;
+	}
+
+	rdata = priv->regulators;
+	for (i = 0; i < ARRAY_SIZE(mt6397_regulator_matches); i++) {
+		rdata->id = i;
+		rdata->name = mt6397_regulator_matches[i].name;
+		rdata->initdata = mt6397_regulator_matches[i].init_data;
+		rdata->reg_node = mt6397_regulator_matches[i].of_node;
+		rdata++;
+	}
+	return 0;
+
+out:
+	of_node_put(np);
+	return ret;
+}
+
+static int mt6397_regulator_probe(struct platform_device *pdev)
+{
+	struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);
+	int ret, i, id, size;
+	struct regulator_config config = {};
+	struct regulator_dev *rdev;
+	struct mt6397_regulator_priv *priv;
+
+	size = sizeof(struct mt6397_regulator_priv);
+	priv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+	ret = mt6397_regulator_dt_init(pdev, priv);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < MT6397_ID_RG_MAX; i++) {
+		id = priv->regulators[i].id;
+		config.dev = &pdev->dev;
+		config.init_data = priv->regulators[i].initdata;
+		config.of_node = priv->regulators[i].reg_node;
+		config.driver_data = mt6397_regulator_matches[i].driver_data;
+		config.regmap = mt6397->regmap;
+
+		rdev = devm_regulator_register(&pdev->dev,
+				&mt6397_regulators[i].desc, &config);
+		if (IS_ERR(rdev)) {
+			dev_err(&pdev->dev, "failed to register %s\n",
+				mt6397_regulators[id].desc.name);
+			return PTR_ERR(rdev);
+		}
+	}
+
+	return 0;
+}
+
+static const struct platform_device_id mt6397_regulator_id[] = {
+	{"mt6397-regulator", 0},
+	{ },
+};
+
+static struct platform_driver mt6397_regulator_driver = {
+	.driver	= {
+		.name = "mt6397-regulator",
+		.owner = THIS_MODULE,
+	},
+	.probe = mt6397_regulator_probe,
+	.id_table = mt6397_regulator_id,
+};
+
+module_platform_driver(mt6397_regulator_driver);
+
+MODULE_AUTHOR("Flora Fu <flora.fu at mediatek.com>");
+MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt6397-regulator");
diff --git a/include/linux/regulator/mt6397-regulator.h b/include/linux/regulator/mt6397-regulator.h
new file mode 100644
index 0000000..d03be02
--- /dev/null
+++ b/include/linux/regulator/mt6397-regulator.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Flora.Fu <flora.fu at mediatek.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.
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_REGULATOR_MT6397_H
+#define __LINUX_REGULATOR_MT6397_H
+
+enum {
+	MT6397_ID_VPCA15 = 0,
+	MT6397_ID_VPCA7,
+	MT6397_ID_VSRAMCA15,
+	MT6397_ID_VSRAMCA7,
+	MT6397_ID_VCORE,
+	MT6397_ID_VGPU,
+	MT6397_ID_VDRM,
+	MT6397_ID_VIO18 = 7,
+
+	MT6397_ID_VTCXO,
+	MT6397_ID_VA28,
+	MT6397_ID_VCAMA,
+	MT6397_ID_VIO28,
+	MT6397_ID_USB,
+	MT6397_ID_VMC,
+	MT6397_ID_VMCH,
+	MT6397_ID_VEMC3V3,
+	MT6397_ID_VCAMD,
+	MT6397_ID_VCAMIO,
+	MT6397_ID_VCAMAF,
+	MT6397_ID_VGP4,
+	MT6397_ID_VGP5,
+	MT6397_ID_VGP6,
+	MT6397_ID_VIBR,
+
+	MT6397_ID_RG_MAX,
+};
+#define MT6397_MAX_REGULATOR	MT6397_ID_RG_MAX
+#define MT6397_REGULATOR_ID97	0x97
+#define MT6397_REGULATOR_ID91	0x91
+
+#endif /* __LINUX_REGULATOR_MT6397_H */
-- 
1.8.1.1.dirty




More information about the linux-arm-kernel mailing list