Parcourir la source

Input: zforce - add regulator handling

It's possible that the controller has an individually switchable power supply.
Therefore add support to control a supplying regulator.

As this is not always the case, the regulator is requested as optional.

Signed-off-by: Heiko Stuebner <heiko.stuebner@bq.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Heiko Stuebner il y a 11 ans
Parent
commit
3974037039

+ 4 - 0
Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt

@@ -9,6 +9,9 @@ Required properties:
 - x-size: horizontal resolution of touchscreen
 - y-size: vertical resolution of touchscreen
 
+Optional properties:
+- vdd-supply: Regulator controlling the controller supply
+
 Example:
 
 	i2c@00000000 {
@@ -18,6 +21,7 @@ Example:
 			compatible = "neonode,zforce";
 			reg = <0x50>;
 			interrupts = <2 0>;
+			vdd-supply = <&reg_zforce_vdd>;
 
 			gpios = <&gpio5 6 0>, /* INT */
 				<&gpio5 9 0>; /* RST */

+ 31 - 0
drivers/input/touchscreen/zforce_ts.c

@@ -29,6 +29,8 @@
 #include <linux/sysfs.h>
 #include <linux/input/mt.h>
 #include <linux/platform_data/zforce_ts.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 
@@ -117,6 +119,8 @@ struct zforce_ts {
 	const struct zforce_ts_platdata *pdata;
 	char			phys[32];
 
+	struct regulator	*reg_vdd;
+
 	bool			suspending;
 	bool			suspended;
 	bool			boot_complete;
@@ -690,6 +694,11 @@ static void zforce_reset(void *data)
 	struct zforce_ts *ts = data;
 
 	gpio_set_value(ts->pdata->gpio_rst, 0);
+
+	udelay(10);
+
+	if (!IS_ERR(ts->reg_vdd))
+		regulator_disable(ts->reg_vdd);
 }
 
 static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev)
@@ -765,10 +774,32 @@ static int zforce_probe(struct i2c_client *client,
 		return ret;
 	}
 
+	ts->reg_vdd = devm_regulator_get_optional(&client->dev, "vdd");
+	if (IS_ERR(ts->reg_vdd)) {
+		ret = PTR_ERR(ts->reg_vdd);
+		if (ret == -EPROBE_DEFER)
+			return ret;
+	} else {
+		ret = regulator_enable(ts->reg_vdd);
+		if (ret)
+			return ret;
+
+		/*
+		 * according to datasheet add 100us grace time after regular
+		 * regulator enable delay.
+		 */
+		udelay(100);
+	}
+
 	ret = devm_add_action(&client->dev, zforce_reset, ts);
 	if (ret) {
 		dev_err(&client->dev, "failed to register reset action, %d\n",
 			ret);
+
+		/* hereafter the regulator will be disabled by the action */
+		if (!IS_ERR(ts->reg_vdd))
+			regulator_disable(ts->reg_vdd);
+
 		return ret;
 	}