]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
regulator: tps65132: support for active discharge on input pin
authorDaniel Solomon <daniels@nvidia.com>
Sat, 27 Jun 2015 01:35:37 +0000 (18:35 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Wed, 1 Jul 2015 17:40:07 +0000 (10:40 -0700)
Some configurations use delay mechanisms on the
tps65132 enable pin, to keep the regulator enabled
for some time after the enable signal goes low.
Add support to actively discharge this delay
mechanism.

Bug 1630935
Bug 200118211

Change-Id: If7a8fd39d862f35924d7799740f01ead0f65bb71
Signed-off-by: Daniel Solomon <daniels@nvidia.com>
Reviewed-on: http://git-master/r/763398
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Tested-by: Laxman Dewangan <ldewangan@nvidia.com>
Documentation/devicetree/bindings/regulator/tps65132.txt
drivers/regulator/tps65132-regulator.c

index d0968d6dcfa9a63a6faebdd5962752e3d1dde091..b57a816aa3673ee1b22fb673ed0f06ce6b23b011 100644 (file)
@@ -15,7 +15,13 @@ Device supports two regulators OUTP and OUTN. A sub node within the
    it is connected to GPIO through host system then provide the
    gpio number as per gpio.txt.
 -ti,disable-active-discharge: Boolean, presence of this property
-   will disable active discharge.
+   will disable active discharge on the regulator output.
+-ti,active-discharge-gpio: Some configurations use delay mechanisms
+  on the enable pin, to keep the regulator enabled for some time after
+  the enable signal goes low. This GPIO is used to actively discharge
+  the delay mechanism. Requires specification of ti,active-discharge-time
+-ti,active-discharge-time: how long the active discharge gpio should be
+  asserted for during active discharge, in microseconds.
 
 Each regulator is defined using the standard binding for regulators.
 
index 72b32a4a63598fd747c7d0d2929a76ae8e4f74f3..82a976f7c246c36281e7ba1f0013bb149000f207 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #define tps65132_rails(_name)  "tps65132-"#_name
 
 #define TPS65132_REGULATOR_ID_VNEG     1
 #define TPS65132_MAX_REGULATORS                2
 
+#define TPS65132_ACT_DIS_TIME_SLACK            1000
+
 struct tps65132_regulator_pdata {
        int enable_gpio;
        bool disable_active_discharge;
        struct regulator_init_data *ridata;
+       int active_discharge_gpio;
+       unsigned int active_discharge_time;
 };
 
 struct tps65132_regulator {
@@ -89,8 +94,26 @@ static int tps65132_post_enable(struct regulator_dev *rdev)
        return 0;
 }
 
+static int tps65132_post_disable(struct regulator_dev *rdev)
+{
+       struct tps65132_regulator *tps = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
+       int act_dis_gpio = tps->reg_pdata[id].active_discharge_gpio;
+       unsigned int act_dis_time_us = tps->reg_pdata[id].active_discharge_time;
+
+       if (gpio_is_valid(act_dis_gpio)) {
+               gpio_set_value(act_dis_gpio, 1);
+               usleep_range(act_dis_time_us,
+                       act_dis_time_us + TPS65132_ACT_DIS_TIME_SLACK);
+               gpio_set_value(act_dis_gpio, 0);
+       }
+
+       return 0;
+}
+
 static struct regulator_ops tps65132_regulator_ops = {
        .post_enable = tps65132_post_enable,
+       .post_disable = tps65132_post_disable,
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
@@ -152,7 +175,23 @@ static int tps65132_get_regulator_dt_data(struct device *dev,
 
                rpdata->disable_active_discharge = of_property_read_bool(rnode,
                                                "ti,disable-active-discharge");
+
+               rpdata->active_discharge_gpio = of_get_named_gpio(rnode,
+                                               "ti,active-discharge-gpio", 0);
+               if (rpdata->active_discharge_gpio == -EPROBE_DEFER) {
+                       return -EPROBE_DEFER;
+               } else if (gpio_is_valid(rpdata->active_discharge_gpio)) {
+                       ret = of_property_read_u32(rnode,
+                               "ti,active-discharge-time",
+                               &rpdata->active_discharge_time);
+                       if (ret < 0) {
+                               dev_err(dev, "Discharge time read failed: %d\n",
+                                       ret);
+                               return ret;
+                       }
+               }
        }
+
        return 0;
 }
 
@@ -196,6 +235,9 @@ static int tps65132_probe(struct i2c_client *client,
        if (ret == -EPROBE_DEFER) {
                dev_err(dev, "Probe deffered\n");
                return ret;
+       } else if (ret < 0) {
+               dev_err(dev, "Reading data from DT failed: %d\n", ret);
+               return ret;
        }
 
        tps->rmap = devm_regmap_init_i2c(client, &tps65132_regmap_config);
@@ -227,6 +269,21 @@ static int tps65132_probe(struct i2c_client *client,
                                config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
                }
 
+               if (gpio_is_valid(rpdata->active_discharge_gpio)) {
+                       ret = devm_gpio_request_one(dev,
+                               rpdata->active_discharge_gpio,
+                               GPIOF_OUT_INIT_LOW, rdesc->name);
+                       if (ret < 0) {
+                               dev_err(dev,
+                                       "act dis gpio req failed for %s: %d\n",
+                                       rdesc->name, ret);
+                               return ret;
+                       }
+               } else {
+                       dev_info(dev, "No active discharge gpio for regulator %s\n",
+                               rdesc->name);
+               }
+
                tps->rdev[id] = devm_regulator_register(dev, rdesc, &config);
                if (IS_ERR(tps->rdev[id])) {
                        ret = PTR_ERR(tps->rdev[id]);