public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator
@ 2015-08-04  5:32 Peng Fan
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 1/6] power: pfuze100 correct SWBST macro definition Peng Fan
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Peng Fan @ 2015-08-04  5:32 UTC (permalink / raw)
  To: u-boot

This patch set is to support driver model for pfuze100 and implement
regulator driver for pfuze100. Patches has been tested on i.MX7D
validation board.

Here registeres for standby mode are not touched, all operation read/write
register are for NORMAL state. For example, to pfuze100,
sw1volt is for controlling voltage for normal state, sw1stdby is for
controlling voltage for standby state. The driver only read/write sw1volt,
but not touch sw1stdby. This will be done later, since I do not come up
with a good idea to operate sw1stdby.

This pfuze driver model part and regulator driver use max77686 driver
as a reference.

Changes v2:
 Addressed comments from Simon and Przemyslaw. Detailed changelog see
 each patch.

Peng Fan (6):
  power: pfuze100 correct SWBST macro definition
  power: regulator use node name when no regulator-name
  power: regulator: update comments for regulator-name
  power: pmic: pfuze100 support driver model
  power: regulator: add pfuze100 support
  fsl: common: pfuze: no use original pfuze code if DM_PMIC

 board/freescale/common/pfuze.c                   |   2 +
 doc/device-tree-bindings/regulator/regulator.txt |  19 +-
 drivers/power/pmic/Kconfig                       |   7 +
 drivers/power/pmic/Makefile                      |   2 +-
 drivers/power/pmic/pfuze100.c                    | 121 +++++
 drivers/power/pmic/pmic_pfuze100.c               |  32 --
 drivers/power/regulator/Kconfig                  |   8 +
 drivers/power/regulator/Makefile                 |   1 +
 drivers/power/regulator/pfuze100.c               | 554 +++++++++++++++++++++++
 drivers/power/regulator/regulator-uclass.c       |   4 +-
 include/power/pfuze100_pmic.h                    |  33 +-
 include/power/regulator.h                        |   8 +-
 12 files changed, 737 insertions(+), 54 deletions(-)
 create mode 100644 drivers/power/pmic/pfuze100.c
 delete mode 100644 drivers/power/pmic/pmic_pfuze100.c
 create mode 100644 drivers/power/regulator/pfuze100.c

-- 
1.8.4

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 1/6] power: pfuze100 correct SWBST macro definition
  2015-08-04  5:32 [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator Peng Fan
@ 2015-08-04  5:32 ` Peng Fan
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 2/6] power: regulator use node name when no regulator-name Peng Fan
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Peng Fan @ 2015-08-04  5:32 UTC (permalink / raw)
  To: u-boot

According to datasheet, SWBST_MODE starts from bit 2 and it occupies 2 bits.
So SWBST_MODE_MASK should be 0xC, and SWBST_MODE_xx should be ([mode] << 2).

Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Cc: Przemyslaw Marczak <p.marczak@samsung.com>
Cc: Stefano Babic <sbabic@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes v2:
 None

 include/power/pfuze100_pmic.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
index 57b9ca9..cb10605 100644
--- a/include/power/pfuze100_pmic.h
+++ b/include/power/pfuze100_pmic.h
@@ -193,11 +193,11 @@ enum {
 #define SWBST_5_15V	3
 
 #define SWBST_VOL_MASK	0x3
-#define SWBST_MODE_MASK	0x6
-#define SWBST_MODE_OFF	(2 << 0)
-#define SWBST_MODE_PFM	(2 << 1)
+#define SWBST_MODE_MASK	0xC
+#define SWBST_MODE_OFF	(0 << 2)
+#define SWBST_MODE_PFM	(1 << 2)
 #define SWBST_MODE_AUTO	(2 << 2)
-#define SWBST_MODE_APS	(2 << 3)
+#define SWBST_MODE_APS	(3 << 2)
 
 /*
  * Regulator Mode Control
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 2/6] power: regulator use node name when no regulator-name
  2015-08-04  5:32 [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator Peng Fan
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 1/6] power: pfuze100 correct SWBST macro definition Peng Fan
@ 2015-08-04  5:32 ` Peng Fan
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 3/6] power: regulator: update comments for regulator-name Peng Fan
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Peng Fan @ 2015-08-04  5:32 UTC (permalink / raw)
  To: u-boot

If there is no property named 'regulator-name' for regulators,
choose node name instead, but not directly return failure value.

Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Cc: Przemyslaw Marczak <p.marczak@samsung.com>
Cc: Simon Glass <sjg@chromium.org>
---

Changes v2:
 none. The comments update patch, see 3/6.

 drivers/power/regulator/regulator-uclass.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c
index 12e141b..d4f06d5 100644
--- a/drivers/power/regulator/regulator-uclass.c
+++ b/drivers/power/regulator/regulator-uclass.c
@@ -256,7 +256,9 @@ static int regulator_post_bind(struct udevice *dev)
 	if (!uc_pdata->name) {
 		debug("%s: dev: %s has no property 'regulator-name'\n",
 		      __func__, dev->name);
-		return -EINVAL;
+		uc_pdata->name = fdt_get_name(blob, offset, NULL);
+		if (!uc_pdata->name)
+			return -EINVAL;
 	}
 
 	if (regulator_name_is_unique(dev, uc_pdata->name))
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 3/6] power: regulator: update comments for regulator-name
  2015-08-04  5:32 [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator Peng Fan
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 1/6] power: pfuze100 correct SWBST macro definition Peng Fan
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 2/6] power: regulator use node name when no regulator-name Peng Fan
@ 2015-08-04  5:32 ` Peng Fan
  2015-08-04 13:10   ` Przemyslaw Marczak
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 4/6] power: pmic: pfuze100 support driver model Peng Fan
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Peng Fan @ 2015-08-04  5:32 UTC (permalink / raw)
  To: u-boot

We do not need that "regulator-name" property must be provided in dts.
If "regulator-name" property is not provided in dts, node name
will chosen for settings '.name' field of uc_pdata.

Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Cc: Przemyslaw Marczak <p.marczak@samsung.com>
Cc: Simon Glass <sjg@chromium.org>
---

Changes v2:
 New patch. Update comments for regulator-name property.

 doc/device-tree-bindings/regulator/regulator.txt | 19 ++++++++-----------
 include/power/regulator.h                        |  8 +++++---
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/doc/device-tree-bindings/regulator/regulator.txt b/doc/device-tree-bindings/regulator/regulator.txt
index 68b02a8..2cf4b9d 100644
--- a/doc/device-tree-bindings/regulator/regulator.txt
+++ b/doc/device-tree-bindings/regulator/regulator.txt
@@ -15,15 +15,8 @@ For the node name e.g.: "prefix[:alpha:]num { ... }":
 
 Example the prefix "ldo" will pass for: "ldo1", "ldo at 1", "LDO1", "LDOREG at 1"...
 
-Required properties:
-- regulator-name: a string, required by the regulator uclass
-
-Note
-The "regulator-name" constraint is used for setting the device's uclass
-platform data '.name' field. And the regulator device name is set from
-it's node name.
-
 Optional properties:
+- regulator-name: a string, required by the regulator uclass
 - regulator-min-microvolt: a minimum allowed Voltage value
 - regulator-max-microvolt: a maximum allowed Voltage value
 - regulator-min-microamp: a minimum allowed Current value
@@ -31,6 +24,12 @@ Optional properties:
 - regulator-always-on: regulator should never be disabled
 - regulator-boot-on: enabled by bootloader/firmware
 
+Note
+The "regulator-name" constraint is used for setting the device's uclass
+platform data '.name' field. And the regulator device name is set from
+it's node name. If "regulator-name" is not provided in dts, node name
+is chosen for setting the device's uclass platform data '.name' field.
+
 Other kernel-style properties, are currently not used.
 
 Note:
@@ -41,10 +40,8 @@ For the regulator autoset from constraints, the framework expects that:
 
 Example:
 ldo0 {
-	/* Mandatory */
-	regulator-name = "VDDQ_EMMC_1.8V";
-
 	/* Optional */
+	regulator-name = "VDDQ_EMMC_1.8V";
 	regulator-min-microvolt = <1800000>;
 	regulator-max-microvolt = <1800000>;
 	regulator-min-microamp = <100000>;
diff --git a/include/power/regulator.h b/include/power/regulator.h
index 0152290..2198664 100644
--- a/include/power/regulator.h
+++ b/include/power/regulator.h
@@ -34,7 +34,7 @@
  * regulator constraints, like in the example below:
  *
  * ldo1 {
- *      regulator-name = "VDD_MMC_1.8V";     (must be unique for proper bind)
+ *      regulator-name = "VDD_MMC_1.8V";     (optional)
  *      regulator-min-microvolt = <1000000>; (optional)
  *      regulator-max-microvolt = <1000000>; (optional)
  *      regulator-min-microamp = <1000>;     (optional)
@@ -44,8 +44,10 @@
  * };
  *
  * Note: For the proper operation, at least name constraint is needed, since
- * it can be used when calling regulator_get_by_platname(). And the mandatory
- * rule for this name is, that it must be globally unique for the single dts.
+ * it can be used when calling regulator_get_by_platname(). If regulator-name
+ * property is not provided, node name will be chosen for platname. And the
+ * mandatory rule for this name is, that it must be globally unique for the
+ * single dts.
  *
  * Regulator bind:
  * For each regulator device, the device_bind() should be called with passed
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 4/6] power: pmic: pfuze100 support driver model
  2015-08-04  5:32 [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator Peng Fan
                   ` (2 preceding siblings ...)
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 3/6] power: regulator: update comments for regulator-name Peng Fan
@ 2015-08-04  5:32 ` Peng Fan
  2015-08-04 13:10   ` Przemyslaw Marczak
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support Peng Fan
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 6/6] fsl: common: pfuze: no use original pfuze code if DM_PMIC Peng Fan
  5 siblings, 1 reply; 14+ messages in thread
From: Peng Fan @ 2015-08-04  5:32 UTC (permalink / raw)
  To: u-boot

1. Support driver model for pfuze100.
2. Introduce a new Kconfig entry DM_PMIC_PFUZE100 for pfuze100
3. This driver intends to support PF100, PF200 and PF3000, so add
   the device id into the udevice_id array.
4. Rename PMIC_NUM_OF_REGS macro to PFUZE100_NUM_OF_REGS.
5. Rename file name from pmic_pfuze100.c to pfuze100.c to follow new
   new convention of file naming.

Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Cc: Przemyslaw Marczak <p.marczak@samsung.com>
Cc: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes v2:
 Addressed Przemyslaw's comments:
  Rename PMIC_NUM_OF_REGS to PFUZE100_NUM_OF_REGS
  Sort variables' order
  Define PFUZE100_REGULATOR_DRIVER for "pfuze100_regulator" in header file.

 drivers/power/pmic/Makefile        |   2 +-
 drivers/power/pmic/Kconfig         |   7 +++
 drivers/power/pmic/pfuze100.c      | 121 +++++++++++++++++++++++++++++++++++++
 drivers/power/pmic/pmic_pfuze100.c |  32 ----------
 include/power/pfuze100_pmic.h      |   7 ++-
 5 files changed, 135 insertions(+), 34 deletions(-)
 create mode 100644 drivers/power/pmic/pfuze100.c
 delete mode 100644 drivers/power/pmic/pmic_pfuze100.c

diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 8c1ce3d..6eb357e 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
 obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
 obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
 obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
-obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
+obj-$(CONFIG_POWER_PFUZE100) += pfuze100.o
 obj-$(CONFIG_POWER_TPS65090_I2C) += pmic_tps65090.o
 obj-$(CONFIG_POWER_TPS65090_EC) += pmic_tps65090_ec.o
 obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 164f421..0df91be 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -10,6 +10,13 @@ config DM_PMIC
 	- 'drivers/power/pmic/pmic-uclass.c'
 	- 'include/power/pmic.h'
 
+config DM_PMIC_PFUZE100
+	bool "Enable Driver Model for PMIC PFUZE100"
+	depends on DM_PMIC
+	---help---
+	This config enables implementation of driver-model pmic uclass features
+	for PMIC PFUZE100. The driver implements read/write operations.
+
 config DM_PMIC_MAX77686
 	bool "Enable Driver Model for PMIC MAX77686"
 	depends on DM_PMIC
diff --git a/drivers/power/pmic/pfuze100.c b/drivers/power/pmic/pfuze100.c
new file mode 100644
index 0000000..8b26806
--- /dev/null
+++ b/drivers/power/pmic/pfuze100.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2014 Gateworks Corporation
+ * Tim Harvey <tharvey@gateworks.com>
+ *
+ * Copyright (C) 2015 Freescale Semiconductor, Inc
+ * Peng Fan <Peng.Fan@freescale.com>
+ *
+ * SPDX-License-Identifier:      GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/pfuze100_pmic.h>
+
+#ifndef CONFIG_DM_PMIC
+int power_pfuze100_init(unsigned char bus)
+{
+	static const char name[] = "PFUZE100";
+	struct pmic *p = pmic_alloc();
+
+	if (!p) {
+		printf("%s: POWER allocation error!\n", __func__);
+		return -ENOMEM;
+	}
+
+	p->name = name;
+	p->interface = PMIC_I2C;
+	p->number_of_regs = PMIC_NUM_OF_REGS;
+	p->hw.i2c.addr = CONFIG_POWER_PFUZE100_I2C_ADDR;
+	p->hw.i2c.tx_num = 1;
+	p->bus = bus;
+
+	return 0;
+}
+#else
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+	/* sw[x], swbst */
+	{ .prefix = "s", .driver = PFUZE100_REGULATOR_DRIVER },
+	/* vgen[x], vsnvs, vcc, v33, vcc_sd */
+	{ .prefix = "v", .driver = PFUZE100_REGULATOR_DRIVER },
+	{ },
+};
+
+static int pfuze100_reg_count(struct udevice *dev)
+{
+	return PFUZE100_NUM_OF_REGS;
+}
+
+static int pfuze100_write(struct udevice *dev, uint reg, const uint8_t *buff,
+			  int len)
+{
+	if (dm_i2c_write(dev, reg, buff, len)) {
+		error("write error to device: %p register: %#x!", dev, reg);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+	if (dm_i2c_read(dev, reg, buff, len)) {
+		error("read error from device: %p register: %#x!", dev, reg);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int pfuze100_bind(struct udevice *dev)
+{
+	int children;
+	int regulators_node;
+	const void *blob = gd->fdt_blob;
+
+	regulators_node = fdt_subnode_offset(blob, dev->of_offset,
+					     "regulators");
+	if (regulators_node <= 0) {
+		debug("%s: %s regulators subnode not found!", __func__,
+		      dev->name);
+		return -ENXIO;
+	}
+
+	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+	if (!children)
+		debug("%s: %s - no child found\n", __func__, dev->name);
+
+	/* Always return success for this device */
+	return 0;
+}
+
+static struct dm_pmic_ops pfuze100_ops = {
+	.reg_count = pfuze100_reg_count,
+	.read = pfuze100_read,
+	.write = pfuze100_write,
+};
+
+static const struct udevice_id pfuze100_ids[] = {
+	{ .compatible = "fsl,pfuze100", .data = (long)PFUZE100, },
+	{ .compatible = "fsl,pfuze200", .data = (long)PFUZE200, },
+	{ .compatible = "fsl,pfuze3000", .data = (long)PFUZE3000, },
+	{ }
+};
+
+U_BOOT_DRIVER(pmic_pfuze100) = {
+	.name = "pfuze100 pmic",
+	.id = UCLASS_PMIC,
+	.of_match = pfuze100_ids,
+	.bind = pfuze100_bind,
+	.ops = &pfuze100_ops,
+};
+#endif
diff --git a/drivers/power/pmic/pmic_pfuze100.c b/drivers/power/pmic/pmic_pfuze100.c
deleted file mode 100644
index 22a04c0..0000000
--- a/drivers/power/pmic/pmic_pfuze100.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2014 Gateworks Corporation
- * Tim Harvey <tharvey@gateworks.com>
- *
- * SPDX-License-Identifier:      GPL-2.0+
- */
-
-#include <common.h>
-#include <errno.h>
-#include <i2c.h>
-#include <power/pmic.h>
-#include <power/pfuze100_pmic.h>
-
-int power_pfuze100_init(unsigned char bus)
-{
-	static const char name[] = "PFUZE100";
-	struct pmic *p = pmic_alloc();
-
-	if (!p) {
-		printf("%s: POWER allocation error!\n", __func__);
-		return -ENOMEM;
-	}
-
-	p->name = name;
-	p->interface = PMIC_I2C;
-	p->number_of_regs = PMIC_NUM_OF_REGS;
-	p->hw.i2c.addr = CONFIG_POWER_PFUZE100_I2C_ADDR;
-	p->hw.i2c.tx_num = 1;
-	p->bus = bus;
-
-	return 0;
-}
diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
index cb10605..c40a976 100644
--- a/include/power/pfuze100_pmic.h
+++ b/include/power/pfuze100_pmic.h
@@ -8,6 +8,11 @@
 #ifndef __PFUZE100_PMIC_H_
 #define __PFUZE100_PMIC_H_
 
+/* Device ID */
+enum {PFUZE100 = 0x10, PFUZE200 = 0x11, PFUZE3000 = 0x30};
+
+#define PFUZE100_REGULATOR_DRIVER	"pfuze100_regulator"
+
 /* PFUZE100 registers */
 enum {
 	PFUZE100_DEVICEID	= 0x00,
@@ -54,7 +59,7 @@ enum {
 	PFUZE100_VGEN5VOL	= 0x70,
 	PFUZE100_VGEN6VOL	= 0x71,
 
-	PMIC_NUM_OF_REGS	= 0x7f,
+	PFUZE100_NUM_OF_REGS	= 0x7f,
 };
 
 /*
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support
  2015-08-04  5:32 [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator Peng Fan
                   ` (3 preceding siblings ...)
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 4/6] power: pmic: pfuze100 support driver model Peng Fan
@ 2015-08-04  5:32 ` Peng Fan
  2015-08-04 13:10   ` Przemyslaw Marczak
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 6/6] fsl: common: pfuze: no use original pfuze code if DM_PMIC Peng Fan
  5 siblings, 1 reply; 14+ messages in thread
From: Peng Fan @ 2015-08-04  5:32 UTC (permalink / raw)
  To: u-boot

1. Add new regulator driver pfuze100.
   * Introduce struct pfuze100_regulator_desc for mataining info for regulator.
2. Add new Kconfig entry DM_REGULATOR_PFUZE100 for pfuze100.
3. This driver intends to support PF100, PF200 and PF3000.
4. Add related macro definition in pfuze header file.

Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Cc: Przemyslaw Marczak <p.marczak@samsung.com>
Cc: Simon Glass <sjg@chromium.org>
---

Changes v2:
 Addressed Simon's comments.
 1. Use pmic_reg_read/pmic_reg_write/pmic_clrsetbits
 2. blank line between declarations and rest

Hi Simon,

 type case is still kept there:
 " struct pfuze100_regulator_desc *desc =
   *(struct pfuze100_regulator_desc **)dev_get_platdata(dev); "
 Also use pointer points to pointer type, "struct type **", see this line:
 " .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc **), "

 Each regulator has its own pfuze_regulator_desc, single pointer can not do
 the work well. For example:
 .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc *);

 struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);

 desc = se_desc(pfuze100_regulators, ARRAY_SIZE(pfuze100_regulators),
		dev->name);
 what we changed here is only local variable desc, but not change the pointer
 platdata. What I need here to set the pointer platdata to point to
 correct regulator descriptor. Single pointer can not handle this, so
 use "struct type **".


 drivers/power/regulator/Kconfig    |   8 +
 drivers/power/regulator/Makefile   |   1 +
 drivers/power/regulator/pfuze100.c | 554 +++++++++++++++++++++++++++++++++++++
 include/power/pfuze100_pmic.h      |  24 +-
 4 files changed, 583 insertions(+), 4 deletions(-)
 create mode 100644 drivers/power/regulator/pfuze100.c

diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 6289b83..b854773 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -16,6 +16,14 @@ config DM_REGULATOR
 	for this purpose if PMIC I/O driver is implemented or dm_scan_fdt_node()
 	otherwise. Detailed information can be found in the header file.
 
+config DM_REGULATOR_PFUZE100
+	bool "Enable Driver Model for REGULATOR PFUZE100"
+	depends on DM_REGULATOR && DM_PMIC_PFUZE100
+	---help---
+	This config enables implementation of driver-model regulator uclass
+	features for REGULATOR PFUZE100. The driver implements get/set api for:
+	value, enable and mode.
+
 config DM_REGULATOR_MAX77686
 	bool "Enable Driver Model for REGULATOR MAX77686"
 	depends on DM_REGULATOR && DM_PMIC_MAX77686
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 96aa624..9f8f17b 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -7,5 +7,6 @@
 
 obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
 obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
+obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
 obj-$(CONFIG_DM_REGULATOR_FIXED) += fixed.o
 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
