From patchwork Mon Oct 16 21:57:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Riegel X-Patchwork-Id: 10009929 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 962D460235 for ; Mon, 16 Oct 2017 21:57:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 87CB0286B4 for ; Mon, 16 Oct 2017 21:57:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7C044286F3; Mon, 16 Oct 2017 21:57:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A8B50286B4 for ; Mon, 16 Oct 2017 21:57:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753721AbdJPV5V (ORCPT ); Mon, 16 Oct 2017 17:57:21 -0400 Received: from mail.savoirfairelinux.com ([208.88.110.44]:52024 "EHLO mail.savoirfairelinux.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753509AbdJPV5U (ORCPT ); Mon, 16 Oct 2017 17:57:20 -0400 Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 0BB5D9C29E3; Mon, 16 Oct 2017 17:57:20 -0400 (EDT) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id uU4ftfG6oM12; Mon, 16 Oct 2017 17:57:19 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 60C1D9C2BE9; Mon, 16 Oct 2017 17:57:19 -0400 (EDT) X-Virus-Scanned: amavisd-new at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id u2JTD5OlTm1K; Mon, 16 Oct 2017 17:57:19 -0400 (EDT) Received: from workotop.humanware.local (unknown [192.252.129.34]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 2ABDE9C29E3; Mon, 16 Oct 2017 17:57:19 -0400 (EDT) From: Damien Riegel To: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Dmitry Torokhov , Maxime Ripard , Arnd Bergmann , Guenter Roeck , kernel@savoirfairelinux.com, Damien Riegel Subject: [PATCH] Input: tca8418 - enable interrupt after it has been requested Date: Mon, 16 Oct 2017 17:57:14 -0400 Message-Id: <20171016215714.3878-1-damien.riegel@savoirfairelinux.com> X-Mailer: git-send-email 2.14.2 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, enabling keypad interrupts is one of the first operations done on the keypad, even before the interrupt is requested, so there is a small time window where the keypad can fire interrupts but the driver is not yet ready to handle them. It's fine for level interrupts because they will be handled anyway, but not so much for edge ones. This commit modifies and moves the function in charge of configuring the keypad. Enabling interrupts is now the last thing done on the keypad, and after the interrupt has been requested by the driver. Writing to the config register was also used to determine if the device was indeed present on the bus or not, this has been replaced by reading the lock/event count register to keep the same functionality. Signed-off-by: Damien Riegel --- I originally made this patch on top of: 800e3b9a6801 Input: drop owner assignment from i2c_driver But I only compile-tested it on top of input/next. The issue was spotted thanks to a bootloader that left the keypad configured, only with interrupts disabled. So any button pressed or released during Linux's boot was queued and triggered an interrupt as soon as the driver enabled interrupts. It would really be appreciated if someone could give this patch a try. drivers/input/keyboard/tca8418_keypad.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index e37e335e406f..6da607d3b811 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -234,14 +234,7 @@ static irqreturn_t tca8418_irq_handler(int irq, void *dev_id) static int tca8418_configure(struct tca8418_keypad *keypad_data, u32 rows, u32 cols) { - int reg, error; - - /* Write config register, if this fails assume device not present */ - error = tca8418_write_byte(keypad_data, REG_CFG, - CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN); - if (error < 0) - return -ENODEV; - + int reg, error = 0; /* Assemble a mask for row and column registers */ reg = ~(~0 << rows); @@ -257,6 +250,12 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data, error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS2, reg >> 8); error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS3, reg >> 16); + if (error) + return error; + + error = tca8418_write_byte(keypad_data, REG_CFG, + CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN); + return error; } @@ -268,6 +267,7 @@ static int tca8418_keypad_probe(struct i2c_client *client, struct input_dev *input; u32 rows = 0, cols = 0; int error, row_shift, max_keys; + u8 reg; /* Check i2c driver capabilities */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { @@ -301,10 +301,10 @@ static int tca8418_keypad_probe(struct i2c_client *client, keypad_data->client = client; keypad_data->row_shift = row_shift; - /* Initialize the chip or fail if chip isn't present */ - error = tca8418_configure(keypad_data, rows, cols); - if (error < 0) - return error; + /* Read key lock register, if this fails assume device not present */ + error = tca8418_read_byte(keypad_data, REG_KEY_LCK_EC, ®); + if (error) + return -ENODEV; /* Configure input device */ input = devm_input_allocate_device(dev); @@ -340,6 +340,11 @@ static int tca8418_keypad_probe(struct i2c_client *client, return error; } + /* Initialize the chip */ + error = tca8418_configure(keypad_data, rows, cols); + if (error < 0) + return error; + error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device, error: %d\n",