From nobody Fri Dec 19 12:46:40 2025 Received: from mail-ej1-f44.google.com (mail-ej1-f44.google.com [209.85.218.44]) (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 5EDE4305050 for ; Wed, 5 Nov 2025 10:36:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762338977; cv=none; b=K/fWpkdWkIu5kyEEPGvaYW/osiE7CLTr0L11ECoSr8exThNeIbDgjEN4EVoXpJmPzYJdorRh5nNClIW6sA6oLh6YNLqHcnpWRqb4gEtzFRtFZ9zAN4eProbXMuZLSMsxtM7Ozak+6PI0Em4DjFrBduDOrp9L8Z3dkXUGVzo2QLY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762338977; c=relaxed/simple; bh=C6xy0EtOkalUzkEAMpfGkzXo2GuppE3z47njnMHkoAw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EMOx/nZhkiVZoxvUbLeGbRFuA2IRFT9kA3qUgFuC8Bd0yNC8MWuXH3+SfnRfvxPY8DzyUFRmiadG9dgc+zp55iPr8qMQfFZhzNCUWB7f7hJM5rDMn8Ubg5TFub74yt/n6N5q+cfFEoe71lYtV57fQkgVTIEnq/aikPK7Vl1wRbU= 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=CHHObwFS; arc=none smtp.client-ip=209.85.218.44 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="CHHObwFS" Received: by mail-ej1-f44.google.com with SMTP id a640c23a62f3a-b726f913150so53940766b.0 for ; Wed, 05 Nov 2025 02:36:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762338974; x=1762943774; 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=z92QCHjJmqiDgUUq96F5qxg80YMYR3erevN8MU3XYkM=; b=CHHObwFS8eWuxXbbIri37J6j4JpDrsXYzPfj2v8p0R5ZXf5nGgAkjoqT4ZTP+ewVX3 KEfANSwPHDGzEW0hvyeMJRGcTjGGxe0Cvw/aBXfvfW4+GW5zenYMjxb6omN3WYBh601Z EX/ZuIRXGn0XSX36+9nqjGamhHhahNVmOq6/pe3u+rkRhLNdY6eeJoOcL4zDeBghxghb ui7I2La+KkC3y3KXbqK5KDI4W28/3sLDJg8V3IdfYkMfBGyIX8HE+TuDOf/K9D/zfyV4 FDRyuvlYQA6kPKSBeR9nMAM2Jr1nDsctOMrUZ05/uDwQvMZL9Faanepz0oCz4nvvh1f2 MpIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762338974; x=1762943774; 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=z92QCHjJmqiDgUUq96F5qxg80YMYR3erevN8MU3XYkM=; b=PzLXbJd8Ifo8kPkT1lOXXn00/lywqJDmU1hb0lhKmXlwRku0Jhnc+HfOXwLc7zVZSs LR/ujyHWEdBoPAbBc13yWFqr6RYijERskA+eXhhM9cTQ8CPeOqf1H3IHFBgeER0mIp6W WAUF4+OuY+Qol3OxdPuVNg6c0sIBy8IMIMa3Yj5/XFrCSSaxc+oFcGgkxM5EWe6t+2St b1sNrifsCQ9j5SodCTc2qTKh4I67OfKYhT6IMLr2B86bhk2bp8gsNH1WH+w0OxhD9+ue PCs7oZwOCAiTdysgB4fZakwhjHusNsrb0Q2fhJpqmmeF9F8mqODcr8aCbNsEMqpQ3aGf 7E4Q== X-Forwarded-Encrypted: i=1; AJvYcCVLdRv3lTzZLaqpFFlrVj/8D9k65aSokI9W/w9vtpY+wZImIoOQ8aI9UqyDe2KswphFUGJRQKUDjfZ3LdA=@vger.kernel.org X-Gm-Message-State: AOJu0YyEY9REz41qGTCc/gnKcLU2Y78NXTRSy4nHgGiHHZLvFOMGmKKs KdkTWaVePXpEyPbeTCjqmEqk6I0AvUyE6d2VJlbZrfxWVcK1mqd0g9SD X-Gm-Gg: ASbGncvZdMW9blRmyJ8PCk2tZTMUlxSAmTnH+jjOWLylhvDiHe3TsI+D6pIxIWdv4gB BtYO0mLfCyFKiTFFlyZ8zmWcHT98Ha2Za2MSg5dvg2xJUlczna4FgZT/z4pT9lSla4rPpUIWlBW sSXj7d6eao96a4XySma8maB6eWVbVb85M9Zxa2uzTcVlYN52wHkvfScyTRjRtq1Kdr0XlBxgWn+ T+/YqM4U2a7Yf0cvV5OA1QgatI7kAtMYRVcROdHhUTZUoiwFvlc3LJ3ShBMG7GgYNuWsbNGDdj6 p9qyCU8WFahwe+QJBhtJHRGzvV+bVwDmQcbQq39AYPtLd0kZjXhLe25zzIb1zaLVMeOf5l7mU1u S91FL5bsqzqJEJhPXDy9xZtopjDjbQQ4fM0d+Nu2oO9orQoFm1uVQtHyj7cTgOGfTqsE3xpTY3h jbOX0LpP9YCxABAw== X-Google-Smtp-Source: AGHT+IGlV9RahnJjEAp0aThL3WEmwaxZ6MtiPW+SqHleirKp3I6nYlDscxLoLqIQlJkAEr5XQOfmEA== X-Received: by 2002:a17:906:4888:b0:b72:6a39:49e6 with SMTP id a640c23a62f3a-b726a394f5cmr151258566b.18.1762338973509; Wed, 05 Nov 2025 02:36:13 -0800 (PST) Received: from builder.. ([2001:9e8:f106:5b16:be24:11ff:fe30:5d85]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b7270b56f18sm83426066b.33.2025.11.05.02.36.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 02:36:13 -0800 (PST) From: Jonas Jelonek To: Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Peter Rosin , Geert Uytterhoeven Cc: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Thomas Richard , Jonas Jelonek , Krzysztof Kozlowski Subject: [PATCH v4 1/2] dt-bindings: gpio: add gpio-line-mux controller Date: Wed, 5 Nov 2025 10:36:05 +0000 Message-ID: <20251105103607.393353-2-jelonek.jonas@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251105103607.393353-1-jelonek.jonas@gmail.com> References: <20251105103607.393353-1-jelonek.jonas@gmail.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" Add dt-schema for a gpio-line-mux controller which exposes virtual GPIOs for a shared GPIO controlled by a multiplexer, e.g. a gpio-mux. The gpio-line-mux controller is a gpio-controller, thus has mostly the same semantics. However, it requires a mux-control to be specified upon which it will operate. Signed-off-by: Jonas Jelonek Reviewed-by: Krzysztof Kozlowski --- .../bindings/gpio/gpio-line-mux.yaml | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-line-mux.ya= ml diff --git a/Documentation/devicetree/bindings/gpio/gpio-line-mux.yaml b/Do= cumentation/devicetree/bindings/gpio/gpio-line-mux.yaml new file mode 100644 index 000000000000..fb91500fa10f --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-line-mux.yaml @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-line-mux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO line mux + +maintainers: + - Jonas Jelonek + +description: | + A GPIO controller to provide virtual GPIOs for a 1-to-many input-only ma= pping + backed by a single shared GPIO and a multiplexer. A simple illustrated + example is + + +----- A + IN / + <-----o------- B + / |\ + | | +----- C + | | \ + | | +--- D + | | + M1 M0 + + MUX CONTROL + + M1 M0 IN + 0 0 A + 0 1 B + 1 0 C + 1 1 D + + This can be used in case a real GPIO is connected to multiple inputs and + controlled by a multiplexer, and another subsystem/driver does not work + directly with the multiplexer subsystem. + +properties: + compatible: + const: gpio-line-mux + + gpio-controller: true + + "#gpio-cells": + const: 2 + + gpio-line-mux-states: + description: Mux states corresponding to the virtual GPIOs. + $ref: /schemas/types.yaml#/definitions/uint32-array + + gpio-line-names: true + + mux-controls: + $ref: /schemas/types.yaml#/definitions/phandle-array + maxItems: 1 + description: + Phandle to the multiplexer to control access to the GPIOs. + + ngpios: false + + shared-gpios: + maxItems: 1 + description: + GPIO which is the '1' in 1-to-many and is shared by the virtual GPIOs + and controlled via the mux. + +required: + - compatible + - gpio-controller + - gpio-line-mux-states + - mux-controls + - shared-gpios + +additionalProperties: false + +examples: + - | + #include + #include + + sfp_gpio_mux: mux-controller-1 { + compatible =3D "gpio-mux"; + mux-gpios =3D <&gpio0 0 GPIO_ACTIVE_HIGH>, + <&gpio0 1 GPIO_ACTIVE_HIGH>; + #mux-control-cells =3D <0>; + idle-state =3D ; + }; + + sfp1_gpio: sfp-gpio-1 { + compatible =3D "gpio-line-mux"; + gpio-controller; + #gpio-cells =3D <2>; + + mux-controls =3D <&sfp_gpio_mux>; + shared-gpios =3D <&gpio0 2 GPIO_ACTIVE_HIGH>; + + gpio-line-names =3D "SFP1_LOS", "SFP1_MOD_ABS", "SFP1_TX_FAULT"; + gpio-line-mux-states =3D <0>, <1>, <3>; + }; + + sfp1: sfp-p1 { + compatible =3D "sff,sfp"; + + i2c-bus =3D <&sfp1_i2c>; + los-gpios =3D <&sfp1_gpio 0 GPIO_ACTIVE_HIGH>; + mod-def0-gpios =3D <&sfp1_gpio 1 GPIO_ACTIVE_LOW>; + tx-fault-gpios =3D <&sfp1_gpio 2 GPIO_ACTIVE_HIGH>; + }; --=20 2.48.1 From nobody Fri Dec 19 12:46:40 2025 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 3622630505B for ; Wed, 5 Nov 2025 10:36:16 +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=1762338979; cv=none; b=tOyWbql2zqG8H1jmUPsaj6K+q2CtxmkUYKZpt/o4NdYvG+ufTRAuFTmeqJu88FynTUq2wguy/3Zg6kJMMBF3mVWfSCZxaCqm6pgdpdvSHBjBHxTMWTcc8YDpAAXpE1nI7ktIYFtlVzdzbTkBWfbbvwwJS0/cXwzVdekOcGXi30w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1762338979; c=relaxed/simple; bh=KDesIfsn2xu6U2CtUzSWMng87iI1n+RYPUP8WaYWAoM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ljKLId/zTrtJEbXvBBfRGzW1Y4TrSPrA+cC7TytZJOsYW2bZHz6DkrF3pfh8mg0vMZ/3Q+Pfu4s8PW+jFikcqlz5TVz+36bPPbViCEzCKaNUaE63+mHML2Zfk2S+bdzX0Yf6LW4peuTwgN4yQYz56CIfgIZGfAHhlVsEjPYjYYo= 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=Cl9moNAX; 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="Cl9moNAX" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-afcb7ae6ed0so1173527066b.3 for ; Wed, 05 Nov 2025 02:36:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762338974; x=1762943774; 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=TiWeWU99+P2OBlwtwLukYVoiHCgrNeTiK3bQO2+aHuQ=; b=Cl9moNAXDHNcQpfGIGCc2uow2sveCRVmKwVvl6zBGUGEQu3vMqpWsqmQ4IUmWnOYam s9tWS7yICph/WKP2fx+AwlLgWoUNH+mqvPlJUmVJkt7AXvuXTyzL/TVo4h5YMu7GTvKe J70ZcwHWULdCTl9fAHuSxdlIanWqB01RcvLqfamNgNIRB0inzkQpEbPgE3ZGIQsz6Vjc 1MkcZAlm6O9ZxuYgMFgxpo8cW0Lt1eQrcr5nGmriIH6+dUTmAAtev/6I3h+6FszmD9y+ 8s7CwlmoQPh9t4vMgQItxjXk/C/xWY5J5zi0bVSSJ2U2DcvVSFvo1aoJ3HTXxqKkUe0V YO1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762338974; x=1762943774; 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=TiWeWU99+P2OBlwtwLukYVoiHCgrNeTiK3bQO2+aHuQ=; b=aWrZK+I6Pz18qJRVeJtlHe3zhP6VcS4zu8V8/BlmE4krL4r+Q589bQyFfJ4a7QGh40 vwOFYqKC8GHszbURDzfzdl0xcPjZc6Hr80Fp8SdsGRe7J8/KJxYsPTxoxaCWD73rIOrD u7dKLOmtvgdVDIhJFlSQdaXZ+umg1gfUmS6Ximj19sK7lg4UIyr0vRzkWVDLbWDUg3WH EwGzan5V7/OYc6K7O05kBupR7Me1uiqg6c99zkDDsNNSskIeb/Tl5i/i31niaWd6UV7U ioKCRenLh3t6+el2zvs2jNv1tVTrGcwU1RQ4wIw5BE+lYtJLY5a+4D2rfGU61YLkl/Fj 6VBQ== X-Forwarded-Encrypted: i=1; AJvYcCXDO4iP3c0OcBRamKzqlLbZ0TxxKuRZfk6PD6OSZ6QbmmDXl2CP4XT+5w9i0s6zdEYH3H7ZkZbtRTWmZTE=@vger.kernel.org X-Gm-Message-State: AOJu0YwCT78MEO5h4PYHt/sYr6bv44IgYzoF7ZLqpUHGL0EftQy9GFzc izcYOfGdHrBEM4y9k38CvLQwiWRjaSD8ydyPdh9ECW6t6cWmY7D+gVBV X-Gm-Gg: ASbGncsh8Lc8ApwbmIfJm3rDMY75miz3wv1IeSlj35bPrjgoYELUnppcpEGbIwPg95i 1aBaipZzz8EF9qzsKDV7tHdYpU4KGOh6sg67dH0LhXPTkJttJArBwtbdvUWMOoO84Yy5MeHdICQ PDL14B9xehE/NkFmWsrZA89Wu0mWXDKbzRboRjpnBesCjbppwG+t6KxIHNofYkQXA30ks1WLkDD 8UbCwFXciCmHqhSEqkl0A7KgJ80n3PjxUKFK1533GW4O/rZll1HJSvIuTWYNFg3IsNJ6V+zwgFo CVdGamZOWYHzC1K4pG14l77tOyTnKmdtASNJLfLnz0i/h96XV3/5IBU7BLNT3kxqmg5LZsmfdnX k2SQobNjdeG5e0Dw4lnUyikWsviusyigdQYDrpV7ImTa5UVNQ6a1LFLhizv8dDAi05twdjjakAs qqwZI= X-Google-Smtp-Source: AGHT+IEM16NafFW2nC97ok9XEm+53qMVZBe4OIJxe3eLowZZOL6gKamZMEdrt0F28He7dGEhTIoj1g== X-Received: by 2002:a17:907:6e89:b0:b70:b1e1:8294 with SMTP id a640c23a62f3a-b7265156582mr234675166b.4.1762338974287; Wed, 05 Nov 2025 02:36:14 -0800 (PST) Received: from builder.. ([2001:9e8:f106:5b16:be24:11ff:fe30:5d85]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b7270b56f18sm83426066b.33.2025.11.05.02.36.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Nov 2025 02:36:14 -0800 (PST) From: Jonas Jelonek To: Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Peter Rosin , Geert Uytterhoeven Cc: linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Thomas Richard , Jonas Jelonek Subject: [PATCH v4 2/2] gpio: add gpio-line-mux driver Date: Wed, 5 Nov 2025 10:36:06 +0000 Message-ID: <20251105103607.393353-3-jelonek.jonas@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251105103607.393353-1-jelonek.jonas@gmail.com> References: <20251105103607.393353-1-jelonek.jonas@gmail.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" Add a new driver which provides a 1-to-many mapping for a single real GPIO using a multiplexer. Each virtual GPIO corresponds to a multiplexer state which, if set for the multiplexer, connects the real GPIO to the corresponding virtual GPIO. This can help in various usecases. One practical case is the special hardware design of the Realtek-based XS1930-10 switch from Zyxel. It features two SFP+ ports/cages whose signals are wired directly to the switch SoC. Although Realtek SoCs are short on GPIOs, there are usually enough the fit the SFP signals without any hacks. However, Zyxel did some weird design and connected RX_LOS, MOD_ABS and TX_FAULT of one SFP cage onto a single GPIO line controlled by a multiplexer (the same for the other SFP cage). The single multiplexer controls the lines for both SFP and depending on the state, the designated 'signal GPIO lines' are connected to one of the three SFP signals. Because the SFP core/driver doesn't support multiplexer but needs single GPIOs for each of the signals, this driver fills the gap between both. It registers a gpio_chip, provides multiple virtual GPIOs and sets the backing multiplexer accordingly. Due to several practical issues, this is input-only and doesn't support IRQs. Signed-off-by: Jonas Jelonek Reviewed-by: Thomas Richard --- MAINTAINERS | 6 ++ drivers/gpio/Kconfig | 9 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-line-mux.c | 129 +++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 drivers/gpio/gpio-line-mux.c diff --git a/MAINTAINERS b/MAINTAINERS index 3da2c26a796b..66f8706d9b4b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10653,6 +10653,12 @@ S: Maintained F: Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.yaml F: drivers/media/rc/gpio-ir-tx.c =20 +GPIO LINE MUX +M: Jonas Jelonek +S: Maintained +F: Documentation/devicetree/bindings/gpio/gpio-line-mux.yaml +F: drivers/gpio/gpio-line-mux.c + GPIO MOCKUP DRIVER M: Bamvor Jian Zhang L: linux-gpio@vger.kernel.org diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ce237398fa00..5f8082ae99cc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1986,6 +1986,15 @@ config GPIO_LATCH Say yes here to enable a driver for GPIO multiplexers based on latches connected to other GPIOs. =20 +config GPIO_LINE_MUX + tristate "GPIO line mux driver" + depends on OF_GPIO + select MULTIPLEXER + help + Say Y here to support the GPIO line mux, which can provide virtual + GPIOs backed by a shared real GPIO and a multiplexer in a 1-to-many + fashion. + config GPIO_MOCKUP tristate "GPIO Testing Driver (DEPRECATED)" select IRQ_SIM diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ee260a0809d3..6caee52b0356 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -89,6 +89,7 @@ obj-$(CONFIG_GPIO_IXP4XX) +=3D gpio-ixp4xx.o obj-$(CONFIG_GPIO_JANZ_TTL) +=3D gpio-janz-ttl.o obj-$(CONFIG_GPIO_KEMPLD) +=3D gpio-kempld.o obj-$(CONFIG_GPIO_LATCH) +=3D gpio-latch.o +obj-$(CONFIG_GPIO_LINE_MUX) +=3D gpio-line-mux.o obj-$(CONFIG_GPIO_LJCA) +=3D gpio-ljca.o obj-$(CONFIG_GPIO_LOGICVC) +=3D gpio-logicvc.o obj-$(CONFIG_GPIO_LOONGSON1) +=3D gpio-loongson1.o diff --git a/drivers/gpio/gpio-line-mux.c b/drivers/gpio/gpio-line-mux.c new file mode 100644 index 000000000000..50e351d212b8 --- /dev/null +++ b/drivers/gpio/gpio-line-mux.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * GPIO line mux which acts as virtual gpiochip and provides a 1-to-many + * mapping between virtual GPIOs and a real GPIO + multiplexer. + * + * Copyright (c) 2025 Jonas Jelonek + */ + +#include +#include +#include +#include +#include +#include + +#define MUX_SELECT_DELAY_US 100 + +struct gpio_lmux { + struct gpio_chip gc; + struct mux_control *mux; + + struct gpio_desc *shared_gpio; + /* dynamically sized, must be last */ + unsigned int gpio_mux_states[]; +}; + +static int gpio_lmux_gpio_get(struct gpio_chip *gc, unsigned int offset) +{ + struct gpio_lmux *glm =3D gpiochip_get_data(gc); + int ret; + + if (offset > gc->ngpio) + return -EINVAL; + + ret =3D mux_control_select_delay(glm->mux, glm->gpio_mux_states[offset], + MUX_SELECT_DELAY_US); + if (ret < 0) + return ret; + + ret =3D gpiod_get_raw_value_cansleep(glm->shared_gpio); + mux_control_deselect(glm->mux); + return ret; +} + +static int gpio_lmux_gpio_set(struct gpio_chip *gc, unsigned int offset, + int value) +{ + return -EOPNOTSUPP; +} + +static int gpio_lmux_gpio_get_direction(struct gpio_chip *gc, + unsigned int offset) +{ + return GPIO_LINE_DIRECTION_IN; +} + +static int gpio_lmux_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct gpio_lmux *glm; + unsigned int ngpio; + size_t size; + int ret; + + ngpio =3D device_property_count_u32(dev, "gpio-line-mux-states"); + if (!ngpio) + return -EINVAL; + + size =3D struct_size(glm, gpio_mux_states, ngpio); + glm =3D devm_kzalloc(dev, size, GFP_KERNEL); + if (!glm) + return -ENOMEM; + + glm->gc.base =3D -1; + glm->gc.can_sleep =3D true; + glm->gc.fwnode =3D dev_fwnode(dev); + glm->gc.label =3D dev_name(dev); + glm->gc.ngpio =3D ngpio; + glm->gc.owner =3D THIS_MODULE; + glm->gc.parent =3D dev; + + glm->gc.get =3D gpio_lmux_gpio_get; + glm->gc.set =3D gpio_lmux_gpio_set; + glm->gc.get_direction =3D gpio_lmux_gpio_get_direction; + + glm->mux =3D devm_mux_control_get(dev, NULL); + if (IS_ERR(glm->mux)) + return dev_err_probe(dev, PTR_ERR(glm->mux), + "could not get mux controller\n"); + + glm->shared_gpio =3D devm_gpiod_get(dev, "shared", GPIOD_ASIS); + if (IS_ERR(glm->shared_gpio)) + return dev_err_probe(dev, PTR_ERR(glm->shared_gpio), + "could not get shared-gpio\n"); + + ret =3D gpiod_direction_input(glm->shared_gpio); + if (ret) + return dev_err_probe(dev, ret, "could not set shared gpio as input\n"); + + ret =3D device_property_read_u32_array(dev, "gpio-line-mux-states", + &glm->gpio_mux_states[0], ngpio); + if (ret) + return dev_err_probe(dev, ret, "could not get mux states\n"); + + ret =3D devm_gpiochip_add_data(dev, &glm->gc, glm); + if (ret) + return dev_err_probe(dev, ret, "failed to add gpiochip\n"); + + return 0; +} + +static const struct of_device_id gpio_lmux_of_match[] =3D { + { .compatible =3D "gpio-line-mux" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpio_lmux_of_match); + +static struct platform_driver gpio_lmux_driver =3D { + .driver =3D { + .name =3D "gpio-line-mux", + .of_match_table =3D gpio_lmux_of_match, + }, + .probe =3D gpio_lmux_probe, +}; +module_platform_driver(gpio_lmux_driver); + +MODULE_AUTHOR("Jonas Jelonek "); +MODULE_DESCRIPTION("GPIO line mux driver"); +MODULE_LICENSE("GPL"); --=20 2.48.1