From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932843AbbLHMFF (ORCPT ); Tue, 8 Dec 2015 07:05:05 -0500 Received: from mail-lb0-f180.google.com ([209.85.217.180]:33125 "EHLO mail-lb0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751354AbbLHMFB (ORCPT ); Tue, 8 Dec 2015 07:05:01 -0500 Date: Tue, 8 Dec 2015 15:04:59 +0300 From: Aleksei Mamlin To: Irina Tirdea Cc: Dmitry Torokhov , Bastien Nocera , Karsten Merker , linux-input@vger.kernel.org, Mark Rutland , Rob Herring , Octavian Purdila , linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: Re: [PATCH v11 2/8] Input: goodix - reset device at init Message-Id: <20151208150459.bfc26a32aee88da2c7f8e8bd@gmail.com> In-Reply-To: <1447936001-21420-3-git-send-email-irina.tirdea@intel.com> References: <1447936001-21420-1-git-send-email-irina.tirdea@intel.com> <1447936001-21420-3-git-send-email-irina.tirdea@intel.com> X-Mailer: Sylpheed 3.4.2 (GTK+ 2.24.28; x86_64-pc-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, 19 Nov 2015 14:26:35 +0200 Irina Tirdea wrote: > After power on, it is recommended that the driver resets the device. > The reset procedure timing is described in the datasheet and is used > at device init (before writing device configuration) and > for power management. It is a sequence of setting the interrupt > and reset pins high/low at specific timing intervals. This procedure > also includes setting the slave address to the one specified in the > ACPI/device tree. > > This is based on Goodix datasheets for GT911 and GT9271 and on Goodix > driver gt9xx.c for Android (publicly available in Android kernel > trees for various devices). > > For reset the driver needs to control the interrupt and > reset gpio pins (configured through ACPI/device tree). For devices > that do not have the gpio pins properly declared, the functionality > depending on these pins will not be available, but the device can still > be used with basic functionality. > > For both device tree and ACPI, the interrupt gpio pin configuration is > read from the "irq-gpios" property and the reset pin configuration is > read from the "reset-gpios" property. For ACPI 5.1, named properties > can be specified using the _DSD section. This functionality will not be > available for devices that use indexed gpio pins declared in the _CRS > section (we need to provide backward compatibility with devices > that do not support using the interrupt gpio pin as output). > > For ACPI, the pins can be specified using ACPI 5.1: > Device (STAC) > { > Name (_HID, "GDIX1001") > ... > > Method (_CRS, 0, Serialized) > { > Name (RBUF, ResourceTemplate () > { > I2cSerialBus (0x0014, ControllerInitiated, 0x00061A80, > AddressingMode7Bit, "\\I2C0", > 0x00, ResourceConsumer, , > ) > > GpioInt (Edge, ActiveHigh, Exclusive, PullNone, 0x0000, > "\\I2C0", 0x00, ResourceConsumer, , > ) > { // Pin list > 0 > } > > GpioIo (Exclusive, PullDown, 0x0000, 0x0000, > IoRestrictionOutputOnly, "\\I2C0", 0x00, > ResourceConsumer, , > ) > { > 1 > } > }) > Return (RBUF) > } > > Name (_DSD, Package () > { > ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), > Package () > { > Package (2) {"irq-gpios", Package() {^STAC, 0, 0, 0 }}, > Package (2) {"reset-gpios", Package() {^STAC, 1, 0, 0 }}, > ... > } > } > > Signed-off-by: Octavian Purdila > Signed-off-by: Irina Tirdea Works on the Wexler TAB7200 Tested-by: Aleksei Mamlin > --- > .../bindings/input/touchscreen/goodix.txt | 9 ++ > drivers/input/touchscreen/Kconfig | 1 + > drivers/input/touchscreen/goodix.c | 101 +++++++++++++++++++++ > 3 files changed, 111 insertions(+) > > diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt > index 8ba98ee..c42d2ce 100644 > --- a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt > +++ b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt > @@ -13,6 +13,12 @@ Required properties: > - interrupt-parent : Interrupt controller to which the chip is connected > - interrupts : Interrupt to which the chip is connected > > +Optional properties: > + > + - irq-gpios : GPIO pin used for IRQ. The driver uses the > + interrupt gpio pin as output to reset the device. > + - reset-gpios : GPIO pin used for reset > + > Example: > > i2c@00000000 { > @@ -23,6 +29,9 @@ Example: > reg = <0x5d>; > interrupt-parent = <&gpio>; > interrupts = <0 0>; > + > + irq-gpios = <&gpio1 0 0>; > + reset-gpios = <&gpio1 1 0>; > }; > > /* ... */ > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig > index 2ccc522..121a0ac 100644 > --- a/drivers/input/touchscreen/Kconfig > +++ b/drivers/input/touchscreen/Kconfig > @@ -324,6 +324,7 @@ config TOUCHSCREEN_FUJITSU > config TOUCHSCREEN_GOODIX > tristate "Goodix I2C touchscreen" > depends on I2C > + depends on GPIOLIB > help > Say Y here if you have the Goodix touchscreen (such as one > installed in Onda v975w tablets) connected to your > diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c > index 56d0330..4744032 100644 > --- a/drivers/input/touchscreen/goodix.c > +++ b/drivers/input/touchscreen/goodix.c > @@ -16,6 +16,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -37,8 +38,13 @@ struct goodix_ts_data { > unsigned int int_trigger_type; > bool rotated_screen; > int cfg_len; > + struct gpio_desc *gpiod_int; > + struct gpio_desc *gpiod_rst; > }; > > +#define GOODIX_GPIO_INT_NAME "irq" > +#define GOODIX_GPIO_RST_NAME "reset" > + > #define GOODIX_MAX_HEIGHT 4096 > #define GOODIX_MAX_WIDTH 4096 > #define GOODIX_INT_TRIGGER 1 > @@ -237,6 +243,88 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) > return IRQ_HANDLED; > } > > +static int goodix_int_sync(struct goodix_ts_data *ts) > +{ > + int error; > + > + error = gpiod_direction_output(ts->gpiod_int, 0); > + if (error) > + return error; > + msleep(50); /* T5: 50ms */ > + > + return gpiod_direction_input(ts->gpiod_int); > +} > + > +/** > + * goodix_reset - Reset device during power on > + * > + * @ts: goodix_ts_data pointer > + */ > +static int goodix_reset(struct goodix_ts_data *ts) > +{ > + int error; > + > + /* begin select I2C slave addr */ > + error = gpiod_direction_output(ts->gpiod_rst, 0); > + if (error) > + return error; > + msleep(20); /* T2: > 10ms */ > + /* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ > + error = gpiod_direction_output(ts->gpiod_int, ts->client->addr == 0x14); > + if (error) > + return error; > + usleep_range(100, 2000); /* T3: > 100us */ > + error = gpiod_direction_output(ts->gpiod_rst, 1); > + if (error) > + return error; > + usleep_range(6000, 10000); /* T4: > 5ms */ > + /* end select I2C slave addr */ > + error = gpiod_direction_input(ts->gpiod_rst); > + if (error) > + return error; > + return goodix_int_sync(ts); > +} > + > +/** > + * goodix_get_gpio_config - Get GPIO config from ACPI/DT > + * > + * @ts: goodix_ts_data pointer > + */ > +static int goodix_get_gpio_config(struct goodix_ts_data *ts) > +{ > + int error; > + struct device *dev; > + struct gpio_desc *gpiod; > + > + if (!ts->client) > + return -EINVAL; > + dev = &ts->client->dev; > + > + /* Get the interrupt GPIO pin number */ > + gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); > + if (IS_ERR(gpiod)) { > + error = PTR_ERR(gpiod); > + if (error != -EPROBE_DEFER) > + dev_dbg(dev, "Failed to get %s GPIO: %d\n", > + GOODIX_GPIO_INT_NAME, error); > + return error; > + } > + ts->gpiod_int = gpiod; > + > + /* Get the reset line GPIO pin number */ > + gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, GPIOD_IN); > + if (IS_ERR(gpiod)) { > + error = PTR_ERR(gpiod); > + if (error != -EPROBE_DEFER) > + dev_dbg(dev, "Failed to get %s GPIO: %d\n", > + GOODIX_GPIO_RST_NAME, error); > + return error; > + } > + ts->gpiod_rst = gpiod; > + > + return 0; > +} > + > /** > * goodix_read_config - Read the embedded configuration of the panel > * > @@ -405,6 +493,19 @@ static int goodix_ts_probe(struct i2c_client *client, > ts->client = client; > i2c_set_clientdata(client, ts); > > + error = goodix_get_gpio_config(ts); > + if (error) > + return error; > + > + if (ts->gpiod_int && ts->gpiod_rst) { > + /* reset the controller */ > + error = goodix_reset(ts); > + if (error) { > + dev_err(&client->dev, "Controller reset failed.\n"); > + return error; > + } > + } > + > error = goodix_i2c_test(client); > if (error) { > dev_err(&client->dev, "I2C communication failure: %d\n", error); > -- > 1.9.1 > -- Thanks and regards, Aleksei Mamlin From mboxrd@z Thu Jan 1 00:00:00 1970 From: Aleksei Mamlin Subject: Re: [PATCH v11 2/8] Input: goodix - reset device at init Date: Tue, 8 Dec 2015 15:04:59 +0300 Message-ID: <20151208150459.bfc26a32aee88da2c7f8e8bd@gmail.com> References: <1447936001-21420-1-git-send-email-irina.tirdea@intel.com> <1447936001-21420-3-git-send-email-irina.tirdea@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1447936001-21420-3-git-send-email-irina.tirdea-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> Sender: devicetree-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: Irina Tirdea Cc: Dmitry Torokhov , Bastien Nocera , Karsten Merker , linux-input-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Mark Rutland , Rob Herring , Octavian Purdila , linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org List-Id: devicetree@vger.kernel.org On Thu, 19 Nov 2015 14:26:35 +0200 Irina Tirdea wrote: > After power on, it is recommended that the driver resets the device. > The reset procedure timing is described in the datasheet and is used > at device init (before writing device configuration) and > for power management. It is a sequence of setting the interrupt > and reset pins high/low at specific timing intervals. This procedure > also includes setting the slave address to the one specified in the > ACPI/device tree. > > This is based on Goodix datasheets for GT911 and GT9271 and on Goodix > driver gt9xx.c for Android (publicly available in Android kernel > trees for various devices). > > For reset the driver needs to control the interrupt and > reset gpio pins (configured through ACPI/device tree). For devices > that do not have the gpio pins properly declared, the functionality > depending on these pins will not be available, but the device can still > be used with basic functionality. > > For both device tree and ACPI, the interrupt gpio pin configuration is > read from the "irq-gpios" property and the reset pin configuration is > read from the "reset-gpios" property. For ACPI 5.1, named properties > can be specified using the _DSD section. This functionality will not be > available for devices that use indexed gpio pins declared in the _CRS > section (we need to provide backward compatibility with devices > that do not support using the interrupt gpio pin as output). > > For ACPI, the pins can be specified using ACPI 5.1: > Device (STAC) > { > Name (_HID, "GDIX1001") > ... > > Method (_CRS, 0, Serialized) > { > Name (RBUF, ResourceTemplate () > { > I2cSerialBus (0x0014, ControllerInitiated, 0x00061A80, > AddressingMode7Bit, "\\I2C0", > 0x00, ResourceConsumer, , > ) > > GpioInt (Edge, ActiveHigh, Exclusive, PullNone, 0x0000, > "\\I2C0", 0x00, ResourceConsumer, , > ) > { // Pin list > 0 > } > > GpioIo (Exclusive, PullDown, 0x0000, 0x0000, > IoRestrictionOutputOnly, "\\I2C0", 0x00, > ResourceConsumer, , > ) > { > 1 > } > }) > Return (RBUF) > } > > Name (_DSD, Package () > { > ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), > Package () > { > Package (2) {"irq-gpios", Package() {^STAC, 0, 0, 0 }}, > Package (2) {"reset-gpios", Package() {^STAC, 1, 0, 0 }}, > ... > } > } > > Signed-off-by: Octavian Purdila > Signed-off-by: Irina Tirdea Works on the Wexler TAB7200 Tested-by: Aleksei Mamlin > --- > .../bindings/input/touchscreen/goodix.txt | 9 ++ > drivers/input/touchscreen/Kconfig | 1 + > drivers/input/touchscreen/goodix.c | 101 +++++++++++++++++++++ > 3 files changed, 111 insertions(+) > > diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt > index 8ba98ee..c42d2ce 100644 > --- a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt > +++ b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt > @@ -13,6 +13,12 @@ Required properties: > - interrupt-parent : Interrupt controller to which the chip is connected > - interrupts : Interrupt to which the chip is connected > > +Optional properties: > + > + - irq-gpios : GPIO pin used for IRQ. The driver uses the > + interrupt gpio pin as output to reset the device. > + - reset-gpios : GPIO pin used for reset > + > Example: > > i2c@00000000 { > @@ -23,6 +29,9 @@ Example: > reg = <0x5d>; > interrupt-parent = <&gpio>; > interrupts = <0 0>; > + > + irq-gpios = <&gpio1 0 0>; > + reset-gpios = <&gpio1 1 0>; > }; > > /* ... */ > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig > index 2ccc522..121a0ac 100644 > --- a/drivers/input/touchscreen/Kconfig > +++ b/drivers/input/touchscreen/Kconfig > @@ -324,6 +324,7 @@ config TOUCHSCREEN_FUJITSU > config TOUCHSCREEN_GOODIX > tristate "Goodix I2C touchscreen" > depends on I2C > + depends on GPIOLIB > help > Say Y here if you have the Goodix touchscreen (such as one > installed in Onda v975w tablets) connected to your > diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c > index 56d0330..4744032 100644 > --- a/drivers/input/touchscreen/goodix.c > +++ b/drivers/input/touchscreen/goodix.c > @@ -16,6 +16,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -37,8 +38,13 @@ struct goodix_ts_data { > unsigned int int_trigger_type; > bool rotated_screen; > int cfg_len; > + struct gpio_desc *gpiod_int; > + struct gpio_desc *gpiod_rst; > }; > > +#define GOODIX_GPIO_INT_NAME "irq" > +#define GOODIX_GPIO_RST_NAME "reset" > + > #define GOODIX_MAX_HEIGHT 4096 > #define GOODIX_MAX_WIDTH 4096 > #define GOODIX_INT_TRIGGER 1 > @@ -237,6 +243,88 @@ static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) > return IRQ_HANDLED; > } > > +static int goodix_int_sync(struct goodix_ts_data *ts) > +{ > + int error; > + > + error = gpiod_direction_output(ts->gpiod_int, 0); > + if (error) > + return error; > + msleep(50); /* T5: 50ms */ > + > + return gpiod_direction_input(ts->gpiod_int); > +} > + > +/** > + * goodix_reset - Reset device during power on > + * > + * @ts: goodix_ts_data pointer > + */ > +static int goodix_reset(struct goodix_ts_data *ts) > +{ > + int error; > + > + /* begin select I2C slave addr */ > + error = gpiod_direction_output(ts->gpiod_rst, 0); > + if (error) > + return error; > + msleep(20); /* T2: > 10ms */ > + /* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ > + error = gpiod_direction_output(ts->gpiod_int, ts->client->addr == 0x14); > + if (error) > + return error; > + usleep_range(100, 2000); /* T3: > 100us */ > + error = gpiod_direction_output(ts->gpiod_rst, 1); > + if (error) > + return error; > + usleep_range(6000, 10000); /* T4: > 5ms */ > + /* end select I2C slave addr */ > + error = gpiod_direction_input(ts->gpiod_rst); > + if (error) > + return error; > + return goodix_int_sync(ts); > +} > + > +/** > + * goodix_get_gpio_config - Get GPIO config from ACPI/DT > + * > + * @ts: goodix_ts_data pointer > + */ > +static int goodix_get_gpio_config(struct goodix_ts_data *ts) > +{ > + int error; > + struct device *dev; > + struct gpio_desc *gpiod; > + > + if (!ts->client) > + return -EINVAL; > + dev = &ts->client->dev; > + > + /* Get the interrupt GPIO pin number */ > + gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); > + if (IS_ERR(gpiod)) { > + error = PTR_ERR(gpiod); > + if (error != -EPROBE_DEFER) > + dev_dbg(dev, "Failed to get %s GPIO: %d\n", > + GOODIX_GPIO_INT_NAME, error); > + return error; > + } > + ts->gpiod_int = gpiod; > + > + /* Get the reset line GPIO pin number */ > + gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_RST_NAME, GPIOD_IN); > + if (IS_ERR(gpiod)) { > + error = PTR_ERR(gpiod); > + if (error != -EPROBE_DEFER) > + dev_dbg(dev, "Failed to get %s GPIO: %d\n", > + GOODIX_GPIO_RST_NAME, error); > + return error; > + } > + ts->gpiod_rst = gpiod; > + > + return 0; > +} > + > /** > * goodix_read_config - Read the embedded configuration of the panel > * > @@ -405,6 +493,19 @@ static int goodix_ts_probe(struct i2c_client *client, > ts->client = client; > i2c_set_clientdata(client, ts); > > + error = goodix_get_gpio_config(ts); > + if (error) > + return error; > + > + if (ts->gpiod_int && ts->gpiod_rst) { > + /* reset the controller */ > + error = goodix_reset(ts); > + if (error) { > + dev_err(&client->dev, "Controller reset failed.\n"); > + return error; > + } > + } > + > error = goodix_i2c_test(client); > if (error) { > dev_err(&client->dev, "I2C communication failure: %d\n", error); > -- > 1.9.1 > -- Thanks and regards, Aleksei Mamlin -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html