From nobody Mon Oct 6 08:12:24 2025 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 50F8928982B for ; Thu, 24 Jul 2025 09:25:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753349104; cv=none; b=soezP6Tc2GAFXkjydBioSyqJkr5FviSF6F3uUQvoybzswds2lYfdJNEG90l5PVPnvDt4binDn64orPcbDDefVbWHVty+hbCaoVAmwY//L471USkOOQtLujADurNwE8OcbWmAfVE8SqMGR2IpvCSaW1A1spXXmtT8u1qRTrYZYns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753349104; c=relaxed/simple; bh=DO00Ils0PNbfp2/iTgw3UaaSPsoLw3lP/8/WxATgwBQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aPJ6b9Qqno7BBZgE/Hqlxhy1swVicrGQ1H6pGyJJ7JvtBo4NhUUVwjYkfNH7CPm9NYFF/v46utojAOs8kMMT3sbjOVDemoE6moH5TXvy9gEXBGqGq95ZyZVZeENdVGiNwBDKrQ+8wdCNl7jn5DjUwfi5dgNnRoY9kzb+xz0Jjb4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=bgdev.pl; spf=none smtp.mailfrom=bgdev.pl; dkim=pass (2048-bit key) header.d=bgdev-pl.20230601.gappssmtp.com header.i=@bgdev-pl.20230601.gappssmtp.com header.b=ibiXC+0T; arc=none smtp.client-ip=209.85.221.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=bgdev.pl Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bgdev-pl.20230601.gappssmtp.com header.i=@bgdev-pl.20230601.gappssmtp.com header.b="ibiXC+0T" Received: by mail-wr1-f53.google.com with SMTP id ffacd0b85a97d-3a503d9ef59so474128f8f.3 for ; Thu, 24 Jul 2025 02:25:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20230601.gappssmtp.com; s=20230601; t=1753349098; x=1753953898; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=q5Et21tlNKz8QCzLOQeaVbz2wkUry/HGWm7xpHNYV/E=; b=ibiXC+0TvtwwKiwy5Ym1Pe/MUtXYsqlnCZUFVakGfyaFJWMj9Z94xeFBMQkBJOIhHx frrjPKiT0uLMB9ZhKr8vxY1c8b+8S85pFYCYyPUt2zw/I5FnapTp7yI7rnLd0X+Fpy1m G1D8BFdFgxuleW9XoIvsde2edd9iw4mZTv/RHeQbdJiaBYiwIiCBDLpW4rgyZ+zExzAl mi1/mXWEPfEj4m42LHKoGCVDTdBklnRGjkanvk36E+3MkY7TkrBRWD0EvHYM8xn9qiMB ZPvY0WWuuQcQ453Ybg7CwlTsaTp4VyI5GjLQSO7p1X9dxGLMjE55qDyIztfrKHaR/ZFo 27Iw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1753349098; x=1753953898; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=q5Et21tlNKz8QCzLOQeaVbz2wkUry/HGWm7xpHNYV/E=; b=j9rd3IE/KTHUfmb+ZYnISkPpTBvnPlMmhStlgspVTm63BOvFFZwPk37fpi/3XFMAsS UpBFgl3z9X9IxbVrfhJY3N+daRei8oqwQSlgVqWSsQ8oEqiLpN1N2I1ZoJQ8ZyYaj4uC rUofbk0EMgW/6FDU/XIvNYQk24klS+z4yhK8qpx8eKIpc+KvZQ4EhhmEkQeLitTDYfCZ DBoW1CWOCQlGk+STl+p6bxKCrJ3n+E4R3cO21wHmCoWqrk22i6ZL0t2WgOSBULnoI7is rRiOBCFKy3M2tLeE78m6nD0XsO7MIXpD3kQpsiolWFTrLmUucyYOtaVEzxMkApjRcHGg 5aVQ== X-Forwarded-Encrypted: i=1; AJvYcCUtJuHWOYpC0+Tra8GhSCAAz0/swDqRCouPFtRh5V8+VtlROdwMz7aIytCm3jS2DUkIfAB4gu+tfjG6WiI=@vger.kernel.org X-Gm-Message-State: AOJu0YxvMrivRIvk+pChHv1pqnbgVLEd2S90YDIAsQFizw+DnzRH2u39 7lMxW8ngWHXOAjxzh3sRftcSVh2suSZJGnbjIjRkjwM2EYR3clX574ml1kVqD8SSMVo= X-Gm-Gg: ASbGncuNQaHoyAbZ/X+5YI+t5p+r1HKrzrsj5wm4NUokWI5Oj3K55OaOgcmVdVma7md prbC5oH2X3gnzDZrFe8j+6eeMAFKu5K6GWPzx1efHkkX1zvA2Y2KQiJAm4BOjUh+c1/XCT1Yd+H N9bT4wtgd+njaAHfWXE/KDNJPv89KcRTOa7EP71/0DaYNGwur4Z+PeAauDGL+Ixn87UGwidiiZm 65hWoErSjdltFUpdwEKG4N5wEKLsddowtCrNyGAYQ6f/QSEbsEhRP8iezp6dBbVo9CXOD1lw5If 0tKUIRT97x4vQ64sZzQINfAjT73yos0M3XTMmS8x6BNvONaKZEoSxdu8y+fTxAirTxWhHaXmFvz BNAVa3k5JwxFOw5+LOh36ghIH81U= X-Google-Smtp-Source: AGHT+IHK9ym35s7NHF150oDopl7CdxsijIcKei5Gs6AFRhmReJ4MEWnZ4kKTub7TlD3dR6aW1McU3g== X-Received: by 2002:a5d:5f83:0:b0:3b7:649a:6a7b with SMTP id ffacd0b85a97d-3b768f27067mr5266406f8f.49.1753349098181; Thu, 24 Jul 2025 02:24:58 -0700 (PDT) Received: from [127.0.1.1] ([2a01:cb1d:dc:7e00:f44c:20db:7ada:b556]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3b76fc72548sm1600833f8f.30.2025.07.24.02.24.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Jul 2025 02:24:57 -0700 (PDT) From: Bartosz Golaszewski Date: Thu, 24 Jul 2025 11:24:40 +0200 Subject: [PATCH v3 12/15] pinctrl: allow to mark pin functions as requestable GPIOs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250724-pinctrl-gpio-pinfuncs-v3-12-af4db9302de4@linaro.org> References: <20250724-pinctrl-gpio-pinfuncs-v3-0-af4db9302de4@linaro.org> In-Reply-To: <20250724-pinctrl-gpio-pinfuncs-v3-0-af4db9302de4@linaro.org> To: Linus Walleij , Bjorn Andersson , Konrad Dybcio , Alexey Klimov , Lorenzo Bianconi , Sean Wang , Matthias Brugger , AngeloGioacchino Del Regno , Paul Cercueil , Kees Cook , Andy Shevchenko , Andrew Morton , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Dong Aisheng , Fabio Estevam , Shawn Guo , Jacky Bai , Pengutronix Kernel Team , NXP S32 Linux Team , Sascha Hauer , Tony Lindgren , Haojian Zhuang , Geert Uytterhoeven Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-mips@vger.kernel.org, linux-hardening@vger.kernel.org, linux-mm@kvack.org, imx@lists.linux.dev, linux-omap@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Bartosz Golaszewski X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6779; i=bartosz.golaszewski@linaro.org; h=from:subject:message-id; bh=xKvZSJeqL1YS+RHLa6ZJ9ocJVsZVH7/NUKTdgRxyg9w=; b=owEBbQKS/ZANAwAKARGnLqAUcddyAcsmYgBogfvUEkzW0EQIuejJliJGAXd3b4hhn0Y90AKiK aMxE033XniJAjMEAAEKAB0WIQQWnetsC8PEYBPSx58Rpy6gFHHXcgUCaIH71AAKCRARpy6gFHHX ctZcD/9/win0ZTkZvv3o5OiADBgTXuQ9ZWagTSXWjrtJX4ta/fmW0osfTxhRQh8DQUeD40zNykY ZlumO0Lhv4nMQ5KVmmjzNYUHlhhmaZAslGLbjXMr57XHuqjwh1bzDimxv/YcU+CqFz/EUxDJDBT OWT1O88kRCz3ozoMKIiXSfkrtky+GT4VOOK4vasxtmqzfjVoVR2SgJUNZszPdM0wJaYtrY/iX5o zpbRdv7eUBksHcBgJS8pS6pIVPkhTVnCYo15H0Ed1VojOsGENvvstFyBNCp01nqZNxnB6w0bsbQ W+4cVp6T0bCpksTxYPu3J7hfyFYQ56QQ76Ezatfv4Azt+x/1x7PEZ5I7gRXvFpJYw+YGV+e3LAs JZzjN7zQXWD1NhFDFInObmVDoraBCp/ya0qXNqH3qrlm2HbobuvQAFFYt8cCP5aIZXKgBX+MQN/ t4dR5V7zTs4YukzUhSXpYxR9B+sD4Ui3aQ/GrXLm+r3u0Zu9KamRs64j/7VHFbD5MDMeB2m+q24 TRG9TOQ5nydi4Yajwig9MqOEPQ8ss4zaUfOm1ObHbWSRIVTQVlrzKIBoVGyLzQA2c4GwDd02eTd E13s+/MXe+gZmBCllLp3OCEpGtPQlsgrWqYuTFY4QYPRiq7jYWdxF60a/QnO9caJyCVH8nsniom GbDpdUV96wJsDTw== X-Developer-Key: i=bartosz.golaszewski@linaro.org; a=openpgp; fpr=169DEB6C0BC3C46013D2C79F11A72EA01471D772 From: Bartosz Golaszewski The name of the pin function has no real meaning to pinctrl core and is there only for human readability of device properties. Some pins are muxed as GPIOs but for "strict" pinmuxers it's impossible to request them as GPIOs if they're bound to a devide - even if their function name explicitly says "gpio". Add a new field to struct pinfunction that allows to pass additional flags to pinctrl core. While we could go with a boolean "is_gpio" field, a flags field is more future-proof. If the PINFUNCTION_FLAG_GPIO is set for a given function, the pin muxed to it can be requested as GPIO even on strict pin controllers. Add a new callback to struct pinmux_ops - function_is_gpio() - that allows pinmux core to inspect a function and see if it's a GPIO one. Provide a generic implementation of this callback. Signed-off-by: Bartosz Golaszewski --- drivers/pinctrl/pinmux.c | 36 ++++++++++++++++++++++++++++++++++-- drivers/pinctrl/pinmux.h | 3 +++ include/linux/pinctrl/pinctrl.h | 14 ++++++++++++++ include/linux/pinctrl/pinmux.h | 2 ++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 504dbb3e97cf334e39b49121137c6768081fcd40..52623b47cc87b49b649610eabfa= 547d7543292dd 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c @@ -89,13 +89,19 @@ bool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pc= tldev, unsigned int pin) { struct pin_desc *desc =3D pin_desc_get(pctldev, pin); const struct pinmux_ops *ops =3D pctldev->desc->pmxops; + const struct pinctrl_setting_mux *mux_setting =3D desc->mux_setting; + bool func_is_gpio =3D false; =20 /* Can't inspect pin, assume it can be used */ if (!desc || !ops) return true; =20 guard(mutex)(&desc->mux_lock); - if (ops->strict && desc->mux_usecount) + if (ops->function_is_gpio && mux_setting) + func_is_gpio =3D ops->function_is_gpio(pctldev, + mux_setting->func); + + if (ops->strict && desc->mux_usecount && !func_is_gpio) return false; =20 return !(ops->strict && !!desc->gpio_owner); @@ -116,7 +122,9 @@ static int pin_request(struct pinctrl_dev *pctldev, { struct pin_desc *desc; const struct pinmux_ops *ops =3D pctldev->desc->pmxops; + const struct pinctrl_setting_mux *mux_setting; int status =3D -EINVAL; + bool func_is_gpio =3D false; =20 desc =3D pin_desc_get(pctldev, pin); if (desc =3D=3D NULL) { @@ -126,11 +134,16 @@ static int pin_request(struct pinctrl_dev *pctldev, goto out; } =20 + mux_setting =3D desc->mux_setting; + dev_dbg(pctldev->dev, "request pin %d (%s) for %s\n", pin, desc->name, owner); =20 scoped_guard(mutex, &desc->mux_lock) { - if ((!gpio_range || ops->strict) && + if (ops->function_is_gpio && mux_setting) + func_is_gpio =3D ops->function_is_gpio(pctldev, + mux_setting->func); + if ((!gpio_range || ops->strict) && !func_is_gpio && desc->mux_usecount && strcmp(desc->mux_owner, owner)) { dev_err(pctldev->dev, "pin %s already requested by %s; cannot claim for %s\n", @@ -861,6 +874,25 @@ pinmux_generic_get_function(struct pinctrl_dev *pctlde= v, unsigned int selector) } EXPORT_SYMBOL_GPL(pinmux_generic_get_function); =20 +/** + * pinmux_generic_function_is_gpio() - returns true if given function is a= GPIO + * @pctldev: pin controller device + * @selector: function number + */ +bool pinmux_generic_function_is_gpio(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct function_desc *function; + + function =3D radix_tree_lookup(&pctldev->pin_function_tree, + selector); + if (!function) + return false; + + return function->func->flags & PINFUNCTION_FLAG_GPIO; +} +EXPORT_SYMBOL_GPL(pinmux_generic_function_is_gpio); + /** * pinmux_generic_add_function() - adds a function group * @pctldev: pin controller device diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h index 653684290666d78fd725febb5f8bc987b66a1afb..4e826c1a5246cf8b1ac814c8c0d= f24c4e036edd2 100644 --- a/drivers/pinctrl/pinmux.h +++ b/drivers/pinctrl/pinmux.h @@ -169,6 +169,9 @@ int pinmux_generic_remove_function(struct pinctrl_dev *= pctldev, =20 void pinmux_generic_free_functions(struct pinctrl_dev *pctldev); =20 +bool pinmux_generic_function_is_gpio(struct pinctrl_dev *pctldev, + unsigned int selector); + #else =20 static inline void pinmux_generic_free_functions(struct pinctrl_dev *pctld= ev) diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctr= l.h index d138e18156452e008f24ca06358fcab45135632f..1a8084e2940537f8f0862761d3e= 47c56c8783193 100644 --- a/include/linux/pinctrl/pinctrl.h +++ b/include/linux/pinctrl/pinctrl.h @@ -11,6 +11,7 @@ #ifndef __LINUX_PINCTRL_PINCTRL_H #define __LINUX_PINCTRL_PINCTRL_H =20 +#include #include =20 struct device; @@ -206,16 +207,20 @@ extern int pinctrl_get_group_pins(struct pinctrl_dev = *pctldev, const char *pin_group, const unsigned int **pins, unsigned int *num_pins); =20 +#define PINFUNCTION_FLAG_GPIO BIT(0) + /** * struct pinfunction - Description about a function * @name: Name of the function * @groups: An array of groups for this function * @ngroups: Number of groups in @groups + * @flags: Additional pin function flags */ struct pinfunction { const char *name; const char * const *groups; size_t ngroups; + unsigned long flags; }; =20 /* Convenience macro to define a single named pinfunction */ @@ -226,6 +231,15 @@ struct pinfunction { .ngroups =3D (_ngroups), \ } =20 +/* Same as PINCTRL_PINFUNCTION() but for the GPIO category of functions */ +#define PINCTRL_GPIO_PINFUNCTION(_name, _groups, _ngroups) \ +(struct pinfunction) { \ + .name =3D (_name), \ + .groups =3D (_groups), \ + .ngroups =3D (_ngroups), \ + .flags =3D PINFUNCTION_FLAG_GPIO, \ + } + #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_PINCTRL) extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np); #else diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h index d6f7b58d6ad0cce421aad80463529c9ccc65d68e..6db6c3e1ccc2249d4b4204e6fc1= 9bf7b4397cc81 100644 --- a/include/linux/pinctrl/pinmux.h +++ b/include/linux/pinctrl/pinmux.h @@ -66,6 +66,8 @@ struct pinmux_ops { unsigned int selector, const char * const **groups, unsigned int *num_groups); + bool (*function_is_gpio) (struct pinctrl_dev *pctldev, + unsigned int selector); int (*set_mux) (struct pinctrl_dev *pctldev, unsigned int func_selector, unsigned int group_selector); int (*gpio_request_enable) (struct pinctrl_dev *pctldev, --=20 2.48.1