From patchwork Sun Jan 10 19:05:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 12009383 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 48BCCC4321A for ; Sun, 10 Jan 2021 19:07:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 306FA22AAE for ; Sun, 10 Jan 2021 19:07:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726686AbhAJTHC (ORCPT ); Sun, 10 Jan 2021 14:07:02 -0500 Received: from muru.com ([72.249.23.125]:42322 "EHLO muru.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726267AbhAJTHC (ORCPT ); Sun, 10 Jan 2021 14:07:02 -0500 Received: from hillo.muru.com (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id D12238191; Sun, 10 Jan 2021 19:05:50 +0000 (UTC) From: Tony Lindgren To: Dmitry Torokhov Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org, Arthur Demchenkov , Carl Philipp Klemm , Merlijn Wajer , Pavel Machek , ruleh , Sebastian Reichel Subject: [PATCH 5/5] Input: omap4-keypad - implement errata check for lost key-up events Date: Sun, 10 Jan 2021 21:05:29 +0200 Message-Id: <20210110190529.46135-6-tony@atomide.com> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210110190529.46135-1-tony@atomide.com> References: <20210110190529.46135-1-tony@atomide.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org We are still missing handling for errata i689 related issues for the case where we never see a key up interrupt for the last pressed key. To fix the issue, we must scan the key state again after the keyboard controller has idled to check if a key up event was missed. This is described in the omap4 silicon errata documentation for Errata ID i689 "1.32 Keyboard Key Up Event Can Be Missed": "When a key is released for a time shorter than the debounce time, in-between 2 key press (KP1 and KP2), the keyboard state machine will go to idle mode and will never detect the key release (after KP1, and also after KP2), and thus will never generate a new IRQ indicating the key release." We can use PM runtime autosuspend features to check the keyboard state after it enters idle. Cc: Arthur Demchenkov Cc: Carl Philipp Klemm Cc: Merlijn Wajer Cc: Pavel Machek Cc: ruleh Cc: Sebastian Reichel Signed-off-by: Tony Lindgren Signed-off-by: Tony Lindgren --- drivers/input/keyboard/omap4-keypad.c | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -60,6 +60,8 @@ ((((dbms) * 1000) / ((1 << ((ptv) + 1)) * (1000000 / 32768))) - 1) #define OMAP4_VAL_DEBOUNCINGTIME_16MS \ OMAP4_KEYPAD_DEBOUNCINGTIME_MS(16, OMAP4_KEYPAD_PTV_DIV_128) +#define OMAP4_KEYPAD_AUTOIDLE_MS 50 /* Approximate measured time */ +#define OMAP4_KEYPAD_IDLE_CHECK_MS (OMAP4_KEYPAD_AUTOIDLE_MS / 2) enum { KBD_REVISION_OMAP4 = 0, @@ -312,6 +314,32 @@ static int omap4_keypad_check_revision(struct device *dev, return 0; } +/* + * Errata ID i689 "1.32 Keyboard Key Up Event Can Be Missed". + * Interrupt may not happen for key-up events. We must clear stuck + * key-up events after the keyboard hardware has auto-idled. + */ +static int __maybe_unused omap4_keypad_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap4_keypad *keypad_data = platform_get_drvdata(pdev); + u32 active; + + active = kbd_readl(keypad_data, OMAP4_KBD_STATEMACHINE); + if (active) { + pm_runtime_mark_last_busy(dev); + return -EBUSY; + } + + omap4_keypad_scan_keys(keypad_data, true); + + return 0; +} + +static const struct dev_pm_ops omap4_keypad_pm_ops = { + SET_RUNTIME_PM_OPS(omap4_keypad_runtime_suspend, NULL, NULL) +}; + static void omap4_disable_pm(void *d) { pm_runtime_dont_use_autosuspend(d); @@ -358,6 +386,7 @@ static int omap4_keypad_probe(struct platform_device *pdev) return PTR_ERR(keypad_data->base); pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, OMAP4_KEYPAD_IDLE_CHECK_MS); pm_runtime_enable(dev); error = devm_add_action_or_reset(dev, omap4_disable_pm, dev); @@ -470,6 +499,7 @@ static struct platform_driver omap4_keypad_driver = { .driver = { .name = "omap4-keypad", .of_match_table = omap_keypad_dt_match, + .pm = &omap4_keypad_pm_ops, }, }; module_platform_driver(omap4_keypad_driver);