From patchwork Wed Mar 19 13:09:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Lothar_Wa=C3=9Fmann?= X-Patchwork-Id: 3859161 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id BD1629F334 for ; Wed, 19 Mar 2014 18:14:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 88E2F200EC for ; Wed, 19 Mar 2014 18:14:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5908520117 for ; Wed, 19 Mar 2014 18:14:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934209AbaCSNKo (ORCPT ); Wed, 19 Mar 2014 09:10:44 -0400 Received: from mail.karo-electronics.de ([81.173.242.67]:50149 "EHLO mail.karo-electronics.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934203AbaCSNKl (ORCPT ); Wed, 19 Mar 2014 09:10:41 -0400 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= To: Dmitry Torokhov , Fugang Duan , Grant Likely , Henrik Rydberg , Ian Campbell , Jingoo Han , Kumar Gala , Mark Rutland , Pawel Moll , Rob Herring , Rob Landley , Sachin Kamat , devicetree@vger.kernel.org, linux-doc@vger.kernel.org, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Simon Budig , =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Subject: [PATCHv4 2/5] Input: edt-ft5x06: Add DT support Date: Wed, 19 Mar 2014 14:09:20 +0100 Message-Id: <1395234563-11034-3-git-send-email-LW@KARO-electronics.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1395234563-11034-1-git-send-email-LW@KARO-electronics.de> References: <1395234563-11034-1-git-send-email-LW@KARO-electronics.de> MIME-Version: 1.0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Lothar Waßmann --- .../bindings/input/touchscreen/edt-ft5x06.txt | 41 ++++++ drivers/input/touchscreen/edt-ft5x06.c | 144 +++++++++++++++----- 2 files changed, 154 insertions(+), 31 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt diff --git a/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt new file mode 100644 index 0000000..e5adc76 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/edt-ft5x06.txt @@ -0,0 +1,41 @@ +FocalTech EDT-FT5x06 Polytouch driver +===================================== + +Required properties: + - compatible: "edt,edt-ft5x06" + - reg: I2C slave address of the chip (0x38) + - interrupt-parent: a phandle pointing to the interrupt controller + serving the interrupt for this chip + - interrupts: interrupt specification for this chip + +Optional properties: + - reset-gpios: GPIO specification for the RESET input + - wake-gpios: GPIO specification for the WAKE input + + - pinctrl-names: should be "default" + - pinctrl-0: a phandle pointing to the pin settings for the + control gpios + + - threshold: allows setting the "click"-threshold in the range + from 20 to 80. + + - gain: allows setting the sensitivity in the range from 0 to + 31. Note that lower values indicate higher + sensitivity. + + - offset: allows setting the edge compensation in the range from + 0 to 31. + - report_rate: allows setting the report rate in the range from 3 to + 14. + +Example: + polytouch: edt-ft5x06@38 { + compatible = "edt,edt-ft5x06"; + reg = <0x38>; + pinctrl-names = "default"; + pinctrl-0 = <&edt_ft5x06_pins>; + interrupt-parent = <&gpio2>; + interrupts = <5 0>; + reset-gpios = <&gpio2 6 1>; + wake-gpios = <&gpio4 9 0>; + }; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 7b4470d..257a1c8 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -65,6 +66,10 @@ struct edt_ft5x06_ts_data { u16 num_x; u16 num_y; + int reset_pin; + int irq_pin; + int wake_pin; + #if defined(CONFIG_DEBUG_FS) struct dentry *debug_dir; u8 *raw_buffer; @@ -617,24 +622,38 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) static int edt_ft5x06_ts_reset(struct i2c_client *client, - int reset_pin) + struct edt_ft5x06_ts_data *tsdata) { int error; - if (gpio_is_valid(reset_pin)) { + if (gpio_is_valid(tsdata->wake_pin)) { + error = devm_gpio_request_one(&client->dev, + tsdata->wake_pin, GPIOF_OUT_INIT_LOW, + "edt-ft5x06 wake"); + if (error) { + dev_err(&client->dev, + "Failed to request GPIO %d as wake pin, error %d\n", + tsdata->wake_pin, error); + return error; + } + + mdelay(5); + gpio_set_value(tsdata->wake_pin, 1); + } + if (gpio_is_valid(tsdata->reset_pin)) { /* this pulls reset down, enabling the low active reset */ - error = devm_gpio_request_one(&client->dev, reset_pin, - GPIOF_OUT_INIT_LOW, - "edt-ft5x06 reset"); + error = devm_gpio_request_one(&client->dev, + tsdata->reset_pin, GPIOF_OUT_INIT_LOW, + "edt-ft5x06 reset"); if (error) { dev_err(&client->dev, "Failed to request GPIO %d as reset pin, error %d\n", - reset_pin, error); + tsdata->reset_pin, error); return error; } mdelay(50); - gpio_set_value(reset_pin, 1); + gpio_set_value(tsdata->reset_pin, 1); mdelay(100); } @@ -675,6 +694,21 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, pdata->name <= edt_ft5x06_attr_##name.limit_high) \ edt_ft5x06_register_write(tsdata, reg, pdata->name) +#define EDT_GET_PROP(name, reg) { \ + const u32 *prop = of_get_property(np, #name, NULL); \ + if (prop) \ + edt_ft5x06_register_write(tsdata, reg, be32_to_cpu(*prop)); \ +} + +static void edt_ft5x06_ts_get_dt_defaults(struct device_node *np, + struct edt_ft5x06_ts_data *tsdata) +{ + EDT_GET_PROP(threshold, WORK_REGISTER_THRESHOLD); + EDT_GET_PROP(gain, WORK_REGISTER_GAIN); + EDT_GET_PROP(offset, WORK_REGISTER_OFFSET); + EDT_GET_PROP(report_rate, WORK_REGISTER_REPORT_RATE); +} + static void edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, const struct edt_ft5x06_platform_data *pdata) @@ -702,6 +736,33 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); } +#ifdef CONFIG_OF +static int edt_ft5x06_i2c_ts_probe_dt(struct device *dev, + struct edt_ft5x06_ts_data *tsdata) +{ + struct device_node *np = dev->of_node; + + if (!np) + return -ENODEV; + + /* + * irq_pin is not needed for DT setup. + * irq is associated via 'interrupts' property in DT + */ + tsdata->irq_pin = -EINVAL; + tsdata->reset_pin = of_get_named_gpio(np, "reset-gpios", 0); + tsdata->wake_pin = of_get_named_gpio(np, "wake-gpios", 0); + + return 0; +} +#else +static inline int edt_ft5x06_i2c_ts_probe_dt(struct device *dev, + struct edt_ft5x06_i2c_ts_data *tsdata) +{ + return -ENODEV; +} +#endif + static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -714,32 +775,40 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n"); + tsdata = devm_kzalloc(&client->dev, sizeof(*tsdata), GFP_KERNEL); + if (!tsdata) { + dev_err(&client->dev, "failed to allocate driver data.\n"); + return -ENOMEM; + } + if (!pdata) { - dev_err(&client->dev, "no platform data?\n"); - return -EINVAL; + error = edt_ft5x06_i2c_ts_probe_dt(&client->dev, tsdata); + if (error) { + dev_err(&client->dev, + "DT probe failed and no platform data present\n"); + return error; + } + } else { + tsdata->reset_pin = pdata->reset_pin; + tsdata->irq_pin = pdata->irq_pin; + tsdata->wake_pin = -EINVAL; } - error = edt_ft5x06_ts_reset(client, pdata->reset_pin); + error = edt_ft5x06_ts_reset(client, tsdata); if (error) return error; - if (gpio_is_valid(pdata->irq_pin)) { - error = devm_gpio_request_one(&client->dev, pdata->irq_pin, - GPIOF_IN, "edt-ft5x06 irq"); + if (gpio_is_valid(tsdata->irq_pin)) { + error = devm_gpio_request_one(&client->dev, tsdata->irq_pin, + GPIOF_IN, "edt-ft5x06 irq"); if (error) { dev_err(&client->dev, "Failed to request GPIO %d, error %d\n", - pdata->irq_pin, error); + tsdata->irq_pin, error); return error; } } - tsdata = devm_kzalloc(&client->dev, sizeof(*tsdata), GFP_KERNEL); - if (!tsdata) { - dev_err(&client->dev, "failed to allocate driver data.\n"); - return -ENOMEM; - } - input = devm_input_allocate_device(&client->dev); if (!input) { dev_err(&client->dev, "failed to allocate input device.\n"); @@ -757,7 +826,11 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; } - edt_ft5x06_ts_get_defaults(tsdata, pdata); + if (!pdata) + edt_ft5x06_ts_get_dt_defaults(client->dev.of_node, tsdata); + else + edt_ft5x06_ts_get_defaults(tsdata, pdata); + edt_ft5x06_ts_get_parameters(tsdata); dev_dbg(&client->dev, @@ -787,10 +860,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, input_set_drvdata(input, tsdata); i2c_set_clientdata(client, tsdata); - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, edt_ft5x06_ts_isr, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->name, tsdata); + error = devm_request_threaded_irq(&client->dev, client->irq, NULL, + edt_ft5x06_ts_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->name, tsdata); if (error) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); return error; @@ -801,19 +874,21 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client, return error; error = input_register_device(input); - if (error) { - sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); - return error; - } + if (error) + goto err_remove_attrs; edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev)); device_init_wakeup(&client->dev, 1); dev_dbg(&client->dev, - "EDT FT5x06 initialized: IRQ pin %d, Reset pin %d.\n", - pdata->irq_pin, pdata->reset_pin); + "EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n", + client->irq, tsdata->wake_pin, tsdata->reset_pin); return 0; + +err_remove_attrs: + sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group); + return error; } static int edt_ft5x06_ts_remove(struct i2c_client *client) @@ -857,10 +932,17 @@ static const struct i2c_device_id edt_ft5x06_ts_id[] = { }; MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); +static const struct of_device_id edt_ft5x06_of_match[] = { + { .compatible = "edt,edt-ft5x06", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); + static struct i2c_driver edt_ft5x06_ts_driver = { .driver = { .owner = THIS_MODULE, .name = "edt_ft5x06", + .of_match_table = edt_ft5x06_of_match, .pm = &edt_ft5x06_ts_pm_ops, }, .id_table = edt_ft5x06_ts_id,