From nobody Tue Dec 2 00:02:17 2025 Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) (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 C6386288D6 for ; Tue, 25 Nov 2025 10:19:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764065961; cv=none; b=lP6Ed4m1n+r31XXpG2qSKjsAXshTtsA48Cq+PZMzOulRLLYnvcY9wW15CVqota2pvOAkLsFP8ZwPo20a5Ht/fri+pQnWxkiWy0lzO9xlNeHuO0PP29uNFcwqhE2wR5FpgpogLmznFMtSAiIhHCX/Rvb1oqoZW9BrnT/Loakvxrg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764065961; c=relaxed/simple; bh=4TjQoesRtOi9VvDdWCFJB2g5O3xdH21QKzdf450490I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=dlDOxImhFlkZogMo5K/E2BRfKn56gVxmdFvElIjRKPBdv9VptkAcZxNjDnMqCfqD8xX21rZ43/106IYjYdm2/rc/HuSYusMBevA2znJeF6HZuC4QvF/FDmI1The11wDukbtkqgaRHcdxEiSmi8pGH6dMBuFouCdE3AdX53tVCEk= 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=ah3Z+H5K; arc=none smtp.client-ip=209.85.221.47 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="ah3Z+H5K" Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-429ce7e79f8so2995760f8f.0 for ; Tue, 25 Nov 2025 02:19:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bgdev-pl.20230601.gappssmtp.com; s=20230601; t=1764065957; x=1764670757; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=mHsazSRjBBdLw/5wTjNE+V06skEMqfKGBJCeXidVHP8=; b=ah3Z+H5KCFIwNFETk3M6EMhMJ5eG7tk5xaTsszAnRGNliWPgFlWyL153zr6GRBKdjN PpZ/EJeEo/IIlP+SEm02NxXI53UEb7S568TxvRJfhq8nRirF4IXnLTTSZCOCtjyArktD a2nYDnWZRJ8y18hK23MMLJr8S2fz3Am9dYtwK3qssyP15C9n5fGM8/8a7R0PaKInk+Vq /WtYUO7tvw+ueTXRWhPzCIW83Q+f9rUaLEzXypcOrRPK5tCt7Q0hb3WU9YtduE/wpile Z8kcSKvae4urDrmAsFxyexdqN74FE1dSDAB+i+rtSPg8nivuHWfs8+t9akXCqUsZS//v gEDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764065957; x=1764670757; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=mHsazSRjBBdLw/5wTjNE+V06skEMqfKGBJCeXidVHP8=; b=tDhIQNS+8rD8qqCbyW8I2JY6YcOyKqDcF9J4FP9cz6IZmJ53Y8wCxku6rGGber72qa 92Yi+Vb4cxggZdwanb7gofKf21wNf6bW4JSBkdKVjaqOOSj8bJwIbbS0HPRKGvUwf2yJ KEcOFqYzE42OiYTA6SqHG9HC7l5K2c5rbDZkNhX48IOPJ8XbLebI6Dlp2PQsoMtGYT6h +PloBjSpW07CSCKFBX9h8r5N+BelXoFK6R5zwi7E6q27TsaS5UogCiA6InMo+ZHeEHqE HkDSwBUdzsHRNa56oK/aOp+24a/1MIjXnpiEgPoO9tVI8aWH85PTtmzlPAWtD5FakJuG SzRw== X-Forwarded-Encrypted: i=1; AJvYcCUngAl+I+GUUVS+c4+P86XFTEbaRsanw616gWp8donWkJxAULrLod6uradiBwREZO18OtPP0Jk4b+1rCF0=@vger.kernel.org X-Gm-Message-State: AOJu0YxJZc9t8KHOAc0MhPLkq8qAnLf5rD3rpgpO8Au+sdOsFniDHUPB o44snGrkWS788NjTSOME1epuWkbDqJ2du3J4dbYUowEwpDSG1RFJ1Xl806iF9ildp6w= X-Gm-Gg: ASbGnctjIMjhNzIwrdeLhcltjRFUG1/z5SpHjOhP1ifqkom+dz7zHFlCcobUlECqc+I +EGqhyzQoYUk6rlJBNgSn80T2aDm8eYxkE88tsavh78G1lj5nyHq6Hk6DPA9g4xBIkcCo4uMi3O iV3ZmSky4LPcNBDL2ELvf2uKkvcpI+v+cIKU54bHYNruBf9h7rFvwJp2CZNSwzJvvCl+9GmtMQA QPT6s2xLvppNQuJMXYPJO4DVEbu6/zitFWy6wRNx5oCMhDaVTYrv930Svg84Xd1drm4qfC34aSl UUTHJ4eFmiYPY9NgbbkmRPtYcrdT73qnJyx2DOsxS3T7KINqHav2rL72L+8MEH8RLd8dFmgysRT LWLL4F1j2mMm6n4YN9l+eL/wb/QjoCdww4cAmkGgV63UOjAY8WlfGQ7qfCROSuj26aiyOYTHHAr El7rCsgA== X-Google-Smtp-Source: AGHT+IElDzPPFo4R1Ku7VyEdXDsLFVn8Cz67qhPRUicZhyExrx80sPETRT42LzKc2vysci1RyB+4NA== X-Received: by 2002:a05:6000:1789:b0:42b:3ccc:91ec with SMTP id ffacd0b85a97d-42e0f2047b3mr2147500f8f.22.1764065956581; Tue, 25 Nov 2025 02:19:16 -0800 (PST) Received: from [127.0.1.1] ([2a01:cb1d:dc:7e00:df0c:79ae:5345:c3b0]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-42cb7fb8a29sm34001497f8f.30.2025.11.25.02.19.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 25 Nov 2025 02:19:16 -0800 (PST) From: Bartosz Golaszewski Date: Tue, 25 Nov 2025 11:19:09 +0100 Subject: [PATCH v2] gpio: shared: handle the reset-gpios corner case 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: <20251125-gpiolib-shared-reset-gpio-fix-v2-1-4eb6fa41f1dd@linaro.org> X-B4-Tracking: v=1; b=H4sIAJyCJWkC/42NQQqDMBAAvyJ77hY3WGt78h/Fg4kbXRAjGwkt4 t+b+oIeZw4zO0RW4QjPYgflJFHCksFcCnBTv4yMMmQGU5obkSEcVwmzWIxTrzygcuTtlOjlja5 hqsk+fO0s5MaqnPXZf3WZJ4lb0M+5S/Sz/5YTIaHzJZnGc2WrezvL0mu4Bh2hO47jC2VFOoHLA AAA X-Change-ID: 20251121-gpiolib-shared-reset-gpio-fix-c8e161b9f6cb To: Val Packett , Krzysztof Kozlowski , Philipp Zabel , Linus Walleij , Bartosz Golaszewski Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Bartosz Golaszewski X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=5799; i=bartosz.golaszewski@linaro.org; h=from:subject:message-id; bh=Bh4WSLi6y/CnVH3wsSIW37S1oJbk0T+/9wnfMDOpxrY=; b=owEBbQKS/ZANAwAKAQWdLsv/NoTDAcsmYgBpJYKgXlWqwGiMyybTu1eEQuKBS/GGqWEztq0G1 Stt4o0MRM2JAjMEAAEKAB0WIQSR5RMt5bVGHXuiZfwFnS7L/zaEwwUCaSWCoAAKCRAFnS7L/zaE w8RpD/4iTjKDMaSQseHyBVPfP6DcSIFr6FMR1aaoASkR7Ung6+kb13y3dxPvAfLSqQn5+qFvzGL ZErUbONFVgA7xx+dtSlnSDkJNwvl8XXKuYiWtRexZUisSarB0oZa0S+1GqPTE7t8J4zcV2IK6Rn tX5EXLaWv5zo2ncE9y3r0f7rjRNUW5Y7OZ+DgeAEhUg75o7blDvWHKBHiZ0XPX9E0OBoJljR9fN Ikxys1kJLn2FsUYom/cXsl+c2JpqQwEafBxaPzbl/kblWTzkH5pNbjLAKIaF5P2fdireW1KnD31 vjXGsUATf4NPeCwFrFVXIRpnB0pOyae56jzoB2SQK7Sn9IR+A9dDUXIZXFO8ZzF/kTyoNasTZk+ nuuJovWnOswBJlT2OiW4Q40Iwv/bmyqZeNqWQmV2kFBzbhF/RgZimMJxspoG/pWUuBwu4FG54Xm xO5bRt0iMg23UQd3hCIPck2Z0g3IRBH8ysVLcX88rOEivVtEqDRnqWsKfwUcFXsdU3Pq5oEDZmj Oyav87GhqHJorCgb6bi9OJ0VgDaQuUvGzjVWU/m/up6Yv8fU8y05sT8E74Tv5JzduNbKzf9efdg SqiR7XMUjBhn6ChCyKPaAmFtNUOFZscotSprdrfcw5Delickr82uZ4XBinId1gcFB3bfVA+09ER 8w/HRWgDZR/Cfkw== X-Developer-Key: i=bartosz.golaszewski@linaro.org; a=openpgp; fpr=169DEB6C0BC3C46013D2C79F11A72EA01471D772 From: Bartosz Golaszewski There's an unexpected interaction between the reset-gpio driver and the shared GPIO support. The reset-gpio device is an auxiliary device that's created dynamically and fulfills a similar role to the gpio-shared-proxy driver but is limited in scope to just supporting the "reset-gpios" property. The shared GPIO core code does not take into account that the machine lookup entry we create when scanning the device-tree must connect the reset-gpio device - that is the actual consumer of the GPIO and not the consumer defined on the device tree, which in turn consumes the shared reset control exposed by the reset-gpio device - to the GPIO controller. We also must not skip the gpio-shared-proxy driver as it's possible that a shared GPIO may be used by one consumer as a reset-gpios going through the reset-gpio device and another that uses GPIOLIB. We need to make it a special case handled in gpiolib-shared.c. Add a new function - gpio_shared_dev_is_reset_gpio() - whose role it is to verify if a non-matching consumer of a shared pin is a reset-gpio device and make sure it's the right one for this pin. To that end make sure that its parent is the GPIO controller in question and that the fwnode we identified as sharing the pin references that controller via the "reset-gpios" property. Only include that code if the reset-gpio driver is enabled. Fixes: a060b8c511ab ("gpiolib: implement low-level, shared GPIO support") Reported-by: Val Packett Closes: https://lore.kernel.org/all/3b5d9df5-934d-4591-8827-6c9573a6f7ba@pa= ckett.cool/ Signed-off-by: Bartosz Golaszewski Tested-by: Abel Vesa Tested-by: Val Packett --- Changes in v2: - Make the reset-gpio checks stricter to cover use-cases with multiple reset-gpio devices using pins from the same controller - Link to v1: https://lore.kernel.org/r/20251121-gpiolib-shared-reset-gpio-= fix-v1-1-cf0128fe4b47@linaro.org --- drivers/gpio/gpiolib-shared.c | 81 +++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c index 3803b5c938f9933dab01c6d777c349ed3b42ce9b..cc8646f563d2fa7b1972c94c734= b19c4cb01244c 100644 --- a/drivers/gpio/gpiolib-shared.c +++ b/drivers/gpio/gpiolib-shared.c @@ -253,6 +253,84 @@ static int gpio_shared_make_adev(struct gpio_device *g= dev, return 0; } =20 +#if IS_ENABLED(CONFIG_RESET_GPIO) +/* + * Special case: reset-gpio is an auxiliary device that's created dynamica= lly + * and put in between the GPIO controller and consumers of shared GPIOs + * referred to by the "reset-gpios" property. + * + * If the supposed consumer of a shared GPIO didn't match any of the mappi= ngs + * we created when scanning the firmware nodes, it's still possible that i= t's + * the reset-gpio device which didn't exist at the time of the scan. + * + * This function verifies it an return true if it's the case. + */ +static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, + struct gpio_shared_entry *entry, + struct gpio_shared_ref *ref) +{ + struct fwnode_handle *reset_fwnode =3D dev_fwnode(consumer); + struct fwnode_reference_args ref_args, aux_args; + struct device *parent =3D consumer->parent; + bool match; + int ret; + + /* The reset-gpio device must have a parent AND a firmware node. */ + if (!parent || !reset_fwnode) + return false; + + /* + * FIXME: use device_is_compatible() once the reset-gpio drivers gains + * a compatible string which it currently does not have. + */ + if (!strstarts(dev_name(consumer), "reset.gpio.")) + return false; + + /* + * Parent of the reset-gpio auxiliary device is the GPIO chip whose + * fwnode we stored in the entry structure. + */ + if (!device_match_fwnode(parent, entry->fwnode)) + return false; + + /* + * The device associated with the shared reference's firmware node is + * the consumer of the reset control exposed by the reset-gpio device. + * It must have a "reset-gpios" property that's referencing the entry's + * firmware node. + * + * The reference args must agree between the real consumer and the + * auxiliary reset-gpio device. + */ + ret =3D fwnode_property_get_reference_args(ref->fwnode, "reset-gpios", + NULL, 2, 0, &ref_args); + if (ret) + return false; + + ret =3D fwnode_property_get_reference_args(reset_fwnode, "reset-gpios", + NULL, 2, 0, &aux_args); + if (ret) { + fwnode_handle_put(ref_args.fwnode); + return false; + } + + match =3D ((ref_args.fwnode =3D=3D entry->fwnode) && + (aux_args.fwnode =3D=3D entry->fwnode) && + (ref_args.args[0] =3D=3D aux_args.args[0])); + + fwnode_handle_put(ref_args.fwnode); + fwnode_handle_put(aux_args.fwnode); + return match; +} +#else +static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, + struct gpio_shared_entry *entry, + struct gpio_shared_ref *ref) +{ + return false; +} +#endif /* CONFIG_RESET_GPIO */ + int gpio_shared_add_proxy_lookup(struct device *consumer, unsigned long lf= lags) { const char *dev_id =3D dev_name(consumer); @@ -268,7 +346,8 @@ int gpio_shared_add_proxy_lookup(struct device *consume= r, unsigned long lflags) =20 list_for_each_entry(entry, &gpio_shared_list, list) { list_for_each_entry(ref, &entry->refs, list) { - if (!device_match_fwnode(consumer, ref->fwnode)) + if (!device_match_fwnode(consumer, ref->fwnode) && + !gpio_shared_dev_is_reset_gpio(consumer, entry, ref)) continue; =20 /* We've already done that on a previous request. */ --- base-commit: 71dfa12e37df94917955574484b122abaf0e7bf5 change-id: 20251121-gpiolib-shared-reset-gpio-fix-c8e161b9f6cb Best regards, --=20 Bartosz Golaszewski