Message ID | 1444314231-19206-3-git-send-email-irina.tirdea@intel.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
On Thu, 2015-10-08 at 17:23 +0300, 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-gpio" property and the reset pin configuration is > read from the "reset-gpio" 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-gpio", Package() {^STAC, 0, 0, 0 }}, > Package (2) {"reset-gpio", Package() {^STAC, 1, 0, 0 }}, > ... > } > } > > Signed-off-by: Octavian Purdila <octavian.purdila@intel.com> > Signed-off-by: Irina Tirdea <irina.tirdea@intel.com> Didn't actually cause problems on my system, and the documentation looks good. Acked-by: Bastien Nocera <hadess@hadess.net> -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Irina, [auto build test ERROR on v4.3-rc4 -- if it's inappropriate base, please ignore] config: x86_64-randconfig-h0-10110617 (attached as .config) reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): drivers/input/touchscreen/goodix.c: In function 'goodix_int_sync': >> drivers/input/touchscreen/goodix.c:250:10: error: implicit declaration of function 'gpiod_direction_output' [-Werror=implicit-function-declaration] error = gpiod_direction_output(ts->gpiod_int, 0); ^ >> drivers/input/touchscreen/goodix.c:255:9: error: implicit declaration of function 'gpiod_direction_input' [-Werror=implicit-function-declaration] return gpiod_direction_input(ts->gpiod_int); ^ drivers/input/touchscreen/goodix.c: In function 'goodix_get_gpio_config': >> drivers/input/touchscreen/goodix.c:304:10: error: implicit declaration of function 'devm_gpiod_get' [-Werror=implicit-function-declaration] gpiod = devm_gpiod_get(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); ^ >> drivers/input/touchscreen/goodix.c:304:52: error: 'GPIOD_IN' undeclared (first use in this function) gpiod = devm_gpiod_get(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); ^ drivers/input/touchscreen/goodix.c:304:52: note: each undeclared identifier is reported only once for each function it appears in cc1: some warnings being treated as errors vim +/gpiod_direction_output +250 drivers/input/touchscreen/goodix.c 244 } 245 246 static int goodix_int_sync(struct goodix_ts_data *ts) 247 { 248 int error; 249 > 250 error = gpiod_direction_output(ts->gpiod_int, 0); 251 if (error) 252 return error; 253 msleep(50); /* T5: 50ms */ 254 > 255 return gpiod_direction_input(ts->gpiod_int); 256 } 257 258 /** 259 * goodix_reset - Reset device during power on 260 * 261 * @ts: goodix_ts_data pointer 262 */ 263 static int goodix_reset(struct goodix_ts_data *ts) 264 { 265 int error; 266 267 /* begin select I2C slave addr */ 268 error = gpiod_direction_output(ts->gpiod_rst, 0); 269 if (error) 270 return error; 271 msleep(20); /* T2: > 10ms */ 272 /* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ 273 error = gpiod_direction_output(ts->gpiod_int, ts->client->addr == 0x14); 274 if (error) 275 return error; 276 usleep_range(100, 2000); /* T3: > 100us */ 277 error = gpiod_direction_output(ts->gpiod_rst, 1); 278 if (error) 279 return error; 280 usleep_range(6000, 10000); /* T4: > 5ms */ 281 /* end select I2C slave addr */ 282 error = gpiod_direction_input(ts->gpiod_rst); 283 if (error) 284 return error; 285 return goodix_int_sync(ts); 286 } 287 288 /** 289 * goodix_get_gpio_config - Get GPIO config from ACPI/DT 290 * 291 * @ts: goodix_ts_data pointer 292 */ 293 static int goodix_get_gpio_config(struct goodix_ts_data *ts) 294 { 295 int error; 296 struct device *dev; 297 struct gpio_desc *gpiod; 298 299 if (!ts->client) 300 return -EINVAL; 301 dev = &ts->client->dev; 302 303 /* Get the interrupt GPIO pin number */ > 304 gpiod = devm_gpiod_get(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); 305 if (IS_ERR(gpiod)) { 306 error = PTR_ERR(gpiod); 307 if (error != -EPROBE_DEFER) --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt index 8ba98ee..7137881 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/goodix.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/goodix.txt @@ -12,6 +12,8 @@ Required properties: - reg : I2C address of the chip. Should be 0x5d or 0x14 - interrupt-parent : Interrupt controller to which the chip is connected - interrupts : Interrupt to which the chip is connected + - irq-gpio : GPIO pin used for IRQ + - reset-gpio : GPIO pin used for reset Example: @@ -23,6 +25,9 @@ Example: reg = <0x5d>; interrupt-parent = <&gpio>; interrupts = <0 0>; + + irq-gpio = <&gpio1 0 0>; + reset-gpio = <&gpio1 1 0>; }; /* ... */ diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 56d0330..87304ac 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -16,6 +16,7 @@ #include <linux/kernel.h> #include <linux/dmi.h> +#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/input.h> #include <linux/input/mt.h> @@ -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(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(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 == -EPROBE_DEFER) + 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);