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
WARNING: multiple messages have this Message-ID (diff)
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
next prev parent reply other threads:[~2019-08-16 8:40 UTC|newest] Thread overview: 16+ 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 2019-08-16 8:34 ` Jiada Wang [this message] 2019-08-16 8:34 ` [PATCH v1 36/63] Input: atmel_mxt_ts - configure and use gpios as real gpios Jiada Wang 2019-08-16 17:24 ` Dmitry Torokhov 2019-08-23 5:16 ` Jiada Wang 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:34 ` 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 ` 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 8:35 ` Jiada Wang 2019-08-16 17:25 ` Dmitry Torokhov 2019-08-22 7:57 ` Jiada Wang 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: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.