linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiada Wang <jiada_wang@mentor.com>
To: <nick@shmanahar.org>, <dmitry.torokhov@gmail.com>
Cc: <linux-input@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<jiada_wang@mentor.com>, <george_davis@mentor.com>
Subject: [PATCH v1 36/63] Input: atmel_mxt_ts - configure and use gpios as real gpios
Date: Fri, 16 Aug 2019 17:34:58 +0900	[thread overview]
Message-ID: <20190816083525.19071-2-jiada_wang@mentor.com> (raw)
In-Reply-To: <20190816083525.19071-1-jiada_wang@mentor.com>

From: Kautuk Consul <kautuk_consul@mentor.com>

The upstream Atmel mXT driver implementation seems to handle the
T19 GPIO/PWM object as a key pad. Keys can be defined in the
device tree ("linux,gpio-keymap") and will be transported as key
events to the Linux input device if GPIO state changes.

With our hardware, the GPIO pins of the touch controller are
connected to a PWM/backlight controller and used as supervision
inputs. We like to read the status of the pins by a script or an
application in the sysfs.

Adding newer sysfs entries which shall be placed in the input
class directory eg:
/sys/class/input/input<n>/backlight_error1

Signed-off-by: Kautuk Consul <kautuk_consul@mentor.com>
Signed-off-by: Balasubramani Vivekanandan <balasubramani_vivekanandan@mentor.com>
Signed-off-by: George G. Davis <george_davis@mentor.com>
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
---
 .../bindings/input/atmel,maxtouch.txt         |  15 +++
 drivers/input/touchscreen/atmel_mxt_ts.c      | 120 ++++++++++++++++++
 2 files changed, 135 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
index d7db16920083..7afe12a93202 100644
--- a/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
+++ b/Documentation/devicetree/bindings/input/atmel,maxtouch.txt
@@ -42,6 +42,9 @@ Optional properties for main touchpad device:
 
 - atmel,input_name: Override name of input device from the default.
 
+- atmel,gpios: Specify the GPIO input pins whose status will be read via the
+    /sys/class/input/input<n>/backlight_error<x> sysfs entries.
+
 Example:
 
 	touch@4b {
@@ -49,4 +52,16 @@ Example:
 		reg = <0x4b>;
 		interrupt-parent = <&gpio>;
 		interrupts = <TEGRA_GPIO(W, 3) IRQ_TYPE_LEVEL_LOW>;
+
+		atmel,gpios {
+			backlight_error1 {
+				gpio = <3 GPIO_ACTIVE_HIGH>; /* connected to
+							      * the GPIO3 pin of mXT input */
+			};
+
+			backlight_error2 {
+				gpio = <5 GPIO_ACTIVE_HIGH>; /* connected to
+							      * the GPIO5 pin of mXT input */
+			};
+		};
 	};
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 9cdb7754599c..a8e2b927bb12 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -414,6 +414,15 @@ struct mxt_data {
 
 	/* Indicates whether device is updating configuration */
 	bool updating_config;
+
+	unsigned long gpio_input_pin_status;
+	struct attribute_group gpio_attrs;
+	unsigned long gpio_input_pin_status_default;
+};
+
+struct mxt_gpio_attr {
+	struct device_attribute attr;
+	int bit_index;
 };
 
 struct mxt_vb2_buffer {
@@ -1381,6 +1390,7 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message)
 	} else if (report_id == data->T19_reportid) {
 		mxt_input_button(data, message);
 		data->update_input = true;
+		data->gpio_input_pin_status = message[1];
 	} else if (report_id >= data->T15_reportid_min
 		   && report_id <= data->T15_reportid_max) {
 		mxt_proc_t15_messages(data, message);
@@ -2747,6 +2757,16 @@ static int mxt_initialize_input_device(struct mxt_data *data)
 		goto err_free_mem;
 	}
 
+	if (data->gpio_attrs.attrs) {
+		error = sysfs_create_group(&input_dev->dev.kobj,
+					   &data->gpio_attrs);
+		if (error) {
+			dev_err(dev, "Failure %d creating sysfs group\n",
+				error);
+			goto err_free_mem;
+		}
+	}
+
 	data->input_dev = input_dev;
 
 	return 0;
@@ -3995,10 +4015,26 @@ static void mxt_input_close(struct input_dev *dev)
 		dev_err(&data->client->dev, "%s failed rc=%d\n", __func__, ret);
 }
 
