From patchwork Wed Nov 9 00:26:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 623134 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94559C43217 for ; Wed, 9 Nov 2022 00:27:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229868AbiKIA1K (ORCPT ); Tue, 8 Nov 2022 19:27:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60026 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229464AbiKIA1D (ORCPT ); Tue, 8 Nov 2022 19:27:03 -0500 Received: from mail-pf1-x430.google.com (mail-pf1-x430.google.com [IPv6:2607:f8b0:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF9D75EFB1; Tue, 8 Nov 2022 16:26:59 -0800 (PST) Received: by mail-pf1-x430.google.com with SMTP id b29so15211817pfp.13; Tue, 08 Nov 2022 16:26:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GdJFy/Jw06zpP+63ffqxVPckP7PtfLIb1CoKR1TTueA=; b=B6xgDrY0FQj+FeOAhKIAYNhe4CsrKt4yX/MzFScf+l6bg0804fCWBAAmfQPozPsrxp tOWrMYTaexVuozV8NcFDcjvEJ8xIW81CY29hEEZ1iKLqEekUhyc4uwITGo4c+8u5uD4g VlfgdFJ3sxpQO2je1ttQjgWxlZOwupqfl6kBsGLZCgY71LdxGBrN4x5CxsLa7/kcYtBZ Cr+7021m0HzaFzBQcwy4zGBVNOuVDZQll9Md6Kg5sWNV/6IgYrf/xh7UCpOmqGbxpdeY qulG20zUXOnmCG9j64yA49r/FZ0YHMuQg2YTGS4SxWl/2sgkBrUHwnrmaIX6VyuFT3g/ 5Iaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GdJFy/Jw06zpP+63ffqxVPckP7PtfLIb1CoKR1TTueA=; b=TciNV4tkobjnuVX+9NuVvGR5JzLUAIjbHCn2WRMnyC65b6PpDOzGAhPm5LDvsG9MfU N/i1Yu6zx5k1nU4aKi6/s6JhefPtFUymhtyfXDh+SkZ5jG1swr2/4Oaz5h5ejn3PHtLM ILdDAzgkqPq30u8ELi35BsdCye3nhjYUBlvJc/T5ZwbcAL+ehEWBX/aICpYSSujv5Ybd nqiOxGb8uEbkkucjiil/TBnsIQBp+JbV2tO7+W63MEBD51dnL64u5fMJHHn4pL4OSgOp adLZEwqtJCZTClFDvHpwo7aUb5FxpB3WPmtDj7+8kXhwSxqhb3GPvfgZIk7ShP40ju4b pICg== X-Gm-Message-State: ANoB5pnuJJeFd/d0UuFRAP08bbkoxf3M6JMmEaagAHceukA9dD8X/I42 cgHv9luSp8xXYuL1ouNlEQk= X-Google-Smtp-Source: AA0mqf6cq77sVAjFrtWY7KsMrtzH87UogLsLJf136+kvmIcfyZBvJliTJdR4lmwpNpW11nBSNFlOzA== X-Received: by 2002:a05:6a00:1689:b0:56e:d7f4:3aca with SMTP id k9-20020a056a00168900b0056ed7f43acamr19140154pfc.55.1667953619205; Tue, 08 Nov 2022 16:26:59 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:9f46:7242:26:f220]) by smtp.gmail.com with ESMTPSA id i65-20020a626d44000000b0056bd737fdf3sm6907324pfc.123.2022.11.08.16.26.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Nov 2022 16:26:58 -0800 (PST) From: Dmitry Torokhov To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski Cc: linux-acpi@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/6] gpiolib: acpi: change acpi_find_gpio() to accept firmware node Date: Tue, 8 Nov 2022 16:26:47 -0800 Message-Id: <20221031-gpiolib-swnode-v2-2-81f55af5fa0e@gmail.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <20221031-gpiolib-swnode-v2-0-81f55af5fa0e@gmail.com> References: <20221031-gpiolib-swnode-v2-0-81f55af5fa0e@gmail.com> MIME-Version: 1.0 X-Mailer: b4 0.11.0-dev-28747 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org In preparation of switching all ACPI-based GPIO lookups to go through acpi_find_gpio() let's change it to accept device node as its argument as we do not always have access to device structure. Reviewed-by: Andy Shevchenko Acked-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/gpio/gpiolib-acpi.c | 8 ++++++-- drivers/gpio/gpiolib-acpi.h | 4 ++-- drivers/gpio/gpiolib.c | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 064ba5150fd4..ccb74e208989 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -906,18 +906,22 @@ static bool acpi_can_fallback_to_crs(struct acpi_device *adev, return con_id == NULL; } -struct gpio_desc *acpi_find_gpio(struct device *dev, +struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, unsigned long *lookupflags) { - struct acpi_device *adev = ACPI_COMPANION(dev); + struct acpi_device *adev; struct acpi_gpio_info info; struct gpio_desc *desc; char propname[32]; int i; + adev = to_acpi_device_node(fwnode); + if (!adev) + return ERR_PTR(-ENODEV); + /* Try first from _DSD */ for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { if (con_id) { diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h index 01e0cb480a00..bd1f9b92ea9e 100644 --- a/drivers/gpio/gpiolib-acpi.h +++ b/drivers/gpio/gpiolib-acpi.h @@ -60,7 +60,7 @@ int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, struct acpi_gpio_info *info); -struct gpio_desc *acpi_find_gpio(struct device *dev, +struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, @@ -95,7 +95,7 @@ acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags, } static inline struct gpio_desc * -acpi_find_gpio(struct device *dev, const char *con_id, +acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx, enum gpiod_flags *dflags, unsigned long *lookupflags) { diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c5a80def8be4..eebcdaca5e06 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4081,7 +4081,8 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, con_id, idx, &lookupflags); } else if (is_acpi_node(fwnode)) { dev_dbg(dev, "using ACPI for GPIO lookup\n"); - desc = acpi_find_gpio(dev, con_id, idx, &flags, &lookupflags); + desc = acpi_find_gpio(fwnode, + con_id, idx, &flags, &lookupflags); } /* From patchwork Wed Nov 9 00:26:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 623135 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF9E2C433FE for ; Wed, 9 Nov 2022 00:27:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229775AbiKIA1H (ORCPT ); Tue, 8 Nov 2022 19:27:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229498AbiKIA1D (ORCPT ); Tue, 8 Nov 2022 19:27:03 -0500 Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8264B61752; Tue, 8 Nov 2022 16:27:01 -0800 (PST) Received: by mail-pj1-x1034.google.com with SMTP id f5-20020a17090a4a8500b002131bb59d61so2323282pjh.1; Tue, 08 Nov 2022 16:27:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=p+ottrNj/QWc9Vetbcog1ENbzksG0RcS9PunOwnV9HY=; b=ZqBpG8BfUkybUiVdBIKdARy6xeWxswsMIW3yHqDRbH08RNiM+d2EX83oOSpX4MmJFX iIOua9nJRgFn7Fk4ICu6AkDl4+Dz0EXfsF1OdMbQgZEAkZb4kD8rxsq1leGQPZXeIiuR B9Yr13twNSvLwLKyssTTQDQLg7whFH0NNqlx3aWwnMIEgoLewjNCtNeTuMG5Iq/D9Gbh EcQiHDtJV3BsxDXRLmxaKHmuRV6JsnFDdX6hPt/Z/uXZWXDJng70WbWTxrxU70i6qjU8 lyfd8GNgL9QM43CO8lZg3WfYbd3vgcxUoalYcomPvWtNAbvnAesXa1b+T+JY7R44AqO8 OELg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=p+ottrNj/QWc9Vetbcog1ENbzksG0RcS9PunOwnV9HY=; b=LhJgIfTffIPEdusWpbzU2mR2DgUxopeftKLyFTM0S1WLjXALtCQLNyjqXN850yrkNn zNjRGqUV2k7TKspWJ53InyNOoM8qjVOJD8+eJSYGP/vdvlBXAuq35uqyQEHp4WwoGxsw tVMyUgAv9NMA1xpnX2G13dU8Ul+0+VJbBMQrlSh+o4rU4nUtIvmZ9RzSMms1G2BVDWP1 n03KbSL18QFfOZ81eStEyUXI0T0hWPxSMN/cZQB0KFRaS3C/LW2CNrOQKaNpd4akXKf5 USzmsMSXM3qHPL10kA3xXt5QHF+S9YaP4MUsFWIQVGjl9fPQxa6R7LyprrpEUnQbYbS/ 7P1Q== X-Gm-Message-State: ACrzQf2VWgBgNuqRsQQ1EJ0KAxR41mSq8eKyz6pfDK0FCyNeCRAn4T1P P9NLOvRu8L+2aMl9OuR5UCuSkJVzyqA= X-Google-Smtp-Source: AMsMyM5O0k8JKg9ogKCre8rCQLaBu01TUUisDKYtJn68jPV5hZp2qSBxSdPupMy/2V8xIdb0ZHzFgw== X-Received: by 2002:a17:902:c94b:b0:187:3da6:37ab with SMTP id i11-20020a170902c94b00b001873da637abmr39685125pla.50.1667953620830; Tue, 08 Nov 2022 16:27:00 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:9f46:7242:26:f220]) by smtp.gmail.com with ESMTPSA id i65-20020a626d44000000b0056bd737fdf3sm6907324pfc.123.2022.11.08.16.26.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Nov 2022 16:27:00 -0800 (PST) From: Dmitry Torokhov To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski Cc: linux-acpi@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 3/6] gpiolib: acpi: teach acpi_find_gpio() to handle data-only nodes Date: Tue, 8 Nov 2022 16:26:48 -0800 Message-Id: <20221031-gpiolib-swnode-v2-3-81f55af5fa0e@gmail.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <20221031-gpiolib-swnode-v2-0-81f55af5fa0e@gmail.com> References: <20221031-gpiolib-swnode-v2-0-81f55af5fa0e@gmail.com> MIME-Version: 1.0 X-Mailer: b4 0.11.0-dev-28747 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org In preparation of switching all ACPI-based GPIO lookups to go through acpi_find_gpio() we need to make sure it can handle data-only ACPI nodes, same as existing acpi_node_get_gpiod(). Reviewed-by: Andy Shevchenko Acked-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/gpio/gpiolib-acpi.c | 76 +++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index ccb74e208989..d51bf2a3203d 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -864,8 +864,9 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, * function only returns the first. */ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, - const char *propname, int index, - struct acpi_gpio_info *info) + const char *propname, + int index, + struct acpi_gpio_info *info) { struct acpi_gpio_lookup lookup; int ret; @@ -896,6 +897,44 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, return ret ? ERR_PTR(ret) : lookup.desc; } +/** + * acpi_get_gpiod_from_data() - get a GPIO descriptor from ACPI data node + * @fwnode: pointer to an ACPI firmware node to get the GPIO information from + * @propname: Property name of the GPIO + * @index: index of GpioIo/GpioInt resource (starting from %0) + * @info: info pointer to fill in (optional) + * + * This function uses the property-based GPIO lookup to get to the GPIO + * resource with the relevant information from a data-only ACPI firmware node + * and uses that to obtain the GPIO descriptor to return. + * + * If the GPIO cannot be translated or there is an error an ERR_PTR is + * returned. + */ +static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode, + const char *propname, + int index, + struct acpi_gpio_info *info) +{ + struct acpi_gpio_lookup lookup; + int ret; + + if (!is_acpi_data_node(fwnode)) + return ERR_PTR(-ENODEV); + + if (!propname) + return ERR_PTR(-EINVAL); + + lookup.index = index; + + ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup); + if (ret) + return ERR_PTR(ret); + + ret = acpi_gpio_resource_lookup(&lookup, info); + return ret ? ERR_PTR(ret) : lookup.desc; +} + static bool acpi_can_fallback_to_crs(struct acpi_device *adev, const char *con_id) { @@ -912,16 +951,12 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, enum gpiod_flags *dflags, unsigned long *lookupflags) { - struct acpi_device *adev; + struct acpi_device *adev = to_acpi_device_node(fwnode); struct acpi_gpio_info info; struct gpio_desc *desc; char propname[32]; int i; - adev = to_acpi_device_node(fwnode); - if (!adev) - return ERR_PTR(-ENODEV); - /* Try first from _DSD */ for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) { if (con_id) { @@ -932,7 +967,12 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, gpio_suffixes[i]); } - desc = acpi_get_gpiod_by_index(adev, propname, idx, &info); + if (adev) + desc = acpi_get_gpiod_by_index(adev, + propname, idx, &info); + else + desc = acpi_get_gpiod_from_data(fwnode, + propname, idx, &info); if (!IS_ERR(desc)) break; if (PTR_ERR(desc) == -EPROBE_DEFER) @@ -941,7 +981,7 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, /* Then from plain _CRS GPIOs */ if (IS_ERR(desc)) { - if (!acpi_can_fallback_to_crs(adev, con_id)) + if (!adev || !acpi_can_fallback_to_crs(adev, con_id)) return ERR_PTR(-ENOENT); desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info); @@ -979,29 +1019,13 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, int index, struct acpi_gpio_info *info) { - struct acpi_gpio_lookup lookup; struct acpi_device *adev; - int ret; adev = to_acpi_device_node(fwnode); if (adev) return acpi_get_gpiod_by_index(adev, propname, index, info); - if (!is_acpi_data_node(fwnode)) - return ERR_PTR(-ENODEV); - - if (!propname) - return ERR_PTR(-EINVAL); - - memset(&lookup, 0, sizeof(lookup)); - lookup.index = index; - - ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup); - if (ret) - return ERR_PTR(ret); - - ret = acpi_gpio_resource_lookup(&lookup, info); - return ret ? ERR_PTR(ret) : lookup.desc; + return acpi_get_gpiod_from_data(fwnode, propname, index, info); } /** From patchwork Wed Nov 9 00:26:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Torokhov X-Patchwork-Id: 623133 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AF71CC433FE for ; Wed, 9 Nov 2022 00:27:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229958AbiKIA1d (ORCPT ); Tue, 8 Nov 2022 19:27:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60120 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229576AbiKIA1a (ORCPT ); Tue, 8 Nov 2022 19:27:30 -0500 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76BC661746; Tue, 8 Nov 2022 16:27:07 -0800 (PST) Received: by mail-pj1-x102c.google.com with SMTP id m14-20020a17090a3f8e00b00212dab39bcdso410331pjc.0; Tue, 08 Nov 2022 16:27:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0Ijc7x8fTPDGZNvBUT+idDBJ96j7Q8JpBhejyZkqpOE=; b=cno7Z9azlDI6o85fEz8MD2y/a8szxhVEbZY6MEh6gZBL/HphROAHhLzvsJCRI80MoE aqTCiO6+fj+O8UytedhuuTc3mA7WLJeEHv0igHqHpz4YpjKwSElnXEmhStte6ro6aTkY rLgPj221M3z+N+65Hk/BGHAMtEZI5SPBraZFsv8ATL/8mhe3RbcmrfW5HxWqQrpwABLz +4m5BQ7AonG4CL0y1Vx+iEWG6dP85VlgmiTTK+Q+yI/aP2bWyS3WJ3A+HlqKgDmz+h/F mb89E5qBHZ8G2HwECBGE6ULIg4JeCDp4L/35vqTLrsjyn6ztfwisBzJJ+YM+9UsBoqz/ +7JQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=0Ijc7x8fTPDGZNvBUT+idDBJ96j7Q8JpBhejyZkqpOE=; b=S5SdAI2pjLdU+I/lpnse7pN+e6xjAjHnVNusGTpRpas2IcMLrSTVOFkWg3JQrZZ9GJ +mMoNwiJKaHRtI++8qit5W4rJa1hmFfOIpvHBoWurtAkbB+RULx/wIF4ZqfmqDRGwxKP 1LxWNS5Vtm8JKLeS4Cz2h97ezdBvWuSIjkL2iUiDs4uEIq7Eh7YAyjRBFfnVqbA+2SND I/Xb9Fv3LT99yN+xeg1XhIxtj0OoREodZqURRyA8VNZEmUhSn753voEkWvy1ibmBiC6F swO8HlWQa8jMW8BztO10P5ODpOM9yAe0wiXPZ1eVhGKZ59E3lmcxkjEL+Xett12+zhYq 509Q== X-Gm-Message-State: ACrzQf0eP3JzRMnb7fvcrm0FupOrm2yNwzZWvHLJBajo6ogyYfQbZZGF 16IM1dfBDx1CvBp5eeP8ufU= X-Google-Smtp-Source: AMsMyM5C5riJ1nVd+Rtkgzz6gmb2zCxGgtA8Ic5C4bQw2CZdCRWTFvM5ZL1aVP1hHeVJmLwuWA2Tmw== X-Received: by 2002:a17:90b:1212:b0:213:a3a4:4d97 with SMTP id gl18-20020a17090b121200b00213a3a44d97mr58093759pjb.225.1667953626621; Tue, 08 Nov 2022 16:27:06 -0800 (PST) Received: from dtor-ws.mtv.corp.google.com ([2620:15c:9d:2:9f46:7242:26:f220]) by smtp.gmail.com with ESMTPSA id i65-20020a626d44000000b0056bd737fdf3sm6907324pfc.123.2022.11.08.16.27.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Nov 2022 16:27:05 -0800 (PST) From: Dmitry Torokhov To: Linus Walleij , Andy Shevchenko , Bartosz Golaszewski Cc: linux-acpi@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 6/6] gpiolib: add support for software nodes Date: Tue, 8 Nov 2022 16:26:51 -0800 Message-Id: <20221031-gpiolib-swnode-v2-6-81f55af5fa0e@gmail.com> X-Mailer: git-send-email 2.38.1.431.g37b22c650d-goog In-Reply-To: <20221031-gpiolib-swnode-v2-0-81f55af5fa0e@gmail.com> References: <20221031-gpiolib-swnode-v2-0-81f55af5fa0e@gmail.com> MIME-Version: 1.0 X-Mailer: b4 0.11.0-dev-28747 Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org Now that static device properties understand notion of child nodes and references, let's teach gpiolib to handle them: - GPIOs are represented as a references to software nodes representing gpiochip - references must have 2 arguments - GPIO number within the chip and GPIO flags (GPIO_ACTIVE_LOW/GPIO_ACTIVE_HIGH, etc) - a new PROPERTY_ENTRY_GPIO() macro is supplied to ensure the above - name of the software node representing gpiochip must match label of the gpiochip, as we use it to locate gpiochip structure at runtime The following illustrates use of software nodes to describe a "System" button that is currently specified via use of gpio_keys_platform_data in arch/mips/alchemy/board-mtx1.c. It follows bindings specified in Documentation/devicetree/bindings/input/gpio-keys.yaml. static const struct software_node mxt1_gpiochip2_node = { .name = "alchemy-gpio2", }; static const struct property_entry mtx1_gpio_button_props[] = { PROPERTY_ENTRY_U32("linux,code", BTN_0), PROPERTY_ENTRY_STRING("label", "System button"), PROPERTY_ENTRY_GPIO("gpios", &mxt1_gpiochip2_node, 7, GPIO_ACTIVE_LOW), { } }; Similarly, arch/arm/mach-tegra/board-paz00.c can be converted to: static const struct software_node tegra_gpiochip_node = { .name = "tegra-gpio", }; static struct property_entry wifi_rfkill_prop[] __initdata = { PROPERTY_ENTRY_STRING("name", "wifi_rfkill"), PROPERTY_ENTRY_STRING("type", "wlan"), PROPERTY_ENTRY_GPIO("reset-gpios", &tegra_gpiochip_node, 25, GPIO_ACTIVE_HIGH); PROPERTY_ENTRY_GPIO("shutdown-gpios", &tegra_gpiochip_node, 85, GPIO_ACTIVE_HIGH); { }, }; static struct platform_device wifi_rfkill_device = { .name = "rfkill_gpio", .id = -1, }; ... software_node_register(&tegra_gpiochip_node); device_create_managed_software_node(&wifi_rfkill_device.dev, wifi_rfkill_prop, NULL); Acked-by: Linus Walleij Signed-off-by: Dmitry Torokhov --- drivers/gpio/Makefile | 1 + drivers/gpio/gpiolib-swnode.c | 128 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpio/gpiolib-swnode.h | 14 +++++ drivers/gpio/gpiolib.c | 12 +++- include/linux/gpio/property.h | 11 ++++ 5 files changed, 164 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 8629e9eaf79e..010587025fc8 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_CDEV) += gpiolib-cdev.o obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o +obj-$(CONFIG_GPIOLIB) += gpiolib-swnode.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_REGMAP) += gpio-regmap.o diff --git a/drivers/gpio/gpiolib-swnode.c b/drivers/gpio/gpiolib-swnode.c new file mode 100644 index 000000000000..4cf41234bfc6 --- /dev/null +++ b/drivers/gpio/gpiolib-swnode.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Software Node helpers for the GPIO API + * + * Copyright 2022 Google LLC + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gpiolib.h" +#include "gpiolib-swnode.h" + +static void swnode_format_propname(const char *con_id, char *propname, + size_t max_size) +{ + /* + * Note we do not need to try both -gpios and -gpio suffixes, + * as, unlike OF and ACPI, we can fix software nodes to conform + * to the proper binding. + */ + if (con_id) + snprintf(propname, max_size, "%s-gpios", con_id); + else + strscpy(propname, "gpios", max_size); +} + +static int swnode_gpiochip_match_name(struct gpio_chip *chip, void *data) +{ + return !strcmp(chip->label, data); +} + +static struct gpio_chip *swnode_get_chip(struct fwnode_handle *fwnode) +{ + const struct software_node *chip_node; + struct gpio_chip *chip; + + chip_node = to_software_node(fwnode); + if (!chip_node || !chip_node->name) + return ERR_PTR(-EINVAL); + + chip = gpiochip_find((void *)chip_node->name, + swnode_gpiochip_match_name); + if (!chip) + return ERR_PTR(-EPROBE_DEFER); + + return chip; +} + +struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode, + const char *con_id, unsigned int idx, + unsigned long *flags) +{ + const struct software_node *swnode; + struct fwnode_reference_args args; + struct gpio_chip *chip; + struct gpio_desc *desc; + char propname[32]; /* 32 is max size of property name */ + int error; + + swnode = to_software_node(fwnode); + if (!swnode) + return ERR_PTR(-EINVAL); + + swnode_format_propname(con_id, propname, sizeof(propname)); + + /* + * We expect all swnode-described GPIOs have GPIO number and + * polarity arguments, hence nargs is set to 2. + */ + error = fwnode_property_get_reference_args(fwnode, propname, NULL, + 2, idx, &args); + if (error) { + pr_debug("%s: can't parse '%s' property of node '%pfwP[%d]'\n", + __func__, propname, fwnode, idx); + return ERR_PTR(error); + } + + chip = swnode_get_chip(args.fwnode); + fwnode_handle_put(args.fwnode); + if (IS_ERR(chip)) + return ERR_CAST(chip); + + desc = gpiochip_get_desc(chip, args.args[0]); + *flags = args.args[1]; /* We expect native GPIO flags */ + + pr_debug("%s: parsed '%s' property of node '%pfwP[%d]' - status (%d)\n", + __func__, propname, fwnode, idx, PTR_ERR_OR_ZERO(desc)); + + return desc; +} + +/** + * swnode_gpio_count - count the GPIOs associated with a device / function + * @fwnode: firmware node of the GPIO consumer, can be %NULL for + * system-global GPIOs + * @con_id: function within the GPIO consumer + * + * Return: + * The number of GPIOs associated with a device / function or %-ENOENT, + * if no GPIO has been assigned to the requested function. + */ +int swnode_gpio_count(struct fwnode_handle *fwnode, const char *con_id) +{ + struct fwnode_reference_args args; + char propname[32]; + int count; + + swnode_format_propname(con_id, propname, sizeof(propname)); + + /* + * This is not very efficient, but GPIO lists usually have only + * 1 or 2 entries. + */ + count = 0; + while (fwnode_property_get_reference_args(fwnode, propname, NULL, + 0, count, &args) == 0) { + fwnode_handle_put(args.fwnode); + count++; + } + + return count ?: -ENOENT; +} diff --git a/drivers/gpio/gpiolib-swnode.h b/drivers/gpio/gpiolib-swnode.h new file mode 100644 index 000000000000..4e07be56ed9f --- /dev/null +++ b/drivers/gpio/gpiolib-swnode.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef GPIOLIB_SWNODE_H +#define GPIOLIB_SWNODE_H + +struct fwnode_handle; +struct gpio_desc; + +struct gpio_desc *swnode_find_gpio(struct fwnode_handle *fwnode, + const char *con_id, unsigned int idx, + unsigned long *flags); +int swnode_gpio_count(struct fwnode_handle *fwnode, const char *con_id); + +#endif /* GPIOLIB_SWNODE_H */ diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c33ffdd47667..bf5c072206da 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -26,6 +26,7 @@ #include "gpiolib.h" #include "gpiolib-of.h" #include "gpiolib-acpi.h" +#include "gpiolib-swnode.h" #include "gpiolib-cdev.h" #include "gpiolib-sysfs.h" @@ -3821,6 +3822,9 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode, } else if (is_acpi_node(fwnode)) { dev_dbg(consumer, "using ACPI for GPIO lookup\n"); desc = acpi_find_gpio(fwnode, con_id, idx, flags, lookupflags); + } else if (is_software_node(fwnode)) { + dev_dbg(consumer, "using software node for GPIO lookup\n"); + desc = swnode_find_gpio(fwnode, con_id, idx, lookupflags); } else { desc = ERR_PTR(-ENOENT); } @@ -3934,13 +3938,17 @@ EXPORT_SYMBOL_GPL(fwnode_gpiod_get_index); */ int gpiod_count(struct device *dev, const char *con_id) { - const struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL; - int count = -ENOENT; + struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL; + int count; if (is_of_node(fwnode)) count = of_gpio_get_count(dev, con_id); else if (is_acpi_node(fwnode)) count = acpi_gpio_count(dev, con_id); + else if (is_software_node(fwnode)) + count = swnode_gpio_count(fwnode, con_id); + else + count = -ENOENT; if (count < 0) count = platform_gpio_count(dev, con_id); diff --git a/include/linux/gpio/property.h b/include/linux/gpio/property.h new file mode 100644 index 000000000000..f76a46469f66 --- /dev/null +++ b/include/linux/gpio/property.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ +#ifndef __LINUX_GPIO_PROPERTY_H +#define __LINUX_GPIO_PROPERTY_H + +#include +#include + +#define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \ + PROPERTY_ENTRY_REF(_name_, _chip_node_, _idx_, _flags_) + +#endif /* __LINUX_GPIO_PROPERTY_H */