Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: zforce - make the interrupt GPIO optional

Add support for hardware which uses an I2C Serializer / Deserializer
(SerDes) to communicate with the zFroce touch driver. In this case the
SerDes will be configured as an interrupt controller and the zForce driver
will have no access to poll the GPIO line.

To support this, we add two dedicated new GPIOs in the device tree:
reset-gpios and irq-gpios, with the irq-gpios being optional.

To not break the existing device trees, the index based 'gpios' entries
are still supported, but marked as deprecated.

With this, if the interrupt GPIO is available, either via the old or new
device tree style, the while loop will read and handle the packets as long
as the GPIO indicates that the interrupt is asserted (existing, unchanged
driver behavior).

If the interrupt GPIO isn't available, i.e. not configured via the new
device tree style, we are falling back to one read per ISR invocation
(new behavior to support the SerDes).

Note that the gpiod functions help to handle the optional GPIO:
devm_gpiod_get_index_optional() will return NULL in case the interrupt
GPIO isn't available. And gpiod_get_value_cansleep() does cover this, too,
by returning 0 in this case.

Signed-off-by: Dirk Behme <dirk.behme@de.bosch.com>
Reviewed-by: Heiko Stuebner <heiko.stuebner@bq.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Dirk Behme and committed by
Dmitry Torokhov
62f46669 0642ffd6

+53 -18
+4 -4
Documentation/devicetree/bindings/input/touchscreen/zforce_ts.txt
··· 4 4 - compatible: must be "neonode,zforce" 5 5 - reg: I2C address of the chip 6 6 - interrupts: interrupt to which the chip is connected 7 - - gpios: gpios the chip is connected to 8 - first one is the interrupt gpio and second one the reset gpio 7 + - reset-gpios: reset gpio the chip is connected to 9 8 - x-size: horizontal resolution of touchscreen 10 9 - y-size: vertical resolution of touchscreen 11 10 12 11 Optional properties: 12 + - irq-gpios : interrupt gpio the chip is connected to 13 13 - vdd-supply: Regulator controlling the controller supply 14 14 15 15 Example: ··· 23 23 interrupts = <2 0>; 24 24 vdd-supply = <&reg_zforce_vdd>; 25 25 26 - gpios = <&gpio5 6 0>, /* INT */ 27 - <&gpio5 9 0>; /* RST */ 26 + reset-gpios = <&gpio5 9 0>; /* RST */ 27 + irq-gpios = <&gpio5 6 0>; /* IRQ, optional */ 28 28 29 29 x-size = <800>; 30 30 y-size = <600>;
+49 -14
drivers/input/touchscreen/zforce_ts.c
··· 510 510 if (!ts->suspending && device_may_wakeup(&client->dev)) 511 511 pm_stay_awake(&client->dev); 512 512 513 - while (gpiod_get_value_cansleep(ts->gpio_int)) { 513 + /* 514 + * Run at least once and exit the loop if 515 + * - the optional interrupt GPIO isn't specified 516 + * (there is only one packet read per ISR invocation, then) 517 + * or 518 + * - the GPIO isn't active any more 519 + * (packet read until the level GPIO indicates that there is 520 + * no IRQ any more) 521 + */ 522 + do { 514 523 ret = zforce_read_packet(ts, payload_buffer); 515 524 if (ret < 0) { 516 525 dev_err(&client->dev, ··· 586 577 payload[RESPONSE_ID]); 587 578 break; 588 579 } 589 - } 580 + } while (gpiod_get_value_cansleep(ts->gpio_int)); 590 581 591 582 if (!ts->suspending && device_may_wakeup(&client->dev)) 592 583 pm_relax(&client->dev); ··· 763 754 if (!ts) 764 755 return -ENOMEM; 765 756 766 - /* INT GPIO */ 767 - ts->gpio_int = devm_gpiod_get_index(&client->dev, NULL, 0, GPIOD_IN); 768 - if (IS_ERR(ts->gpio_int)) { 769 - ret = PTR_ERR(ts->gpio_int); 770 - dev_err(&client->dev, 771 - "failed to request interrupt GPIO: %d\n", ret); 772 - return ret; 773 - } 774 - 775 - /* RST GPIO */ 776 - ts->gpio_rst = devm_gpiod_get_index(&client->dev, NULL, 1, 777 - GPIOD_OUT_HIGH); 757 + ts->gpio_rst = devm_gpiod_get_optional(&client->dev, "reset", 758 + GPIOD_OUT_HIGH); 778 759 if (IS_ERR(ts->gpio_rst)) { 779 760 ret = PTR_ERR(ts->gpio_rst); 780 761 dev_err(&client->dev, 781 762 "failed to request reset GPIO: %d\n", ret); 782 763 return ret; 764 + } 765 + 766 + if (ts->gpio_rst) { 767 + ts->gpio_int = devm_gpiod_get_optional(&client->dev, "irq", 768 + GPIOD_IN); 769 + if (IS_ERR(ts->gpio_int)) { 770 + ret = PTR_ERR(ts->gpio_int); 771 + dev_err(&client->dev, 772 + "failed to request interrupt GPIO: %d\n", ret); 773 + return ret; 774 + } 775 + } else { 776 + /* 777 + * Deprecated GPIO handling for compatibility 778 + * with legacy binding. 779 + */ 780 + 781 + /* INT GPIO */ 782 + ts->gpio_int = devm_gpiod_get_index(&client->dev, NULL, 0, 783 + GPIOD_IN); 784 + if (IS_ERR(ts->gpio_int)) { 785 + ret = PTR_ERR(ts->gpio_int); 786 + dev_err(&client->dev, 787 + "failed to request interrupt GPIO: %d\n", ret); 788 + return ret; 789 + } 790 + 791 + /* RST GPIO */ 792 + ts->gpio_rst = devm_gpiod_get_index(&client->dev, NULL, 1, 793 + GPIOD_OUT_HIGH); 794 + if (IS_ERR(ts->gpio_rst)) { 795 + ret = PTR_ERR(ts->gpio_rst); 796 + dev_err(&client->dev, 797 + "failed to request reset GPIO: %d\n", ret); 798 + return ret; 799 + } 783 800 } 784 801 785 802 ts->reg_vdd = devm_regulator_get_optional(&client->dev, "vdd");