+static ssize_t mxt_gpio_input_pin_read(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct mxt_gpio_attr *attr_p = container_of(attr, struct mxt_gpio_attr,
+						    attr);
+	int pin_status = test_bit(attr_p->bit_index,
+				  &data->gpio_input_pin_status);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", pin_status);
+}
+
 static int mxt_parse_device_properties(struct mxt_data *data)
 {
 	static const char keymap_property[] = "linux,gpio-keymap";
+	static const char gpios_property[] = "atmel,gpios";
 	struct device *dev = &data->client->dev;
+	struct device_node *np = dev ? dev->of_node : NULL;
+	struct device_node *np_gpio;
 	u32 *keymap;
 	int n_keys;
 	int error;
@@ -4036,7 +4072,89 @@ static int mxt_parse_device_properties(struct mxt_data *data)
 
 	device_property_read_u32(dev, "atmel,suspend-mode", &data->suspend_mode);
 
+	np_gpio = of_get_child_by_name(np, gpios_property);
+	if (np_gpio) {
+		int gpio_pin;
+		struct mxt_gpio_attr *attr_p;
+		char *sysfs_gpio_file_name;
+		u8 num_gpio_pins = 0;
+
+		np_gpio = of_find_node_with_property(np_gpio, "gpio");
+		if (!np_gpio)
+			return -EINVAL;
+
+		data->gpio_attrs.attrs =
+			devm_kzalloc(dev,
+				     9 * sizeof(struct attribute *),
+				     GFP_KERNEL);
+		if (!data->gpio_attrs.attrs) {
+			error = -ENOMEM;
+			goto err_gpios_property_put;
+		}
+
+		do {
+			attr_p = devm_kmalloc(dev,
+					      sizeof(struct mxt_gpio_attr),
+					      GFP_KERNEL);
+			if (!attr_p) {
+				error = -ENOMEM;
+				goto err_gpios_property_put;
+			}
+
+			error = of_property_read_u32_index(np_gpio, "gpio", 0,
+							   &gpio_pin);
+			if (error) {
+				dev_warn(dev,
+					 "Couldn't read gpio property for node : %s\n",
+					 np_gpio->name);
+				error = -EINVAL;
+				goto err_gpios_property_put;
+			}
+
+			if (gpio_pin > 7) {
+				dev_warn(dev,
+					 "Incorrect GPIO pin index for node %s: %u\n",
+					 np_gpio->name, gpio_pin);
+				error = -EINVAL;
+				goto err_gpios_property_put;
+			}
+
+			sysfs_gpio_file_name =
+					devm_kmalloc(dev,
+						     strlen(np_gpio->name) + 1,
+						     GFP_KERNEL);
+			if (!sysfs_gpio_file_name) {
+				error = -ENOMEM;
+				goto err_gpios_property_put;
+			}
+
+			strcpy(sysfs_gpio_file_name, np_gpio->name);
+
+			sysfs_attr_init(&attr_p->attr.attr);
+
+			attr_p->attr.attr.name = sysfs_gpio_file_name;
+			attr_p->attr.attr.mode = 0444;
+			attr_p->attr.show = mxt_gpio_input_pin_read;
+			attr_p->attr.store = NULL;
+			attr_p->bit_index = gpio_pin;
+
+			data->gpio_input_pin_status_default |= BIT(gpio_pin);
+
+			data->gpio_attrs.attrs[num_gpio_pins++] =
+							&attr_p->attr.attr;
+		} while ((np_gpio =
+			  of_find_node_with_property(np_gpio, "gpio")) &&
+			 num_gpio_pins < 8);
+
+		if (np_gpio)
+			of_node_put(np_gpio);
+	}
+
 	return 0;
+
+err_gpios_property_put:
+	of_node_put(np_gpio);
+	return error;
 }
 
 static const struct dmi_system_id chromebook_T9_suspend_dmi[] = {
@@ -4106,6 +4224,8 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (error)
 		return error;
 
+	data->gpio_input_pin_status = data->gpio_input_pin_status_default;
+
 	if (data->pcfg_name)
 		mxt_update_file_name(&data->client->dev,
 				     &data->cfg_name,
-- 
2.19.2


  reply	other threads:[~2019-08-16  8:40 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-16  8:34 [PATCH v1 35/63] Input: atmel_mxt_ts - rely on calculated_crc rather than file config_crc Jiada Wang
2019-08-16  8:34 ` Jiada Wang [this message]
2019-08-16 17:24   ` [PATCH v1 36/63] Input: atmel_mxt_ts - configure and use gpios as real gpios Dmitry Torokhov
2019-08-23  5:16     ` Jiada Wang
2019-08-16  8:34 ` [PATCH v1 37/63] input: atmel_mxt_ts: export GPIO reset line via sysfs Jiada Wang
2019-08-16  8:35 ` [PATCH v1 38/63] Input: atmel_mxt_ts: Add support for run self-test routine Jiada Wang
2019-08-16  8:35 ` [PATCH v1 39/63] Input: touchscreen: Atmel: Add device tree support for T15 key array objects Jiada Wang
2019-08-16 17:25   ` Dmitry Torokhov
2019-08-22  7:57     ` Jiada Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190816083525.19071-2-jiada_wang@mentor.com \
    --to=jiada_wang@mentor.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=george_davis@mentor.com \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nick@shmanahar.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).