From nobody Sun Feb 8 15:42:44 2026 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (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 A1DCF2FF153 for ; Sun, 25 Jan 2026 19:51:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769370703; cv=none; b=oBQwTCYni+v5WesSJXiyFe9u03z3R+lEqVIA146vUADT8IaArDVKfwNhAHLI+7Hf6M1vRWtHpxLb91vcK0E9fbrokDidgCJqusX0+4+sN++OUYXPykS6rabsGodzjQZGVXz6Gef9Pxx6qZ+YDUBBi8l3U6UXejuw/LPhhFraY0c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769370703; c=relaxed/simple; bh=tQ0GUXHlvLjzR+49qpOK5aB36nhWTrg04e7AKSsJQxk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=P3tcgjaV6XtXziVP3G5m7BpT29hnIBGiRqRXKo5JP6YYl5GTggaf9I88BeqGC30ZhuDFyC2uI85pcMG6MqaVdUz9/tVuR3kXW3UZUlBNFFrGZqw0KYrwh3ocgmfuyDS0rGb9dfvBpLpe1e6AYWTkb8o6E7vf32a7SBP7E4E83eA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=kwGRjLrI; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kwGRjLrI" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-b884a84e655so509456266b.0 for ; Sun, 25 Jan 2026 11:51:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769370700; x=1769975500; darn=vger.kernel.org; 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=E+7+mKj8XKCXDrFYnXFD6aPpUYuOrtmLT/xGxemFmLg=; b=kwGRjLrIhDKmLCesfcvfyV6Usw5qEMyHLBTuuN/ipdTDJfU3WAUL/hkytQdUS/Rxmq mKeyFMYH8javNmGUXkpTUqp+14X0cxKQUat6Tq2OIlCArrDi3nH+8pRUxiTthofc+QeP hbJelIfSlV/fWo1qCQKKECGu6eN5jWLDbb6NjzTX4ExfXkBqmeUb1RLG5rQ8KXYu1F5U xihPy+ZS3p45ddht7nx6VAt7rpN6pS3QAXCe7Cu6ntrpDVGLTSDA8MSFZXqDnvy5KrDT d8IWIac5Y7NuTh5RHdLf3bIVQZKzvb8NlJx2usYqPDVxmp92FxllE2J5KvLBiQoYDsZy StSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769370700; x=1769975500; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=E+7+mKj8XKCXDrFYnXFD6aPpUYuOrtmLT/xGxemFmLg=; b=qSVT03m2JfCig8Dk1EaGBHlTUxZ2DcPZZq3J3Rwb/SqhC3ydKSTlYP3thq7LlTusGa Eyi3ncuusz24iGFebRVyMvORf1wghSapqWvCI0D7JBNZcEmEwHV1NxO6zxkP439/UHOi xQzhSXvRfi4MLRWFKXnhw5y3tHKMfIW0kqioOiE9ejFFNgMoiT1DhOycoXAsPU/n9KJr TVAMhY7L5NffvVaE6tsdNScTvX1ma+xn132Bqm8oyjOCTCf+6vDMl8GUVjGkUeOF4E/M b1ZGFT3ep+k270BI+DPvIjdqd8pDkIB+QwaBgS6Z1KBEgwtN+1H5Eref72CazjqRuoU+ //Tw== X-Forwarded-Encrypted: i=1; AJvYcCXPN347oe8OIKYNt3wFAgvTqLUHBoLnMZsEWfwu68tJrfcY2yZkLxWUY7Rj2A5Aci9X6STGt6ZHXpqkVDw=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/VlwA/uqDYvN9i+E5vWwfkREq+ERqnvxGjrOn8mZC/kV1nLh2 CzQPIShcJLLCsXSdPjFPKQ4VqWX8kCS8vCvvglh4arzzo/UV1G0FAp4K X-Gm-Gg: AZuq6aLt3hruHMpwmZNdhz6DnsF0FITPcMC+h4RFLA85Cm2ic47DXC6yiyjg1rCNBMK h7B/fNcPhA71QvrlWNvVChUX+2yNufeIDz8GtJ5MzE0hwSjvvc6hQWLPeGkerT5gj7VH/8TVWg3 W8/8L+pN7iN12KdEQJmC6YSlPKXIgKI9svBVZIYTQNVYQ3BCy/OmBHFCI45qyVd0jFrnkvjMZPJ LxYZ+rFHsZukM68o+/ebbOzN9/2wQT9acMK4tBhrOIT2ioINNXun8zoaBEqcLLFdAqfXa4Fr8Ud eJyz+AeKksvTs45LJhsdSd8hVgXZWMNQZZ+7jmq7db5okLqP9o95QgsA4GM7jqOV3JKXMc4TlR0 FMs2OV5AQ74H776dNwUjIgC6hx4l2c/RBOu3zRV1VnIhqTE0LJWL2A85v54Ebu2kegml32DDUL6 6OEr9Y+MNUlUOSZZZj6Mybg72lrH3e7g46HA== X-Received: by 2002:a17:907:3f0f:b0:b88:4fc9:a196 with SMTP id a640c23a62f3a-b8d2e85e0ffmr170791566b.34.1769370699647; Sun, 25 Jan 2026 11:51:39 -0800 (PST) Received: from C-PF5D4647.localdomain ([147.161.248.108]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6584b965df4sm4010232a12.31.2026.01.25.11.51.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Jan 2026 11:51:39 -0800 (PST) From: Jie Li X-Google-Original-From: Jie Li To: wsa@kernel.org, linus.walleij@linaro.org Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Jie Li Subject: [PATCH v2 1/2] gpiolib: add gpiod_is_single_ended() helper Date: Sun, 25 Jan 2026 20:51:22 +0100 Message-ID: <20260125195123.248798-2-jie.i.li@nokia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260125195123.248798-1-jie.i.li@nokia.com> References: <20260125195123.248798-1-jie.i.li@nokia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The direction of a single-ended (open-drain or open-source) GPIO line cannot always be reliably determined by reading hardware registers. In true open-drain implementations, the "high" state is achieved by entering a high-impedance mode, which many hardware controllers report as "input" even if the software intends to use it as an output. This creates issues for consumer drivers (like I2C) that rely on gpiod_get_direction() to decide if a line can be driven. Introduce gpiod_is_single_ended() to allow consumers to check the software configuration (GPIO_FLAG_OPEN_DRAIN/GPIO_FLAG_OPEN_SOURCE) of a descriptor. This provides a robust way to identify lines that are capable of being driven, regardless of their instantaneous hardware state. Signed-off-by: Jie Li --- drivers/gpio/gpiolib.c | 22 ++++++++++++++++++++++ include/linux/gpio/consumer.h | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 1578cf3a8c74..96c34bf65c7e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -486,6 +486,28 @@ int gpiod_get_direction(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiod_get_direction); =20 +/** + * gpiod_is_single_ended - check if the GPIO is configured as single-ended + * @desc: the GPIO descriptor to check + * + * Returns true if the GPIO is configured as either Open Drain or Open Sou= rce. + * In these modes, the direction of the line cannot always be reliably + * determined by reading hardware registers, as the "off" state (High-Z) + * is physically indistinguishable from an input state. + */ +int gpiod_is_single_ended(struct gpio_desc *desc) +{ + if (!desc) + return 0; + + if (test_bit(GPIOD_FLAG_OPEN_DRAIN, &desc->flags) || + test_bit(GPIOD_FLAG_OPEN_SOURCE, &desc->flags)) + return 1; + + return 0; +} +EXPORT_SYMBOL_GPL(gpiod_is_single_ended); + /* * Add a new chip to the global chips list, keeping the list of chips sort= ed * by range(means [base, base + ngpio - 1]) order. diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index cafeb7a40ad1..c5847c8f66fe 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -109,6 +109,7 @@ void devm_gpiod_unhinge(struct device *dev, struct gpio= _desc *desc); void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs); =20 int gpiod_get_direction(struct gpio_desc *desc); +int gpiod_is_single_ended(struct gpio_desc *desc); int gpiod_direction_input(struct gpio_desc *desc); int gpiod_direction_output(struct gpio_desc *desc, int value); int gpiod_direction_output_raw(struct gpio_desc *desc, int value); @@ -335,6 +336,10 @@ static inline int gpiod_get_direction(const struct gpi= o_desc *desc) WARN_ON(desc); return -ENOSYS; } +static inline int gpiod_is_single_ended(struct gpio_desc *desc) +{ + return 0; +} static inline int gpiod_direction_input(struct gpio_desc *desc) { /* GPIO can never have been requested */ --=20 2.43.0 From nobody Sun Feb 8 15:42:44 2026 Received: from mail-ed1-f46.google.com (mail-ed1-f46.google.com [209.85.208.46]) (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 B9FA92FF65B for ; Sun, 25 Jan 2026 19:51:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769370707; cv=none; b=PtfO7GdOkj6/w/iW97sNGABzSuDrKYuf7mTlZjEBv7Ac/W9b2f1Nldz7jcGHaELvmvIJJ3wmVNgtAUvopK2/B9WODi9Tlya2Lfm5le437LFSBWReiy3+TpLlKd7KOQ4YcrNI5sXW3IX8zBNIUZG0LHv2sxaBIhJ02B+4MFYjR94= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769370707; c=relaxed/simple; bh=yOJ54pYpL2f9TTcF6tyIQse6Pob6FYPNHJ3RzR+Wm5w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bHFg8hbB8mY6RkVNwUQtyMWxxQJSc5bIslOzjI1qhO7s6oNFDGoZarXy372UFTpDLYGIs7pvUz7EEtEWZNOIb9r2WTu9xEp4JOCKq3xnTWyuYHlwZSWMYKeydiEcnsb/KPB3vL6zF4VQXUbyoQ4pwakcbX7cLhUCjjCQrCNr28k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Av0Hlmsx; arc=none smtp.client-ip=209.85.208.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Av0Hlmsx" Received: by mail-ed1-f46.google.com with SMTP id 4fb4d7f45d1cf-652fdd043f9so6863062a12.1 for ; Sun, 25 Jan 2026 11:51:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1769370704; x=1769975504; darn=vger.kernel.org; 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=p1NkWW5tAbnDHrUHLuon+4jkp7FZIlzNu5NjUea5Lk8=; b=Av0HlmsxmAQXgP6vapbuxYcC4Wm4OtQoveFCE3TEGHbei/JKjzp3nq7fNiEA21DTxf HaSajvsn/ZgT8Zw3eM1G0NLvrdafqxKSadRI489sWFNGHSpPfh/KIO78RYEGjgG+zhK4 s/mZ5G/gDIKfKe3CeSwPFeQY9koON+y6C1Xf6VcCTvhpOJjFRcuhF+2IHPutRaCUbLqx g4t2dJTqwQ2w7+0YzGIx+KG/EFURZJfgeN9XxL+UZ6OZFLmVRiKOWhDIS/U6z3/k5Y8p 1YyUvVRbJYbZdMpl5+ruKSC4kuIiKNpX8hEbXfSdrYD56Q8IwstNN/GWLrjzID0d6zCb yMPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769370704; x=1769975504; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=p1NkWW5tAbnDHrUHLuon+4jkp7FZIlzNu5NjUea5Lk8=; b=qGol7wjpTJj5cwTAsrYViS45S8WBQlT09XWkQOB5kciI+/6iebAPnAW6/IhOfd/G2v utRA0jWANiaEOZhpDIgNCHC1qztk0XHbHyhBFslOhdsrQWdyy0wFcMScCzHXRE+8JGyg Rwk+bGdZJRYZQE3qtWfCbk929RriCneCHC2BBRaXLN4w26HHihxeBNX3s4m71NEVYl28 7J31LPcxwR9c+yc+4QmDFACwxQ64bsgy5+BwX7ZFofdqSXz+Vs0JGvtpCvJkbHRDxzsG Gh7jBnGygAdVzkSyPutLwJDp9mvWP4vUOdag3B38S/GscOhxb/U/CawD0eYkLE3iq+gT 4jWw== X-Forwarded-Encrypted: i=1; AJvYcCUNUD4V3Kq1VfUzNs3Om1i1Z5ZhWnGkUs6kx6+r7os8bDS2HZgAczcp3tE5gtTkTfzNMSy343ZTf0TCkCA=@vger.kernel.org X-Gm-Message-State: AOJu0Yz7+y6jVBknGB7oKQcM5UUy+KbMotHnY9ugq6Tu+2grbZhcFuDe hLCt9D4YeE4LNIbApfDCAzys1uKtva+60n8T/Jn5GkW2jVgasOOPjzCf X-Gm-Gg: AZuq6aJA9dH9vVWvhER9t+7R6vzcqIFOCNDxcUshp8qU1CVNw++qP14vZMpgXzzovzt IUisZ70GUT7Hrquvi51W5o2C1Qc03NdHwxhRqvWTh+ZaMMWFEJK7RXe4oKf6hYIEHWIhDZRgARk 0JUuxqVT7n+YLJFO/M4Cj21sY+l6FBiV9QXlVM4uXBDcu0GUj8I41j1cxK4Dhj897PhLxFc9XOP iLFQ6DaKhXfwvPD3yoWeqHcPn1p/Cp6dGt62WTO3yLcmaL/wtJtQ/BqmsV3SGjhAC/+RhiAgumV 1brkrjSieAYx1aQ8X9bLulv/uKPSk1b+UGo0BVI5fBaZ5+nGRjaWVz80pIpqEvDjqi5g6RKB2zG n5EDzc8/KLL1r+VOegDtl4wz/wTvCxws8/SzBF4CNOEAalRcJ3+55EjFYHgIVXQ71twlUaNu3jh bcYXsDOH+lZbYfdzVF+BfLdko= X-Received: by 2002:a05:6402:26c7:b0:658:1b1b:15a2 with SMTP id 4fb4d7f45d1cf-658706aa73emr1572957a12.7.1769370703967; Sun, 25 Jan 2026 11:51:43 -0800 (PST) Received: from C-PF5D4647.localdomain ([147.161.248.108]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6584b965df4sm4010232a12.31.2026.01.25.11.51.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 25 Jan 2026 11:51:43 -0800 (PST) From: Jie Li X-Google-Original-From: Jie Li To: wsa@kernel.org, linus.walleij@linaro.org Cc: linux-i2c@vger.kernel.org, linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org, Jie Li Subject: [PATCH v2 2/2] i2c: core: support recovery for single-ended GPIOs Date: Sun, 25 Jan 2026 20:51:23 +0100 Message-ID: <20260125195123.248798-3-jie.i.li@nokia.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260125195123.248798-1-jie.i.li@nokia.com> References: <20260125195123.248798-1-jie.i.li@nokia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, i2c_init_recovery() only assigns the set_sda/set_scl hooks if gpiod_get_direction() returns 0 (output). This logic fails on certain SoC controllers where open-drain lines in a high-impedance state are physically reported as inputs. This leads to a "deadlock" where the I2C core refuses to assign the recovery hooks because it incorrectly assumes the pins are input-only, even though they are fully capable of driving the bus low for recovery. Update the recovery initialization to use the new gpiod_is_single_ended() helper. If a GPIO is configured as open-drain or open-source in the firmware, it is safe to assume it can be used for bus recovery, even if the current hardware direction is reported as input. Signed-off-by: Jie Li Reviewed-by: Linus Walleij --- drivers/i2c/i2c-core-base.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index ae7e9c8b65a6..11bd801418e8 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -446,7 +446,8 @@ static int i2c_init_recovery(struct i2c_adapter *adap) if (bri->sda_gpiod) { bri->get_sda =3D get_sda_gpio_value; /* FIXME: add proper flag instead of '0' once available */ - if (gpiod_get_direction(bri->sda_gpiod) =3D=3D 0) + if (gpiod_get_direction(bri->sda_gpiod) =3D=3D 0 || + gpiod_is_single_ended(bri->sda_gpiod)) bri->set_sda =3D set_sda_gpio_value; } } else if (bri->recover_bus =3D=3D i2c_generic_scl_recovery) { --=20 2.43.0