From patchwork Fri Nov 24 08:32:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 169283 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce62:0:b0:403:3b70:6f57 with SMTP id o2csp1005938vqx; Fri, 24 Nov 2023 00:39:31 -0800 (PST) X-Google-Smtp-Source: AGHT+IHip+cgEifTVgE/pgEnc6XMq4Y8ZopZ2uW3O0r/nVHfODf0IJK4KXLobOWmkor+oDw3kfYy X-Received: by 2002:a05:6808:bce:b0:3a7:d566:8b5e with SMTP id o14-20020a0568080bce00b003a7d5668b5emr2490670oik.44.1700815171058; Fri, 24 Nov 2023 00:39:31 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700815171; cv=none; d=google.com; s=arc-20160816; b=G+LTW7DkQly6q6Dw9xMsF5JMpjgYL/h2AuH3q1E7K6ojd98llQU2HDaooEh3lJFT80 UIldomKiHIkWRk8aa7Z5Po07v+t5nPf7TgZh5UMpU5yCoVwXAU06qDhg0LzZZJAmGP1Z rpGfXFdqKDYYRcVX3HsOMWFbK80OqmNFRt4YydsqlVo63853UC7H1J6hihy3nwp1I3Y8 +7cZovwKnuYYiiJjvHvZXBU+AvAG64T9mcHRAGTecM/gEatOo7xfDZirzVQm0vcE60Mq l2Calb0c/hlxheG0I58Rheh8K42q5RTZtp1rtqE+yBPSl1jw/5u+CmhdBPvLJQmjGAK2 x7Ww== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=KhzdsnhpWA4nCkOZI+QT75IM63Hv95XdfK1F9b8paAc=; fh=59PZC+djxGUP3m275QCpGeKuaYDU8QwCFhap2D9fK60=; b=mLwjY9cim0TXsZA9EUzlYqvxsMEjBXsEJgOAwVDfsDEsNbfKJyuDp0b8FocdPhM9m4 W+/E2ZkFmH8wYl+ygcE1/QA6kGeZBmHata+/PoRj67PsXwY+M5qQ4C2Bb6af00WA9aih t6lQiSI3nXpU8f883YEKB3E4EAlr81Cy15P4fv+8pavK5dAgJqUIDn3hWCad0pMAKdFE ld35Zcj256vmCw1ma/XqXhibG0RfWh79tttqMmjsfNZ6XCYcESq71Bd7dSsvu8qI7baw tbadQmFpAon7+zFblsHFd6sNEbk1HvDFp25wAqT66bn14YSeJldP74+9Koc0sOIn8lBB 5WHQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@atomide.com header.s=25mailst header.b=deq8gQJo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from morse.vger.email (morse.vger.email. [2620:137:e000::3:1]) by mx.google.com with ESMTPS id bw1-20020a056a02048100b005ac86e7df6esi3459127pgb.363.2023.11.24.00.39.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Nov 2023 00:39:31 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) client-ip=2620:137:e000::3:1; Authentication-Results: mx.google.com; dkim=fail header.i=@atomide.com header.s=25mailst header.b=deq8gQJo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:1 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by morse.vger.email (Postfix) with ESMTP id 684CA805A5E5; Fri, 24 Nov 2023 00:39:28 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at morse.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344985AbjKXIjL (ORCPT + 99 others); Fri, 24 Nov 2023 03:39:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57220 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229742AbjKXIjH (ORCPT ); Fri, 24 Nov 2023 03:39:07 -0500 X-Greylist: delayed 368 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Fri, 24 Nov 2023 00:39:14 PST Received: from mail5.25mail.st (mail5.25mail.st [74.50.62.9]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A45E1AD; Fri, 24 Nov 2023 00:39:13 -0800 (PST) Received: from localhost (91-158-86-216.elisa-laajakaista.fi [91.158.86.216]) by mail5.25mail.st (Postfix) with ESMTPSA id 5A57C60B1C; Fri, 24 Nov 2023 08:33:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=atomide.com; s=25mailst; t=1700814812; bh=X9UAYrEpltlL4BFSrotnsyJ28JU1NDy+XhYUgWFsj3c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=deq8gQJoV8AuDJyfkujArZSATCptJGPR0oRvGeUQHKRlosVOvT+oW0d7diQ6tztdi PgqjHJn6mqxEpebsOYh9vNXzAf0cgcnySdleHpY5arlQOCEKe68YzB+y9u+dMD2vJR WhuxWudhbeaeCkdg/URqXQwtJ8w2In3hd7zSx5onHwfszgAcA6F5B62DF2M5pLZsgv deaEPLf1R0VOS3sCQwk3FIGCTXhQvZrBdi7FMPyyst07aPjGnh5+uZTPQG1islIacA riYzbWoxf8TfsNjPEqKHvN/RYuSmSiixjV9Z5KajH8QWWa+L41EHiA/nty5hFChEC4 75L2s+1h3F4eA== From: Tony Lindgren To: Dmitry Torokhov Cc: Rob Herring , Krzysztof Kozlowski , Conor Dooley , linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Rob Herring , Dhruva Gole Subject: [PATCH v4 2/2] Input: gpio-keys - Add system suspend support for dedicated wakeirqs Date: Fri, 24 Nov 2023 10:32:41 +0200 Message-ID: <20231124083241.40780-2-tony@atomide.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231124083241.40780-1-tony@atomide.com> References: <20231124083241.40780-1-tony@atomide.com> MIME-Version: 1.0 X-Spam-Status: No, score=-0.6 required=5.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on morse.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (morse.vger.email [0.0.0.0]); Fri, 24 Nov 2023 00:39:28 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783433968588997791 X-GMAIL-MSGID: 1783433968588997791 Some SoCs have a separate dedicated wake-up interrupt controller that can be used to wake up the system from deeper idle states. We already support configuring a separate interrupt for a gpio-keys button to be used with a gpio line. However, we are lacking support system suspend for cases where a separate interrupt needs to be used in deeper sleep modes. Because of it's nature, gpio-keys does not know about the runtime PM state of the button gpios, and may have several gpio buttons configured for each gpio-keys device instance. Implementing runtime PM support for gpio-keys does not help, and we cannot use drivers/base/power/wakeirq.c support. We need to implement custom wakeirq support for gpio-keys. For handling a dedicated wakeirq for system suspend, we enable and disable it with gpio_keys_enable_wakeup() and gpio_keys_disable_wakeup() that we already use based on device_may_wakeup(). Some systems may have a dedicated wakeirq that can also be used as the main interrupt, this is already working for gpio-keys. Let's add some wakeirq related comments while at it as the usage with a gpio line and separate interrupt line may not be obvious. Tested-by: Dhruva Gole Signed-off-by: Tony Lindgren --- No changes from v1 --- drivers/input/keyboard/gpio_keys.c | 69 ++++++++++++++++++++++++++++-- include/linux/gpio_keys.h | 2 + 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -45,7 +45,9 @@ struct gpio_button_data { unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ unsigned int irq; + unsigned int wakeirq; unsigned int wakeup_trigger_type; + spinlock_t lock; bool disabled; bool key_pressed; @@ -511,6 +513,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, struct gpio_button_data *bdata = &ddata->data[idx]; irq_handler_t isr; unsigned long irqflags; + const char *wakedesc; int irq; int error; @@ -575,6 +578,14 @@ static int gpio_keys_setup_key(struct platform_device *pdev, !gpiod_cansleep(bdata->gpiod); } + /* + * If an interrupt was specified, use it instead of the gpio + * interrupt and use the gpio for reading the state. A separate + * interrupt may be used as the main button interrupt for + * runtime PM to detect events also in deeper idle states. If a + * dedicated wakeirq is used for system suspend only, see below + * for bdata->wakeirq setup. + */ if (button->irq) { bdata->irq = button->irq; } else { @@ -672,6 +683,36 @@ static int gpio_keys_setup_key(struct platform_device *pdev, return error; } + if (!button->wakeirq) + return 0; + + /* Use :wakeup suffix like drivers/base/power/wakeirq.c does */ + wakedesc = devm_kasprintf(dev, GFP_KERNEL, "%s:wakeup", desc); + if (!wakedesc) + return -ENOMEM; + + bdata->wakeirq = button->wakeirq; + irqflags |= IRQF_NO_SUSPEND; + + /* + * Wakeirq shares the handler with the main interrupt, it's only + * active during system suspend. See gpio_keys_button_enable_wakeup() + * and gpio_keys_button_disable_wakeup(). + */ + error = devm_request_any_context_irq(dev, bdata->wakeirq, isr, + irqflags, wakedesc, bdata); + if (error < 0) { + dev_err(dev, "Unable to claim wakeirq %d; error %d\n", + bdata->irq, error); + return error; + } + + /* + * Disable wakeirq until suspend. IRQF_NO_AUTOEN won't work if + * IRQF_SHARED was set based on !button->can_disable. + */ + disable_irq_nosync(bdata->wakeirq); + return 0; } @@ -728,7 +769,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) struct gpio_keys_platform_data *pdata; struct gpio_keys_button *button; struct fwnode_handle *child; - int nbuttons; + int nbuttons, irq; nbuttons = device_get_child_node_count(dev); if (nbuttons == 0) @@ -750,9 +791,19 @@ gpio_keys_get_devtree_pdata(struct device *dev) device_property_read_string(dev, "label", &pdata->name); device_for_each_child_node(dev, child) { - if (is_of_node(child)) - button->irq = - irq_of_parse_and_map(to_of_node(child), 0); + if (is_of_node(child)) { + irq = of_irq_get_byname(to_of_node(child), "irq"); + if (irq > 0) + button->irq = irq; + + irq = of_irq_get_byname(to_of_node(child), "wakeup"); + if (irq > 0) + button->wakeirq = irq; + + if (!button->irq && !button->wakeirq) + button->irq = + irq_of_parse_and_map(to_of_node(child), 0); + } if (fwnode_property_read_u32(child, "linux,code", &button->code)) { @@ -921,6 +972,11 @@ gpio_keys_button_enable_wakeup(struct gpio_button_data *bdata) } } + if (bdata->wakeirq) { + enable_irq(bdata->wakeirq); + disable_irq_nosync(bdata->irq); + } + return 0; } @@ -929,6 +985,11 @@ gpio_keys_button_disable_wakeup(struct gpio_button_data *bdata) { int error; + if (bdata->wakeirq) { + enable_irq(bdata->irq); + disable_irq_nosync(bdata->wakeirq); + } + /* * The trigger type is always both edges for gpio-based keys and we do * not support changing wakeup trigger for interrupt-based keys. diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h --- a/include/linux/gpio_keys.h +++ b/include/linux/gpio_keys.h @@ -21,6 +21,7 @@ struct device; * disable button via sysfs * @value: axis value for %EV_ABS * @irq: Irq number in case of interrupt keys + * @wakeirq: Optional dedicated wake-up interrupt */ struct gpio_keys_button { unsigned int code; @@ -34,6 +35,7 @@ struct gpio_keys_button { bool can_disable; int value; unsigned int irq; + unsigned int wakeirq; }; /**