From patchwork Wed Nov 29 11:06:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 171245 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:a5a7:0:b0:403:3b70:6f57 with SMTP id d7csp260313vqn; Wed, 29 Nov 2023 03:07:26 -0800 (PST) X-Google-Smtp-Source: AGHT+IHQKXUZWrIO2GyN5o/YDWNnd8Gro1aFjUONEhs7H0s4eac2CKY/tBd36rz4y5Rux/u9/Acm X-Received: by 2002:a17:90b:4f43:b0:286:19b9:b7f with SMTP id pj3-20020a17090b4f4300b0028619b90b7fmr1904747pjb.6.1701256046183; Wed, 29 Nov 2023 03:07:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701256046; cv=none; d=google.com; s=arc-20160816; b=O41AGx8iZJ0rWRegv+RNiSaUjvM86aLektdytsJMQvBAWeHxQIRIirvNAXokAZsTFX 1xLNNcnWgF68p9TQ6c0gsScS+v9rF1FB5xUfbHag2lguiaaFI13guycBmlGuBwaW8cUy 1LBzTeFK4vEZpFpFXlM/EIZB0ESgksWR+B0sgww6mL9HFhDLBlLqpq3wUzSNr/SjgjjQ /c0s544HZ3lIzONHw2LSAA4jOPQD55vBGKLL3JXp1pBLNHtrXnW8dj0HZvKzZpGVAYf9 uSWDUm62KiWruBgj6Ur+GcVThzYdSbzVGqPsadbIEea6pswWOhRasCMxqQL/ovXTDRMz W+Jg== 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=1OLrLSe8zgwEk8/U6BpuhSJF1VhwTWPoYdcRwZ9iv5A=; fh=FCvgWT233a5DOmO4XE9xWNSt5LI2rBcRWrPm64F0VAw=; b=G0JCgD0v4Vaf5Y0XVbRRkCfMb9bSGZEEOe/fYZukx+WZIYvbpyAP0So5KAzTgnpYfE KMys5M1NuZaRxCqsUyna8XqRvGjKsgsINPzCqj3h3C+LKKqiJqZ2ERVUNnOix+Jr1Qe1 Rc473JfF4s2j1jYLH8PeFbws1Nc4mhH+EODJk83PDsCqCOXBGh4DZKzU5C+bbYcGqgZd aQTkVSeZHDtKtufmTjfsh02hJrgyfcQUfW34QLkILittOmdsABbtlDS8fo0BCVZp6SoD g3Ptk2F66m8zU8EW2cxACBGE4412wRexmH+7pB3ASvWubNcrnPrO5DyjrraO9dylMK4P zAvQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@atomide.com header.s=25mailst header.b=Z8r5oWyG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from pete.vger.email (pete.vger.email. [23.128.96.36]) by mx.google.com with ESMTPS id lp8-20020a17090b4a8800b002859bac814dsi1130121pjb.21.2023.11.29.03.07.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Nov 2023 03:07:26 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 as permitted sender) client-ip=23.128.96.36; Authentication-Results: mx.google.com; dkim=fail header.i=@atomide.com header.s=25mailst header.b=Z8r5oWyG; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.36 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 pete.vger.email (Postfix) with ESMTP id 46755805001F; Wed, 29 Nov 2023 03:07:21 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at pete.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230513AbjK2LHM (ORCPT + 99 others); Wed, 29 Nov 2023 06:07:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39116 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231148AbjK2LHK (ORCPT ); Wed, 29 Nov 2023 06:07:10 -0500 Received: from mail5.25mail.st (mail5.25mail.st [74.50.62.9]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB3D61990; Wed, 29 Nov 2023 03:07:15 -0800 (PST) Received: from localhost (91-158-86-216.elisa-laajakaista.fi [91.158.86.216]) by mail5.25mail.st (Postfix) with ESMTPSA id BC90F603F4; Wed, 29 Nov 2023 11:07:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=atomide.com; s=25mailst; t=1701256035; bh=QLE5HdiOb5o5sP/1aVwOBc3v1Ohi4Ot5lukAFe+jq0c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z8r5oWyGRwgjer8PhRkZD8N7tlSmr0Ff2RU/uKGX+/ZDOdPwteg8a+MnG/9moVx7g R+U7U1Fw+rdDihH2skLuCIdVZDMN9Epg+rQRh1OgMWgvaVDvobVFvNXuJAjNMYHUbl 3cJwXEyQzKdL6tlIQK5Jr2CEYtxw70N0awMYm68ygO5ltFh0+mTDMJ1AuFm9c6M7yJ lwPOvrxaQXzZNng3kVY3W5YJi91grp1h8RGANNeOMfXJqXnepUPzRagqCliam6Gr9D 8wFzv6QLZycvxcebXAURdZd/3siEeD7HvKq0L5QdCWGmXv6rEeQCHpemcDRZdrMO4r xCgjskoosZOUw== From: Tony Lindgren To: Dmitry Torokhov Cc: Rob Herring , linux-input@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Dhruva Gole Subject: [PATCH v5 2/2] Input: gpio-keys - Add system suspend support for dedicated wakeirqs Date: Wed, 29 Nov 2023 13:06:15 +0200 Message-ID: <20231129110618.27551-2-tony@atomide.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <20231129110618.27551-1-tony@atomide.com> References: <20231129110618.27551-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 pete.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 (pete.vger.email [0.0.0.0]); Wed, 29 Nov 2023 03:07:21 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783896260279851695 X-GMAIL-MSGID: 1783896260279851695 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 --- Changes since v5 - Use normal disable_irq() as suggested by Dmitry No driver changes between v1 and v4 --- 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(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(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(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; }; /**