Received: by 2002:a05:7412:37c9:b0:e2:908c:2ebd with SMTP id jz9csp1271654rdb; Wed, 20 Sep 2023 04:54:47 -0700 (PDT) X-Google-Smtp-Source: AGHT+IE0yhh/Uam+YqcgVO5MNfhj4OT9oeCckteQ/zhDzVPIDCBThMrFGgUTdTb+1qVb5r3o1FCr X-Received: by 2002:a05:6a00:1a51:b0:690:3b59:cc7b with SMTP id h17-20020a056a001a5100b006903b59cc7bmr2572782pfv.32.1695210886850; Wed, 20 Sep 2023 04:54:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695210886; cv=none; d=google.com; s=arc-20160816; b=PpqNKLdUNclsGkcvTYWBiruESX++gYyAbSJ80riRPBZ2951j5YSP8WK7XHfG/2eiWQ mkFAX229Mi9T6JQK3RW79A2Q2TkTGLv/t8QJ+/+dCDGpBoKiYv4QSR54PbHRafxxPgXE gEUioaA2u8skIaP+YRq0uxVARl/01+vNxmlJeGEyAov0GHDxUoHdWgcRYZ/5B4Ag2uuX f4rKpIa5stanunzJQSfndrDUm8yPTK42ijDTb37JB45M8Pyijo++hrmTFk9bgd2q0lvc AJhXy2s5g2m9hfKi091w6v+n73uLGgvGcvP83OKqeWwDUea+q3Kzu25TxwkMIvgD49g3 ajzw== 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; bh=HwLaQ+6HKpY/FNj+M2cMjUhGRyzQjB+L6YdXIw3ThMY=; fh=4u/NwaYCJqDVkYV7nM7yfXV2TONryeZvEIFFjJkIhjs=; b=TdY6diR2NKMo8NVHVd/XDV8VVmTVvhAM+6DAjq4e/B/imIu+qpehB5QfyBguQlM4Da 2zwMaAt5PaITErAMugTdfAmsz8gJU5Uzel/CHQU3dAQitG4NUZz5mCpJdqH03BzjaMqL 1dDdU0iNnqPU2FvucHHMpjnbqMfR3n0yO7ZLWwpTRhx4l6CW9fWOkSlL3yRpDnjpBulj F8ggrGHM6TSIhzsqgf3aJfUHNcgxOYK0Gmf0R5ExipUpqDVZTVH5fFzB36PELiJO11o1 I24xyvA28jgtHq9pCqEK2JidxepnbCXuyCuBFH7oRxkFbD+QJQuiSb85JrvV9duQlyD5 RenA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from agentk.vger.email (agentk.vger.email. [2620:137:e000::3:2]) by mx.google.com with ESMTPS id bu4-20020a056a00410400b0069024c6a9a8si11578582pfb.389.2023.09.20.04.54.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Sep 2023 04:54:46 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) client-ip=2620:137:e000::3:2; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 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 agentk.vger.email (Postfix) with ESMTP id 36A2481A0C3F; Wed, 20 Sep 2023 04:51:07 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at agentk.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234699AbjITLvD (ORCPT + 99 others); Wed, 20 Sep 2023 07:51:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33246 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234695AbjITLvB (ORCPT ); Wed, 20 Sep 2023 07:51:01 -0400 Received: from muru.com (muru.com [72.249.23.125]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 525EAB4; Wed, 20 Sep 2023 04:50:55 -0700 (PDT) Received: from hillo.muru.com (localhost [127.0.0.1]) by muru.com (Postfix) with ESMTP id 5731B810A; Wed, 20 Sep 2023 11:50:53 +0000 (UTC) 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, Dhruva Gole Subject: [PATCH v2 2/2] Input: gpio-keys - Add system suspend support for dedicated wakeirqs Date: Wed, 20 Sep 2023 14:50:44 +0300 Message-ID: <20230920115044.53098-2-tony@atomide.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20230920115044.53098-1-tony@atomide.com> References: <20230920115044.53098-1-tony@atomide.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on agentk.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 (agentk.vger.email [0.0.0.0]); Wed, 20 Sep 2023 04:51:07 -0700 (PDT) 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 since 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; }; /** -- 2.42.0