diff --git a/drivers/power/regulator/pfuze100.c b/drivers/power/regulator/pfuze100.c
new file mode 100644
index 0000000..300aee8
--- /dev/null
+++ b/drivers/power/regulator/pfuze100.c
@@ -0,0 +1,554 @@
+#include <common.h>
+#include <fdtdec.h>
+#include <errno.h>
+#include <dm.h>
+#include <i2c.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+#include <power/pfuze100_pmic.h>
+
+/**
+ * struct pfuze100_regulator_desc - regulator descriptor
+ *
+ * @name: Identify name for the regulator.
+ * @type: Indicates the regulator type.
+ * @uV_step: Voltage increase for each selector.
+ * @vsel_reg: Register for adjust regulator voltage for normal.
+ * @vsel_mask: Mask bit for setting regulator voltage for normal.
+ * @stby_reg: Register for adjust regulator voltage for standby.
+ * @stby_mask: Mask bit for setting regulator voltage for standby.
+ * @volt_table: Voltage mapping table (if table based mapping).
+ * @voltage: Current voltage for REGULATOR_TYPE_FIXED type regulator.
+ */
+struct pfuze100_regulator_desc {
+	char *name;
+	enum regulator_type type;
+	unsigned int uV_step;
+	unsigned int vsel_reg;
+	unsigned int vsel_mask;
+	unsigned int stby_reg;
+	unsigned int stby_mask;
+	unsigned int *volt_table;
+	unsigned int voltage;
+};
+
+#define PFUZE100_FIXED_REG(_name, base, vol)				\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_FIXED,		\
+		.voltage	=	(vol),				\
+	}
+
+#define PFUZE100_SW_REG(_name, base, step)				\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_BUCK,		\
+		.uV_step	=	(step),				\
+		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
+		.vsel_mask	=	0x3F,				\
+		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
+		.stby_mask	=	0x3F,				\
+	}
+
+#define PFUZE100_SWB_REG(_name, base, mask, step, voltages)		\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_BUCK,		\
+		.uV_step	=	(step),				\
+		.vsel_reg	=	(base),				\
+		.vsel_mask	=	(mask),				\
+		.volt_table	=	(voltages),			\
+	}
+
+#define PFUZE100_SNVS_REG(_name, base, mask, voltages)			\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_OTHER,		\
+		.vsel_reg	=	(base),				\
+		.vsel_mask	=	(mask),				\
+		.volt_table	=	(voltages),			\
+	}
+
+#define PFUZE100_VGEN_REG(_name, base, step)				\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_LDO,		\
+		.uV_step	=	(step),				\
+		.vsel_reg	=	(base),				\
+		.vsel_mask	=	0xF,				\
+		.stby_reg	=	(base),				\
+		.stby_mask	=	0x20,				\
+	}
+
+#define PFUZE3000_VCC_REG(_name, base, step)				\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_LDO,		\
+		.uV_step	=	(step),				\
+		.vsel_reg	=	(base),				\
+		.vsel_mask	=	0x3,				\
+		.stby_reg	=	(base),				\
+		.stby_mask	=	0x20,				\
+}
+
+#define PFUZE3000_SW1_REG(_name, base, step)				\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_BUCK,		\
+		.uV_step	=	(step),				\
+		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
+		.vsel_mask	=	0x1F,				\
+		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
+		.stby_mask	=	0x1F,				\
+	}
+
+#define PFUZE3000_SW2_REG(_name, base, step)				\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_BUCK,		\
+		.uV_step	=	(step),				\
+		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
+		.vsel_mask	=	0x7,				\
+		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
+		.stby_mask	=	0x7,				\
+	}
+
+#define PFUZE3000_SW3_REG(_name, base, step)				\
+	{								\
+		.name		=	#_name,				\
+		.type		=	REGULATOR_TYPE_BUCK,		\
+		.uV_step	=	(step),				\
+		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
+		.vsel_mask	=	0xF,				\
+		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
+		.stby_mask	=	0xF,				\
+	}
+
+static unsigned int pfuze100_swbst[] = {
+	5000000, 5050000, 5100000, 5150000
+};
+
+static unsigned int pfuze100_vsnvs[] = {
+	1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, -1
+};
+
+static unsigned int pfuze3000_vsnvs[] = {
+	-1, -1, -1, -1, -1, -1, 3000000, -1
+};
+
+static unsigned int pfuze3000_sw2lo[] = {
+	1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000
+};
+
+/* PFUZE100 */
+static struct pfuze100_regulator_desc pfuze100_regulators[] = {
+	PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
+	PFUZE100_SW_REG(sw1c, PFUZE100_SW1CVOL, 25000),
+	PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
+	PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
+	PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
+	PFUZE100_SW_REG(sw4, PFUZE100_SW4VOL, 25000),
+	PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
+	PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
+	PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
+	PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
+	PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
+	PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
+	PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
+	PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
+	PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
+};
+
+/* PFUZE200 */
+static struct pfuze100_regulator_desc pfuze200_regulators[] = {
+	PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
+	PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
+	PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
+	PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
+	PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
+	PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
+	PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
+	PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
+	PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
+	PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
+	PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
+	PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
+	PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
+};
+
+/* PFUZE3000 */
+static struct pfuze100_regulator_desc pfuze3000_regulators[] = {
+	PFUZE3000_SW1_REG(sw1a, PFUZE100_SW1ABVOL, 25000),
+	PFUZE3000_SW1_REG(sw1b, PFUZE100_SW1CVOL, 25000),
+	PFUZE100_SWB_REG(sw2, PFUZE100_SW2VOL, 0x7, 50000, pfuze3000_sw2lo),
+	PFUZE3000_SW3_REG(sw3, PFUZE100_SW3AVOL, 50000),
+	PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
+	PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze3000_vsnvs),
+	PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
+	PFUZE100_VGEN_REG(vldo1, PFUZE100_VGEN1VOL, 100000),
+	PFUZE100_VGEN_REG(vldo2, PFUZE100_VGEN2VOL, 50000),
+	PFUZE3000_VCC_REG(vccsd, PFUZE100_VGEN3VOL, 150000),
+	PFUZE3000_VCC_REG(v33, PFUZE100_VGEN4VOL, 150000),
+	PFUZE100_VGEN_REG(vldo3, PFUZE100_VGEN5VOL, 100000),
+	PFUZE100_VGEN_REG(vldo4, PFUZE100_VGEN6VOL, 100000),
+};
+
+#define MODE(_id, _val, _name) { \
+	.id = _id, \
+	.register_value = _val, \
+	.name = _name, \
+}
+
+/* SWx Buck regulator mode */
+static struct dm_regulator_mode pfuze_sw_modes[] = {
+	MODE(OFF_OFF, OFF_OFF, "OFF_OFF"),
+	MODE(PWM_OFF, PWM_OFF, "PWM_OFF"),
+	MODE(PFM_OFF, PFM_OFF, "PFM_OFF"),
+	MODE(APS_OFF, APS_OFF, "APS_OFF"),
+	MODE(PWM_PWM, PWM_PWM, "PWM_PWM"),
+	MODE(PWM_APS, PWM_APS, "PWM_APS"),
+	MODE(APS_APS, APS_APS, "APS_APS"),
+	MODE(APS_PFM, APS_PFM, "APS_PFM"),
+	MODE(PWM_PFM, PWM_PFM, "PWM_PFM"),
+};
+
+/* Boost Buck regulator mode for normal operation */
+static struct dm_regulator_mode pfuze_swbst_modes[] = {
+	MODE(SWBST_MODE_OFF, SWBST_MODE_OFF , "SWBST_MODE_OFF"),
+	MODE(SWBST_MODE_PFM, SWBST_MODE_PFM, "SWBST_MODE_PFM"),
+	MODE(SWBST_MODE_AUTO, SWBST_MODE_AUTO, "SWBST_MODE_AUTO"),
+	MODE(SWBST_MODE_APS, SWBST_MODE_APS, "SWBST_MODE_APS"),
+};
+
+/* VGENx LDO regulator mode for normal operation */
+static struct dm_regulator_mode pfuze_ldo_modes[] = {
+	MODE(LDO_MODE_OFF, LDO_MODE_OFF, "LDO_MODE_OFF"),
+	MODE(LDO_MODE_ON, LDO_MODE_ON, "LDO_MODE_ON"),
+};
+
+static struct pfuze100_regulator_desc *se_desc(struct pfuze100_regulator_desc *desc,
+					       int size,
+					       const char *name)
+{
+	int i;
+
+	for (i = 0; i < size; desc++) {
+		if (!strcmp(desc->name, name))
+			return desc;
+		continue;
+	}
+
+	return NULL;
+}
+
+static int pfuze100_regulator_probe(struct udevice *dev)
+{
+	struct dm_regulator_uclass_platdata *uc_pdata;
+	struct pfuze100_regulator_desc **desc = dev_get_platdata(dev);
+
+	switch (dev_get_driver_data(dev_get_parent(dev))) {
+	case PFUZE100:
+		*desc = se_desc(pfuze100_regulators,
+				ARRAY_SIZE(pfuze100_regulators),
+				dev->name);
+		break;
+	case PFUZE200:
+		*desc = se_desc(pfuze200_regulators,
+				ARRAY_SIZE(pfuze200_regulators),
+				dev->name);
+		break;
+	case PFUZE3000:
+		*desc = se_desc(pfuze3000_regulators,
+				ARRAY_SIZE(pfuze3000_regulators),
+				dev->name);
+		break;
+	}
+	if (!*desc) {
+		debug("Do not support regulator %s\n", dev->name);
+		return -EINVAL;
+	}
+
+	uc_pdata = dev_get_uclass_platdata(dev);
+
+	uc_pdata->type = (*desc)->type;
+	if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
+		if (!strcmp(dev->name, "swbst")) {
+			uc_pdata->mode = pfuze_swbst_modes;
+			uc_pdata->mode_count = ARRAY_SIZE(pfuze_swbst_modes);
+		} else {
+			uc_pdata->mode = pfuze_sw_modes;
+			uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes);
+		}
+	} else if (uc_pdata->type == REGULATOR_TYPE_LDO) {
+		uc_pdata->mode = pfuze_ldo_modes;
+		uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes);
+	} else {
+		uc_pdata->mode = NULL;
+		uc_pdata->mode_count = 0;
+	}
+
+	return 0;
+}
+
+static int pfuze100_regulator_mode(struct udevice *dev, int op, int *opmode)
+{
+	unsigned char val;
+	struct pfuze100_regulator_desc *desc =
+		*(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
+
+	if (op == PMIC_OP_GET) {
+		if (desc->type == REGULATOR_TYPE_BUCK) {
+			if (!strcmp(dev->name, "swbst")) {
+				val = pmic_reg_read(dev->parent,
+						    desc->vsel_reg);
+				if (val < 0)
+					return val;
+
+				val &= SWBST_MODE_MASK;
+				val >>= SWBST_MODE_SHIFT;
+				*opmode = val;
+
+				return 0;
+			}
+			val = pmic_reg_read(dev->parent,
+					    desc->vsel_reg +
+					    PFUZE100_MODE_OFFSET);
+			if (val < 0)
+				return val;
+
+			val &= SW_MODE_MASK;
+			val >>= SW_MODE_SHIFT;
+			*opmode = val;
+
+			return 0;
+
+		} else if (desc->type == REGULATOR_TYPE_LDO) {
+			val = pmic_reg_read(dev->parent, desc->vsel_reg);
+			if (val < 0)
+				return val;
+
+			val &= LDO_MODE_MASK;
+			val >>= LDO_MODE_SHIFT;
+			*opmode = val;
+
+			return 0;
+		} else {
+			return -EINVAL;
+		}
+	}
+
+	if (desc->type == REGULATOR_TYPE_BUCK) {
+		if (!strcmp(dev->name, "swbst"))
+			return pmic_clrsetbits(dev->parent, desc->vsel_reg,
+					       SWBST_MODE_MASK,
+					       *opmode << SWBST_MODE_SHIFT);
+
+		val = pmic_clrsetbits(dev->parent,
+				       desc->vsel_reg + PFUZE100_MODE_OFFSET,
+				       SW_MODE_MASK,
+				       *opmode << SW_MODE_SHIFT);
+
+	} else if (desc->type == REGULATOR_TYPE_LDO) {
+		val = pmic_clrsetbits(dev->parent, desc->vsel_reg,
+				       LDO_MODE_MASK,
+				       *opmode << LDO_MODE_SHIFT);
+		return val;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int pfuze100_regulator_enable(struct udevice *dev, int op, bool *enable)
+{
+	unsigned char val;
+	int ret, on_off;
+	struct dm_regulator_uclass_platdata *uc_pdata =
+		dev_get_uclass_platdata(dev);
+
+	if (op == PMIC_OP_GET) {
+		if (!strcmp(dev->name, "vrefddr")) {
+			val = pmic_reg_read(dev->parent, PFUZE100_VREFDDRCON);
+			if (val < 0)
+				return val;
+
+			if (val & VREFDDRCON_EN)
+				*enable = true;
+			else
+				*enable = false;
+			return 0;
+		}
+		ret = pfuze100_regulator_mode(dev, op, &on_off);
+		if (ret)
+			return ret;
+		switch (on_off) {
+		/* OFF_OFF, SWBST_MODE_OFF, LDO_MODE_OFF have same value */
+		case OFF_OFF:
+			*enable = false;
+			break;
+		default:
+			*enable = true;
+			break;
+		}
+	} else if (op == PMIC_OP_SET) {
+		if (!strcmp(dev->name, "vrefddr")) {
+			val = pmic_reg_read(dev->parent, PFUZE100_VREFDDRCON);
+			if (val < 0)
+				return val;
+
+			if (val & VREFDDRCON_EN)
+				return 0;
+			val |= VREFDDRCON_EN;
+
+			return pmic_reg_write(dev->parent, PFUZE100_VREFDDRCON,
+					      val);
+		}
+
+		if (uc_pdata->type == REGULATOR_TYPE_LDO) {
+			on_off = *enable ? LDO_MODE_ON : LDO_MODE_OFF;
+		} else if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
+			if (!strcmp(dev->name, "swbst"))
+				on_off = *enable ? SWBST_MODE_AUTO :
+					SWBST_MODE_OFF;
+			else
+				on_off = *enable ? APS_PFM : OFF_OFF;
+		} else {
+			return -EINVAL;
+		}
+
+		return pfuze100_regulator_mode(dev, op, &on_off);
+	}
+
+	return 0;
+}
+
+static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV)
+{
+	unsigned char val;
+	int i;
+	struct pfuze100_regulator_desc *desc =
+		*(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
+	struct dm_regulator_uclass_platdata *uc_pdata =
+		dev_get_uclass_platdata(dev);
+
+	if (op == PMIC_OP_GET) {
+		*uV = 0;
+		if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
+			*uV = desc->voltage;
+		} else if (desc->volt_table) {
+			val = pmic_reg_read(dev->parent, desc->vsel_reg);
+			if (val < 0)
+				return val;
+			val &= desc->vsel_mask;
+			*uV = desc->volt_table[val];
+		} else {
+			if (uc_pdata->min_uV < 0) {
+				debug("Need to provide min_uV in dts.\n");
+				return -EINVAL;
+			}
+			val = pmic_reg_read(dev->parent, desc->vsel_reg);
+			if (val < 0)
+				return val;
+			val &= desc->vsel_mask;
+			*uV = uc_pdata->min_uV + (int)val * desc->uV_step;
+		}
+
+		return 0;
+	}
+
+	if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
+		debug("Set voltage for REGULATOR_TYPE_FIXED regulator\n");
+		return -EINVAL;
+	} else if (desc->volt_table) {
+		for (i = 0; i < desc->vsel_mask; i++) {
+			if (*uV == desc->volt_table[i])
+				break;
+		}
+		if (i == desc->vsel_mask) {
+			debug("Unsupported voltage %u\n", *uV);
+			return -EINVAL;
+		}
+
+		return pmic_clrsetbits(dev->parent, desc->vsel_reg,
+				       desc->vsel_mask, i);
+	} else {
+		if (uc_pdata->min_uV < 0) {
+			debug("Need to provide min_uV in dts.\n");
+			return -EINVAL;
+		}
+		return pmic_clrsetbits(dev->parent, desc->vsel_reg,
+				       desc->vsel_mask,
+				       (*uV - uc_pdata->min_uV) / desc->uV_step);
+	}
+
+	return 0;
+}
+
+static int pfuze100_regulator_get_value(struct udevice *dev)
+{
+	int uV;
+	int ret;
+
+	ret = pfuze100_regulator_val(dev, PMIC_OP_GET, &uV);
+	if (ret)
+		return ret;
+
+	return uV;
+}
+
+static int pfuze100_regulator_set_value(struct udevice *dev, int uV)
+{
+	return pfuze100_regulator_val(dev, PMIC_OP_SET, &uV);
+}
+
+static bool pfuze100_regulator_get_enable(struct udevice *dev)
+{
+	int ret;
+	bool enable = false;
+
+	ret = pfuze100_regulator_enable(dev, PMIC_OP_GET, &enable);
+	if (ret)
+		return ret;
+
+	return enable;
+}
+
+static int pfuze100_regulator_set_enable(struct udevice *dev, bool enable)
+{
+	return pfuze100_regulator_enable(dev, PMIC_OP_SET, &enable);
+}
+
+static int pfuze100_regulator_get_mode(struct udevice *dev)
+{
+	int mode;
+	int ret;
+
+	ret = pfuze100_regulator_mode(dev, PMIC_OP_GET, &mode);
+	if (ret)
+		return ret;
+
+	return mode;
+}
+
+static int pfuze100_regulator_set_mode(struct udevice *dev, int mode)
+{
+	return pfuze100_regulator_mode(dev, PMIC_OP_SET, &mode);
+}
+
+static const struct dm_regulator_ops pfuze100_regulator_ops = {
+	.get_value  = pfuze100_regulator_get_value,
+	.set_value  = pfuze100_regulator_set_value,
+	.get_enable = pfuze100_regulator_get_enable,
+	.set_enable = pfuze100_regulator_set_enable,
+	.get_mode   = pfuze100_regulator_get_mode,
+	.set_mode   = pfuze100_regulator_set_mode,
+};
+
+U_BOOT_DRIVER(pfuze100_regulator) = {
+	.name = "pfuze100_regulator",
+	.id = UCLASS_REGULATOR,
+	.ops = &pfuze100_regulator_ops,
+	.probe = pfuze100_regulator_probe,
+	.platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc **),
+};
diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
index c40a976..41cb710 100644
--- a/include/power/pfuze100_pmic.h
+++ b/include/power/pfuze100_pmic.h
@@ -62,6 +62,13 @@ enum {
 	PFUZE100_NUM_OF_REGS	= 0x7f,
 };
 
+/* Registor offset based on VOLT register */
+#define PFUZE100_VOL_OFFSET	0
+#define PFUZE100_STBY_OFFSET	1
+#define PFUZE100_OFF_OFFSET	2
+#define PFUZE100_MODE_OFFSET	3
+#define PFUZE100_CONF_OFFSET	4
+
 /*
  * Buck Regulators
  */
