From patchwork Fri Jun 21 18:09:56 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerhard Sittig X-Patchwork-Id: 2763841 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E9972C0AB1 for ; Fri, 21 Jun 2013 18:17:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5F6AD201C0 for ; Fri, 21 Jun 2013 18:17:46 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 284C5201BC for ; Fri, 21 Jun 2013 18:17:45 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Uq5rN-0007jB-7b; Fri, 21 Jun 2013 18:15:03 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Uq5pL-0002Dt-7G; Fri, 21 Jun 2013 18:12:51 +0000 Received: from mail-out.m-online.net ([212.18.0.9]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Uq5oN-00028T-9z for linux-arm-kernel@lists.infradead.org; Fri, 21 Jun 2013 18:11:53 +0000 Received: from frontend1.mail.m-online.net (unknown [192.168.8.180]) by mail-out.m-online.net (Postfix) with ESMTP id 3bcScS3JZdz4KK2r; Fri, 21 Jun 2013 20:10:32 +0200 (CEST) Received: from localhost (dynscan1.mnet-online.de [192.168.6.68]) by mail.m-online.net (Postfix) with ESMTP id 3bcScS2skxzbbj9; Fri, 21 Jun 2013 20:10:32 +0200 (CEST) X-Virus-Scanned: amavisd-new at mnet-online.de Received: from mail.mnet-online.de ([192.168.8.180]) by localhost (dynscan1.mail.m-online.net [192.168.6.68]) (amavisd-new, port 10024) with ESMTP id l6OImIqTd0TJ; Fri, 21 Jun 2013 20:10:30 +0200 (CEST) X-Auth-Info: hEk7vIH7jJZDBYY3+XSPFi7K8EO32cjJkpw8QLDUYXc= Received: from localhost (kons-4d027c0a.pool.mediaWays.net [77.2.124.10]) by mail.mnet-online.de (Postfix) with ESMTPA; Fri, 21 Jun 2013 20:10:30 +0200 (CEST) From: Gerhard Sittig To: Dmitry Torokhov , linux-input@vger.kernel.org, devicetree-discuss@lists.ozlabs.org, linux-arm-kernel@lists.infradead.org, Chao Xie Subject: [PATCH v1 10/12] input: keypad_matrix: use usleep_range() for scan delay Date: Fri, 21 Jun 2013 20:09:56 +0200 Message-Id: <1371838198-7327-11-git-send-email-gsi@denx.de> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1371838198-7327-1-git-send-email-gsi@denx.de> References: <1371838198-7327-1-git-send-email-gsi@denx.de> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130621_141151_619661_1662424C X-CRM114-Status: GOOD ( 22.47 ) X-Spam-Score: -1.9 (-) Cc: Eric Miao , Detlev Zundel , Arnd Bergmann , Tony Lindgren , Gerhard Sittig , Sekhar Nori , Haojian Zhuang , Marek Vasut , Ralf Baechle , Anatolij Gustschin X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.7 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 querying keyboards isn't a time critical task and does not depend on exact timing in the microseconds order -- the timeouts and delays are arbitrary choices or educated guesses at best anyway so we can be nice and reduce stress on the timer management - use usleep_range() for the scan delay (a delay in microseconds between activating a column and reading rows) - allow optional range specs in device tree nodes in addition to the previous simple integer spec of an exact delay - allow for platform data to optionally specify a delay range this implementation assumes an exact delay with the first or only integer spec when no upper bound for the range was specified as well as when the range spec is invalid, as well as keeps up the scan delay's being optional -- this results in compatible behaviour to the previous implementation and an improvement on system load when the newly introduced feature gets used normalization of the range spec (enforcing a valid upper bound against the lower bound, and assuming the exact value when no range was specified) happens during probe in the devide tree case, but cannot be done for the non-DT case because the platform data is read-only during probe -- that's why the routine which enables the columns and optionally applies the delay will enforce the constraints on the range spec -- this is not a problem, and is perfectly acceptable given the low cost of the min/max check and the potential benefit of reduced timer management cost Signed-off-by: Gerhard Sittig --- .../bindings/input/gpio-matrix-keypad.txt | 7 +++-- drivers/input/keyboard/matrix_keypad.c | 29 +++++++++++++++++--- include/linux/input/matrix_keypad.h | 5 ++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt index 75e9e28..1562681 100644 --- a/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt +++ b/Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt @@ -93,7 +93,10 @@ Optional Properties: a column line and reading back its row status, such that pin levels can settle after propagating through the matrix and its - associated hardware components + associated hardware components, can be specified + with either one value giving the exact delay, or + with two values giving a delay range (allowing + for reduced timer management overhead) - col-switch-delay-ms: columns switch interval in milliseconds instead of using interrupts to detect key press changes, enables polling mode when specified @@ -146,7 +149,7 @@ Examples: matrix_keypad { compatible = "gpio-matrix-keypad"; debounce-delay-ms = <5>; - col-scan-delay-us = <1>; + col-scan-delay-us = <2 10>; col-switch-delay-ms = <20>; col-gpios-binary; diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index c015f0d..275b157 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -100,6 +100,7 @@ static void activate_col(const struct matrix_keypad_platform_data *pdata, int col, bool on) { int bit, lvl; + u32 delay_min, delay_max; if (!pdata->col_gpios_binary_encoded) { /* one-out-of-N approach, just setup the one pin */ @@ -115,8 +116,19 @@ static void activate_col(const struct matrix_keypad_platform_data *pdata, /* EMPTY */ } - if (on && pdata->col_scan_delay_us) - udelay(pdata->col_scan_delay_us); + if (on && pdata->col_scan_delay_us) { + /* + * the platform data is 'const' aka 'read-only' here, so + * we may not modify it, yet might not have had a chance + * to normalize its data before (we did for the DT case, + * but did not for non-DT cases), which is why we have + * to use local variables here to enforce sane input + * data for the usleep range spec + */ + delay_min = pdata->col_scan_delay_us; + delay_max = max(delay_min, pdata->col_scan_delay_us_max); + usleep_range(delay_min, delay_max); + } } /* @@ -609,6 +621,7 @@ matrix_keypad_parse_dt(struct device *dev) unsigned int *gpios; int i; int err; + u32 us[2]; if (!np) { dev_err(dev, "device lacks DT data for the keypad config\n"); @@ -655,8 +668,15 @@ matrix_keypad_parse_dt(struct device *dev) /* get delay and interval timing specs */ of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms); - of_property_read_u32(np, "col-scan-delay-us", - &pdata->col_scan_delay_us); + us[0] = us[1] = 0; + err = of_property_read_u32_array(np, "col-scan-delay-us", &us[0], 2); + if (err == -EOVERFLOW) { + err = of_property_read_u32(np, "col-scan-delay-us", &us[0]); + us[1] = us[0]; + } + us[1] = max(us[1], us[0]); + pdata->col_scan_delay_us = us[0]; + pdata->col_scan_delay_us_max = us[1]; of_property_read_u32(np, "col-switch-delay-ms", &pdata->col_switch_delay_ms); if (pdata->col_gpios_binary_encoded && !pdata->col_switch_delay_ms) { @@ -744,6 +764,7 @@ static int matrix_keypad_probe(struct platform_device *pdev) /* start in stopped state, open(2) will activate the scan */ keypad->stopped = true; INIT_DELAYED_WORK(&keypad->work_scan_matrix, matrix_keypad_scan); + /* we cannot normalize pdata here for the non-DT case, it's read-only */ INIT_DELAYED_WORK(&keypad->work_switch_column, matrix_keypad_switch); keypad->col_to_poll = pdata->num_matrix_cols; spin_lock_init(&keypad->lock); diff --git a/include/linux/input/matrix_keypad.h b/include/linux/input/matrix_keypad.h index 82db84a..fa093b2 100644 --- a/include/linux/input/matrix_keypad.h +++ b/include/linux/input/matrix_keypad.h @@ -43,6 +43,10 @@ struct matrix_keymap_data { * @num_matrix_cols: number of logical column lines in the matrix * @col_scan_delay_us: delay in microseconds, the interval between * activating a column and reading back row information + * @col_scan_delay_us_max: maximum delay in microseconds between + * activating a column and reading back row information, + * defaults to @col_scan_delay_us when not specified, allows + * for reduced timer management overhead * @col_switch_delay_ms: delay in milliseconds, the interval with which * colums periodically get checked for changes in key press status * @debounce_ms: debounce interval in milliseconds, the interval between @@ -80,6 +84,7 @@ struct matrix_keypad_platform_data { /* delays and intervals specs */ unsigned int col_scan_delay_us; + unsigned int col_scan_delay_us_max; unsigned int col_switch_delay_ms; unsigned int debounce_ms;