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)

Reply via email to