@@ -138,6 +145,9 @@ enum {
 #define SW1x_STBY_MASK    0x3f
 #define SW1x_OFF_MASK     0x3f
 
+#define SW_MODE_MASK	0xf
+#define SW_MODE_SHIFT	0
+
 #define SW1xCONF_DVSSPEED_MASK 0xc0
 #define SW1xCONF_DVSSPEED_2US  0x00
 #define SW1xCONF_DVSSPEED_4US  0x40
@@ -186,7 +196,12 @@ enum {
 
 #define LDO_VOL_MASK	0xf
 #define LDO_EN		(1 << 4)
+#define LDO_MODE_SHIFT	4
+#define LDO_MODE_MASK	(1 << 4)
+#define LDO_MODE_OFF	0
+#define LDO_MODE_ON	1
 
+#define VREFDDRCON_EN	(1 << 4)
 /*
  * Boost Regulator
  */
@@ -199,10 +214,11 @@ enum {
 
 #define SWBST_VOL_MASK	0x3
 #define SWBST_MODE_MASK	0xC
-#define SWBST_MODE_OFF	(0 << 2)
-#define SWBST_MODE_PFM	(1 << 2)
-#define SWBST_MODE_AUTO	(2 << 2)
-#define SWBST_MODE_APS	(3 << 2)
+#define SWBST_MODE_SHIFT 0x2
+#define SWBST_MODE_OFF	0
+#define SWBST_MODE_PFM	1
+#define SWBST_MODE_AUTO	2
+#define SWBST_MODE_APS	3
 
 /*
  * Regulator Mode Control
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 6/6] fsl: common: pfuze: no use original pfuze code if DM_PMIC
  2015-08-04  5:32 [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator Peng Fan
                   ` (4 preceding siblings ...)
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support Peng Fan
@ 2015-08-04  5:32 ` Peng Fan
  5 siblings, 0 replies; 14+ messages in thread
From: Peng Fan @ 2015-08-04  5:32 UTC (permalink / raw)
  To: u-boot

If enable DM PMIC and REGULATOR, we should not use original power
framework. So need to comment out the pfuze code for original power
framework, when CONFIG_DM_PMIC_PFUZE100 defined.

Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Cc: Przemyslaw Marczak <p.marczak@samsung.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Stefano Babic <sbabic@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---

Changes v2:
 None

 board/freescale/common/pfuze.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/board/freescale/common/pfuze.c b/board/freescale/common/pfuze.c
index d6a209e..783c46d 100644
--- a/board/freescale/common/pfuze.c
+++ b/board/freescale/common/pfuze.c
@@ -9,6 +9,7 @@
 #include <power/pmic.h>
 #include <power/pfuze100_pmic.h>
 
+#ifndef CONFIG_DM_PMIC_PFUZE100
 int pfuze_mode_init(struct pmic *p, u32 mode)
 {
 	unsigned char offset, i, switch_num;
@@ -90,3 +91,4 @@ struct pmic *pfuze_common_init(unsigned char i2cbus)
 
 	return p;
 }
+#endif
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 3/6] power: regulator: update comments for regulator-name
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 3/6] power: regulator: update comments for regulator-name Peng Fan
@ 2015-08-04 13:10   ` Przemyslaw Marczak
  2015-08-04 13:12     ` Peng Fan
  0 siblings, 1 reply; 14+ messages in thread
From: Przemyslaw Marczak @ 2015-08-04 13:10 UTC (permalink / raw)
  To: u-boot

Hello Peng,

On 08/04/2015 07:32 AM, Peng Fan wrote:
> We do not need that "regulator-name" property must be provided in dts.
> If "regulator-name" property is not provided in dts, node name
> will chosen for settings '.name' field of uc_pdata.
>
> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
> Cc: Przemyslaw Marczak <p.marczak@samsung.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>
> Changes v2:
>   New patch. Update comments for regulator-name property.
>
>   doc/device-tree-bindings/regulator/regulator.txt | 19 ++++++++-----------
>   include/power/regulator.h                        |  8 +++++---
>   2 files changed, 13 insertions(+), 14 deletions(-)
>
> diff --git a/doc/device-tree-bindings/regulator/regulator.txt b/doc/device-tree-bindings/regulator/regulator.txt
> index 68b02a8..2cf4b9d 100644
> --- a/doc/device-tree-bindings/regulator/regulator.txt
> +++ b/doc/device-tree-bindings/regulator/regulator.txt
> @@ -15,15 +15,8 @@ For the node name e.g.: "prefix[:alpha:]num { ... }":
>
>   Example the prefix "ldo" will pass for: "ldo1", "ldo at 1", "LDO1", "LDOREG at 1"...
>
> -Required properties:
> -- regulator-name: a string, required by the regulator uclass
> -
> -Note
> -The "regulator-name" constraint is used for setting the device's uclass
> -platform data '.name' field. And the regulator device name is set from
> -it's node name.
> -
>   Optional properties:
> +- regulator-name: a string, required by the regulator uclass
>   - regulator-min-microvolt: a minimum allowed Voltage value
>   - regulator-max-microvolt: a maximum allowed Voltage value
>   - regulator-min-microamp: a minimum allowed Current value
> @@ -31,6 +24,12 @@ Optional properties:
>   - regulator-always-on: regulator should never be disabled
>   - regulator-boot-on: enabled by bootloader/firmware
>
> +Note
> +The "regulator-name" constraint is used for setting the device's uclass
> +platform data '.name' field. And the regulator device name is set from
> +it's node name. If "regulator-name" is not provided in dts, node name
> +is chosen for setting the device's uclass platform data '.name' field.
> +
>   Other kernel-style properties, are currently not used.
>
>   Note:
> @@ -41,10 +40,8 @@ For the regulator autoset from constraints, the framework expects that:
>
>   Example:
>   ldo0 {
> -	/* Mandatory */
> -	regulator-name = "VDDQ_EMMC_1.8V";
> -
>   	/* Optional */
> +	regulator-name = "VDDQ_EMMC_1.8V";
>   	regulator-min-microvolt = <1800000>;
>   	regulator-max-microvolt = <1800000>;
>   	regulator-min-microamp = <100000>;
> diff --git a/include/power/regulator.h b/include/power/regulator.h
> index 0152290..2198664 100644
> --- a/include/power/regulator.h
> +++ b/include/power/regulator.h
> @@ -34,7 +34,7 @@
>    * regulator constraints, like in the example below:
>    *
>    * ldo1 {

When using node name, then it's automatically unique, otherwise not. So 
I would like to keep this information here.

> - *      regulator-name = "VDD_MMC_1.8V";     (must be unique for proper bind)
> + *      regulator-name = "VDD_MMC_1.8V";     (optional)
>    *      regulator-min-microvolt = <1000000>; (optional)
>    *      regulator-max-microvolt = <1000000>; (optional)
>    *      regulator-min-microamp = <1000>;     (optional)
> @@ -44,8 +44,10 @@
>    * };
>    *
>    * Note: For the proper operation, at least name constraint is needed, since
> - * it can be used when calling regulator_get_by_platname(). And the mandatory
> - * rule for this name is, that it must be globally unique for the single dts.
> + * it can be used when calling regulator_get_by_platname(). If regulator-name
> + * property is not provided, node name will be chosen for platname. And the
> + * mandatory rule for this name is, that it must be globally unique for the
> + * single dts.
>    *
>    * Regulator bind:
>    * For each regulator device, the device_bind() should be called with passed
>

Best regards,
-- 
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 4/6] power: pmic: pfuze100 support driver model
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 4/6] power: pmic: pfuze100 support driver model Peng Fan
@ 2015-08-04 13:10   ` Przemyslaw Marczak
  0 siblings, 0 replies; 14+ messages in thread
From: Przemyslaw Marczak @ 2015-08-04 13:10 UTC (permalink / raw)
  To: u-boot

Hello Peng,

On 08/04/2015 07:32 AM, Peng Fan wrote:
> 1. Support driver model for pfuze100.
> 2. Introduce a new Kconfig entry DM_PMIC_PFUZE100 for pfuze100
> 3. This driver intends to support PF100, PF200 and PF3000, so add
>     the device id into the udevice_id array.
> 4. Rename PMIC_NUM_OF_REGS macro to PFUZE100_NUM_OF_REGS.
> 5. Rename file name from pmic_pfuze100.c to pfuze100.c to follow new
>     new convention of file naming.
>
> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
> Cc: Przemyslaw Marczak <p.marczak@samsung.com>
> Cc: Simon Glass <sjg@chromium.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes v2:
>   Addressed Przemyslaw's comments:
>    Rename PMIC_NUM_OF_REGS to PFUZE100_NUM_OF_REGS
>    Sort variables' order
>    Define PFUZE100_REGULATOR_DRIVER for "pfuze100_regulator" in header file.
>
>   drivers/power/pmic/Makefile        |   2 +-
>   drivers/power/pmic/Kconfig         |   7 +++
>   drivers/power/pmic/pfuze100.c      | 121 +++++++++++++++++++++++++++++++++++++
>   drivers/power/pmic/pmic_pfuze100.c |  32 ----------
>   include/power/pfuze100_pmic.h      |   7 ++-
>   5 files changed, 135 insertions(+), 34 deletions(-)
>   create mode 100644 drivers/power/pmic/pfuze100.c
>   delete mode 100644 drivers/power/pmic/pmic_pfuze100.c
>
> diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
> index 8c1ce3d..6eb357e 100644
> --- a/drivers/power/pmic/Makefile
> +++ b/drivers/power/pmic/Makefile
> @@ -13,7 +13,7 @@ obj-$(CONFIG_POWER_MAX8998) += pmic_max8998.o
>   obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
>   obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
>   obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
> -obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o

You add DM_PMIC_PFUZE100 to Kconfig, but here you check 
CONFIG_POWER_PFUZE100.

> +obj-$(CONFIG_POWER_PFUZE100) += pfuze100.o
>   obj-$(CONFIG_POWER_TPS65090_I2C) += pmic_tps65090.o
>   obj-$(CONFIG_POWER_TPS65090_EC) += pmic_tps65090_ec.o
>   obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
> diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
> index 164f421..0df91be 100644
> --- a/drivers/power/pmic/Kconfig
> +++ b/drivers/power/pmic/Kconfig
> @@ -10,6 +10,13 @@ config DM_PMIC
>   	- 'drivers/power/pmic/pmic-uclass.c'
>   	- 'include/power/pmic.h'
>
> +config DM_PMIC_PFUZE100
> +	bool "Enable Driver Model for PMIC PFUZE100"
> +	depends on DM_PMIC
> +	---help---
> +	This config enables implementation of driver-model pmic uclass features
> +	for PMIC PFUZE100. The driver implements read/write operations.
> +
>   config DM_PMIC_MAX77686
>   	bool "Enable Driver Model for PMIC MAX77686"
>   	depends on DM_PMIC
> diff --git a/drivers/power/pmic/pfuze100.c b/drivers/power/pmic/pfuze100.c
> new file mode 100644
> index 0000000..8b26806
> --- /dev/null
> +++ b/drivers/power/pmic/pfuze100.c
> @@ -0,0 +1,121 @@
> +/*
> + * Copyright (C) 2014 Gateworks Corporation
> + * Tim Harvey <tharvey@gateworks.com>
> + *
> + * Copyright (C) 2015 Freescale Semiconductor, Inc
> + * Peng Fan <Peng.Fan@freescale.com>
> + *
> + * SPDX-License-Identifier:      GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <errno.h>
> +#include <dm.h>
> +#include <i2c.h>
> +#include <power/pmic.h>
> +#include <power/regulator.h>
> +#include <power/pfuze100_pmic.h>
> +

Last time I meant, that the old code like this inside the ifndef, should 
stay in an old file, and the new one for DM in this new file.

Then you also don't need #ifdef, only separated config options in 
Makefile: CONFIG_DM_PMIC_PFUZE100 and CONFIG_POWER_PFUZE100.

> +#ifndef CONFIG_DM_PMIC
> +int power_pfuze100_init(unsigned char bus)
> +{
> +	static const char name[] = "PFUZE100";
> +	struct pmic *p = pmic_alloc();
> +
> +	if (!p) {
> +		printf("%s: POWER allocation error!\n", __func__);
> +		return -ENOMEM;
> +	}
> +
> +	p->name = name;
> +	p->interface = PMIC_I2C;
> +	p->number_of_regs = PMIC_NUM_OF_REGS;
> +	p->hw.i2c.addr = CONFIG_POWER_PFUZE100_I2C_ADDR;
> +	p->hw.i2c.tx_num = 1;
> +	p->bus = bus;
> +
> +	return 0;
> +}
> +#else
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static const struct pmic_child_info pmic_children_info[] = {
> +	/* sw[x], swbst */
> +	{ .prefix = "s", .driver = PFUZE100_REGULATOR_DRIVER },
> +	/* vgen[x], vsnvs, vcc, v33, vcc_sd */
> +	{ .prefix = "v", .driver = PFUZE100_REGULATOR_DRIVER },
> +	{ },
> +};
> +
> +static int pfuze100_reg_count(struct udevice *dev)
> +{
> +	return PFUZE100_NUM_OF_REGS;
> +}
> +
> +static int pfuze100_write(struct udevice *dev, uint reg, const uint8_t *buff,
> +			  int len)
> +{
> +	if (dm_i2c_write(dev, reg, buff, len)) {
> +		error("write error to device: %p register: %#x!", dev, reg);
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
> +{
> +	if (dm_i2c_read(dev, reg, buff, len)) {
> +		error("read error from device: %p register: %#x!", dev, reg);
> +		return -EIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pfuze100_bind(struct udevice *dev)
> +{
> +	int children;
> +	int regulators_node;
> +	const void *blob = gd->fdt_blob;
> +
> +	regulators_node = fdt_subnode_offset(blob, dev->of_offset,
> +					     "regulators");
> +	if (regulators_node <= 0) {
> +		debug("%s: %s regulators subnode not found!", __func__,
> +		      dev->name);
> +		return -ENXIO;
> +	}
> +
> +	debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
> +
> +	children = pmic_bind_children(dev, regulators_node, pmic_children_info);
> +	if (!children)
> +		debug("%s: %s - no child found\n", __func__, dev->name);
> +
> +	/* Always return success for this device */
> +	return 0;
> +}
> +
> +static struct dm_pmic_ops pfuze100_ops = {
> +	.reg_count = pfuze100_reg_count,
> +	.read = pfuze100_read,
> +	.write = pfuze100_write,
> +};
> +
> +static const struct udevice_id pfuze100_ids[] = {

You don't need casting and the commas before parenthesis at the end of line.

{ .compatible = "fsl,pfuze100", .data = PFUZE100 },

> +	{ .compatible = "fsl,pfuze100", .data = (long)PFUZE100, },
> +	{ .compatible = "fsl,pfuze200", .data = (long)PFUZE200, },
> +	{ .compatible = "fsl,pfuze3000", .data = (long)PFUZE3000, },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(pmic_pfuze100) = {
> +	.name = "pfuze100 pmic",
> +	.id = UCLASS_PMIC,
> +	.of_match = pfuze100_ids,
> +	.bind = pfuze100_bind,
> +	.ops = &pfuze100_ops,
> +};
> +#endif
> diff --git a/drivers/power/pmic/pmic_pfuze100.c b/drivers/power/pmic/pmic_pfuze100.c
> deleted file mode 100644
> index 22a04c0..0000000

And this file can stay as it is, just add the new one with new config.

> --- a/drivers/power/pmic/pmic_pfuze100.c
> +++ /dev/null
> @@ -1,32 +0,0 @@
> -/*
> - * Copyright (C) 2014 Gateworks Corporation
> - * Tim Harvey <tharvey@gateworks.com>
> - *
> - * SPDX-License-Identifier:      GPL-2.0+
> - */
> -
> -#include <common.h>
> -#include <errno.h>
> -#include <i2c.h>
> -#include <power/pmic.h>
> -#include <power/pfuze100_pmic.h>
> -
> -int power_pfuze100_init(unsigned char bus)
> -{
> -	static const char name[] = "PFUZE100";
> -	struct pmic *p = pmic_alloc();
> -
> -	if (!p) {
> -		printf("%s: POWER allocation error!\n", __func__);
> -		return -ENOMEM;
> -	}
> -
> -	p->name = name;
> -	p->interface = PMIC_I2C;
> -	p->number_of_regs = PMIC_NUM_OF_REGS;
> -	p->hw.i2c.addr = CONFIG_POWER_PFUZE100_I2C_ADDR;
> -	p->hw.i2c.tx_num = 1;
> -	p->bus = bus;
> -
> -	return 0;
> -}
> diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
> index cb10605..c40a976 100644
> --- a/include/power/pfuze100_pmic.h
> +++ b/include/power/pfuze100_pmic.h
> @@ -8,6 +8,11 @@
>   #ifndef __PFUZE100_PMIC_H_
>   #define __PFUZE100_PMIC_H_
>
> +/* Device ID */
> +enum {PFUZE100 = 0x10, PFUZE200 = 0x11, PFUZE3000 = 0x30};
> +
> +#define PFUZE100_REGULATOR_DRIVER	"pfuze100_regulator"
> +
>   /* PFUZE100 registers */
>   enum {
>   	PFUZE100_DEVICEID	= 0x00,
> @@ -54,7 +59,7 @@ enum {
>   	PFUZE100_VGEN5VOL	= 0x70,
>   	PFUZE100_VGEN6VOL	= 0x71,
>
> -	PMIC_NUM_OF_REGS	= 0x7f,
> +	PFUZE100_NUM_OF_REGS	= 0x7f,
>   };
>
>   /*
>

Best regards,
-- 
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support
  2015-08-04  5:32 ` [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support Peng Fan
@ 2015-08-04 13:10   ` Przemyslaw Marczak
  2015-08-04 13:21     ` Simon Glass
  0 siblings, 1 reply; 14+ messages in thread
From: Przemyslaw Marczak @ 2015-08-04 13:10 UTC (permalink / raw)
  To: u-boot

Hello Peng,

On 08/04/2015 07:32 AM, Peng Fan wrote:
> 1. Add new regulator driver pfuze100.
>     * Introduce struct pfuze100_regulator_desc for mataining info for regulator.
> 2. Add new Kconfig entry DM_REGULATOR_PFUZE100 for pfuze100.
> 3. This driver intends to support PF100, PF200 and PF3000.
> 4. Add related macro definition in pfuze header file.
>
> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
> Cc: Przemyslaw Marczak <p.marczak@samsung.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>
> Changes v2:
>   Addressed Simon's comments.
>   1. Use pmic_reg_read/pmic_reg_write/pmic_clrsetbits
>   2. blank line between declarations and rest
>
> Hi Simon,
>
>   type case is still kept there:
>   " struct pfuze100_regulator_desc *desc =
>     *(struct pfuze100_regulator_desc **)dev_get_platdata(dev); "
>   Also use pointer points to pointer type, "struct type **", see this line:
>   " .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc **), "
>
>   Each regulator has its own pfuze_regulator_desc, single pointer can not do
>   the work well. For example:
>   .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc *);
>
>   struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>
>   desc = se_desc(pfuze100_regulators, ARRAY_SIZE(pfuze100_regulators),
> 		dev->name);
>   what we changed here is only local variable desc, but not change the pointer
>   platdata. What I need here to set the pointer platdata to point to
>   correct regulator descriptor. Single pointer can not handle this, so
>   use "struct type **".
>
>
>   drivers/power/regulator/Kconfig    |   8 +
>   drivers/power/regulator/Makefile   |   1 +
>   drivers/power/regulator/pfuze100.c | 554 +++++++++++++++++++++++++++++++++++++
>   include/power/pfuze100_pmic.h      |  24 +-
>   4 files changed, 583 insertions(+), 4 deletions(-)
>   create mode 100644 drivers/power/regulator/pfuze100.c
>
> diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
> index 6289b83..b854773 100644
> --- a/drivers/power/regulator/Kconfig
> +++ b/drivers/power/regulator/Kconfig
> @@ -16,6 +16,14 @@ config DM_REGULATOR
>   	for this purpose if PMIC I/O driver is implemented or dm_scan_fdt_node()
>   	otherwise. Detailed information can be found in the header file.
>
> +config DM_REGULATOR_PFUZE100
> +	bool "Enable Driver Model for REGULATOR PFUZE100"
> +	depends on DM_REGULATOR && DM_PMIC_PFUZE100
> +	---help---
> +	This config enables implementation of driver-model regulator uclass
> +	features for REGULATOR PFUZE100. The driver implements get/set api for:
> +	value, enable and mode.
> +
>   config DM_REGULATOR_MAX77686
>   	bool "Enable Driver Model for REGULATOR MAX77686"
>   	depends on DM_REGULATOR && DM_PMIC_MAX77686
> diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
> index 96aa624..9f8f17b 100644
> --- a/drivers/power/regulator/Makefile
> +++ b/drivers/power/regulator/Makefile
> @@ -7,5 +7,6 @@
>
>   obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
>   obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
> +obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
>   obj-$(CONFIG_DM_REGULATOR_FIXED) += fixed.o
>   obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
> diff --git a/drivers/power/regulator/pfuze100.c b/drivers/power/regulator/pfuze100.c
> new file mode 100644
> index 0000000..300aee8
> --- /dev/null
> +++ b/drivers/power/regulator/pfuze100.c
> @@ -0,0 +1,554 @@
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <errno.h>
> +#include <dm.h>
> +#include <i2c.h>
> +#include <power/pmic.h>
> +#include <power/regulator.h>
> +#include <power/pfuze100_pmic.h>
> +
> +/**
> + * struct pfuze100_regulator_desc - regulator descriptor
> + *
> + * @name: Identify name for the regulator.
> + * @type: Indicates the regulator type.
> + * @uV_step: Voltage increase for each selector.
> + * @vsel_reg: Register for adjust regulator voltage for normal.
> + * @vsel_mask: Mask bit for setting regulator voltage for normal.
> + * @stby_reg: Register for adjust regulator voltage for standby.
> + * @stby_mask: Mask bit for setting regulator voltage for standby.
> + * @volt_table: Voltage mapping table (if table based mapping).
> + * @voltage: Current voltage for REGULATOR_TYPE_FIXED type regulator.
> + */
> +struct pfuze100_regulator_desc {
> +	char *name;
> +	enum regulator_type type;
> +	unsigned int uV_step;
> +	unsigned int vsel_reg;
> +	unsigned int vsel_mask;
> +	unsigned int stby_reg;
> +	unsigned int stby_mask;
> +	unsigned int *volt_table;
> +	unsigned int voltage;
> +};
> +
> +#define PFUZE100_FIXED_REG(_name, base, vol)				\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_FIXED,		\
> +		.voltage	=	(vol),				\
> +	}
> +
> +#define PFUZE100_SW_REG(_name, base, step)				\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_BUCK,		\
> +		.uV_step	=	(step),				\
> +		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
> +		.vsel_mask	=	0x3F,				\
> +		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
> +		.stby_mask	=	0x3F,				\
> +	}
> +
> +#define PFUZE100_SWB_REG(_name, base, mask, step, voltages)		\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_BUCK,		\
> +		.uV_step	=	(step),				\
> +		.vsel_reg	=	(base),				\
> +		.vsel_mask	=	(mask),				\
> +		.volt_table	=	(voltages),			\
> +	}
> +
> +#define PFUZE100_SNVS_REG(_name, base, mask, voltages)			\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_OTHER,		\
> +		.vsel_reg	=	(base),				\
> +		.vsel_mask	=	(mask),				\
> +		.volt_table	=	(voltages),			\
> +	}
> +
> +#define PFUZE100_VGEN_REG(_name, base, step)				\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_LDO,		\
> +		.uV_step	=	(step),				\
> +		.vsel_reg	=	(base),				\
> +		.vsel_mask	=	0xF,				\
> +		.stby_reg	=	(base),				\
> +		.stby_mask	=	0x20,				\
> +	}
> +
> +#define PFUZE3000_VCC_REG(_name, base, step)				\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_LDO,		\
> +		.uV_step	=	(step),				\
> +		.vsel_reg	=	(base),				\
> +		.vsel_mask	=	0x3,				\
> +		.stby_reg	=	(base),				\
> +		.stby_mask	=	0x20,				\
> +}
> +
> +#define PFUZE3000_SW1_REG(_name, base, step)				\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_BUCK,		\
> +		.uV_step	=	(step),				\
> +		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
> +		.vsel_mask	=	0x1F,				\
> +		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
> +		.stby_mask	=	0x1F,				\
> +	}
> +
> +#define PFUZE3000_SW2_REG(_name, base, step)				\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_BUCK,		\
> +		.uV_step	=	(step),				\
> +		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
> +		.vsel_mask	=	0x7,				\
> +		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
> +		.stby_mask	=	0x7,				\
> +	}
> +
> +#define PFUZE3000_SW3_REG(_name, base, step)				\
> +	{								\
> +		.name		=	#_name,				\
> +		.type		=	REGULATOR_TYPE_BUCK,		\
> +		.uV_step	=	(step),				\
> +		.vsel_reg	=	(base) + PFUZE100_VOL_OFFSET,	\
> +		.vsel_mask	=	0xF,				\
> +		.stby_reg	=	(base) + PFUZE100_STBY_OFFSET,	\
> +		.stby_mask	=	0xF,				\
> +	}
> +
> +static unsigned int pfuze100_swbst[] = {
> +	5000000, 5050000, 5100000, 5150000
> +};
> +
> +static unsigned int pfuze100_vsnvs[] = {
> +	1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, -1
> +};
> +
> +static unsigned int pfuze3000_vsnvs[] = {
> +	-1, -1, -1, -1, -1, -1, 3000000, -1
> +};
> +
> +static unsigned int pfuze3000_sw2lo[] = {
> +	1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000
> +};
> +
> +/* PFUZE100 */
> +static struct pfuze100_regulator_desc pfuze100_regulators[] = {
> +	PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
> +	PFUZE100_SW_REG(sw1c, PFUZE100_SW1CVOL, 25000),
> +	PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
> +	PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
> +	PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
> +	PFUZE100_SW_REG(sw4, PFUZE100_SW4VOL, 25000),
> +	PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
> +	PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
> +	PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
> +	PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
> +	PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
> +	PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
> +	PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
> +	PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
> +	PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
> +};
> +
> +/* PFUZE200 */
> +static struct pfuze100_regulator_desc pfuze200_regulators[] = {
> +	PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
> +	PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
> +	PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
> +	PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
> +	PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
> +	PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
> +	PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
> +	PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
> +	PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
> +	PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
> +	PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
> +	PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
> +	PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
> +};
> +
> +/* PFUZE3000 */
> +static struct pfuze100_regulator_desc pfuze3000_regulators[] = {
> +	PFUZE3000_SW1_REG(sw1a, PFUZE100_SW1ABVOL, 25000),
> +	PFUZE3000_SW1_REG(sw1b, PFUZE100_SW1CVOL, 25000),
> +	PFUZE100_SWB_REG(sw2, PFUZE100_SW2VOL, 0x7, 50000, pfuze3000_sw2lo),
> +	PFUZE3000_SW3_REG(sw3, PFUZE100_SW3AVOL, 50000),
> +	PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000, pfuze100_swbst),
> +	PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze3000_vsnvs),
> +	PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
> +	PFUZE100_VGEN_REG(vldo1, PFUZE100_VGEN1VOL, 100000),
> +	PFUZE100_VGEN_REG(vldo2, PFUZE100_VGEN2VOL, 50000),
> +	PFUZE3000_VCC_REG(vccsd, PFUZE100_VGEN3VOL, 150000),
> +	PFUZE3000_VCC_REG(v33, PFUZE100_VGEN4VOL, 150000),
> +	PFUZE100_VGEN_REG(vldo3, PFUZE100_VGEN5VOL, 100000),
> +	PFUZE100_VGEN_REG(vldo4, PFUZE100_VGEN6VOL, 100000),
> +};
> +
> +#define MODE(_id, _val, _name) { \
> +	.id = _id, \
> +	.register_value = _val, \
> +	.name = _name, \
> +}
> +
> +/* SWx Buck regulator mode */
> +static struct dm_regulator_mode pfuze_sw_modes[] = {
> +	MODE(OFF_OFF, OFF_OFF, "OFF_OFF"),
> +	MODE(PWM_OFF, PWM_OFF, "PWM_OFF"),
> +	MODE(PFM_OFF, PFM_OFF, "PFM_OFF"),
> +	MODE(APS_OFF, APS_OFF, "APS_OFF"),
> +	MODE(PWM_PWM, PWM_PWM, "PWM_PWM"),
> +	MODE(PWM_APS, PWM_APS, "PWM_APS"),
> +	MODE(APS_APS, APS_APS, "APS_APS"),
> +	MODE(APS_PFM, APS_PFM, "APS_PFM"),
> +	MODE(PWM_PFM, PWM_PFM, "PWM_PFM"),
> +};
> +
> +/* Boost Buck regulator mode for normal operation */
> +static struct dm_regulator_mode pfuze_swbst_modes[] = {
> +	MODE(SWBST_MODE_OFF, SWBST_MODE_OFF , "SWBST_MODE_OFF"),
> +	MODE(SWBST_MODE_PFM, SWBST_MODE_PFM, "SWBST_MODE_PFM"),
> +	MODE(SWBST_MODE_AUTO, SWBST_MODE_AUTO, "SWBST_MODE_AUTO"),
> +	MODE(SWBST_MODE_APS, SWBST_MODE_APS, "SWBST_MODE_APS"),
> +};
> +
> +/* VGENx LDO regulator mode for normal operation */
> +static struct dm_regulator_mode pfuze_ldo_modes[] = {
> +	MODE(LDO_MODE_OFF, LDO_MODE_OFF, "LDO_MODE_OFF"),
> +	MODE(LDO_MODE_ON, LDO_MODE_ON, "LDO_MODE_ON"),
> +};
> +
> +static struct pfuze100_regulator_desc *se_desc(struct pfuze100_regulator_desc *desc,
> +					       int size,
> +					       const char *name)
> +{
> +	int i;
> +
> +	for (i = 0; i < size; desc++) {
> +		if (!strcmp(desc->name, name))
> +			return desc;
> +		continue;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int pfuze100_regulator_probe(struct udevice *dev)
> +{
> +	struct dm_regulator_uclass_platdata *uc_pdata;
> +	struct pfuze100_regulator_desc **desc = dev_get_platdata(dev);

Try this:
struct pfuze100_regulator_desc *desc;

> +
> +	switch (dev_get_driver_data(dev_get_parent(dev))) {
> +	case PFUZE100:
> +		*desc = se_desc(pfuze100_regulators,
> +				ARRAY_SIZE(pfuze100_regulators),
> +				dev->name);

Try this:
desc = se_desc(..)

> +		break;
> +	case PFUZE200:
> +		*desc = se_desc(pfuze200_regulators,
> +				ARRAY_SIZE(pfuze200_regulators),
> +				dev->name);
> +		break;
> +	case PFUZE3000:
> +		*desc = se_desc(pfuze3000_regulators,
> +				ARRAY_SIZE(pfuze3000_regulators),
> +				dev->name);
> +		break;
> +	}
> +	if (!*desc) {
> +		debug("Do not support regulator %s\n", dev->name);
> +		return -EINVAL;
> +	}

Try this:
	dev->platdata = desc;

> +
> +	uc_pdata = dev_get_uclass_platdata(dev);
> +

Try this:
	uc_pdata->type = desc->type;

> +	uc_pdata->type = (*desc)->type;
> +	if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
> +		if (!strcmp(dev->name, "swbst")) {
> +			uc_pdata->mode = pfuze_swbst_modes;
> +			uc_pdata->mode_count = ARRAY_SIZE(pfuze_swbst_modes);
> +		} else {
> +			uc_pdata->mode = pfuze_sw_modes;
> +			uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes);
> +		}
> +	} else if (uc_pdata->type == REGULATOR_TYPE_LDO) {
> +		uc_pdata->mode = pfuze_ldo_modes;
> +		uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes);
> +	} else {
> +		uc_pdata->mode = NULL;
> +		uc_pdata->mode_count = 0;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pfuze100_regulator_mode(struct udevice *dev, int op, int *opmode)
> +{
> +	unsigned char val;

Try this:
struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);

> +	struct pfuze100_regulator_desc *desc =
> +		*(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
> +
> +	if (op == PMIC_OP_GET) {
> +		if (desc->type == REGULATOR_TYPE_BUCK) {
> +			if (!strcmp(dev->name, "swbst")) {
> +				val = pmic_reg_read(dev->parent,
> +						    desc->vsel_reg);
> +				if (val < 0)
> +					return val;
> +
> +				val &= SWBST_MODE_MASK;
> +				val >>= SWBST_MODE_SHIFT;
> +				*opmode = val;
> +
> +				return 0;
> +			}
> +			val = pmic_reg_read(dev->parent,
> +					    desc->vsel_reg +
> +					    PFUZE100_MODE_OFFSET);
> +			if (val < 0)
> +				return val;
> +
> +			val &= SW_MODE_MASK;
> +			val >>= SW_MODE_SHIFT;
> +			*opmode = val;
> +
> +			return 0;
> +
> +		} else if (desc->type == REGULATOR_TYPE_LDO) {
> +			val = pmic_reg_read(dev->parent, desc->vsel_reg);
> +			if (val < 0)
> +				return val;
> +
> +			val &= LDO_MODE_MASK;
> +			val >>= LDO_MODE_SHIFT;
> +			*opmode = val;
> +
> +			return 0;
> +		} else {
> +			return -EINVAL;
> +		}
> +	}
> +
> +	if (desc->type == REGULATOR_TYPE_BUCK) {
> +		if (!strcmp(dev->name, "swbst"))
> +			return pmic_clrsetbits(dev->parent, desc->vsel_reg,
> +					       SWBST_MODE_MASK,
> +					       *opmode << SWBST_MODE_SHIFT);
> +
> +		val = pmic_clrsetbits(dev->parent,
> +				       desc->vsel_reg + PFUZE100_MODE_OFFSET,
> +				       SW_MODE_MASK,
> +				       *opmode << SW_MODE_SHIFT);
> +
> +	} else if (desc->type == REGULATOR_TYPE_LDO) {
> +		val = pmic_clrsetbits(dev->parent, desc->vsel_reg,
> +				       LDO_MODE_MASK,
> +				       *opmode << LDO_MODE_SHIFT);
> +		return val;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pfuze100_regulator_enable(struct udevice *dev, int op, bool *enable)
> +{
> +	unsigned char val;
> +	int ret, on_off;
> +	struct dm_regulator_uclass_platdata *uc_pdata =
> +		dev_get_uclass_platdata(dev);
> +
> +	if (op == PMIC_OP_GET) {
> +		if (!strcmp(dev->name, "vrefddr")) {
> +			val = pmic_reg_read(dev->parent, PFUZE100_VREFDDRCON);
> +			if (val < 0)
> +				return val;
> +
> +			if (val & VREFDDRCON_EN)
> +				*enable = true;
> +			else
> +				*enable = false;
> +			return 0;
> +		}
> +		ret = pfuze100_regulator_mode(dev, op, &on_off);
> +		if (ret)
> +			return ret;
> +		switch (on_off) {
> +		/* OFF_OFF, SWBST_MODE_OFF, LDO_MODE_OFF have same value */
> +		case OFF_OFF:
> +			*enable = false;
> +			break;
> +		default:
> +			*enable = true;
> +			break;
> +		}
> +	} else if (op == PMIC_OP_SET) {
> +		if (!strcmp(dev->name, "vrefddr")) {
> +			val = pmic_reg_read(dev->parent, PFUZE100_VREFDDRCON);
> +			if (val < 0)
> +				return val;
> +
> +			if (val & VREFDDRCON_EN)
> +				return 0;
> +			val |= VREFDDRCON_EN;
> +
> +			return pmic_reg_write(dev->parent, PFUZE100_VREFDDRCON,
> +					      val);
> +		}
> +
> +		if (uc_pdata->type == REGULATOR_TYPE_LDO) {
> +			on_off = *enable ? LDO_MODE_ON : LDO_MODE_OFF;
> +		} else if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
> +			if (!strcmp(dev->name, "swbst"))
> +				on_off = *enable ? SWBST_MODE_AUTO :
> +					SWBST_MODE_OFF;
> +			else
> +				on_off = *enable ? APS_PFM : OFF_OFF;
> +		} else {
> +			return -EINVAL;
> +		}
> +
> +		return pfuze100_regulator_mode(dev, op, &on_off);
> +	}
> +
> +	return 0;
> +}
> +
> +static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV)
> +{
> +	unsigned char val;
> +	int i;

Try this:
struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);

> +	struct pfuze100_regulator_desc *desc =
> +		*(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
> +	struct dm_regulator_uclass_platdata *uc_pdata =
> +		dev_get_uclass_platdata(dev);
> +
> +	if (op == PMIC_OP_GET) {
> +		*uV = 0;
> +		if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
> +			*uV = desc->voltage;
> +		} else if (desc->volt_table) {
> +			val = pmic_reg_read(dev->parent, desc->vsel_reg);
> +			if (val < 0)
> +				return val;
> +			val &= desc->vsel_mask;
> +			*uV = desc->volt_table[val];
> +		} else {
> +			if (uc_pdata->min_uV < 0) {
> +				debug("Need to provide min_uV in dts.\n");
> +				return -EINVAL;
> +			}
> +			val = pmic_reg_read(dev->parent, desc->vsel_reg);
> +			if (val < 0)
> +				return val;
> +			val &= desc->vsel_mask;
> +			*uV = uc_pdata->min_uV + (int)val * desc->uV_step;
> +		}
> +
> +		return 0;
> +	}
> +
> +	if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
> +		debug("Set voltage for REGULATOR_TYPE_FIXED regulator\n");
> +		return -EINVAL;
> +	} else if (desc->volt_table) {
> +		for (i = 0; i < desc->vsel_mask; i++) {
> +			if (*uV == desc->volt_table[i])
> +				break;
> +		}
> +		if (i == desc->vsel_mask) {
> +			debug("Unsupported voltage %u\n", *uV);
> +			return -EINVAL;
> +		}
> +
> +		return pmic_clrsetbits(dev->parent, desc->vsel_reg,
> +				       desc->vsel_mask, i);
> +	} else {
> +		if (uc_pdata->min_uV < 0) {
> +			debug("Need to provide min_uV in dts.\n");
> +			return -EINVAL;
> +		}
> +		return pmic_clrsetbits(dev->parent, desc->vsel_reg,
> +				       desc->vsel_mask,
> +				       (*uV - uc_pdata->min_uV) / desc->uV_step);
> +	}
> +
> +	return 0;
> +}
> +
> +static int pfuze100_regulator_get_value(struct udevice *dev)
> +{
> +	int uV;
> +	int ret;
> +
> +	ret = pfuze100_regulator_val(dev, PMIC_OP_GET, &uV);
> +	if (ret)
> +		return ret;
> +
> +	return uV;
> +}
> +
> +static int pfuze100_regulator_set_value(struct udevice *dev, int uV)
> +{
> +	return pfuze100_regulator_val(dev, PMIC_OP_SET, &uV);
> +}
> +
> +static bool pfuze100_regulator_get_enable(struct udevice *dev)
> +{
> +	int ret;
> +	bool enable = false;
> +
> +	ret = pfuze100_regulator_enable(dev, PMIC_OP_GET, &enable);
> +	if (ret)
> +		return ret;
> +
> +	return enable;
> +}
> +
> +static int pfuze100_regulator_set_enable(struct udevice *dev, bool enable)
> +{
> +	return pfuze100_regulator_enable(dev, PMIC_OP_SET, &enable);
> +}
> +
> +static int pfuze100_regulator_get_mode(struct udevice *dev)
> +{
> +	int mode;
> +	int ret;
> +
> +	ret = pfuze100_regulator_mode(dev, PMIC_OP_GET, &mode);
> +	if (ret)
> +		return ret;
> +
> +	return mode;
> +}
> +
> +static int pfuze100_regulator_set_mode(struct udevice *dev, int mode)
> +{
> +	return pfuze100_regulator_mode(dev, PMIC_OP_SET, &mode);
> +}
> +
> +static const struct dm_regulator_ops pfuze100_regulator_ops = {
> +	.get_value  = pfuze100_regulator_get_value,
> +	.set_value  = pfuze100_regulator_set_value,
> +	.get_enable = pfuze100_regulator_get_enable,
> +	.set_enable = pfuze100_regulator_set_enable,
> +	.get_mode   = pfuze100_regulator_get_mode,
> +	.set_mode   = pfuze100_regulator_set_mode,
> +};
> +
> +U_BOOT_DRIVER(pfuze100_regulator) = {
> +	.name = "pfuze100_regulator",
> +	.id = UCLASS_REGULATOR,
> +	.ops = &pfuze100_regulator_ops,
> +	.probe = pfuze100_regulator_probe,

You can use: sizeof(struct pfuze100_regulator_desc *)
It is only size of the pointer not an array.

> +	.platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc **),
> +};
> diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
> index c40a976..41cb710 100644
> --- a/include/power/pfuze100_pmic.h
> +++ b/include/power/pfuze100_pmic.h
> @@ -62,6 +62,13 @@ enum {
>   	PFUZE100_NUM_OF_REGS	= 0x7f,
>   };
>
> +/* Registor offset based on VOLT register */
> +#define PFUZE100_VOL_OFFSET	0
> +#define PFUZE100_STBY_OFFSET	1
> +#define PFUZE100_OFF_OFFSET	2
> +#define PFUZE100_MODE_OFFSET	3
> +#define PFUZE100_CONF_OFFSET	4
> +
>   /*
>    * Buck Regulators
>    */
> @@ -138,6 +145,9 @@ enum {
>   #define SW1x_STBY_MASK    0x3f
>   #define SW1x_OFF_MASK     0x3f
>
> +#define SW_MODE_MASK	0xf
> +#define SW_MODE_SHIFT	0
> +
>   #define SW1xCONF_DVSSPEED_MASK 0xc0
>   #define SW1xCONF_DVSSPEED_2US  0x00
>   #define SW1xCONF_DVSSPEED_4US  0x40
> @@ -186,7 +196,12 @@ enum {
>
>   #define LDO_VOL_MASK	0xf
>   #define LDO_EN		(1 << 4)
> +#define LDO_MODE_SHIFT	4
> +#define LDO_MODE_MASK	(1 << 4)
> +#define LDO_MODE_OFF	0
> +#define LDO_MODE_ON	1
>
> +#define VREFDDRCON_EN	(1 << 4)
>   /*
>    * Boost Regulator
>    */
> @@ -199,10 +214,11 @@ enum {
>
>   #define SWBST_VOL_MASK	0x3
>   #define SWBST_MODE_MASK	0xC
> -#define SWBST_MODE_OFF	(0 << 2)
> -#define SWBST_MODE_PFM	(1 << 2)
> -#define SWBST_MODE_AUTO	(2 << 2)
> -#define SWBST_MODE_APS	(3 << 2)
> +#define SWBST_MODE_SHIFT 0x2
> +#define SWBST_MODE_OFF	0
> +#define SWBST_MODE_PFM	1
> +#define SWBST_MODE_AUTO	2
> +#define SWBST_MODE_APS	3
>
>   /*
>    * Regulator Mode Control
>

Best regards,
-- 
Przemyslaw Marczak
Samsung R&D Institute Poland
Samsung Electronics
p.marczak at samsung.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 3/6] power: regulator: update comments for regulator-name
  2015-08-04 13:10   ` Przemyslaw Marczak
@ 2015-08-04 13:12     ` Peng Fan
  0 siblings, 0 replies; 14+ messages in thread
From: Peng Fan @ 2015-08-04 13:12 UTC (permalink / raw)
  To: u-boot

Hello Przemyslaw,
On Tue, Aug 04, 2015 at 03:10:22PM +0200, Przemyslaw Marczak wrote:
>Hello Peng,
>
>On 08/04/2015 07:32 AM, Peng Fan wrote:
>>We do not need that "regulator-name" property must be provided in dts.
>>If "regulator-name" property is not provided in dts, node name
>>will chosen for settings '.name' field of uc_pdata.
>>
>>Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
>>Cc: Przemyslaw Marczak <p.marczak@samsung.com>
>>Cc: Simon Glass <sjg@chromium.org>
>>---
>>
>>Changes v2:
>>  New patch. Update comments for regulator-name property.
>>
>>  doc/device-tree-bindings/regulator/regulator.txt | 19 ++++++++-----------
>>  include/power/regulator.h                        |  8 +++++---
>>  2 files changed, 13 insertions(+), 14 deletions(-)
>>
>>diff --git a/doc/device-tree-bindings/regulator/regulator.txt b/doc/device-tree-bindings/regulator/regulator.txt
>>index 68b02a8..2cf4b9d 100644
>>--- a/doc/device-tree-bindings/regulator/regulator.txt
>>+++ b/doc/device-tree-bindings/regulator/regulator.txt
>>@@ -15,15 +15,8 @@ For the node name e.g.: "prefix[:alpha:]num { ... }":
>>
>>  Example the prefix "ldo" will pass for: "ldo1", "ldo at 1", "LDO1", "LDOREG at 1"...
>>
>>-Required properties:
>>-- regulator-name: a string, required by the regulator uclass
>>-
>>-Note
>>-The "regulator-name" constraint is used for setting the device's uclass
>>-platform data '.name' field. And the regulator device name is set from
>>-it's node name.
>>-
>>  Optional properties:
>>+- regulator-name: a string, required by the regulator uclass
>>  - regulator-min-microvolt: a minimum allowed Voltage value
>>  - regulator-max-microvolt: a maximum allowed Voltage value
>>  - regulator-min-microamp: a minimum allowed Current value
>>@@ -31,6 +24,12 @@ Optional properties:
>>  - regulator-always-on: regulator should never be disabled
>>  - regulator-boot-on: enabled by bootloader/firmware
>>
>>+Note
>>+The "regulator-name" constraint is used for setting the device's uclass
>>+platform data '.name' field. And the regulator device name is set from
>>+it's node name. If "regulator-name" is not provided in dts, node name
>>+is chosen for setting the device's uclass platform data '.name' field.
>>+
>>  Other kernel-style properties, are currently not used.
>>
>>  Note:
>>@@ -41,10 +40,8 @@ For the regulator autoset from constraints, the framework expects that:
>>
>>  Example:
>>  ldo0 {
>>-	/* Mandatory */
>>-	regulator-name = "VDDQ_EMMC_1.8V";
>>-
>>  	/* Optional */
>>+	regulator-name = "VDDQ_EMMC_1.8V";
>>  	regulator-min-microvolt = <1800000>;
>>  	regulator-max-microvolt = <1800000>;
>>  	regulator-min-microamp = <100000>;
>>diff --git a/include/power/regulator.h b/include/power/regulator.h
>>index 0152290..2198664 100644
>>--- a/include/power/regulator.h
>>+++ b/include/power/regulator.h
>>@@ -34,7 +34,7 @@
>>   * regulator constraints, like in the example below:
>>   *
>>   * ldo1 {
>
>When using node name, then it's automatically unique, otherwise not.
>So I would like to keep this information here.

Ok. Will keep "regulator-name = "VDD_MMC_1.8V" (must be unique for proper bind)"

Regards,
Peng.
>
>>- *      regulator-name = "VDD_MMC_1.8V";     (must be unique for proper bind)
>>+ *      regulator-name = "VDD_MMC_1.8V";     (optional)
>>   *      regulator-min-microvolt = <1000000>; (optional)
>>   *      regulator-max-microvolt = <1000000>; (optional)
>>   *      regulator-min-microamp = <1000>;     (optional)
>>@@ -44,8 +44,10 @@
>>   * };
>>   *
>>   * Note: For the proper operation, at least name constraint is needed, since
>>- * it can be used when calling regulator_get_by_platname(). And the mandatory
>>- * rule for this name is, that it must be globally unique for the single dts.
>>+ * it can be used when calling regulator_get_by_platname(). If regulator-name
>>+ * property is not provided, node name will be chosen for platname. And the
>>+ * mandatory rule for this name is, that it must be globally unique for the
>>+ * single dts.
>>   *
>>   * Regulator bind:
>>   * For each regulator device, the device_bind() should be called with passed
>>
>
>Best regards,
>-- 
>Przemyslaw Marczak
>Samsung R&D Institute Poland
>Samsung Electronics
>p.marczak at samsung.com

-- 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support
  2015-08-04 13:21     ` Simon Glass
@ 2015-08-04 13:14       ` Peng Fan
  2015-08-06  4:52         ` Peng Fan
  0 siblings, 1 reply; 14+ messages in thread
From: Peng Fan @ 2015-08-04 13:14 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 04, 2015 at 07:21:05AM -0600, Simon Glass wrote:
>Hi,
>
>On 4 August 2015 at 07:10, Przemyslaw Marczak <p.marczak@samsung.com> wrote:
>> Hello Peng,
>>
>>
>> On 08/04/2015 07:32 AM, Peng Fan wrote:
>>>
>>> 1. Add new regulator driver pfuze100.
>>>     * Introduce struct pfuze100_regulator_desc for mataining info for
>>> regulator.
>>> 2. Add new Kconfig entry DM_REGULATOR_PFUZE100 for pfuze100.
>>> 3. This driver intends to support PF100, PF200 and PF3000.
>>> 4. Add related macro definition in pfuze header file.
>>>
>>> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
>>> Cc: Przemyslaw Marczak <p.marczak@samsung.com>
>>> Cc: Simon Glass <sjg@chromium.org>
>>> ---
>>>
>>> Changes v2:
>>>   Addressed Simon's comments.
>>>   1. Use pmic_reg_read/pmic_reg_write/pmic_clrsetbits
>>>   2. blank line between declarations and rest
>
>Would still like to see you device tree file somewhere.

See: http://lxr.free-electrons.com/source/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
line from 208 to 306.

>
>>>
>>> Hi Simon,
>>>
>>>   type case is still kept there:
>>>   " struct pfuze100_regulator_desc *desc =
>>>     *(struct pfuze100_regulator_desc **)dev_get_platdata(dev); "
>>>   Also use pointer points to pointer type, "struct type **", see this
>>> line:
>>>   " .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc **),
>>> "
>>>
>>>   Each regulator has its own pfuze_regulator_desc, single pointer can not
>>> do
>>>   the work well. For example:
>>>   .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc *);
>>>
>>>   struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>>>
>>>   desc = se_desc(pfuze100_regulators, ARRAY_SIZE(pfuze100_regulators),
>>>                 dev->name);
>>>   what we changed here is only local variable desc, but not change the
>>> pointer
>>>   platdata. What I need here to set the pointer platdata to point to
>>>   correct regulator descriptor. Single pointer can not handle this, so
>>>   use "struct type **".
>>>
>>>
>>>   drivers/power/regulator/Kconfig    |   8 +
>>>   drivers/power/regulator/Makefile   |   1 +
>>>   drivers/power/regulator/pfuze100.c | 554
>>> +++++++++++++++++++++++++++++++++++++
>>>   include/power/pfuze100_pmic.h      |  24 +-
>>>   4 files changed, 583 insertions(+), 4 deletions(-)
>>>   create mode 100644 drivers/power/regulator/pfuze100.c
>>>
>>> diff --git a/drivers/power/regulator/Kconfig
>>> b/drivers/power/regulator/Kconfig
>>> index 6289b83..b854773 100644
>>> --- a/drivers/power/regulator/Kconfig
>>> +++ b/drivers/power/regulator/Kconfig
>>> @@ -16,6 +16,14 @@ config DM_REGULATOR
>>>         for this purpose if PMIC I/O driver is implemented or
>>> dm_scan_fdt_node()
>>>         otherwise. Detailed information can be found in the header file.
>>>
>>> +config DM_REGULATOR_PFUZE100
>>> +       bool "Enable Driver Model for REGULATOR PFUZE100"
>>> +       depends on DM_REGULATOR && DM_PMIC_PFUZE100
>>> +       ---help---
>>> +       This config enables implementation of driver-model regulator
>>> uclass
>>> +       features for REGULATOR PFUZE100. The driver implements get/set api
>>> for:
>>> +       value, enable and mode.
>>> +
>>>   config DM_REGULATOR_MAX77686
>>>         bool "Enable Driver Model for REGULATOR MAX77686"
>>>         depends on DM_REGULATOR && DM_PMIC_MAX77686
>>> diff --git a/drivers/power/regulator/Makefile
>>> b/drivers/power/regulator/Makefile
>>> index 96aa624..9f8f17b 100644
>>> --- a/drivers/power/regulator/Makefile
>>> +++ b/drivers/power/regulator/Makefile
>>> @@ -7,5 +7,6 @@
>>>
>>>   obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
>>>   obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
>>> +obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
>>>   obj-$(CONFIG_DM_REGULATOR_FIXED) += fixed.o
>>>   obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
>>> diff --git a/drivers/power/regulator/pfuze100.c
>>> b/drivers/power/regulator/pfuze100.c
>>> new file mode 100644
>>> index 0000000..300aee8
>>> --- /dev/null
>>> +++ b/drivers/power/regulator/pfuze100.c
>>> @@ -0,0 +1,554 @@
>>> +#include <common.h>
>>> +#include <fdtdec.h>
>>> +#include <errno.h>
>>> +#include <dm.h>
>>> +#include <i2c.h>
>>> +#include <power/pmic.h>
>>> +#include <power/regulator.h>
>>> +#include <power/pfuze100_pmic.h>
>>> +
>>> +/**
>>> + * struct pfuze100_regulator_desc - regulator descriptor
>>> + *
>>> + * @name: Identify name for the regulator.
>>> + * @type: Indicates the regulator type.
>>> + * @uV_step: Voltage increase for each selector.
>>> + * @vsel_reg: Register for adjust regulator voltage for normal.
>>> + * @vsel_mask: Mask bit for setting regulator voltage for normal.
>>> + * @stby_reg: Register for adjust regulator voltage for standby.
>>> + * @stby_mask: Mask bit for setting regulator voltage for standby.
>>> + * @volt_table: Voltage mapping table (if table based mapping).
>>> + * @voltage: Current voltage for REGULATOR_TYPE_FIXED type regulator.
>>> + */
>>> +struct pfuze100_regulator_desc {
>>> +       char *name;
>>> +       enum regulator_type type;
>>> +       unsigned int uV_step;
>>> +       unsigned int vsel_reg;
>>> +       unsigned int vsel_mask;
>>> +       unsigned int stby_reg;
>>> +       unsigned int stby_mask;
>>> +       unsigned int *volt_table;
>>> +       unsigned int voltage;
>>> +};
>>> +
>>> +#define PFUZE100_FIXED_REG(_name, base, vol)                           \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_FIXED,           \
>>> +               .voltage        =       (vol),                          \
>>> +       }
>>> +
>>> +#define PFUZE100_SW_REG(_name, base, step)                             \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>> +               .uV_step        =       (step),                         \
>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>> +               .vsel_mask      =       0x3F,                           \
>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>> +               .stby_mask      =       0x3F,                           \
>>> +       }
>>> +
>>> +#define PFUZE100_SWB_REG(_name, base, mask, step, voltages)            \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>> +               .uV_step        =       (step),                         \
>>> +               .vsel_reg       =       (base),                         \
>>> +               .vsel_mask      =       (mask),                         \
>>> +               .volt_table     =       (voltages),                     \
>>> +       }
>>> +
>>> +#define PFUZE100_SNVS_REG(_name, base, mask, voltages)                 \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_OTHER,           \
>>> +               .vsel_reg       =       (base),                         \
>>> +               .vsel_mask      =       (mask),                         \
>>> +               .volt_table     =       (voltages),                     \
>>> +       }
>>> +
>>> +#define PFUZE100_VGEN_REG(_name, base, step)                           \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_LDO,             \
>>> +               .uV_step        =       (step),                         \
>>> +               .vsel_reg       =       (base),                         \
>>> +               .vsel_mask      =       0xF,                            \
>>> +               .stby_reg       =       (base),                         \
>>> +               .stby_mask      =       0x20,                           \
>>> +       }
>>> +
>>> +#define PFUZE3000_VCC_REG(_name, base, step)                           \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_LDO,             \
>>> +               .uV_step        =       (step),                         \
>>> +               .vsel_reg       =       (base),                         \
>>> +               .vsel_mask      =       0x3,                            \
>>> +               .stby_reg       =       (base),                         \
>>> +               .stby_mask      =       0x20,                           \
>>> +}
>>> +
>>> +#define PFUZE3000_SW1_REG(_name, base, step)                           \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>> +               .uV_step        =       (step),                         \
>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>> +               .vsel_mask      =       0x1F,                           \
>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>> +               .stby_mask      =       0x1F,                           \
>>> +       }
>>> +
>>> +#define PFUZE3000_SW2_REG(_name, base, step)                           \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>> +               .uV_step        =       (step),                         \
>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>> +               .vsel_mask      =       0x7,                            \
>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>> +               .stby_mask      =       0x7,                            \
>>> +       }
>>> +
>>> +#define PFUZE3000_SW3_REG(_name, base, step)                           \
>>> +       {                                                               \
>>> +               .name           =       #_name,                         \
>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>> +               .uV_step        =       (step),                         \
>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>> +               .vsel_mask      =       0xF,                            \
>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>> +               .stby_mask      =       0xF,                            \
>>> +       }
>>> +
>>> +static unsigned int pfuze100_swbst[] = {
>>> +       5000000, 5050000, 5100000, 5150000
>>> +};
>>> +
>>> +static unsigned int pfuze100_vsnvs[] = {
>>> +       1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, -1
>>> +};
>>> +
>>> +static unsigned int pfuze3000_vsnvs[] = {
>>> +       -1, -1, -1, -1, -1, -1, 3000000, -1
>>> +};
>>> +
>>> +static unsigned int pfuze3000_sw2lo[] = {
>>> +       1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000,
>>> 1850000
>>> +};
>>> +
>>> +/* PFUZE100 */
>>> +static struct pfuze100_regulator_desc pfuze100_regulators[] = {
>>> +       PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
>>> +       PFUZE100_SW_REG(sw1c, PFUZE100_SW1CVOL, 25000),
>>> +       PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
>>> +       PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
>>> +       PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
>>> +       PFUZE100_SW_REG(sw4, PFUZE100_SW4VOL, 25000),
>>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>>> pfuze100_swbst),
>>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
>>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>>> +       PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
>>> +       PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
>>> +       PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
>>> +};
>>> +
>>> +/* PFUZE200 */
>>> +static struct pfuze100_regulator_desc pfuze200_regulators[] = {
>>> +       PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
>>> +       PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
>>> +       PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
>>> +       PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
>>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>>> pfuze100_swbst),
>>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
>>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>>> +       PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
>>> +       PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
>>> +       PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
>>> +};
>>> +
>>> +/* PFUZE3000 */
>>> +static struct pfuze100_regulator_desc pfuze3000_regulators[] = {
>>> +       PFUZE3000_SW1_REG(sw1a, PFUZE100_SW1ABVOL, 25000),
>>> +       PFUZE3000_SW1_REG(sw1b, PFUZE100_SW1CVOL, 25000),
>>> +       PFUZE100_SWB_REG(sw2, PFUZE100_SW2VOL, 0x7, 50000,
>>> pfuze3000_sw2lo),
>>> +       PFUZE3000_SW3_REG(sw3, PFUZE100_SW3AVOL, 50000),
>>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>>> pfuze100_swbst),
>>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze3000_vsnvs),
>>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>>> +       PFUZE100_VGEN_REG(vldo1, PFUZE100_VGEN1VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vldo2, PFUZE100_VGEN2VOL, 50000),
>>> +       PFUZE3000_VCC_REG(vccsd, PFUZE100_VGEN3VOL, 150000),
>>> +       PFUZE3000_VCC_REG(v33, PFUZE100_VGEN4VOL, 150000),
>>> +       PFUZE100_VGEN_REG(vldo3, PFUZE100_VGEN5VOL, 100000),
>>> +       PFUZE100_VGEN_REG(vldo4, PFUZE100_VGEN6VOL, 100000),
>>> +};
>>> +
>>> +#define MODE(_id, _val, _name) { \
>>> +       .id = _id, \
>>> +       .register_value = _val, \
>>> +       .name = _name, \
>>> +}
>>> +
>>> +/* SWx Buck regulator mode */
>>> +static struct dm_regulator_mode pfuze_sw_modes[] = {
>>> +       MODE(OFF_OFF, OFF_OFF, "OFF_OFF"),
>>> +       MODE(PWM_OFF, PWM_OFF, "PWM_OFF"),
>>> +       MODE(PFM_OFF, PFM_OFF, "PFM_OFF"),
>>> +       MODE(APS_OFF, APS_OFF, "APS_OFF"),
>>> +       MODE(PWM_PWM, PWM_PWM, "PWM_PWM"),
>>> +       MODE(PWM_APS, PWM_APS, "PWM_APS"),
>>> +       MODE(APS_APS, APS_APS, "APS_APS"),
>>> +       MODE(APS_PFM, APS_PFM, "APS_PFM"),
>>> +       MODE(PWM_PFM, PWM_PFM, "PWM_PFM"),
>>> +};
>>> +
>>> +/* Boost Buck regulator mode for normal operation */
>>> +static struct dm_regulator_mode pfuze_swbst_modes[] = {
>>> +       MODE(SWBST_MODE_OFF, SWBST_MODE_OFF , "SWBST_MODE_OFF"),
>>> +       MODE(SWBST_MODE_PFM, SWBST_MODE_PFM, "SWBST_MODE_PFM"),
>>> +       MODE(SWBST_MODE_AUTO, SWBST_MODE_AUTO, "SWBST_MODE_AUTO"),
>>> +       MODE(SWBST_MODE_APS, SWBST_MODE_APS, "SWBST_MODE_APS"),
>>> +};
>>> +
>>> +/* VGENx LDO regulator mode for normal operation */
>>> +static struct dm_regulator_mode pfuze_ldo_modes[] = {
>>> +       MODE(LDO_MODE_OFF, LDO_MODE_OFF, "LDO_MODE_OFF"),
>>> +       MODE(LDO_MODE_ON, LDO_MODE_ON, "LDO_MODE_ON"),
>>> +};
>>> +
>>> +static struct pfuze100_regulator_desc *se_desc(struct
>>> pfuze100_regulator_desc *desc,
>>> +                                              int size,
>>> +                                              const char *name)
>>> +{
>>> +       int i;
>>> +
>>> +       for (i = 0; i < size; desc++) {
>>> +               if (!strcmp(desc->name, name))
>>> +                       return desc;
>>> +               continue;
>>> +       }
>>> +
>>> +       return NULL;
>>> +}
>>> +
>>> +static int pfuze100_regulator_probe(struct udevice *dev)
>>> +{
>>> +       struct dm_regulator_uclass_platdata *uc_pdata;
>>> +       struct pfuze100_regulator_desc **desc = dev_get_platdata(dev);
>>
>>
>> Try this:
>> struct pfuze100_regulator_desc *desc;
>>
>>> +
>>> +       switch (dev_get_driver_data(dev_get_parent(dev))) {
>>> +       case PFUZE100:
>>> +               *desc = se_desc(pfuze100_regulators,
>>> +                               ARRAY_SIZE(pfuze100_regulators),
>>> +                               dev->name);
>>
>>
>> Try this:
>> desc = se_desc(..)
>>
>>> +               break;
>>> +       case PFUZE200:
>>> +               *desc = se_desc(pfuze200_regulators,
>>> +                               ARRAY_SIZE(pfuze200_regulators),
>>> +                               dev->name);
>>> +               break;
>>> +       case PFUZE3000:
>>> +               *desc = se_desc(pfuze3000_regulators,
>>> +                               ARRAY_SIZE(pfuze3000_regulators),
>>> +                               dev->name);
>>> +               break;
>>> +       }
>>> +       if (!*desc) {
>>> +               debug("Do not support regulator %s\n", dev->name);
>>> +               return -EINVAL;
>>> +       }
>>
>>
>> Try this:
>>         dev->platdata = desc;
>>
>>> +
>>> +       uc_pdata = dev_get_uclass_platdata(dev);
>>> +
>>
>>
>> Try this:
>>         uc_pdata->type = desc->type;
>>
>>> +       uc_pdata->type = (*desc)->type;
>>> +       if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
>>> +               if (!strcmp(dev->name, "swbst")) {
>>> +                       uc_pdata->mode = pfuze_swbst_modes;
>>> +                       uc_pdata->mode_count =
>>> ARRAY_SIZE(pfuze_swbst_modes);
>>> +               } else {
>>> +                       uc_pdata->mode = pfuze_sw_modes;
>>> +                       uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes);
>>> +               }
>>> +       } else if (uc_pdata->type == REGULATOR_TYPE_LDO) {
>>> +               uc_pdata->mode = pfuze_ldo_modes;
>>> +               uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes);
>>> +       } else {
>>> +               uc_pdata->mode = NULL;
>>> +               uc_pdata->mode_count = 0;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int pfuze100_regulator_mode(struct udevice *dev, int op, int
>>> *opmode)
>>> +{
>>> +       unsigned char val;
>>
>>
>> Try this:
>> struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>>
>>> +       struct pfuze100_regulator_desc *desc =
>>> +               *(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
>>> +
>>> +       if (op == PMIC_OP_GET) {
>>> +               if (desc->type == REGULATOR_TYPE_BUCK) {
>>> +                       if (!strcmp(dev->name, "swbst")) {
>>> +                               val = pmic_reg_read(dev->parent,
>>> +                                                   desc->vsel_reg);
>>> +                               if (val < 0)
>>> +                                       return val;
>>> +
>>> +                               val &= SWBST_MODE_MASK;
>>> +                               val >>= SWBST_MODE_SHIFT;
>>> +                               *opmode = val;
>>> +
>>> +                               return 0;
>>> +                       }
>>> +                       val = pmic_reg_read(dev->parent,
>>> +                                           desc->vsel_reg +
>>> +                                           PFUZE100_MODE_OFFSET);
>>> +                       if (val < 0)
>>> +                               return val;
>>> +
>>> +                       val &= SW_MODE_MASK;
>>> +                       val >>= SW_MODE_SHIFT;
>>> +                       *opmode = val;
>>> +
>>> +                       return 0;
>>> +
>>> +               } else if (desc->type == REGULATOR_TYPE_LDO) {
>>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>>> +                       if (val < 0)
>>> +                               return val;
>>> +
>>> +                       val &= LDO_MODE_MASK;
>>> +                       val >>= LDO_MODE_SHIFT;
>>> +                       *opmode = val;
>>> +
>>> +                       return 0;
>>> +               } else {
>>> +                       return -EINVAL;
>>> +               }
>>> +       }
>>> +
>>> +       if (desc->type == REGULATOR_TYPE_BUCK) {
>>> +               if (!strcmp(dev->name, "swbst"))
>>> +                       return pmic_clrsetbits(dev->parent,
>>> desc->vsel_reg,
>>> +                                              SWBST_MODE_MASK,
>>> +                                              *opmode <<
>>> SWBST_MODE_SHIFT);
>>> +
>>> +               val = pmic_clrsetbits(dev->parent,
>>> +                                      desc->vsel_reg +
>>> PFUZE100_MODE_OFFSET,
>>> +                                      SW_MODE_MASK,
>>> +                                      *opmode << SW_MODE_SHIFT);
>>> +
>>> +       } else if (desc->type == REGULATOR_TYPE_LDO) {
>>> +               val = pmic_clrsetbits(dev->parent, desc->vsel_reg,
>>> +                                      LDO_MODE_MASK,
>>> +                                      *opmode << LDO_MODE_SHIFT);
>>> +               return val;
>>> +       } else {
>>> +               return -EINVAL;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int pfuze100_regulator_enable(struct udevice *dev, int op, bool
>>> *enable)
>>> +{
>>> +       unsigned char val;
>>> +       int ret, on_off;
>>> +       struct dm_regulator_uclass_platdata *uc_pdata =
>>> +               dev_get_uclass_platdata(dev);
>>> +
>>> +       if (op == PMIC_OP_GET) {
>>> +               if (!strcmp(dev->name, "vrefddr")) {
>>> +                       val = pmic_reg_read(dev->parent,
>>> PFUZE100_VREFDDRCON);
>>> +                       if (val < 0)
>>> +                               return val;
>>> +
>>> +                       if (val & VREFDDRCON_EN)
>>> +                               *enable = true;
>>> +                       else
>>> +                               *enable = false;
>>> +                       return 0;
>>> +               }
>>> +               ret = pfuze100_regulator_mode(dev, op, &on_off);
>>> +               if (ret)
>>> +                       return ret;
>>> +               switch (on_off) {
>>> +               /* OFF_OFF, SWBST_MODE_OFF, LDO_MODE_OFF have same value
>>> */
>>> +               case OFF_OFF:
>>> +                       *enable = false;
>>> +                       break;
>>> +               default:
>>> +                       *enable = true;
>>> +                       break;
>>> +               }
>>> +       } else if (op == PMIC_OP_SET) {
>>> +               if (!strcmp(dev->name, "vrefddr")) {
>>> +                       val = pmic_reg_read(dev->parent,
>>> PFUZE100_VREFDDRCON);
>>> +                       if (val < 0)
>>> +                               return val;
>>> +
>>> +                       if (val & VREFDDRCON_EN)
>>> +                               return 0;
>>> +                       val |= VREFDDRCON_EN;
>>> +
>>> +                       return pmic_reg_write(dev->parent,
>>> PFUZE100_VREFDDRCON,
>>> +                                             val);
>>> +               }
>>> +
>>> +               if (uc_pdata->type == REGULATOR_TYPE_LDO) {
>>> +                       on_off = *enable ? LDO_MODE_ON : LDO_MODE_OFF;
>>> +               } else if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
>>> +                       if (!strcmp(dev->name, "swbst"))
>>> +                               on_off = *enable ? SWBST_MODE_AUTO :
>>> +                                       SWBST_MODE_OFF;
>>> +                       else
>>> +                               on_off = *enable ? APS_PFM : OFF_OFF;
>>> +               } else {
>>> +                       return -EINVAL;
>>> +               }
>>> +
>>> +               return pfuze100_regulator_mode(dev, op, &on_off);
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV)
>>> +{
>>> +       unsigned char val;
>>> +       int i;
>>
>>
>> Try this:
>> struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>>
>>> +       struct pfuze100_regulator_desc *desc =
>>> +               *(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
>>> +       struct dm_regulator_uclass_platdata *uc_pdata =
>>> +               dev_get_uclass_platdata(dev);
>>> +
>>> +       if (op == PMIC_OP_GET) {
>>> +               *uV = 0;
>>> +               if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
>>> +                       *uV = desc->voltage;
>>> +               } else if (desc->volt_table) {
>>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>>> +                       if (val < 0)
>>> +                               return val;
>>> +                       val &= desc->vsel_mask;
>>> +                       *uV = desc->volt_table[val];
>>> +               } else {
>>> +                       if (uc_pdata->min_uV < 0) {
>>> +                               debug("Need to provide min_uV in dts.\n");
>>> +                               return -EINVAL;
>>> +                       }
>>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>>> +                       if (val < 0)
>>> +                               return val;
>>> +                       val &= desc->vsel_mask;
>>> +                       *uV = uc_pdata->min_uV + (int)val * desc->uV_step;
>>> +               }
>>> +
>>> +               return 0;
>>> +       }
>>> +
>>> +       if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
>>> +               debug("Set voltage for REGULATOR_TYPE_FIXED regulator\n");
>>> +               return -EINVAL;
>>> +       } else if (desc->volt_table) {
>>> +               for (i = 0; i < desc->vsel_mask; i++) {
>>> +                       if (*uV == desc->volt_table[i])
>>> +                               break;
>>> +               }
>>> +               if (i == desc->vsel_mask) {
>>> +                       debug("Unsupported voltage %u\n", *uV);
>>> +                       return -EINVAL;
>>> +               }
>>> +
>>> +               return pmic_clrsetbits(dev->parent, desc->vsel_reg,
>>> +                                      desc->vsel_mask, i);
>>> +       } else {
>>> +               if (uc_pdata->min_uV < 0) {
>>> +                       debug("Need to provide min_uV in dts.\n");
>>> +                       return -EINVAL;
>>> +               }
>>> +               return pmic_clrsetbits(dev->parent, desc->vsel_reg,
>>> +                                      desc->vsel_mask,
>>> +                                      (*uV - uc_pdata->min_uV) /
>>> desc->uV_step);
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int pfuze100_regulator_get_value(struct udevice *dev)
>>> +{
>>> +       int uV;
>>> +       int ret;
>>> +
>>> +       ret = pfuze100_regulator_val(dev, PMIC_OP_GET, &uV);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>> +       return uV;
>>> +}
>>> +
>>> +static int pfuze100_regulator_set_value(struct udevice *dev, int uV)
>>> +{
>>> +       return pfuze100_regulator_val(dev, PMIC_OP_SET, &uV);
>>> +}
>>> +
>>> +static bool pfuze100_regulator_get_enable(struct udevice *dev)
>>> +{
>>> +       int ret;
>>> +       bool enable = false;
>>> +
>>> +       ret = pfuze100_regulator_enable(dev, PMIC_OP_GET, &enable);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>> +       return enable;
>>> +}
>>> +
>>> +static int pfuze100_regulator_set_enable(struct udevice *dev, bool
>>> enable)
>>> +{
>>> +       return pfuze100_regulator_enable(dev, PMIC_OP_SET, &enable);
>>> +}
>>> +
>>> +static int pfuze100_regulator_get_mode(struct udevice *dev)
>>> +{
>>> +       int mode;
>>> +       int ret;
>>> +
>>> +       ret = pfuze100_regulator_mode(dev, PMIC_OP_GET, &mode);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>> +       return mode;
>>> +}
>>> +
>>> +static int pfuze100_regulator_set_mode(struct udevice *dev, int mode)
>>> +{
>>> +       return pfuze100_regulator_mode(dev, PMIC_OP_SET, &mode);
>>> +}
>>> +
>>> +static const struct dm_regulator_ops pfuze100_regulator_ops = {
>>> +       .get_value  = pfuze100_regulator_get_value,
>>> +       .set_value  = pfuze100_regulator_set_value,
>>> +       .get_enable = pfuze100_regulator_get_enable,
>>> +       .set_enable = pfuze100_regulator_set_enable,
>>> +       .get_mode   = pfuze100_regulator_get_mode,
>>> +       .set_mode   = pfuze100_regulator_set_mode,
>>> +};
>>> +
>>> +U_BOOT_DRIVER(pfuze100_regulator) = {
>>> +       .name = "pfuze100_regulator",
>>> +       .id = UCLASS_REGULATOR,
>>> +       .ops = &pfuze100_regulator_ops,
>>> +       .probe = pfuze100_regulator_probe,
>>
>>
>> You can use: sizeof(struct pfuze100_regulator_desc *)
>> It is only size of the pointer not an array.
>>
>>
>>> +       .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc
>
>BTW if you go with assigning the platdata pointer as above (which I
>think is a good idea) then you can drop the above line. The allocation
>is not needed if you assign the pointer to something else.
>
>>> **),
>>> +};
>>> diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
>>> index c40a976..41cb710 100644
>>> --- a/include/power/pfuze100_pmic.h
>>> +++ b/include/power/pfuze100_pmic.h
>>> @@ -62,6 +62,13 @@ enum {
>>>         PFUZE100_NUM_OF_REGS    = 0x7f,
>>>   };
>>>
>>> +/* Registor offset based on VOLT register */
>>> +#define PFUZE100_VOL_OFFSET    0
>>> +#define PFUZE100_STBY_OFFSET   1
>>> +#define PFUZE100_OFF_OFFSET    2
>>> +#define PFUZE100_MODE_OFFSET   3
>>> +#define PFUZE100_CONF_OFFSET   4
>>> +
>>>   /*
>>>    * Buck Regulators
>>>    */
>>> @@ -138,6 +145,9 @@ enum {
>>>   #define SW1x_STBY_MASK    0x3f
>>>   #define SW1x_OFF_MASK     0x3f
>>>
>>> +#define SW_MODE_MASK   0xf
>>> +#define SW_MODE_SHIFT  0
>>> +
>>>   #define SW1xCONF_DVSSPEED_MASK 0xc0
>>>   #define SW1xCONF_DVSSPEED_2US  0x00
>>>   #define SW1xCONF_DVSSPEED_4US  0x40
>>> @@ -186,7 +196,12 @@ enum {
>>>
>>>   #define LDO_VOL_MASK  0xf
>>>   #define LDO_EN                (1 << 4)
>>> +#define LDO_MODE_SHIFT 4
>>> +#define LDO_MODE_MASK  (1 << 4)
>>> +#define LDO_MODE_OFF   0
>>> +#define LDO_MODE_ON    1
>>>
>>> +#define VREFDDRCON_EN  (1 << 4)
>>>   /*
>>>    * Boost Regulator
>>>    */
>>> @@ -199,10 +214,11 @@ enum {
>>>
>>>   #define SWBST_VOL_MASK        0x3
>>>   #define SWBST_MODE_MASK       0xC
>>> -#define SWBST_MODE_OFF (0 << 2)
>>> -#define SWBST_MODE_PFM (1 << 2)
>>> -#define SWBST_MODE_AUTO        (2 << 2)
>>> -#define SWBST_MODE_APS (3 << 2)
>>> +#define SWBST_MODE_SHIFT 0x2
>>> +#define SWBST_MODE_OFF 0
>>> +#define SWBST_MODE_PFM 1
>>> +#define SWBST_MODE_AUTO        2
>>> +#define SWBST_MODE_APS 3
>>>
>>>   /*
>>>    * Regulator Mode Control
>>>
>>
>> Best regards,
>> --
>> Przemyslaw Marczak
>> Samsung R&D Institute Poland
>> Samsung Electronics
>> p.marczak at samsung.com
>
>Regards,
>Simon

-- 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support
  2015-08-04 13:10   ` Przemyslaw Marczak
@ 2015-08-04 13:21     ` Simon Glass
  2015-08-04 13:14       ` Peng Fan
  0 siblings, 1 reply; 14+ messages in thread
From: Simon Glass @ 2015-08-04 13:21 UTC (permalink / raw)
  To: u-boot

Hi,

On 4 August 2015 at 07:10, Przemyslaw Marczak <p.marczak@samsung.com> wrote:
> Hello Peng,
>
>
> On 08/04/2015 07:32 AM, Peng Fan wrote:
>>
>> 1. Add new regulator driver pfuze100.
>>     * Introduce struct pfuze100_regulator_desc for mataining info for
>> regulator.
>> 2. Add new Kconfig entry DM_REGULATOR_PFUZE100 for pfuze100.
>> 3. This driver intends to support PF100, PF200 and PF3000.
>> 4. Add related macro definition in pfuze header file.
>>
>> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
>> Cc: Przemyslaw Marczak <p.marczak@samsung.com>
>> Cc: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes v2:
>>   Addressed Simon's comments.
>>   1. Use pmic_reg_read/pmic_reg_write/pmic_clrsetbits
>>   2. blank line between declarations and rest

Would still like to see you device tree file somewhere.

>>
>> Hi Simon,
>>
>>   type case is still kept there:
>>   " struct pfuze100_regulator_desc *desc =
>>     *(struct pfuze100_regulator_desc **)dev_get_platdata(dev); "
>>   Also use pointer points to pointer type, "struct type **", see this
>> line:
>>   " .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc **),
>> "
>>
>>   Each regulator has its own pfuze_regulator_desc, single pointer can not
>> do
>>   the work well. For example:
>>   .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc *);
>>
>>   struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>>
>>   desc = se_desc(pfuze100_regulators, ARRAY_SIZE(pfuze100_regulators),
>>                 dev->name);
>>   what we changed here is only local variable desc, but not change the
>> pointer
>>   platdata. What I need here to set the pointer platdata to point to
>>   correct regulator descriptor. Single pointer can not handle this, so
>>   use "struct type **".
>>
>>
>>   drivers/power/regulator/Kconfig    |   8 +
>>   drivers/power/regulator/Makefile   |   1 +
>>   drivers/power/regulator/pfuze100.c | 554
>> +++++++++++++++++++++++++++++++++++++
>>   include/power/pfuze100_pmic.h      |  24 +-
>>   4 files changed, 583 insertions(+), 4 deletions(-)
>>   create mode 100644 drivers/power/regulator/pfuze100.c
>>
>> diff --git a/drivers/power/regulator/Kconfig
>> b/drivers/power/regulator/Kconfig
>> index 6289b83..b854773 100644
>> --- a/drivers/power/regulator/Kconfig
>> +++ b/drivers/power/regulator/Kconfig
>> @@ -16,6 +16,14 @@ config DM_REGULATOR
>>         for this purpose if PMIC I/O driver is implemented or
>> dm_scan_fdt_node()
>>         otherwise. Detailed information can be found in the header file.
>>
>> +config DM_REGULATOR_PFUZE100
>> +       bool "Enable Driver Model for REGULATOR PFUZE100"
>> +       depends on DM_REGULATOR && DM_PMIC_PFUZE100
>> +       ---help---
>> +       This config enables implementation of driver-model regulator
>> uclass
>> +       features for REGULATOR PFUZE100. The driver implements get/set api
>> for:
>> +       value, enable and mode.
>> +
>>   config DM_REGULATOR_MAX77686
>>         bool "Enable Driver Model for REGULATOR MAX77686"
>>         depends on DM_REGULATOR && DM_PMIC_MAX77686
>> diff --git a/drivers/power/regulator/Makefile
>> b/drivers/power/regulator/Makefile
>> index 96aa624..9f8f17b 100644
>> --- a/drivers/power/regulator/Makefile
>> +++ b/drivers/power/regulator/Makefile
>> @@ -7,5 +7,6 @@
>>
>>   obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
>>   obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
>> +obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
>>   obj-$(CONFIG_DM_REGULATOR_FIXED) += fixed.o
>>   obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
>> diff --git a/drivers/power/regulator/pfuze100.c
>> b/drivers/power/regulator/pfuze100.c
>> new file mode 100644
>> index 0000000..300aee8
>> --- /dev/null
>> +++ b/drivers/power/regulator/pfuze100.c
>> @@ -0,0 +1,554 @@
>> +#include <common.h>
>> +#include <fdtdec.h>
>> +#include <errno.h>
>> +#include <dm.h>
>> +#include <i2c.h>
>> +#include <power/pmic.h>
>> +#include <power/regulator.h>
>> +#include <power/pfuze100_pmic.h>
>> +
>> +/**
>> + * struct pfuze100_regulator_desc - regulator descriptor
>> + *
>> + * @name: Identify name for the regulator.
>> + * @type: Indicates the regulator type.
>> + * @uV_step: Voltage increase for each selector.
>> + * @vsel_reg: Register for adjust regulator voltage for normal.
>> + * @vsel_mask: Mask bit for setting regulator voltage for normal.
>> + * @stby_reg: Register for adjust regulator voltage for standby.
>> + * @stby_mask: Mask bit for setting regulator voltage for standby.
>> + * @volt_table: Voltage mapping table (if table based mapping).
>> + * @voltage: Current voltage for REGULATOR_TYPE_FIXED type regulator.
>> + */
>> +struct pfuze100_regulator_desc {
>> +       char *name;
>> +       enum regulator_type type;
>> +       unsigned int uV_step;
>> +       unsigned int vsel_reg;
>> +       unsigned int vsel_mask;
>> +       unsigned int stby_reg;
>> +       unsigned int stby_mask;
>> +       unsigned int *volt_table;
>> +       unsigned int voltage;
>> +};
>> +
>> +#define PFUZE100_FIXED_REG(_name, base, vol)                           \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_FIXED,           \
>> +               .voltage        =       (vol),                          \
>> +       }
>> +
>> +#define PFUZE100_SW_REG(_name, base, step)                             \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>> +               .uV_step        =       (step),                         \
>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>> +               .vsel_mask      =       0x3F,                           \
>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>> +               .stby_mask      =       0x3F,                           \
>> +       }
>> +
>> +#define PFUZE100_SWB_REG(_name, base, mask, step, voltages)            \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>> +               .uV_step        =       (step),                         \
>> +               .vsel_reg       =       (base),                         \
>> +               .vsel_mask      =       (mask),                         \
>> +               .volt_table     =       (voltages),                     \
>> +       }
>> +
>> +#define PFUZE100_SNVS_REG(_name, base, mask, voltages)                 \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_OTHER,           \
>> +               .vsel_reg       =       (base),                         \
>> +               .vsel_mask      =       (mask),                         \
>> +               .volt_table     =       (voltages),                     \
>> +       }
>> +
>> +#define PFUZE100_VGEN_REG(_name, base, step)                           \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_LDO,             \
>> +               .uV_step        =       (step),                         \
>> +               .vsel_reg       =       (base),                         \
>> +               .vsel_mask      =       0xF,                            \
>> +               .stby_reg       =       (base),                         \
>> +               .stby_mask      =       0x20,                           \
>> +       }
>> +
>> +#define PFUZE3000_VCC_REG(_name, base, step)                           \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_LDO,             \
>> +               .uV_step        =       (step),                         \
>> +               .vsel_reg       =       (base),                         \
>> +               .vsel_mask      =       0x3,                            \
>> +               .stby_reg       =       (base),                         \
>> +               .stby_mask      =       0x20,                           \
>> +}
>> +
>> +#define PFUZE3000_SW1_REG(_name, base, step)                           \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>> +               .uV_step        =       (step),                         \
>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>> +               .vsel_mask      =       0x1F,                           \
>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>> +               .stby_mask      =       0x1F,                           \
>> +       }
>> +
>> +#define PFUZE3000_SW2_REG(_name, base, step)                           \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>> +               .uV_step        =       (step),                         \
>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>> +               .vsel_mask      =       0x7,                            \
>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>> +               .stby_mask      =       0x7,                            \
>> +       }
>> +
>> +#define PFUZE3000_SW3_REG(_name, base, step)                           \
>> +       {                                                               \
>> +               .name           =       #_name,                         \
>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>> +               .uV_step        =       (step),                         \
>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>> +               .vsel_mask      =       0xF,                            \
>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>> +               .stby_mask      =       0xF,                            \
>> +       }
>> +
>> +static unsigned int pfuze100_swbst[] = {
>> +       5000000, 5050000, 5100000, 5150000
>> +};
>> +
>> +static unsigned int pfuze100_vsnvs[] = {
>> +       1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, -1
>> +};
>> +
>> +static unsigned int pfuze3000_vsnvs[] = {
>> +       -1, -1, -1, -1, -1, -1, 3000000, -1
>> +};
>> +
>> +static unsigned int pfuze3000_sw2lo[] = {
>> +       1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000,
>> 1850000
>> +};
>> +
>> +/* PFUZE100 */
>> +static struct pfuze100_regulator_desc pfuze100_regulators[] = {
>> +       PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
>> +       PFUZE100_SW_REG(sw1c, PFUZE100_SW1CVOL, 25000),
>> +       PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
>> +       PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
>> +       PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
>> +       PFUZE100_SW_REG(sw4, PFUZE100_SW4VOL, 25000),
>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>> pfuze100_swbst),
>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>> +       PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
>> +       PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
>> +       PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
>> +       PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
>> +       PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
>> +       PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
>> +};
>> +
>> +/* PFUZE200 */
>> +static struct pfuze100_regulator_desc pfuze200_regulators[] = {
>> +       PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
>> +       PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
>> +       PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
>> +       PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>> pfuze100_swbst),
>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>> +       PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
>> +       PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
>> +       PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
>> +       PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
>> +       PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
>> +       PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
>> +};
>> +
>> +/* PFUZE3000 */
>> +static struct pfuze100_regulator_desc pfuze3000_regulators[] = {
>> +       PFUZE3000_SW1_REG(sw1a, PFUZE100_SW1ABVOL, 25000),
>> +       PFUZE3000_SW1_REG(sw1b, PFUZE100_SW1CVOL, 25000),
>> +       PFUZE100_SWB_REG(sw2, PFUZE100_SW2VOL, 0x7, 50000,
>> pfuze3000_sw2lo),
>> +       PFUZE3000_SW3_REG(sw3, PFUZE100_SW3AVOL, 50000),
>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>> pfuze100_swbst),
>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze3000_vsnvs),
>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>> +       PFUZE100_VGEN_REG(vldo1, PFUZE100_VGEN1VOL, 100000),
>> +       PFUZE100_VGEN_REG(vldo2, PFUZE100_VGEN2VOL, 50000),
>> +       PFUZE3000_VCC_REG(vccsd, PFUZE100_VGEN3VOL, 150000),
>> +       PFUZE3000_VCC_REG(v33, PFUZE100_VGEN4VOL, 150000),
>> +       PFUZE100_VGEN_REG(vldo3, PFUZE100_VGEN5VOL, 100000),
>> +       PFUZE100_VGEN_REG(vldo4, PFUZE100_VGEN6VOL, 100000),
>> +};
>> +
>> +#define MODE(_id, _val, _name) { \
>> +       .id = _id, \
>> +       .register_value = _val, \
>> +       .name = _name, \
>> +}
>> +
>> +/* SWx Buck regulator mode */
>> +static struct dm_regulator_mode pfuze_sw_modes[] = {
>> +       MODE(OFF_OFF, OFF_OFF, "OFF_OFF"),
>> +       MODE(PWM_OFF, PWM_OFF, "PWM_OFF"),
>> +       MODE(PFM_OFF, PFM_OFF, "PFM_OFF"),
>> +       MODE(APS_OFF, APS_OFF, "APS_OFF"),
>> +       MODE(PWM_PWM, PWM_PWM, "PWM_PWM"),
>> +       MODE(PWM_APS, PWM_APS, "PWM_APS"),
>> +       MODE(APS_APS, APS_APS, "APS_APS"),
>> +       MODE(APS_PFM, APS_PFM, "APS_PFM"),
>> +       MODE(PWM_PFM, PWM_PFM, "PWM_PFM"),
>> +};
>> +
>> +/* Boost Buck regulator mode for normal operation */
>> +static struct dm_regulator_mode pfuze_swbst_modes[] = {
>> +       MODE(SWBST_MODE_OFF, SWBST_MODE_OFF , "SWBST_MODE_OFF"),
>> +       MODE(SWBST_MODE_PFM, SWBST_MODE_PFM, "SWBST_MODE_PFM"),
>> +       MODE(SWBST_MODE_AUTO, SWBST_MODE_AUTO, "SWBST_MODE_AUTO"),
>> +       MODE(SWBST_MODE_APS, SWBST_MODE_APS, "SWBST_MODE_APS"),
>> +};
>> +
>> +/* VGENx LDO regulator mode for normal operation */
>> +static struct dm_regulator_mode pfuze_ldo_modes[] = {
>> +       MODE(LDO_MODE_OFF, LDO_MODE_OFF, "LDO_MODE_OFF"),
>> +       MODE(LDO_MODE_ON, LDO_MODE_ON, "LDO_MODE_ON"),
>> +};
>> +
>> +static struct pfuze100_regulator_desc *se_desc(struct
>> pfuze100_regulator_desc *desc,
>> +                                              int size,
>> +                                              const char *name)
>> +{
>> +       int i;
>> +
>> +       for (i = 0; i < size; desc++) {
>> +               if (!strcmp(desc->name, name))
>> +                       return desc;
>> +               continue;
>> +       }
>> +
>> +       return NULL;
>> +}
>> +
>> +static int pfuze100_regulator_probe(struct udevice *dev)
>> +{
>> +       struct dm_regulator_uclass_platdata *uc_pdata;
>> +       struct pfuze100_regulator_desc **desc = dev_get_platdata(dev);
>
>
> Try this:
> struct pfuze100_regulator_desc *desc;
>
>> +
>> +       switch (dev_get_driver_data(dev_get_parent(dev))) {
>> +       case PFUZE100:
>> +               *desc = se_desc(pfuze100_regulators,
>> +                               ARRAY_SIZE(pfuze100_regulators),
>> +                               dev->name);
>
>
> Try this:
> desc = se_desc(..)
>
>> +               break;
>> +       case PFUZE200:
>> +               *desc = se_desc(pfuze200_regulators,
>> +                               ARRAY_SIZE(pfuze200_regulators),
>> +                               dev->name);
>> +               break;
>> +       case PFUZE3000:
>> +               *desc = se_desc(pfuze3000_regulators,
>> +                               ARRAY_SIZE(pfuze3000_regulators),
>> +                               dev->name);
>> +               break;
>> +       }
>> +       if (!*desc) {
>> +               debug("Do not support regulator %s\n", dev->name);
>> +               return -EINVAL;
>> +       }
>
>
> Try this:
>         dev->platdata = desc;
>
>> +
>> +       uc_pdata = dev_get_uclass_platdata(dev);
>> +
>
>
> Try this:
>         uc_pdata->type = desc->type;
>
>> +       uc_pdata->type = (*desc)->type;
>> +       if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
>> +               if (!strcmp(dev->name, "swbst")) {
>> +                       uc_pdata->mode = pfuze_swbst_modes;
>> +                       uc_pdata->mode_count =
>> ARRAY_SIZE(pfuze_swbst_modes);
>> +               } else {
>> +                       uc_pdata->mode = pfuze_sw_modes;
>> +                       uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes);
>> +               }
>> +       } else if (uc_pdata->type == REGULATOR_TYPE_LDO) {
>> +               uc_pdata->mode = pfuze_ldo_modes;
>> +               uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes);
>> +       } else {
>> +               uc_pdata->mode = NULL;
>> +               uc_pdata->mode_count = 0;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int pfuze100_regulator_mode(struct udevice *dev, int op, int
>> *opmode)
>> +{
>> +       unsigned char val;
>
>
> Try this:
> struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>
>> +       struct pfuze100_regulator_desc *desc =
>> +               *(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
>> +
>> +       if (op == PMIC_OP_GET) {
>> +               if (desc->type == REGULATOR_TYPE_BUCK) {
>> +                       if (!strcmp(dev->name, "swbst")) {
>> +                               val = pmic_reg_read(dev->parent,
>> +                                                   desc->vsel_reg);
>> +                               if (val < 0)
>> +                                       return val;
>> +
>> +                               val &= SWBST_MODE_MASK;
>> +                               val >>= SWBST_MODE_SHIFT;
>> +                               *opmode = val;
>> +
>> +                               return 0;
>> +                       }
>> +                       val = pmic_reg_read(dev->parent,
>> +                                           desc->vsel_reg +
>> +                                           PFUZE100_MODE_OFFSET);
>> +                       if (val < 0)
>> +                               return val;
>> +
>> +                       val &= SW_MODE_MASK;
>> +                       val >>= SW_MODE_SHIFT;
>> +                       *opmode = val;
>> +
>> +                       return 0;
>> +
>> +               } else if (desc->type == REGULATOR_TYPE_LDO) {
>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>> +                       if (val < 0)
>> +                               return val;
>> +
>> +                       val &= LDO_MODE_MASK;
>> +                       val >>= LDO_MODE_SHIFT;
>> +                       *opmode = val;
>> +
>> +                       return 0;
>> +               } else {
>> +                       return -EINVAL;
>> +               }
>> +       }
>> +
>> +       if (desc->type == REGULATOR_TYPE_BUCK) {
>> +               if (!strcmp(dev->name, "swbst"))
>> +                       return pmic_clrsetbits(dev->parent,
>> desc->vsel_reg,
>> +                                              SWBST_MODE_MASK,
>> +                                              *opmode <<
>> SWBST_MODE_SHIFT);
>> +
>> +               val = pmic_clrsetbits(dev->parent,
>> +                                      desc->vsel_reg +
>> PFUZE100_MODE_OFFSET,
>> +                                      SW_MODE_MASK,
>> +                                      *opmode << SW_MODE_SHIFT);
>> +
>> +       } else if (desc->type == REGULATOR_TYPE_LDO) {
>> +               val = pmic_clrsetbits(dev->parent, desc->vsel_reg,
>> +                                      LDO_MODE_MASK,
>> +                                      *opmode << LDO_MODE_SHIFT);
>> +               return val;
>> +       } else {
>> +               return -EINVAL;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int pfuze100_regulator_enable(struct udevice *dev, int op, bool
>> *enable)
>> +{
>> +       unsigned char val;
>> +       int ret, on_off;
>> +       struct dm_regulator_uclass_platdata *uc_pdata =
>> +               dev_get_uclass_platdata(dev);
>> +
>> +       if (op == PMIC_OP_GET) {
>> +               if (!strcmp(dev->name, "vrefddr")) {
>> +                       val = pmic_reg_read(dev->parent,
>> PFUZE100_VREFDDRCON);
>> +                       if (val < 0)
>> +                               return val;
>> +
>> +                       if (val & VREFDDRCON_EN)
>> +                               *enable = true;
>> +                       else
>> +                               *enable = false;
>> +                       return 0;
>> +               }
>> +               ret = pfuze100_regulator_mode(dev, op, &on_off);
>> +               if (ret)
>> +                       return ret;
>> +               switch (on_off) {
>> +               /* OFF_OFF, SWBST_MODE_OFF, LDO_MODE_OFF have same value
>> */
>> +               case OFF_OFF:
>> +                       *enable = false;
>> +                       break;
>> +               default:
>> +                       *enable = true;
>> +                       break;
>> +               }
>> +       } else if (op == PMIC_OP_SET) {
>> +               if (!strcmp(dev->name, "vrefddr")) {
>> +                       val = pmic_reg_read(dev->parent,
>> PFUZE100_VREFDDRCON);
>> +                       if (val < 0)
>> +                               return val;
>> +
>> +                       if (val & VREFDDRCON_EN)
>> +                               return 0;
>> +                       val |= VREFDDRCON_EN;
>> +
>> +                       return pmic_reg_write(dev->parent,
>> PFUZE100_VREFDDRCON,
>> +                                             val);
>> +               }
>> +
>> +               if (uc_pdata->type == REGULATOR_TYPE_LDO) {
>> +                       on_off = *enable ? LDO_MODE_ON : LDO_MODE_OFF;
>> +               } else if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
>> +                       if (!strcmp(dev->name, "swbst"))
>> +                               on_off = *enable ? SWBST_MODE_AUTO :
>> +                                       SWBST_MODE_OFF;
>> +                       else
>> +                               on_off = *enable ? APS_PFM : OFF_OFF;
>> +               } else {
>> +                       return -EINVAL;
>> +               }
>> +
>> +               return pfuze100_regulator_mode(dev, op, &on_off);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV)
>> +{
>> +       unsigned char val;
>> +       int i;
>
>
> Try this:
> struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>
>> +       struct pfuze100_regulator_desc *desc =
>> +               *(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
>> +       struct dm_regulator_uclass_platdata *uc_pdata =
>> +               dev_get_uclass_platdata(dev);
>> +
>> +       if (op == PMIC_OP_GET) {
>> +               *uV = 0;
>> +               if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
>> +                       *uV = desc->voltage;
>> +               } else if (desc->volt_table) {
>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>> +                       if (val < 0)
>> +                               return val;
>> +                       val &= desc->vsel_mask;
>> +                       *uV = desc->volt_table[val];
>> +               } else {
>> +                       if (uc_pdata->min_uV < 0) {
>> +                               debug("Need to provide min_uV in dts.\n");
>> +                               return -EINVAL;
>> +                       }
>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>> +                       if (val < 0)
>> +                               return val;
>> +                       val &= desc->vsel_mask;
>> +                       *uV = uc_pdata->min_uV + (int)val * desc->uV_step;
>> +               }
>> +
>> +               return 0;
>> +       }
>> +
>> +       if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
>> +               debug("Set voltage for REGULATOR_TYPE_FIXED regulator\n");
>> +               return -EINVAL;
>> +       } else if (desc->volt_table) {
>> +               for (i = 0; i < desc->vsel_mask; i++) {
>> +                       if (*uV == desc->volt_table[i])
>> +                               break;
>> +               }
>> +               if (i == desc->vsel_mask) {
>> +                       debug("Unsupported voltage %u\n", *uV);
>> +                       return -EINVAL;
>> +               }
>> +
>> +               return pmic_clrsetbits(dev->parent, desc->vsel_reg,
>> +                                      desc->vsel_mask, i);
>> +       } else {
>> +               if (uc_pdata->min_uV < 0) {
>> +                       debug("Need to provide min_uV in dts.\n");
>> +                       return -EINVAL;
>> +               }
>> +               return pmic_clrsetbits(dev->parent, desc->vsel_reg,
>> +                                      desc->vsel_mask,
>> +                                      (*uV - uc_pdata->min_uV) /
>> desc->uV_step);
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int pfuze100_regulator_get_value(struct udevice *dev)
>> +{
>> +       int uV;
>> +       int ret;
>> +
>> +       ret = pfuze100_regulator_val(dev, PMIC_OP_GET, &uV);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return uV;
>> +}
>> +
>> +static int pfuze100_regulator_set_value(struct udevice *dev, int uV)
>> +{
>> +       return pfuze100_regulator_val(dev, PMIC_OP_SET, &uV);
>> +}
>> +
>> +static bool pfuze100_regulator_get_enable(struct udevice *dev)
>> +{
>> +       int ret;
>> +       bool enable = false;
>> +
>> +       ret = pfuze100_regulator_enable(dev, PMIC_OP_GET, &enable);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return enable;
>> +}
>> +
>> +static int pfuze100_regulator_set_enable(struct udevice *dev, bool
>> enable)
>> +{
>> +       return pfuze100_regulator_enable(dev, PMIC_OP_SET, &enable);
>> +}
>> +
>> +static int pfuze100_regulator_get_mode(struct udevice *dev)
>> +{
>> +       int mode;
>> +       int ret;
>> +
>> +       ret = pfuze100_regulator_mode(dev, PMIC_OP_GET, &mode);
>> +       if (ret)
>> +               return ret;
>> +
>> +       return mode;
>> +}
>> +
>> +static int pfuze100_regulator_set_mode(struct udevice *dev, int mode)
>> +{
>> +       return pfuze100_regulator_mode(dev, PMIC_OP_SET, &mode);
>> +}
>> +
>> +static const struct dm_regulator_ops pfuze100_regulator_ops = {
>> +       .get_value  = pfuze100_regulator_get_value,
>> +       .set_value  = pfuze100_regulator_set_value,
>> +       .get_enable = pfuze100_regulator_get_enable,
>> +       .set_enable = pfuze100_regulator_set_enable,
>> +       .get_mode   = pfuze100_regulator_get_mode,
>> +       .set_mode   = pfuze100_regulator_set_mode,
>> +};
>> +
>> +U_BOOT_DRIVER(pfuze100_regulator) = {
>> +       .name = "pfuze100_regulator",
>> +       .id = UCLASS_REGULATOR,
>> +       .ops = &pfuze100_regulator_ops,
>> +       .probe = pfuze100_regulator_probe,
>
>
> You can use: sizeof(struct pfuze100_regulator_desc *)
> It is only size of the pointer not an array.
>
>
>> +       .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc

BTW if you go with assigning the platdata pointer as above (which I
think is a good idea) then you can drop the above line. The allocation
is not needed if you assign the pointer to something else.

>> **),
>> +};
>> diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
>> index c40a976..41cb710 100644
>> --- a/include/power/pfuze100_pmic.h
>> +++ b/include/power/pfuze100_pmic.h
>> @@ -62,6 +62,13 @@ enum {
>>         PFUZE100_NUM_OF_REGS    = 0x7f,
>>   };
>>
>> +/* Registor offset based on VOLT register */
>> +#define PFUZE100_VOL_OFFSET    0
>> +#define PFUZE100_STBY_OFFSET   1
>> +#define PFUZE100_OFF_OFFSET    2
>> +#define PFUZE100_MODE_OFFSET   3
>> +#define PFUZE100_CONF_OFFSET   4
>> +
>>   /*
>>    * Buck Regulators
>>    */
>> @@ -138,6 +145,9 @@ enum {
>>   #define SW1x_STBY_MASK    0x3f
>>   #define SW1x_OFF_MASK     0x3f
>>
>> +#define SW_MODE_MASK   0xf
>> +#define SW_MODE_SHIFT  0
>> +
>>   #define SW1xCONF_DVSSPEED_MASK 0xc0
>>   #define SW1xCONF_DVSSPEED_2US  0x00
>>   #define SW1xCONF_DVSSPEED_4US  0x40
>> @@ -186,7 +196,12 @@ enum {
>>
>>   #define LDO_VOL_MASK  0xf
>>   #define LDO_EN                (1 << 4)
>> +#define LDO_MODE_SHIFT 4
>> +#define LDO_MODE_MASK  (1 << 4)
>> +#define LDO_MODE_OFF   0
>> +#define LDO_MODE_ON    1
>>
>> +#define VREFDDRCON_EN  (1 << 4)
>>   /*
>>    * Boost Regulator
>>    */
>> @@ -199,10 +214,11 @@ enum {
>>
>>   #define SWBST_VOL_MASK        0x3
>>   #define SWBST_MODE_MASK       0xC
>> -#define SWBST_MODE_OFF (0 << 2)
>> -#define SWBST_MODE_PFM (1 << 2)
>> -#define SWBST_MODE_AUTO        (2 << 2)
>> -#define SWBST_MODE_APS (3 << 2)
>> +#define SWBST_MODE_SHIFT 0x2
>> +#define SWBST_MODE_OFF 0
>> +#define SWBST_MODE_PFM 1
>> +#define SWBST_MODE_AUTO        2
>> +#define SWBST_MODE_APS 3
>>
>>   /*
>>    * Regulator Mode Control
>>
>
> Best regards,
> --
> Przemyslaw Marczak
> Samsung R&D Institute Poland
> Samsung Electronics
> p.marczak at samsung.com

Regards,
Simon

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support
  2015-08-04 13:14       ` Peng Fan
@ 2015-08-06  4:52         ` Peng Fan
  0 siblings, 0 replies; 14+ messages in thread
From: Peng Fan @ 2015-08-06  4:52 UTC (permalink / raw)
  To: u-boot

On Tue, Aug 04, 2015 at 09:14:17PM +0800, Peng Fan wrote:
>On Tue, Aug 04, 2015 at 07:21:05AM -0600, Simon Glass wrote:
>>Hi,
>>
>>On 4 August 2015 at 07:10, Przemyslaw Marczak <p.marczak@samsung.com> wrote:
>>> Hello Peng,
>>>
>>>
>>> On 08/04/2015 07:32 AM, Peng Fan wrote:
>>>>
>>>> 1. Add new regulator driver pfuze100.
>>>>     * Introduce struct pfuze100_regulator_desc for mataining info for
>>>> regulator.
>>>> 2. Add new Kconfig entry DM_REGULATOR_PFUZE100 for pfuze100.
>>>> 3. This driver intends to support PF100, PF200 and PF3000.
>>>> 4. Add related macro definition in pfuze header file.
>>>>
>>>> Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
>>>> Cc: Przemyslaw Marczak <p.marczak@samsung.com>
>>>> Cc: Simon Glass <sjg@chromium.org>
>>>> ---
>>>>
>>>> Changes v2:
>>>>   Addressed Simon's comments.
>>>>   1. Use pmic_reg_read/pmic_reg_write/pmic_clrsetbits
>>>>   2. blank line between declarations and rest
>>
>>Would still like to see you device tree file somewhere.
>
>See: http://lxr.free-electrons.com/source/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
>line from 208 to 306.
>

Simon,

Do you have further comments about this patch regarding the device tree?
I plan to work out V3 patch.

>>
>>>>
>>>> Hi Simon,
>>>>
>>>>   type case is still kept there:
>>>>   " struct pfuze100_regulator_desc *desc =
>>>>     *(struct pfuze100_regulator_desc **)dev_get_platdata(dev); "

Przemyslaw,

I use the way Simon suggested to me and discard the double pointer.
struct pfuze_platdata {
	struct pfuze100_regulator_desc *desc;
};

>>>>   Also use pointer points to pointer type, "struct type **", see this
>>>> line:
>>>>   " .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc **),
>>>> "
>>>>
>>>>   Each regulator has its own pfuze_regulator_desc, single pointer can not
>>>> do
>>>>   the work well. For example:
>>>>   .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc *);
>>>>
>>>>   struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>>>>
>>>>   desc = se_desc(pfuze100_regulators, ARRAY_SIZE(pfuze100_regulators),
>>>>                 dev->name);
>>>>   what we changed here is only local variable desc, but not change the
>>>> pointer
>>>>   platdata. What I need here to set the pointer platdata to point to
>>>>   correct regulator descriptor. Single pointer can not handle this, so
>>>>   use "struct type **".
>>>>
>>>>
>>>>   drivers/power/regulator/Kconfig    |   8 +
>>>>   drivers/power/regulator/Makefile   |   1 +
>>>>   drivers/power/regulator/pfuze100.c | 554
>>>> +++++++++++++++++++++++++++++++++++++
>>>>   include/power/pfuze100_pmic.h      |  24 +-
>>>>   4 files changed, 583 insertions(+), 4 deletions(-)
>>>>   create mode 100644 drivers/power/regulator/pfuze100.c
>>>>
>>>> diff --git a/drivers/power/regulator/Kconfig
>>>> b/drivers/power/regulator/Kconfig
>>>> index 6289b83..b854773 100644
>>>> --- a/drivers/power/regulator/Kconfig
>>>> +++ b/drivers/power/regulator/Kconfig
>>>> @@ -16,6 +16,14 @@ config DM_REGULATOR
>>>>         for this purpose if PMIC I/O driver is implemented or
>>>> dm_scan_fdt_node()
>>>>         otherwise. Detailed information can be found in the header file.
>>>>
>>>> +config DM_REGULATOR_PFUZE100
>>>> +       bool "Enable Driver Model for REGULATOR PFUZE100"
>>>> +       depends on DM_REGULATOR && DM_PMIC_PFUZE100
>>>> +       ---help---
>>>> +       This config enables implementation of driver-model regulator
>>>> uclass
>>>> +       features for REGULATOR PFUZE100. The driver implements get/set api
>>>> for:
>>>> +       value, enable and mode.
>>>> +
>>>>   config DM_REGULATOR_MAX77686
>>>>         bool "Enable Driver Model for REGULATOR MAX77686"
>>>>         depends on DM_REGULATOR && DM_PMIC_MAX77686
>>>> diff --git a/drivers/power/regulator/Makefile
>>>> b/drivers/power/regulator/Makefile
>>>> index 96aa624..9f8f17b 100644
>>>> --- a/drivers/power/regulator/Makefile
>>>> +++ b/drivers/power/regulator/Makefile
>>>> @@ -7,5 +7,6 @@
>>>>
>>>>   obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
>>>>   obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
>>>> +obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
>>>>   obj-$(CONFIG_DM_REGULATOR_FIXED) += fixed.o
>>>>   obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
>>>> diff --git a/drivers/power/regulator/pfuze100.c
>>>> b/drivers/power/regulator/pfuze100.c
>>>> new file mode 100644
>>>> index 0000000..300aee8
>>>> --- /dev/null
>>>> +++ b/drivers/power/regulator/pfuze100.c
>>>> @@ -0,0 +1,554 @@
>>>> +#include <common.h>
>>>> +#include <fdtdec.h>
>>>> +#include <errno.h>
>>>> +#include <dm.h>
>>>> +#include <i2c.h>
>>>> +#include <power/pmic.h>
>>>> +#include <power/regulator.h>
>>>> +#include <power/pfuze100_pmic.h>
>>>> +
>>>> +/**
>>>> + * struct pfuze100_regulator_desc - regulator descriptor
>>>> + *
>>>> + * @name: Identify name for the regulator.
>>>> + * @type: Indicates the regulator type.
>>>> + * @uV_step: Voltage increase for each selector.
>>>> + * @vsel_reg: Register for adjust regulator voltage for normal.
>>>> + * @vsel_mask: Mask bit for setting regulator voltage for normal.
>>>> + * @stby_reg: Register for adjust regulator voltage for standby.
>>>> + * @stby_mask: Mask bit for setting regulator voltage for standby.
>>>> + * @volt_table: Voltage mapping table (if table based mapping).
>>>> + * @voltage: Current voltage for REGULATOR_TYPE_FIXED type regulator.
>>>> + */
>>>> +struct pfuze100_regulator_desc {
>>>> +       char *name;
>>>> +       enum regulator_type type;
>>>> +       unsigned int uV_step;
>>>> +       unsigned int vsel_reg;
>>>> +       unsigned int vsel_mask;
>>>> +       unsigned int stby_reg;
>>>> +       unsigned int stby_mask;
>>>> +       unsigned int *volt_table;
>>>> +       unsigned int voltage;
>>>> +};
>>>> +
>>>> +#define PFUZE100_FIXED_REG(_name, base, vol)                           \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_FIXED,           \
>>>> +               .voltage        =       (vol),                          \
>>>> +       }
>>>> +
>>>> +#define PFUZE100_SW_REG(_name, base, step)                             \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>>> +               .uV_step        =       (step),                         \
>>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>>> +               .vsel_mask      =       0x3F,                           \
>>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>>> +               .stby_mask      =       0x3F,                           \
>>>> +       }
>>>> +
>>>> +#define PFUZE100_SWB_REG(_name, base, mask, step, voltages)            \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>>> +               .uV_step        =       (step),                         \
>>>> +               .vsel_reg       =       (base),                         \
>>>> +               .vsel_mask      =       (mask),                         \
>>>> +               .volt_table     =       (voltages),                     \
>>>> +       }
>>>> +
>>>> +#define PFUZE100_SNVS_REG(_name, base, mask, voltages)                 \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_OTHER,           \
>>>> +               .vsel_reg       =       (base),                         \
>>>> +               .vsel_mask      =       (mask),                         \
>>>> +               .volt_table     =       (voltages),                     \
>>>> +       }
>>>> +
>>>> +#define PFUZE100_VGEN_REG(_name, base, step)                           \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_LDO,             \
>>>> +               .uV_step        =       (step),                         \
>>>> +               .vsel_reg       =       (base),                         \
>>>> +               .vsel_mask      =       0xF,                            \
>>>> +               .stby_reg       =       (base),                         \
>>>> +               .stby_mask      =       0x20,                           \
>>>> +       }
>>>> +
>>>> +#define PFUZE3000_VCC_REG(_name, base, step)                           \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_LDO,             \
>>>> +               .uV_step        =       (step),                         \
>>>> +               .vsel_reg       =       (base),                         \
>>>> +               .vsel_mask      =       0x3,                            \
>>>> +               .stby_reg       =       (base),                         \
>>>> +               .stby_mask      =       0x20,                           \
>>>> +}
>>>> +
>>>> +#define PFUZE3000_SW1_REG(_name, base, step)                           \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>>> +               .uV_step        =       (step),                         \
>>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>>> +               .vsel_mask      =       0x1F,                           \
>>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>>> +               .stby_mask      =       0x1F,                           \
>>>> +       }
>>>> +
>>>> +#define PFUZE3000_SW2_REG(_name, base, step)                           \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>>> +               .uV_step        =       (step),                         \
>>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>>> +               .vsel_mask      =       0x7,                            \
>>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>>> +               .stby_mask      =       0x7,                            \
>>>> +       }
>>>> +
>>>> +#define PFUZE3000_SW3_REG(_name, base, step)                           \
>>>> +       {                                                               \
>>>> +               .name           =       #_name,                         \
>>>> +               .type           =       REGULATOR_TYPE_BUCK,            \
>>>> +               .uV_step        =       (step),                         \
>>>> +               .vsel_reg       =       (base) + PFUZE100_VOL_OFFSET,   \
>>>> +               .vsel_mask      =       0xF,                            \
>>>> +               .stby_reg       =       (base) + PFUZE100_STBY_OFFSET,  \
>>>> +               .stby_mask      =       0xF,                            \
>>>> +       }
>>>> +
>>>> +static unsigned int pfuze100_swbst[] = {
>>>> +       5000000, 5050000, 5100000, 5150000
>>>> +};
>>>> +
>>>> +static unsigned int pfuze100_vsnvs[] = {
>>>> +       1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, -1
>>>> +};
>>>> +
>>>> +static unsigned int pfuze3000_vsnvs[] = {
>>>> +       -1, -1, -1, -1, -1, -1, 3000000, -1
>>>> +};
>>>> +
>>>> +static unsigned int pfuze3000_sw2lo[] = {
>>>> +       1500000, 1550000, 1600000, 1650000, 1700000, 1750000, 1800000,
>>>> 1850000
>>>> +};
>>>> +
>>>> +/* PFUZE100 */
>>>> +static struct pfuze100_regulator_desc pfuze100_regulators[] = {
>>>> +       PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
>>>> +       PFUZE100_SW_REG(sw1c, PFUZE100_SW1CVOL, 25000),
>>>> +       PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
>>>> +       PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
>>>> +       PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
>>>> +       PFUZE100_SW_REG(sw4, PFUZE100_SW4VOL, 25000),
>>>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>>>> pfuze100_swbst),
>>>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
>>>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>>>> +       PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
>>>> +       PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
>>>> +       PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
>>>> +};
>>>> +
>>>> +/* PFUZE200 */
>>>> +static struct pfuze100_regulator_desc pfuze200_regulators[] = {
>>>> +       PFUZE100_SW_REG(sw1ab, PFUZE100_SW1ABVOL, 25000),
>>>> +       PFUZE100_SW_REG(sw2, PFUZE100_SW2VOL, 25000),
>>>> +       PFUZE100_SW_REG(sw3a, PFUZE100_SW3AVOL, 25000),
>>>> +       PFUZE100_SW_REG(sw3b, PFUZE100_SW3BVOL, 25000),
>>>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>>>> pfuze100_swbst),
>>>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
>>>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>>>> +       PFUZE100_VGEN_REG(vgen1, PFUZE100_VGEN1VOL, 50000),
>>>> +       PFUZE100_VGEN_REG(vgen2, PFUZE100_VGEN2VOL, 50000),
>>>> +       PFUZE100_VGEN_REG(vgen3, PFUZE100_VGEN3VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vgen4, PFUZE100_VGEN4VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vgen5, PFUZE100_VGEN5VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vgen6, PFUZE100_VGEN6VOL, 100000),
>>>> +};
>>>> +
>>>> +/* PFUZE3000 */
>>>> +static struct pfuze100_regulator_desc pfuze3000_regulators[] = {
>>>> +       PFUZE3000_SW1_REG(sw1a, PFUZE100_SW1ABVOL, 25000),
>>>> +       PFUZE3000_SW1_REG(sw1b, PFUZE100_SW1CVOL, 25000),
>>>> +       PFUZE100_SWB_REG(sw2, PFUZE100_SW2VOL, 0x7, 50000,
>>>> pfuze3000_sw2lo),
>>>> +       PFUZE3000_SW3_REG(sw3, PFUZE100_SW3AVOL, 50000),
>>>> +       PFUZE100_SWB_REG(swbst, PFUZE100_SWBSTCON1, 0x3, 50000,
>>>> pfuze100_swbst),
>>>> +       PFUZE100_SNVS_REG(vsnvs, PFUZE100_VSNVSVOL, 0x7, pfuze3000_vsnvs),
>>>> +       PFUZE100_FIXED_REG(vrefddr, PFUZE100_VREFDDRCON, 750000),
>>>> +       PFUZE100_VGEN_REG(vldo1, PFUZE100_VGEN1VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vldo2, PFUZE100_VGEN2VOL, 50000),
>>>> +       PFUZE3000_VCC_REG(vccsd, PFUZE100_VGEN3VOL, 150000),
>>>> +       PFUZE3000_VCC_REG(v33, PFUZE100_VGEN4VOL, 150000),
>>>> +       PFUZE100_VGEN_REG(vldo3, PFUZE100_VGEN5VOL, 100000),
>>>> +       PFUZE100_VGEN_REG(vldo4, PFUZE100_VGEN6VOL, 100000),
>>>> +};
>>>> +
>>>> +#define MODE(_id, _val, _name) { \
>>>> +       .id = _id, \
>>>> +       .register_value = _val, \
>>>> +       .name = _name, \
>>>> +}
>>>> +
>>>> +/* SWx Buck regulator mode */
>>>> +static struct dm_regulator_mode pfuze_sw_modes[] = {
>>>> +       MODE(OFF_OFF, OFF_OFF, "OFF_OFF"),
>>>> +       MODE(PWM_OFF, PWM_OFF, "PWM_OFF"),
>>>> +       MODE(PFM_OFF, PFM_OFF, "PFM_OFF"),
>>>> +       MODE(APS_OFF, APS_OFF, "APS_OFF"),
>>>> +       MODE(PWM_PWM, PWM_PWM, "PWM_PWM"),
>>>> +       MODE(PWM_APS, PWM_APS, "PWM_APS"),
>>>> +       MODE(APS_APS, APS_APS, "APS_APS"),
>>>> +       MODE(APS_PFM, APS_PFM, "APS_PFM"),
>>>> +       MODE(PWM_PFM, PWM_PFM, "PWM_PFM"),
>>>> +};
>>>> +
>>>> +/* Boost Buck regulator mode for normal operation */
>>>> +static struct dm_regulator_mode pfuze_swbst_modes[] = {
>>>> +       MODE(SWBST_MODE_OFF, SWBST_MODE_OFF , "SWBST_MODE_OFF"),
>>>> +       MODE(SWBST_MODE_PFM, SWBST_MODE_PFM, "SWBST_MODE_PFM"),
>>>> +       MODE(SWBST_MODE_AUTO, SWBST_MODE_AUTO, "SWBST_MODE_AUTO"),
>>>> +       MODE(SWBST_MODE_APS, SWBST_MODE_APS, "SWBST_MODE_APS"),
>>>> +};
>>>> +
>>>> +/* VGENx LDO regulator mode for normal operation */
>>>> +static struct dm_regulator_mode pfuze_ldo_modes[] = {
>>>> +       MODE(LDO_MODE_OFF, LDO_MODE_OFF, "LDO_MODE_OFF"),
>>>> +       MODE(LDO_MODE_ON, LDO_MODE_ON, "LDO_MODE_ON"),
>>>> +};
>>>> +
>>>> +static struct pfuze100_regulator_desc *se_desc(struct
>>>> pfuze100_regulator_desc *desc,
>>>> +                                              int size,
>>>> +                                              const char *name)
>>>> +{
>>>> +       int i;
>>>> +
>>>> +       for (i = 0; i < size; desc++) {
>>>> +               if (!strcmp(desc->name, name))
>>>> +                       return desc;
>>>> +               continue;
>>>> +       }
>>>> +
>>>> +       return NULL;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_probe(struct udevice *dev)
>>>> +{
>>>> +       struct dm_regulator_uclass_platdata *uc_pdata;
>>>> +       struct pfuze100_regulator_desc **desc = dev_get_platdata(dev);
>>>
>>>
>>> Try this:
>>> struct pfuze100_regulator_desc *desc;
>>>
>>>> +
>>>> +       switch (dev_get_driver_data(dev_get_parent(dev))) {
>>>> +       case PFUZE100:
>>>> +               *desc = se_desc(pfuze100_regulators,
>>>> +                               ARRAY_SIZE(pfuze100_regulators),
>>>> +                               dev->name);
>>>
>>>
>>> Try this:
>>> desc = se_desc(..)
>>>
>>>> +               break;
>>>> +       case PFUZE200:
>>>> +               *desc = se_desc(pfuze200_regulators,
>>>> +                               ARRAY_SIZE(pfuze200_regulators),
>>>> +                               dev->name);
>>>> +               break;
>>>> +       case PFUZE3000:
>>>> +               *desc = se_desc(pfuze3000_regulators,
>>>> +                               ARRAY_SIZE(pfuze3000_regulators),
>>>> +                               dev->name);
>>>> +               break;
>>>> +       }
>>>> +       if (!*desc) {
>>>> +               debug("Do not support regulator %s\n", dev->name);
>>>> +               return -EINVAL;
>>>> +       }
>>>
>>>
>>> Try this:
>>>         dev->platdata = desc;
>>>
>>>> +
>>>> +       uc_pdata = dev_get_uclass_platdata(dev);
>>>> +
>>>
>>>
>>> Try this:
>>>         uc_pdata->type = desc->type;
>>>
>>>> +       uc_pdata->type = (*desc)->type;
>>>> +       if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
>>>> +               if (!strcmp(dev->name, "swbst")) {
>>>> +                       uc_pdata->mode = pfuze_swbst_modes;
>>>> +                       uc_pdata->mode_count =
>>>> ARRAY_SIZE(pfuze_swbst_modes);
>>>> +               } else {
>>>> +                       uc_pdata->mode = pfuze_sw_modes;
>>>> +                       uc_pdata->mode_count = ARRAY_SIZE(pfuze_sw_modes);
>>>> +               }
>>>> +       } else if (uc_pdata->type == REGULATOR_TYPE_LDO) {
>>>> +               uc_pdata->mode = pfuze_ldo_modes;
>>>> +               uc_pdata->mode_count = ARRAY_SIZE(pfuze_ldo_modes);
>>>> +       } else {
>>>> +               uc_pdata->mode = NULL;
>>>> +               uc_pdata->mode_count = 0;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_mode(struct udevice *dev, int op, int
>>>> *opmode)
>>>> +{
>>>> +       unsigned char val;
>>>
>>>
>>> Try this:
>>> struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>>>
>>>> +       struct pfuze100_regulator_desc *desc =
>>>> +               *(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
>>>> +
>>>> +       if (op == PMIC_OP_GET) {
>>>> +               if (desc->type == REGULATOR_TYPE_BUCK) {
>>>> +                       if (!strcmp(dev->name, "swbst")) {
>>>> +                               val = pmic_reg_read(dev->parent,
>>>> +                                                   desc->vsel_reg);
>>>> +                               if (val < 0)
>>>> +                                       return val;
>>>> +
>>>> +                               val &= SWBST_MODE_MASK;
>>>> +                               val >>= SWBST_MODE_SHIFT;
>>>> +                               *opmode = val;
>>>> +
>>>> +                               return 0;
>>>> +                       }
>>>> +                       val = pmic_reg_read(dev->parent,
>>>> +                                           desc->vsel_reg +
>>>> +                                           PFUZE100_MODE_OFFSET);
>>>> +                       if (val < 0)
>>>> +                               return val;
>>>> +
>>>> +                       val &= SW_MODE_MASK;
>>>> +                       val >>= SW_MODE_SHIFT;
>>>> +                       *opmode = val;
>>>> +
>>>> +                       return 0;
>>>> +
>>>> +               } else if (desc->type == REGULATOR_TYPE_LDO) {
>>>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>>>> +                       if (val < 0)
>>>> +                               return val;
>>>> +
>>>> +                       val &= LDO_MODE_MASK;
>>>> +                       val >>= LDO_MODE_SHIFT;
>>>> +                       *opmode = val;
>>>> +
>>>> +                       return 0;
>>>> +               } else {
>>>> +                       return -EINVAL;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       if (desc->type == REGULATOR_TYPE_BUCK) {
>>>> +               if (!strcmp(dev->name, "swbst"))
>>>> +                       return pmic_clrsetbits(dev->parent,
>>>> desc->vsel_reg,
>>>> +                                              SWBST_MODE_MASK,
>>>> +                                              *opmode <<
>>>> SWBST_MODE_SHIFT);
>>>> +
>>>> +               val = pmic_clrsetbits(dev->parent,
>>>> +                                      desc->vsel_reg +
>>>> PFUZE100_MODE_OFFSET,
>>>> +                                      SW_MODE_MASK,
>>>> +                                      *opmode << SW_MODE_SHIFT);
>>>> +
>>>> +       } else if (desc->type == REGULATOR_TYPE_LDO) {
>>>> +               val = pmic_clrsetbits(dev->parent, desc->vsel_reg,
>>>> +                                      LDO_MODE_MASK,
>>>> +                                      *opmode << LDO_MODE_SHIFT);
>>>> +               return val;
>>>> +       } else {
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_enable(struct udevice *dev, int op, bool
>>>> *enable)
>>>> +{
>>>> +       unsigned char val;
>>>> +       int ret, on_off;
>>>> +       struct dm_regulator_uclass_platdata *uc_pdata =
>>>> +               dev_get_uclass_platdata(dev);
>>>> +
>>>> +       if (op == PMIC_OP_GET) {
>>>> +               if (!strcmp(dev->name, "vrefddr")) {
>>>> +                       val = pmic_reg_read(dev->parent,
>>>> PFUZE100_VREFDDRCON);
>>>> +                       if (val < 0)
>>>> +                               return val;
>>>> +
>>>> +                       if (val & VREFDDRCON_EN)
>>>> +                               *enable = true;
>>>> +                       else
>>>> +                               *enable = false;
>>>> +                       return 0;
>>>> +               }
>>>> +               ret = pfuze100_regulator_mode(dev, op, &on_off);
>>>> +               if (ret)
>>>> +                       return ret;
>>>> +               switch (on_off) {
>>>> +               /* OFF_OFF, SWBST_MODE_OFF, LDO_MODE_OFF have same value
>>>> */
>>>> +               case OFF_OFF:
>>>> +                       *enable = false;
>>>> +                       break;
>>>> +               default:
>>>> +                       *enable = true;
>>>> +                       break;
>>>> +               }
>>>> +       } else if (op == PMIC_OP_SET) {
>>>> +               if (!strcmp(dev->name, "vrefddr")) {
>>>> +                       val = pmic_reg_read(dev->parent,
>>>> PFUZE100_VREFDDRCON);
>>>> +                       if (val < 0)
>>>> +                               return val;
>>>> +
>>>> +                       if (val & VREFDDRCON_EN)
>>>> +                               return 0;
>>>> +                       val |= VREFDDRCON_EN;
>>>> +
>>>> +                       return pmic_reg_write(dev->parent,
>>>> PFUZE100_VREFDDRCON,
>>>> +                                             val);
>>>> +               }
>>>> +
>>>> +               if (uc_pdata->type == REGULATOR_TYPE_LDO) {
>>>> +                       on_off = *enable ? LDO_MODE_ON : LDO_MODE_OFF;
>>>> +               } else if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
>>>> +                       if (!strcmp(dev->name, "swbst"))
>>>> +                               on_off = *enable ? SWBST_MODE_AUTO :
>>>> +                                       SWBST_MODE_OFF;
>>>> +                       else
>>>> +                               on_off = *enable ? APS_PFM : OFF_OFF;
>>>> +               } else {
>>>> +                       return -EINVAL;
>>>> +               }
>>>> +
>>>> +               return pfuze100_regulator_mode(dev, op, &on_off);
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_val(struct udevice *dev, int op, int *uV)
>>>> +{
>>>> +       unsigned char val;
>>>> +       int i;
>>>
>>>
>>> Try this:
>>> struct pfuze100_regulator_desc *desc = dev_get_platdata(dev);
>>>
>>>> +       struct pfuze100_regulator_desc *desc =
>>>> +               *(struct pfuze100_regulator_desc **)dev_get_platdata(dev);
>>>> +       struct dm_regulator_uclass_platdata *uc_pdata =
>>>> +               dev_get_uclass_platdata(dev);
>>>> +
>>>> +       if (op == PMIC_OP_GET) {
>>>> +               *uV = 0;
>>>> +               if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
>>>> +                       *uV = desc->voltage;
>>>> +               } else if (desc->volt_table) {
>>>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>>>> +                       if (val < 0)
>>>> +                               return val;
>>>> +                       val &= desc->vsel_mask;
>>>> +                       *uV = desc->volt_table[val];
>>>> +               } else {
>>>> +                       if (uc_pdata->min_uV < 0) {
>>>> +                               debug("Need to provide min_uV in dts.\n");
>>>> +                               return -EINVAL;
>>>> +                       }
>>>> +                       val = pmic_reg_read(dev->parent, desc->vsel_reg);
>>>> +                       if (val < 0)
>>>> +                               return val;
>>>> +                       val &= desc->vsel_mask;
>>>> +                       *uV = uc_pdata->min_uV + (int)val * desc->uV_step;
>>>> +               }
>>>> +
>>>> +               return 0;
>>>> +       }
>>>> +
>>>> +       if (uc_pdata->type == REGULATOR_TYPE_FIXED) {
>>>> +               debug("Set voltage for REGULATOR_TYPE_FIXED regulator\n");
>>>> +               return -EINVAL;
>>>> +       } else if (desc->volt_table) {
>>>> +               for (i = 0; i < desc->vsel_mask; i++) {
>>>> +                       if (*uV == desc->volt_table[i])
>>>> +                               break;
>>>> +               }
>>>> +               if (i == desc->vsel_mask) {
>>>> +                       debug("Unsupported voltage %u\n", *uV);
>>>> +                       return -EINVAL;
>>>> +               }
>>>> +
>>>> +               return pmic_clrsetbits(dev->parent, desc->vsel_reg,
>>>> +                                      desc->vsel_mask, i);
>>>> +       } else {
>>>> +               if (uc_pdata->min_uV < 0) {
>>>> +                       debug("Need to provide min_uV in dts.\n");
>>>> +                       return -EINVAL;
>>>> +               }
>>>> +               return pmic_clrsetbits(dev->parent, desc->vsel_reg,
>>>> +                                      desc->vsel_mask,
>>>> +                                      (*uV - uc_pdata->min_uV) /
>>>> desc->uV_step);
>>>> +       }
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_get_value(struct udevice *dev)
>>>> +{
>>>> +       int uV;
>>>> +       int ret;
>>>> +
>>>> +       ret = pfuze100_regulator_val(dev, PMIC_OP_GET, &uV);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       return uV;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_set_value(struct udevice *dev, int uV)
>>>> +{
>>>> +       return pfuze100_regulator_val(dev, PMIC_OP_SET, &uV);
>>>> +}
>>>> +
>>>> +static bool pfuze100_regulator_get_enable(struct udevice *dev)
>>>> +{
>>>> +       int ret;
>>>> +       bool enable = false;
>>>> +
>>>> +       ret = pfuze100_regulator_enable(dev, PMIC_OP_GET, &enable);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       return enable;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_set_enable(struct udevice *dev, bool
>>>> enable)
>>>> +{
>>>> +       return pfuze100_regulator_enable(dev, PMIC_OP_SET, &enable);
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_get_mode(struct udevice *dev)
>>>> +{
>>>> +       int mode;
>>>> +       int ret;
>>>> +
>>>> +       ret = pfuze100_regulator_mode(dev, PMIC_OP_GET, &mode);
>>>> +       if (ret)
>>>> +               return ret;
>>>> +
>>>> +       return mode;
>>>> +}
>>>> +
>>>> +static int pfuze100_regulator_set_mode(struct udevice *dev, int mode)
>>>> +{
>>>> +       return pfuze100_regulator_mode(dev, PMIC_OP_SET, &mode);
>>>> +}
>>>> +
>>>> +static const struct dm_regulator_ops pfuze100_regulator_ops = {
>>>> +       .get_value  = pfuze100_regulator_get_value,
>>>> +       .set_value  = pfuze100_regulator_set_value,
>>>> +       .get_enable = pfuze100_regulator_get_enable,
>>>> +       .set_enable = pfuze100_regulator_set_enable,
>>>> +       .get_mode   = pfuze100_regulator_get_mode,
>>>> +       .set_mode   = pfuze100_regulator_set_mode,
>>>> +};
>>>> +
>>>> +U_BOOT_DRIVER(pfuze100_regulator) = {
>>>> +       .name = "pfuze100_regulator",
>>>> +       .id = UCLASS_REGULATOR,
>>>> +       .ops = &pfuze100_regulator_ops,
>>>> +       .probe = pfuze100_regulator_probe,
>>>
>>>
>>> You can use: sizeof(struct pfuze100_regulator_desc *)
>>> It is only size of the pointer not an array.
>>>
>>>
>>>> +       .platdata_auto_alloc_size = sizeof(struct pfuze100_regulator_desc
>>
>>BTW if you go with assigning the platdata pointer as above (which I
>>think is a good idea) then you can drop the above line. The allocation
>>is not needed if you assign the pointer to something else.
>>
>>>> **),
>>>> +};
>>>> diff --git a/include/power/pfuze100_pmic.h b/include/power/pfuze100_pmic.h
>>>> index c40a976..41cb710 100644
>>>> --- a/include/power/pfuze100_pmic.h
>>>> +++ b/include/power/pfuze100_pmic.h
>>>> @@ -62,6 +62,13 @@ enum {
>>>>         PFUZE100_NUM_OF_REGS    = 0x7f,
>>>>   };
>>>>
>>>> +/* Registor offset based on VOLT register */
>>>> +#define PFUZE100_VOL_OFFSET    0
>>>> +#define PFUZE100_STBY_OFFSET   1
>>>> +#define PFUZE100_OFF_OFFSET    2
>>>> +#define PFUZE100_MODE_OFFSET   3
>>>> +#define PFUZE100_CONF_OFFSET   4
>>>> +
>>>>   /*
>>>>    * Buck Regulators
>>>>    */
>>>> @@ -138,6 +145,9 @@ enum {
>>>>   #define SW1x_STBY_MASK    0x3f
>>>>   #define SW1x_OFF_MASK     0x3f
>>>>
>>>> +#define SW_MODE_MASK   0xf
>>>> +#define SW_MODE_SHIFT  0
>>>> +
>>>>   #define SW1xCONF_DVSSPEED_MASK 0xc0
>>>>   #define SW1xCONF_DVSSPEED_2US  0x00
>>>>   #define SW1xCONF_DVSSPEED_4US  0x40
>>>> @@ -186,7 +196,12 @@ enum {
>>>>
>>>>   #define LDO_VOL_MASK  0xf
>>>>   #define LDO_EN                (1 << 4)
>>>> +#define LDO_MODE_SHIFT 4
>>>> +#define LDO_MODE_MASK  (1 << 4)
>>>> +#define LDO_MODE_OFF   0
>>>> +#define LDO_MODE_ON    1
>>>>
>>>> +#define VREFDDRCON_EN  (1 << 4)
>>>>   /*
>>>>    * Boost Regulator
>>>>    */
>>>> @@ -199,10 +214,11 @@ enum {
>>>>
>>>>   #define SWBST_VOL_MASK        0x3
>>>>   #define SWBST_MODE_MASK       0xC
>>>> -#define SWBST_MODE_OFF (0 << 2)
>>>> -#define SWBST_MODE_PFM (1 << 2)
>>>> -#define SWBST_MODE_AUTO        (2 << 2)
>>>> -#define SWBST_MODE_APS (3 << 2)
>>>> +#define SWBST_MODE_SHIFT 0x2
>>>> +#define SWBST_MODE_OFF 0
>>>> +#define SWBST_MODE_PFM 1
>>>> +#define SWBST_MODE_AUTO        2
>>>> +#define SWBST_MODE_APS 3
>>>>
>>>>   /*
>>>>    * Regulator Mode Control
>>>>
>>>
>>> Best regards,
>>> --
>>> Przemyslaw Marczak
>>> Samsung R&D Institute Poland
>>> Samsung Electronics
>>> p.marczak at samsung.com
>>
>>Regards,
>>Simon
>
>-- 
Thanks,
Peng.
-- 

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-08-06  4:52 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-04  5:32 [U-Boot] [PATCH V2 0/6] power: pfuze100: support driver model and regulator Peng Fan
2015-08-04  5:32 ` [U-Boot] [PATCH V2 1/6] power: pfuze100 correct SWBST macro definition Peng Fan
2015-08-04  5:32 ` [U-Boot] [PATCH V2 2/6] power: regulator use node name when no regulator-name Peng Fan
2015-08-04  5:32 ` [U-Boot] [PATCH V2 3/6] power: regulator: update comments for regulator-name Peng Fan
2015-08-04 13:10   ` Przemyslaw Marczak
2015-08-04 13:12     ` Peng Fan
2015-08-04  5:32 ` [U-Boot] [PATCH V2 4/6] power: pmic: pfuze100 support driver model Peng Fan
2015-08-04 13:10   ` Przemyslaw Marczak
2015-08-04  5:32 ` [U-Boot] [PATCH V2 5/6] power: regulator: add pfuze100 support Peng Fan
2015-08-04 13:10   ` Przemyslaw Marczak
2015-08-04 13:21     ` Simon Glass
2015-08-04 13:14       ` Peng Fan
2015-08-06  4:52         ` Peng Fan
2015-08-04  5:32 ` [U-Boot] [PATCH V2 6/6] fsl: common: pfuze: no use original pfuze code if DM_PMIC Peng Fan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox