aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuodong Xu <guodong.xu@linaro.org>2013-01-28 11:31:17 +0800
committerGuodong Xu <guodong.xu@linaro.org>2013-02-21 16:12:30 +0800
commit9e40b6373b27460f5372905dee685941ea0309be (patch)
treecf8d57a0f8310cbdb6f1d992e73b133742dfdad5
parent3cba44e58a5ae4ca2d338695925a8166244ae324 (diff)
regulator: hi6421 driver for each regulator
-rw-r--r--.gitignore3
-rw-r--r--arch/arm/boot/dts/hi4511.dts102
-rw-r--r--drivers/regulator/Kconfig6
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/hi6421-regulator.c478
-rw-r--r--drivers/regulator/of_regulator.c3
6 files changed, 562 insertions, 31 deletions
diff --git a/.gitignore b/.gitignore
index 3b8b9b33be38..42315353f3ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -91,3 +91,6 @@ extra_certificates
signing_key.priv
signing_key.x509
x509.genkey
+
+# ctags index
+TAGS
diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
index f5fe4538a7b6..c3f1b98cdb48 100644
--- a/arch/arm/boot/dts/hi4511.dts
+++ b/arch/arm/boot/dts/hi4511.dts
@@ -831,21 +831,38 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO0";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x20 0x10 0x20>;
hisilicon,hi6421-vset = <0x20 0x07>;
+ hisilicon,hi6421-n-voltages = <8>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
<2400000>, <2500000>,
<2600000>, <2700000>,
<2850000>, <3000000>;
+ hisilicon,hi6421-off-on-delay-us = <10000>;
+ hisilicon,hi6421-enable-time-us = <250>;
};
+
+static const u32 on_off_delay_us[NUM_OF_HI6421_REGULATOR] = {
+ 10000, 10000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 40000, 40000, /* LDO0 ~ 10 */
+ 40000, 40000,40000, 40000,40000, 40000,40000, 40000,40000, 40000, 40000, /* LDO_11 ~ LDO20 ,LDO_AUDIO */
+ 20000, 20000, 100, 20000, 20000, 20000 /* BUCK0 ~ 5*/
+};
+
+static const u32 on_enable_delay_us[NUM_OF_HI6421_REGULATOR] = {
+ 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, /* LDO0 ~ 10 */
+ 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, /* LDO_11 ~ LDO20 ,LDO_AUDIO */
+ 300, 300, 250, 250, 250, 250 /* BUCK0 ~ 5*/
+};
+
+
ldo1: ldo@21 {
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO1";
regulator-min-microvolt = <1700000>;
- regulatro-max-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x21 0x10 0x20>;
hisilicon,hi6421-vset = <0x21 0x03>;
@@ -857,7 +874,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO2";
regulator-min-microvolt = <1050000>;
- regulatro-max-microvolt = <1400000>;
+ regulator-max-microvolt = <1400000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x22 0x10 0x20>;
hisilicon,hi6421-vset = <0x22 0x07>;
@@ -871,7 +888,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO3";
regulator-min-microvolt = <1050000>;
- regulatro-max-microvolt = <1400000>;
+ regulator-max-microvolt = <1400000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x23 0x10 0x20>;
hisilicon,hi6421-vset = <0x23 0x07>;
@@ -885,7 +902,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO4";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x24 0x10 0x20>;
hisilicon,hi6421-vset = <0x24 0x07>;
@@ -899,7 +916,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO5";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x25 0x10 0x20>;
hisilicon,hi6421-vset = <0x25 0x07>;
@@ -913,7 +930,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO6";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x26 0x10 0x20>;
hisilicon,hi6421-vset = <0x26 0x07>;
@@ -927,7 +944,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO7";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x27 0x10 0x20>;
hisilicon,hi6421-vset = <0x27 0x07>;
@@ -941,7 +958,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO8";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x28 0x10 0x20>;
hisilicon,hi6421-vset = <0x28 0x07>;
@@ -955,7 +972,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO9";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x29 0x10 0x20>;
hisilicon,hi6421-vset = <0x29 0x07>;
@@ -969,7 +986,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO10";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x2a 0x10 0x20>;
hisilicon,hi6421-vset = <0x2a 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -982,7 +999,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO11";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x2b 0x10 0x20>;
hisilicon,hi6421-vset = <0x2b 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -995,7 +1012,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO12";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x2c 0x10 0x20>;
hisilicon,hi6421-vset = <0x2c 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1008,7 +1025,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO13";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x2d 0x10 0x20>;
hisilicon,hi6421-vset = <0x2d 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1021,7 +1038,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO14";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x2e 0x10 0x20>;
hisilicon,hi6421-vset = <0x2e 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1034,7 +1051,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO15";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x2f 0x10 0x20>;
hisilicon,hi6421-vset = <0x2f 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1047,7 +1064,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO16";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x30 0x10 0x20>;
hisilicon,hi6421-vset = <0x30 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1060,7 +1077,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO17";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x31 0x10 0x20>;
hisilicon,hi6421-vset = <0x31 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1073,7 +1090,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO18";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x32 0x10 0x20>;
hisilicon,hi6421-vset = <0x32 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1086,7 +1103,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO19";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x2a 0x10 0x20>;
hisilicon,hi6421-vset = <0x2a 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1099,7 +1116,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDO20";
regulator-min-microvolt = <1500000>;
- regulatro-max-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
hisilicon,hi6421-ctrl = <0x34 0x10 0x20>;
hisilicon,hi6421-vset = <0x34 0x07>;
hisilicon,hi6421-vset-table = <1500000>, <1800000>,
@@ -1112,7 +1129,7 @@
compatible = "hisilicon,hi6421-ldo";
regulator-name = "LDOAUDIO";
regulator-min-microvolt = <2800000>;
- regulatro-max-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
hisilicon,hi6421-ctrl = <0x36 0x01 0x02>;
hisilicon,hi6421-vset = <0x36 0x70>;
hisilicon,hi6421-vset-table = <2800000>, <2850000>,
@@ -1121,46 +1138,69 @@
<3200000>, <3300000>;
};
+
+
+static const u32 on_off_delay_us[NUM_OF_HI6421_REGULATOR] = {
+ 10000, 10000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 40000, 40000, /* LDO0 ~ 10 */
+ 40000, 40000,40000, 40000,40000, 40000,40000, 40000,40000, 40000, 40000, /* LDO_11 ~ LDO20 ,LDO_AUDIO */
+ 20000, 20000, 100, 20000, 20000, 20000 /* BUCK0 ~ 5*/
+};
+
+static const u32 on_enable_delay_us[NUM_OF_HI6421_REGULATOR] = {
+ 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, /* LDO0 ~ 10 */
+ 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, /* LDO_11 ~ LDO20 ,LDO_AUDIO */
+ 300, 300, 250, 250, 250, 250 /* BUCK0 ~ 5*/
+};
+
buck0: buck@0c {
compatible = "hisilicon,hi6421-buck012";
regulator-name = "BUCK0";
regulator-min-microvolt = <700000>;
- regulatro-max-microvolt = <1600000>;
+ regulator-max-microvolt = <1600000>;
regulator-boot-on;
regulator-always-on;
hisilicon,hi6421-ctrl = <0x0c 0x01 0x10>;
hisilicon,hi6421-vset = <0x0d 0x7f>;
- hisilicon,hi6421-vset-stage = <128>;
+ hisilicon,hi6421-n-voltages = <128>;
+ hisilicon,hi6421-uv-step = <7087>;
+ hisilicon,hi6421-off-on-delay-us = <20000>;
+ hisilicon,hi6421-enable-time-us = <300>;
};
buck1: buck@0e {
compatible = "hisilicon,hi6421-buck012";
regulator-name = "BUCK1";
regulator-min-microvolt = <700000>;
- regulatro-max-microvolt = <1600000>;
+ regulator-max-microvolt = <1600000>;
regulator-boot-on;
regulator-always-on;
hisilicon,hi6421-ctrl = <0x0e 0x01 0x10>;
hisilicon,hi6421-vset = <0x0f 0x7f>;
- hisilicon,hi6421-vset-stage = <128>;
+ hisilicon,hi6421-n-voltages = <128>;
+ hisilicon,hi6421-uv-step = <7087>;
+ hisilicon,hi6421-off-on-delay-us = <20000>;
+ hisilicon,hi6421-enable-time-us = <300>;
};
buck2: buck@10 {
compatible = "hisilicon,hi6421-buck012";
regulator-name = "BUCK2";
regulator-min-microvolt = <700000>;
- regulatro-max-microvolt = <1600000>;
+ regulator-max-microvolt = <1600000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x10 0x01 0x10>;
hisilicon,hi6421-vset = <0x11 0x7f>;
- hisilicon,hi6421-vset-stage = <128>;
+ hisilicon,hi6421-n-voltages = <128>;
+ hisilicon,hi6421-uv-step = <7087>;
+ hisilicon,hi6421-off-on-delay-us = <100>;
+ hisilicon,hi6421-enable-time-us = <250>;
};
buck3: buck@12 {
compatible = "hisilicon,hi6421-buck345";
regulator-name = "BUCK3";
regulator-min-microvolt = <950000>;
- regulatro-max-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x12 0x01 0x10>;
hisilicon,hi6421-vset = <0x13 0x07>;
@@ -1174,7 +1214,7 @@
compatible = "hisilicon,hi6421-buck345";
regulator-name = "BUCK4";
regulator-min-microvolt = <1150000>;
- regulatro-max-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x14 0x01 0x10>;
hisilicon,hi6421-vset = <0x15 0x07>;
@@ -1188,7 +1228,7 @@
compatible = "hisilicon,hi6421-buck345";
regulator-name = "BUCK5";
regulator-min-microvolt = <1150000>;
- regulatro-max-microvolt = <1900000>;
+ regulator-max-microvolt = <1900000>;
regulator-boot-on;
hisilicon,hi6421-ctrl = <0x16 0x01 0x10>;
hisilicon,hi6421-vset = <0x17 0x07>;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 551a22b07538..a0c63e7eaecd 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -504,5 +504,11 @@ config REGULATOR_AS3711
This driver provides support for the voltage regulators on the
AS3711 PMIC
+config REGULATOR_HI6421
+ tristate "HiSilicon Hi6421 PMIC"
+ help
+ This driver provides support for the voltage regulators of the
+ HiSilicon Hi6421 PMIC.
+
endif
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index b802b0c7fb02..b58ef7afd547 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -69,6 +69,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_HI6421) += hi6421-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/hi6421-regulator.c b/drivers/regulator/hi6421-regulator.c
new file mode 100644
index 000000000000..5815d4c54a5d
--- /dev/null
+++ b/drivers/regulator/hi6421-regulator.c
@@ -0,0 +1,478 @@
+/*
+ * Device driver for regulators in Hi6421 IC
+ *
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (C) 2011 Hisilicon.
+ *
+ * Guodong Xu <guodong.xu@linaro.org>
+ *
+ * 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.
+ *
+ * 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/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+struct hi6421_regulator_register_info {
+ u32 ctrl_reg;
+ u32 enable_mask;
+ u32 eco_mode_mask;
+ u32 vset_reg;
+ u32 vset_mask;
+}
+
+struct hi6421_regulator {
+ const char *name;
+ struct hi6421_regulator_register_info register_info;
+/* u32 control_reg;
+ struct regmap *anatop;
+ int vol_bit_shift;
+ int vol_bit_width;
+ int min_bit_val;
+ int min_voltage;
+ int max_voltage;
+ */
+ u32 off_on_delay;
+ struct regulator_desc rdesc;
+ int (*dt_parse)(struct hi6421_regulator *, struct platform_device *);
+/* struct regulator_init_data *initdata;
+ */
+};
+
+#if 0
+static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
+ unsigned selector)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+
+ if (!anatop_reg->control_reg)
+ return -ENOTSUPP;
+
+ return regulator_set_voltage_sel_regmap(reg, selector);
+}
+
+static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
+{
+ struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
+
+ if (!anatop_reg->control_reg)
+ return -ENOTSUPP;
+
+ return regulator_get_voltage_sel_regmap(reg);
+}
+#endif
+
+static int hi6421_regulator_enable(struct regulator_dev *dev)
+{
+ int ret = 0;
+ struct timeval tv;
+ u32 diff;
+ struct hi6421_regulator *sreg = rdev_get_drvdata(dev);
+
+#ifdef HI6421_REGULATOR_DEBUG
+ rdev_info(dev, "will be enabled\n");
+#endif
+
+ /*
+ do_gettimeofday(&tv);
+ diff = (tv.tv_sec - hi6421_regulator_data->lastoff_time[regulator_id].tv_sec) * USEC_PER_SEC
+ + tv.tv_usec - hi6421_regulator_data->lastoff_time[regulator_id].tv_usec;
+ if (diff < on_off_delay_us[regulator_id]) {
+ msleep((on_off_delay_us[regulator_id] - diff + 999 )/1000);
+ }
+
+ if (regulator_id == HI6421_LDO12) {
+ ret = gpio_request(SD_GPIO_DCDC, "sdcard_dcdc");
+ if (ret < 0) {
+ rdev_err(NULL, "hi6421 regulator gpio_request failed,please check!\n");
+ return ret;
+ }
+ gpio_direction_output(SD_GPIO_DCDC, 1);
+ }
+ if (regulator_id <= HI6421_LDO20) {
+ hi6421_regulator_set_bits(hi6421_regulator_data, regulator_ctrl_to_reg[regulator_id], HI6421_LDO_ENA_MASK, HI6421_LDO_ENA);
+ } else if (regulator_id == HI6421_LDOAUDIO) {
+ hi6421_regulator_set_bits(hi6421_regulator_data, regulator_ctrl_to_reg[regulator_id], HI6421_LDOAUDIO_ENA_MASK, HI6421_LDOAUDIO_ENA);
+ } else {
+ hi6421_regulator_set_bits(hi6421_regulator_data, regulator_ctrl_to_reg[regulator_id], HI6421_BUCK_ENA_MASK, HI6421_BUCK_ENA);
+ }
+
+ udelay(on_enable_delay_us[regulator_id]);
+
+ return 0;
+}
+
+static int hi6421_dt_parse_common(struct hi6421_regulator *sreg, struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct regulator_desc *rdesc = sreg->rdesc;
+ unsigned int register_info[3];
+ int ret = 0;
+
+ /* parse .register_info.ctrl_reg */
+ ret = of_property_read_u32_array(np, "hisilicon,hi6421-ctrl", register_info, 3);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-ctrl property set\n");
+ goto dt_parse_common_end;
+ }
+ sreg->register_info.ctrl_reg = register_info[0];
+ sreg->register_info.enable_mask = register_info[1];
+ sreg->register_info.eco_mode_mask = register_info[2];
+
+ /* parse .register_info.vset_reg */
+ ret = of_property_read_u32_array(np, "hisilicon,hi6421-vset", register_info, 2);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-vset property set\n");
+ goto dt_parse_common_end;
+ }
+ sreg->register_info.vset_reg = register_info[0];
+ sreg->register_info.vset_mask = register_info[1];
+ /* debug info */
+ {
+ int i;
+ printk("regulator: hi6421-register_info:\n");
+ for(i=0;i<5;i++){
+ printk("regulator: reg_infor[%d]=%d\n", i, (u32 *)(&(sreg->register_info))[i]);
+ }
+ }
+
+ /* parse .off-on-delay */
+ ret = of_property_read_u32(np, "hisilicon,hi6421-off-on-delay-us",
+ &sreg->off_on_delay);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-off-on-delay-us property set\n");
+ goto dt_parse_common_end;
+ }
+
+ /* parse .enable_time */
+ ret = of_property_read_u32(np, "hisilicon,hi6421-enable-time-us",
+ &rdesc->enable_time);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-enable-time-us property set\n");
+ goto dt_parse_common_end;
+ }
+
+dt_parse_common_end:
+ return ret;
+
+}
+
+static int hi6421_dt_parse_ldo(struct hi6421_regulator *sreg, struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct regulator_desc *rdesc = sreg->rdesc;
+ int ret = 0;
+
+ /* parse .n_voltages, and .volt_table */
+ ret = of_property_read_u32(np, "hisilicon,hi6421-n-voltages",
+ &rdesc->n_voltages);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-n-voltages property set\n");
+ goto dt_parse_ldo_end;
+ }
+
+ /* alloc space for .volt_table */
+ rdesc->volt_table = devm_kzalloc(dev, sizeof(unsigned int) * rdesc->n_voltages, GFP_KERNEL);
+ if (unlikely(!rdesc->volt_table)) {
+ ret = -ENOMEM;
+ dev_err(dev, "no memory for .volt_table\n");
+ goto dt_parse_ldo_end;
+ }
+
+ ret = of_property_read_u32_array(np, "hisilicon,hi6421-vset-table", rdesc->volt_table, rdesc->n_voltages);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-vset-table property set\n");
+ goto dt_parse_ldo_end1;
+ }
+ /* debug info */
+ {
+ int i;
+ printk("regulator: hi6421-vset-table:\n");
+ for(i=0;i<rdesc->volt_table;i++){
+ printk("regulator: hi6421 desc.volt_table[%d]=%d\n", i, rdesc->volt_table[i]);
+ }
+ }
+
+ /* parse hi6421 regulator's dt common part */
+ ret = hi6421_dt_parse_common(sreg, pdev);
+ if (ret) {
+ dev_err(dev, "failure in hi6421_dt_parse_common\n");
+ goto dt_parse_ldo_end1;
+ }
+
+dt_parse_ldo_end1:
+ devm_kfree(dev, rdesc->volt_table);
+dt_parse_ldo_end:
+ return ret;
+}
+
+static int hi6421_dt_parse_buck012(struct hi6421_regulator *sreg, struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct regulator_desc *rdesc = sreg->rdesc;
+ int ret = 0;
+
+ /* parse .n_voltages, and .uV_step */
+ ret = of_property_read_u32(np, "hisilicon,hi6421-n-voltages",
+ &rdesc->n_voltages);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-n-voltages property set\n");
+ goto dt_parse_buck012_end;
+ }
+ ret = of_property_read_u32(np, "hisilicon,hi6421-uv-step",
+ &rdesc->uV_step);
+ if (ret) {
+ dev_err(dev, "no hisilicon,hi6421-uv-step property set\n");
+ goto dt_parse_buck012_end;
+ }
+
+ /* parse hi6421 regulator's dt common part */
+ ret = hi6421_dt_parse_common(sreg, pdev);
+ if (ret) {
+ dev_err(dev, "failure in hi6421_dt_parse_common\n");
+ goto dt_parse_ldo_end1;
+ }
+
+dt_parse_buck012_end:
+ return ret;
+}
+
+static struct regulator_ops hi6421_rops_ldo = {
+#if 0 /* ref from v3.0.8 */
+ .is_enabled = hi6421_regulator_is_enabled,
+ .enable = hi6421_regulator_enable,
+ .disable = hi6421_regulator_disable,
+ .list_voltage = hi6421_regulator_list_voltage,
+ .get_voltage = hi6421_regulator_get_voltage,
+ .set_voltage = hi6421_regulator_set_voltage,
+ .get_mode = hi6421_regulator_get_mode,
+ .set_mode = hi6421_regulator_set_mode,
+ .get_optimum_mode = hi6421_regulator_get_optimum_mode,
+#endif
+/*
+ .set_voltage_sel = anatop_regmap_set_voltage_sel,
+ .get_voltage_sel = anatop_regmap_get_voltage_sel,
+ .list_voltage = regulator_list_voltage_linear,
+ .map_voltage = regulator_map_voltage_linear,
+*/
+};
+
+
+
+static const struct hi6421_regulator hi6421_regulator_ldo = {
+/* .base = offset,
+ .min_mV = min_mVolts,
+ .max_mV = max_mVolts,
+ */
+ .rdesc = {
+/* .name = #label, \
+ .id = TWL6030_REG_##label, \
+ .n_voltages = 32, \
+ */
+ .ops = &hi6421_rops_ldo,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .dt_parse = hi6421_dt_parse_ldo,
+};
+
+static const struct hi6421_regulator hi6421_regulator_buck012 = {
+/* .base = offset,
+ .min_mV = min_mVolts,
+ .max_mV = max_mVolts,
+ */
+ .rdesc = {
+/* .name = #label, \
+ .id = TWL6030_REG_##label, \
+ .n_voltages = 32, \
+ */
+ .ops = &hi6421_rops_ldo,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .dt_parse = hi6421_dt_parse_buck012,
+};
+
+static const struct hi6421_regulator hi6421_regulator_buck345 = {
+/* .base = offset,
+ .min_mV = min_mVolts,
+ .max_mV = max_mVolts,
+ */
+ .rdesc = {
+/* .name = #label, \
+ .id = TWL6030_REG_##label, \
+ .n_voltages = 32, \
+ */
+ .ops = &hi6421_rops_ldo,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .dt_parse = hi6421_dt_parse_ldo,
+};
+
+static struct of_device_id of_hi6421_regulator_match_tbl[] = {
+ {
+ .compatible = "hisilicon,hi6421-ldo",
+ .data = &hi6421_regulator_ldo,
+ },
+ {
+ .compatible = "hisilicon,hi6421-buck012",
+ .data = &hi6421_regulator_buck012,
+ },
+ {
+ .compatible = "hisilicon,hi6421-buck345",
+ .data = &hi6421_regulator_buck345,
+ },
+ { /* end */ }
+};
+
+static int hi6421_regulator_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct device_node *hi6421_np;
+ struct regulator_desc *rdesc;
+ struct regulator_dev *rdev;
+ struct hi6421_regulator *sreg = NULL;
+ struct regulator_init_data *initdata;
+ struct regulator_config config = { };
+ const struct of_device_id *match;
+ const struct hi6421_regulator *template;
+ unsigned int register_info[3];
+ int ret = 0;
+
+ /* to check which type of regulator this is */
+ match = of_match_device(of_hi6421_regulator_match_tbl, &pdev->dev);
+ if (match) {
+ template = match->data;
+/* id = template->desc.id; */
+/* initdata = of_get_regulator_init_data(dev, np); */
+ printk("regulator: hi6421 match found!\n");
+ } else {
+ printk("regulator: hi6421 ERROR!\n");
+ }
+
+ initdata = of_get_regulator_init_data(dev, np);
+ sreg = kmemdup(template, sizeof (*sreg), GFP_KERNEL);
+ if (!sreg)
+ return -ENOMEM;
+
+/* initdata is already in regulator_config */
+/* sreg->initdata = initdata; */
+
+ sreg->name = initdata->constraints.name;
+ rdesc = &sreg->rdesc;
+ rdesc->name = initdata->constraints.name;
+
+ /* not needed any more. coming from template. */
+/* rdesc->ops = &hi6421_rops_ldo;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->owner = THIS_MODULE;
+ */
+
+
+ /* to parse device tree data for regulator specific */
+ ret = sreg->dt_parse(sreg, pdev);
+ if (ret) {
+ dev_err(dev, "device tree parameter parse error!\n");
+ goto hi6421_probe_end;
+ }
+
+#if 0
+ anatop_np = of_get_parent(np);
+ if (!anatop_np)
+ return -ENODEV;
+ sreg->anatop = syscon_node_to_regmap(anatop_np);
+ of_node_put(anatop_np);
+ if (IS_ERR(sreg->anatop))
+ return PTR_ERR(sreg->anatop);
+#endif
+
+ config.dev = &pdev->dev;
+ config.init_data = initdata;
+ config.driver_data = sreg;
+ config.of_node = pdev->dev.of_node;
+
+/* config.regmap = sreg->anatop; */ /* ?? */
+
+ /* register regulator */
+ rdev = regulator_register(rdesc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "failed to register %s\n",
+ rdesc->name);
+ ret = PTR_ERR(rdev);
+ goto hi6421_probe_end;
+ }
+
+ platform_set_drvdata(pdev, rdev);
+
+hi6421_probe_end:
+ if (sreg)
+ kfree(sreg);
+ return ret;
+}
+
+static int hi6421_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+ struct hi6421_regulator *sreg = rdev_get_drvdata(rdev);
+
+ regulator_unregister(rdev);
+
+ /* TODO: should i worry about that? devm_kzalloc */
+ if (sreg->rdesc->volt_table)
+ devm_kfree(pdev->dev, sreg->rdesc->volt_table);
+
+ kfree(sreg);
+ return 0;
+}
+
+static struct platform_driver hi6421_regulator_driver = {
+ .driver = {
+ .name = "hi6421_regulator",
+ .owner = THIS_MODULE,
+ .of_match_table = of_hi6421_regulator_match_tbl,
+ },
+ .probe = hi6421_regulator_probe,
+ .remove = hi6421_regulator_remove,
+};
+
+static int __init hi6421_regulator_init(void)
+{
+ return platform_driver_register(&hi6421_regulator_driver);
+}
+postcore_initcall(hi6421_regulator_init);
+
+static void __exit hi6421_regulator_exit(void)
+{
+ platform_driver_unregister(&hi6421_regulator_driver);
+}
+module_exit(hi6421_regulator_exit);
+
+MODULE_AUTHOR("Guodong Xu <guodong.xu@linaro.org>");
+MODULE_DESCRIPTION("Hi6421 regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 66ca769287ab..3ba7dc6b96ee 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -32,6 +32,9 @@ static void of_get_regulation_constraints(struct device_node *np,
if (max_uV)
constraints->max_uV = be32_to_cpu(*max_uV);
+ printk("regulator: name=%s,min/max=%d/%d\n", constraints->name,\
+ constraints->min_uV, constraints->max_uV);
+
/* Voltage change possible? */
if (constraints->min_uV != constraints->max_uV)
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;