[PATCH 02/16] regulator: twl: Expose the TWL4030's REGEN signal as a regulator

"H. Nikolaus Schaller" <[email protected]>
Newsgroups dev.linux.lists.mfd,org.freedesktop.lists.dri-devel,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-fbdev,org.kernel.vger.linux-kernel,org.kernel.vger.linux-omap,org.kernel.vger.linux-sound
Message-ID <1746667e5c17e2d39fc0747d7e098b32b3d7b479.1783749722.git.hns@goldelico.com>
From: Grond <[email protected]>

This is needed on some boards (for example, the Pandora), where REGEN is
used to drive external regulators.

Signed-off-by: Grond <[email protected]>
Signed-off-by: H. Nikolaus Schaller <[email protected]>
---
 drivers/regulator/twl-regulator.c | 52 +++++++++++++++++++++++++++++++
 include/linux/mfd/twl.h           |  3 ++
 2 files changed, 55 insertions(+)

diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 5bacfcebf59aa..d883ee8abec32 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -451,6 +451,16 @@ static const struct regulator_ops twl4030fixed_ops = {
 	.get_status	= twl4030reg_get_status,
 };
 
+static const struct regulator_ops twl4030signal_ops = {
+	.enable		= twl4030reg_enable,
+	.disable	= twl4030reg_disable,
+	.is_enabled	= twl4030reg_is_enabled,
+
+	.set_mode	= twl4030reg_set_mode,
+
+	.get_status	= twl4030reg_get_status,
+};
+
 /*----------------------------------------------------------------------*/
 
 #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) \
@@ -511,6 +521,24 @@ static const struct twlreg_info TWLFIXED_INFO_##label = { \
 		}, \
 	}
 
+#define TWL4030_SIGNAL(label, offset, num, remap_conf) \
+static const struct twlreg_info TWLSIGNAL_INFO_##label = { \
+	.base = offset, \
+	.id = num, \
+	.remap = remap_conf, \
+	.desc = { \
+		.name = #label, \
+		.id = TWL4030_REG_##label, \
+		.n_voltages = 1, \
+		.fixed_uV = 0, /* filled in from DT later */ \
+		.ops = &twl4030signal_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+		.enable_time = 0, /* also filled in from DT */ \
+		.of_map_mode = twl4030reg_map_mode, \
+		}, \
+	}
+
 /*
  * We list regulators here if systems need some level of
  * software control over them after boot.
@@ -536,6 +564,7 @@ TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08);
 TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08);
 TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08);
 TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08);
+TWL4030_SIGNAL(REGEN, 0x7f, 21, 0x08);
 
 #define TWL_OF_MATCH(comp, family, label) \
 	{ \
@@ -548,6 +577,7 @@ TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08);
 #define TWL6032_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6032, label)
 #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
 #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
+#define TWLSIGNAL_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSIGNAL, label)
 
 static const struct of_device_id twl_of_match[] = {
 	TWL4030_OF_MATCH("ti,twl4030-vaux1", VAUX1),
@@ -570,6 +600,7 @@ static const struct of_device_id twl_of_match[] = {
 	TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5),
 	TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8),
 	TWLFIXED_OF_MATCH("ti,twl4030-vusb3v1", VUSB3V1),
+	TWLSIGNAL_OF_MATCH("ti,twl4030-regen", REGEN),
 	{},
 };
 MODULE_DEVICE_TABLE(of, twl_of_match);
@@ -583,6 +614,7 @@ static int twlreg_probe(struct platform_device *pdev)
 	struct regulation_constraints	*c;
 	struct regulator_dev		*rdev;
 	struct regulator_config		config = { };
+	int ret;
 
 	template = of_device_get_match_data(&pdev->dev);
 	if (!template)
@@ -615,6 +647,26 @@ static int twlreg_probe(struct platform_device *pdev)
 	case TWL4030_REG_VINTANA2:
 	case TWL4030_REG_VINTDIG:
 		c->always_on = true;
+		break;
+	case TWL4030_REG_REGEN:
+		if (c->min_uV == 0 || c->max_uV == 0) {
+			dev_err(&pdev->dev, "minimum or maximum regulator voltage zero in DT\n");
+			return -EINVAL;
+		}
+
+		if (c->min_uV != c->max_uV) {
+			dev_err(&pdev->dev, "minimum and maximum voltage are different in DT\n");
+			return -EINVAL;
+		}
+		info->desc.fixed_uV = c->min_uV;
+
+		ret = of_property_read_u32(pdev->dev.of_node, "startup-delay-us",
+					   &info->desc.enable_time);
+		if (ret) {
+			dev_err(&pdev->dev, "no valid startup delay set in DT: %d\n", ret);
+			return ret;
+		}
+
 		break;
 	default:
 		break;
diff --git a/include/linux/mfd/twl.h b/include/linux/mfd/twl.h
index b31e07fa4d516..d249b4b22c898 100644
--- a/include/linux/mfd/twl.h
+++ b/include/linux/mfd/twl.h
@@ -738,6 +738,9 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base);
 #define TWL4030_REG_VUSB1V8	18
 #define TWL4030_REG_VUSB3V1	19
 
+/* digital output signal for enabling external regulators */
+#define TWL4030_REG_REGEN	21
+
 /* TWL6030 SMPS/LDO's */
 /* EXTERNAL dc-to-dc buck convertor controllable via SR */
 #define TWL6030_REG_VDD1	30
-- 
2.50.1 (Apple Git-155)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.