Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp4317981ybc; Fri, 22 Nov 2019 00:31:43 -0800 (PST) X-Google-Smtp-Source: APXvYqwHALz7YjnEa+sQ69fA8s0NIKJt7MIaoYluWkBbrRrD1J3yE3fKjd/1HdXVJhklAZ1c21C2 X-Received: by 2002:a05:600c:410:: with SMTP id q16mr14969301wmb.2.1574411503257; Fri, 22 Nov 2019 00:31:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574411503; cv=none; d=google.com; s=arc-20160816; b=p5tUSSE0LpIgGrtxKn06tY2f1RAj7WWY8fbb/0kBhugN7jpx3mA2aSDUNgxw7kzfgv W8RqBXVgqYUWUzQioAyYWw67M06RcQNZbnpZPHMc6Jt92oMVMd6Ac5NaKNPU1z81lqkV I+RsuMsWTePWVUIrAylt3V3j22UeoRDUBl52wN/j6Agyn1U3lkxhRJQd3IjLfkyYs7pq uKGLHagEdcvafHtahmnmyBo6Ak4QJ5B9N2VvdyewgOeVpGxk4gXQCyqMlMm31iNZx8aR ADNiN4GeSWj81Tu3t9FRQQyt7cZJJtP+62+3sFUKWzhOhzwkLY/FcNDL8HpzW13wJAX2 5vbw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:ironport-sdr:ironport-sdr; bh=qO8YcSdnN5SM5Vhb4gku8qc0XAA4OZDOkaJWpFTz8fI=; b=Y7FNDizrI4X3qMW6fF7LflWHAhcBSq5y8YZTP6BxopuE/vHTslXWs+oNcKK6CBGZAW FtLtK0hvO+v4cEpIZy5sPGasvUOfkKHwqohordD/1nWA3GCeRK8V6GGjehb2mbRrsU1Z D3lp3bkIk/1cCSglyjRh91YzV9Hq9ROw/igvmpQI0VS7Z8QhbsIECJvitlSdOuDR8DKa 6b9ZBrhdSUfcxlKu1UpMcQ5qu+KoGCZ1OhKl2KKhXADeojmH5c6RWIuDC/2Xm8sdybQe n7TKLkOrLP2vJFS4e7UGoVxJk6dwFlmQwJqmgpBvIvrPNnHO2gj+QQykhk5hBnkqwajy Wr8A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id by4si4291514edb.87.2019.11.22.00.31.19; Fri, 22 Nov 2019 00:31:43 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727763AbfKVI0z (ORCPT + 99 others); Fri, 22 Nov 2019 03:26:55 -0500 Received: from esa4.mentor.iphmx.com ([68.232.137.252]:62619 "EHLO esa4.mentor.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727072AbfKVI0x (ORCPT ); Fri, 22 Nov 2019 03:26:53 -0500 IronPort-SDR: NNX/WdYnl0pgXwwvNEkVt4p71GGYcqU/hLBOHaR4DpNJ5DMB3UVK4iV5DEIMppJHjccuMmisUL yHAwauf0pmu9abZym018GohMle3wvrroWr/dtIDItD0+ky3S8BZc+EbKB8sGI37ZcINY/gtBlU 09n647lSgyjNb3CmKUzu30Z++UKT8h4vdoYPKhGbC8UiQJou9ZuK4yKQg5HGjhxqH6ih2WcaS5 BYChLC1Smbu7hSBFIZeNrqq6XYVMXjfjJJzaug9eSbtQHXzBtpDuOZ1wxL4A01Cal0A98daTWl Ohw= X-IronPort-AV: E=Sophos;i="5.69,229,1571731200"; d="scan'208";a="43457658" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa4.mentor.iphmx.com with ESMTP; 22 Nov 2019 00:26:53 -0800 IronPort-SDR: NRGWBFE7DkDJ3fTnL1zZqR1VtZoWeouk2j5ZiTTkZ/HinOupN3FmKibqNznTVt+KczRSOQ4ugx Khz1HRP9CzrUFXmYc5XPN7NiaziM7tsztLYOjYUNeJPWp4FChEY+csXcrQFXHuxO4AsHa26Etl YwLtdX6cHw2WDuFxGjQBsS0KGF4QVlL1gQ0YcyKYN8Goed4TwGZSoWv1AbjMh6scU3kS0H2Gby ArajvZRtrb1OBJyp8FJpkGLKNbYyQQqmpbpN7Bwu23398hKes3Kkky1wJEGNBMnC0Sulh9OkKf 5J0= From: Jiada Wang To: , , , , CC: , , , , Subject: [PATCH v6 45/48] input: touchscreen: atmel_mxt_ts: Added sysfs entry for touchscreen status Date: Fri, 22 Nov 2019 17:23:59 +0900 Message-ID: <20191122082402.18173-46-jiada_wang@mentor.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191122082402.18173-1-jiada_wang@mentor.com> References: <20191122082402.18173-1-jiada_wang@mentor.com> MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Naveen Chakka To know the current communication status of the touch controller during runtime, sysfs interface is added sysfs interface: /sys/class/i2c-dev/i2c-*/device/*/touch_dev_stat Executing the above sysfs interface provides two output values 1)Status of the touch device value 0 represents device is inactive value 1 represents device is active 2)Error counter value represents the number of times device in inactive since last read Signed-off-by: Naveen Chakka Signed-off-by: Sanjeev Chugh Signed-off-by: George G. Davis Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 109 +++++++++++++++++++++-- 1 file changed, 102 insertions(+), 7 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 78903806c0b4..d22a00ec69c1 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -222,6 +223,7 @@ enum t100_type { #define MXT_CHG_DELAY 100 /* msec */ #define MXT_POWERON_DELAY 150 /* msec */ #define MXT_BOOTLOADER_WAIT 36E5 /* 1 minute */ +#define MXT_WATCHDOG_TIMEOUT 1000 /* msec */ /* Command to unlock bootloader */ #define MXT_UNLOCK_CMD_MSB 0xaa @@ -317,6 +319,12 @@ struct mxt_flash { struct delayed_work work; }; +struct mxt_statusinfo { + bool dev_status; + bool intp_triggered; + u32 error_count; +}; + /* Each client has this additional data */ struct mxt_data { struct i2c_client *client; @@ -372,6 +380,9 @@ struct mxt_data { const char *pcfg_name; const char *input_name; struct mxt_flash *flash; + struct work_struct watchdog_work; + struct timer_list watchdog_timer; + struct mxt_statusinfo mxt_status; /* Cached parameters from object table */ u16 T5_address; @@ -1624,11 +1635,30 @@ static int mxt_process_messages(struct mxt_data *data) return total_handled; } +static void mxt_start_wd_timer(struct mxt_data *data) +{ + mod_timer(&data->watchdog_timer, jiffies + + msecs_to_jiffies(MXT_WATCHDOG_TIMEOUT)); +} + +static void mxt_stop_wd_timer(struct mxt_data *data) +{ + /* + * Ensure we wait until the watchdog timer + * running on a different CPU finishes + */ + del_timer_sync(&data->watchdog_timer); + cancel_work_sync(&data->watchdog_work); + del_timer_sync(&data->watchdog_timer); +} + static irqreturn_t mxt_interrupt(int irq, void *dev_id) { struct mxt_data *data = dev_id; int ret; + data->mxt_status.intp_triggered = true; + if (data->in_bootloader) { complete(&data->chg_completion); @@ -1636,21 +1666,25 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) cancel_delayed_work_sync(&data->flash->work); ret = mxt_check_bootloader(data); - return IRQ_RETVAL(ret); + ret = IRQ_RETVAL(ret); + goto exit; } - if (!data->object_table) - return IRQ_HANDLED; + if (!data->object_table) { + ret = IRQ_HANDLED; + goto exit; + } if (data->T44_address) ret = mxt_process_messages_t44(data); else ret = mxt_process_messages(data); - if (ret <= 0) - return IRQ_NONE; - else - return IRQ_HANDLED; + ret = (ret <= 0) ? IRQ_NONE : IRQ_HANDLED; + +exit: + data->mxt_status.intp_triggered = false; + return ret; } static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset, @@ -2970,6 +3004,36 @@ static int mxt_bootloader_status(struct mxt_data *data) return 0; } +static void mxt_watchdog_timer(struct timer_list *t) +{ + struct mxt_data *data = from_timer(data, t, watchdog_timer); + + if (!work_pending(&data->watchdog_work)) { + if (!data->mxt_status.intp_triggered) + schedule_work(&data->watchdog_work); + } + + mxt_start_wd_timer(data); +} + +static void mxt_watchdog_work(struct work_struct *work) +{ + struct mxt_data *data = + container_of(work, struct mxt_data, watchdog_work); + u16 info_buf; + int ret = 0; + u8 size = 2; + + ret = __mxt_read_reg(data->client, 0, size, &info_buf); + + if (ret) { + data->mxt_status.error_count++; + data->mxt_status.dev_status = false; + } else { + data->mxt_status.dev_status = true; + } +} + static int mxt_initialize(struct mxt_data *data) { struct i2c_client *client = data->client; @@ -3947,6 +4011,22 @@ static const struct attribute_group mxt_fw_attr_group = { .attrs = mxt_fw_attrs, }; +static ssize_t mxt_touch_device_status(struct device *dev, struct + device_attribute *attr, char *buf) +{ + struct mxt_data *data = dev_get_drvdata(dev); + int ret = 0; + + if (data->mxt_status.dev_status) + data->mxt_status.error_count = 0; + + ret = snprintf(buf, PAGE_SIZE, "%d %d\n", data->mxt_status.dev_status, + data->mxt_status.error_count); + /* clear the error counter once it is read */ + data->mxt_status.error_count = 0; + return ret; +} + static DEVICE_ATTR(fw_version, S_IRUGO, mxt_fw_version_show, NULL); static DEVICE_ATTR(hw_version, S_IRUGO, mxt_hw_version_show, NULL); static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); @@ -3958,6 +4038,7 @@ static DEVICE_ATTR(debug_v2_enable, S_IWUSR | S_IRUSR, NULL, mxt_debug_v2_enable_store); static DEVICE_ATTR(debug_notify, S_IRUGO, mxt_debug_notify_show, NULL); static DEVICE_ATTR(t25, 0600, mxt_t25_selftest_show, mxt_t25_selftest_store); +static DEVICE_ATTR(touch_dev_stat, 0444, mxt_touch_device_status, NULL); static struct attribute *mxt_attrs[] = { &dev_attr_fw_version.attr, @@ -3969,6 +4050,7 @@ static struct attribute *mxt_attrs[] = { &dev_attr_debug_v2_enable.attr, &dev_attr_debug_notify.attr, &dev_attr_t25.attr, + &dev_attr_touch_dev_stat.attr, NULL }; @@ -4321,6 +4403,13 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) msleep(MXT_RESET_TIME); } + INIT_WORK(&data->watchdog_work, mxt_watchdog_work); + + /* setup watchdog timer */ + timer_setup(&data->watchdog_timer, mxt_watchdog_timer, 0); + + mxt_start_wd_timer(data); + error = mxt_initialize(data); if (error) goto err_free_object; @@ -4335,8 +4424,11 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; err_free_object: + cancel_work_sync(&data->watchdog_work); + mxt_stop_wd_timer(data); mxt_free_input_device(data); mxt_free_object_table(data); + del_timer(&data->watchdog_timer); if (data->reset_gpio) { sysfs_remove_link(&client->dev.kobj, "reset"); gpiod_unexport(data->reset_gpio); @@ -4359,6 +4451,9 @@ static int mxt_remove(struct i2c_client *client) mxt_free_input_device(data); mxt_free_object_table(data); + cancel_work_sync(&data->watchdog_work); + mxt_stop_wd_timer(data); + return 0; } -- 2.17.1