From nobody Sat Feb 7 06:35:34 2026 Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) (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 C48B1205E25 for ; Sat, 27 Dec 2025 18:01:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766858506; cv=none; b=RiLNF4vXJQGt5dDUnyeJoI7nAIycPGvw93Su+hOAGp5BynE80czSizkjwkldu4JBi4xj+XNm8nP7ZdiU6fW3AAD8CnAjCvCB4BPiMA5bAdRBxZiZ0u6GwvZE6naPqWOsMD6+nRUtPUV8g1eguzzG+mbKuVp+7cJYMo9Lqu5BQkA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766858506; c=relaxed/simple; bh=RzAjmD2QpwAb0Iwims6jlShtVpnuGrDR/qh6hQP5qd0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lIzXPsRp6cfF17yxNfH62W9JrtNrc+kffQXr1ttzmrbHagjbGJcRnECsXHplSIQ57iXk6gLB98DqSQkQ167FrzrnYK0MF7blva/syiy3AHl3eLqKdbsNXBZb3qXDOejgVhQIi30ovKK8IPQBe6kViTupmIv/WvQUc9OwUFsJD2g= 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=l/pX28Lb; arc=none smtp.client-ip=209.85.218.42 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="l/pX28Lb" Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-b7ffa5d1b80so1008289266b.0 for ; Sat, 27 Dec 2025 10:01:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766858503; x=1767463303; 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=vNr2NQjhqtvw3/ELF26rbEOZcLfS+9yH2UWT2cZxXrM=; b=l/pX28LbpA/BBYn/OWRgBWNQEVnwZEn1yTmvC2pymkKLYjwnFKqB8gqXlSQry7mpb6 NtRj97zjq+sE45fBlBZetlrouA4ACA9EVvkkM2nFjGuVv4hxrQrmkB5hEQFiqG3WhD8f W/NH0Wp6PLwx3Z1SSL8IK1C61fGkWzWgC/nlTW6Z/NcUZu7UGKl+xcGwq78GxsDypCbK HtHvHNj82f9oBF1wUuMm2maeh6JegtxD9DBuqkJrM/8TERGrl/HjuuR62KCowIGP/eV5 OL30MDa39qknTGiWkaJWw1d8Of6aWohABHGIRdS0pwHXYGZMFAIqq50itBo1N+2wx6WB FsbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766858503; x=1767463303; 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=vNr2NQjhqtvw3/ELF26rbEOZcLfS+9yH2UWT2cZxXrM=; b=OUqMxhYSC+SGKdClUq+S3/SxZqw2JDwfZlLbNItrOcszMj4KMAoljMPolUp57eSunC 8EeymqWrIKUl8Cyz3VSNilS6qhcMpG+2DEER5QlkzcaW2NmzLDidpj+fyHPd66xCJCSi 9Pw3x5MuhkRhMDQv44fqsFEKfny1NV2Z9ZhP6tub4Uuo6QuJXvqGqe5PPnCt9Gu61Vd9 7fc65UAEG1AuvbpiF4ViD07N/aCXwwCFC6uY4NB5OpufaCmwjU2PFYt+RuS5GIKdoAgy AO9fwZxg4teJrkTOsxxAHBJPPqXcHkZTRyCDysfZNihHRULryvvJng62EW15xADK5a46 PXRw== X-Forwarded-Encrypted: i=1; AJvYcCXb5Vd3ubqYe136/op42XHMS/kWIxH56DCI+2gjTDf+KTUaXTw/YzrXS5FxFKgWzmTGhbVlREQfDY90HAM=@vger.kernel.org X-Gm-Message-State: AOJu0YwwYyo+Th+jRfFHAlSU21A9s0bK2HH02NrSoNaF7hH4Ldds6DZt Ru0sf5eFf9Zo7aIjcAH25ClWCjXpyk27l8u0URrEzHy/iFGmIM4cmLHV X-Gm-Gg: AY/fxX7qStf05cU3sC0s6zAAwI3miHcyqP/V2FoGWqiFYx6TRc7DPVSkYTt2cJ8/zTm B5nL7eVdayIDHyqQCtoBJws7LYpOXh0zWhW9j19jqEfd7wQUBh/cMksTuIcgsfw17ErzN088pMA FKgJ9HEpsDTVWv0Qu2bE2qfelaDCP6J4dFJjCc/Eno42F3YSsuffZ9DBS6PlFNl567LZKhEC4Xe g1KpeYPf7rgZboz60liJPCHl4zkT1iAMV3wLS5j2YGMobmzj3zZoihZB505Thy7HgbWbS7VoEIR iOZtmrd4LyB3cemSCKtqSa6XYr5FHkGiAeFSyBu5oZr8jgVkajdLw4IZ8kjf7d4qArsf6zvmG45 bKkErXpaCGaFlD5mYG3kCK0VWijTiOCBn9fpEqy4FVMfnXf4sRciqEA3rMiqklQYConHN9wuwTL vNFk4JJeQw5HwUliM= X-Google-Smtp-Source: AGHT+IGgnTebWb4iw57E/p9PtBigV+m6q6bb9WY70BT7u/VewoxWOOpVr2GiX7SzqjX9JM7lg2ZmmQ== X-Received: by 2002:a17:907:8686:b0:b76:8163:f1f8 with SMTP id a640c23a62f3a-b80371d6725mr2792072466b.53.1766858502693; Sat, 27 Dec 2025 10:01:42 -0800 (PST) Received: from builder.. ([2001:9e8:f10d:7316:be24:11ff:fe30:5d85]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b8037de1421sm2794835666b.41.2025.12.27.10.01.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Dec 2025 10:01:42 -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 , Conor Dooley Subject: [PATCH v7 1/2] dt-bindings: gpio: add gpio-line-mux controller Date: Sat, 27 Dec 2025 18:01:33 +0000 Message-ID: <20251227180134.1262138-2-jelonek.jonas@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251227180134.1262138-1-jelonek.jonas@gmail.com> References: <20251227180134.1262138-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: Conor Dooley Reviewed-by: Linus Walleij --- .../bindings/gpio/gpio-line-mux.yaml | 107 ++++++++++++++++++ 1 file changed, 107 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..f49c05249ca7 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-line-mux.yaml @@ -0,0 +1,107 @@ +# 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: + maxItems: 1 + description: + Phandle to the multiplexer to control access to the GPIOs. + + ngpios: false + + muxed-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 + - muxed-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>; + muxed-gpios =3D <&gpio0 2 GPIO_ACTIVE_HIGH>; + + 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 Sat Feb 7 06:35:34 2026 Received: from mail-ej1-f46.google.com (mail-ej1-f46.google.com [209.85.218.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 6655C21E0BA for ; Sat, 27 Dec 2025 18:01:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766858507; cv=none; b=O+3nsm7vJMoP8B7KzRP6vskhbopy1PUASICPV/4IesBdh8OaC5+Her5wIVEexeMDWrRdiAoh0I6+b16ZpPliyn8d7itL80Zes+UiZmneLhf1HHwtpbQern9F1ujogToWaOwSTfwXPUoqoKUHpb4yFVe1gbiUEfefjV52TYOl8yg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766858507; c=relaxed/simple; bh=e8YVyW49DbFA1obivdBn8/Pnhvbl84qe6o+D/PBtoO4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lzjqHUBEaiLew4y8vzkSTsViLvgqw3Jg42nBnNce6ULht6TUl+it7qZ5m515qD9/KiNyDscDg8pWKxk1Pv1UiK7UsQH3EdWKteT9bDi4OMwV7vSZmjEQdPxW+smeOWqxkSzL4qoxW6CaM7BWwU5WvkvlhxlvSvjsNVsfUDhRv5o= 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=H0jzYcGK; arc=none smtp.client-ip=209.85.218.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="H0jzYcGK" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-b7ffa5d1b80so1008290066b.0 for ; Sat, 27 Dec 2025 10:01:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766858503; x=1767463303; 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=sTALi2qrQQaNiy7RTP6OBTzsPFHWxY/VKluyG/WXiPQ=; b=H0jzYcGKiQLVoe/KVz063EstGwqVDyRhv/ROFadORH1vQtqNx+Ewr/8LuG5M6PRH3y jAps5auXwfvOGvzFR38heBUaO8W0qxYkvyF/8jEYt8ORJa/Mx0/+mfFp/mdB3jk5zsJR Ko/Qab0mpw3iSHrCxXxm8GXqmYFf5JMo+KRLBSIRrcfakFf9+W9VF0h7Flqh/CR31+OS GdcTKz9Ae8GDjkP62VnT1vBlyO0OiIiwSvCM7ankJlsVfbHqSIABgBGqK8qsaCeWm6XU k8iGvZB4OLIykn5H0ESMr8IDXED2Yt4NNT9fU2lXSlwcMqM8bUxtwrK1QoyTPl6dIVGk +ieQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766858503; x=1767463303; 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=sTALi2qrQQaNiy7RTP6OBTzsPFHWxY/VKluyG/WXiPQ=; b=usVHpR1MUJDYnE5UfJxvxLqvSadCUgkZOzF18FJhGlT5ydNaogbJ1XA91WZ4HXlx/C 5P0FF4LrXhEIiEx7WZCA2ehpewCHxL3+/e7CBPlxeJpdfK3maH1+FrF/1yodksy+ArP9 Kr5CuaM9uRY8B9y/ZqzfnnyOT2r2ZRLlM0Ehw1R1zclH2d3A+FqTalc76kQkdoivdg+D Fo/p3KbRkMjFJfYLZWUTNoQjP3287Jo1lNSGyfnR7xeWVcD3ACELHomUirv+U04jf5AD W99/vY6jEmxz2sFlr4kH1DTmdFkYrkkIf5mvuSXZ01mj+J7YS4LZ/ldN7c4qDxQX6lqK yVAg== X-Forwarded-Encrypted: i=1; AJvYcCUSSCLUc5mEGCpB3vGPlHO5plFERwcay7cmLZyaYhTlFQduc1xEetjrES+F9g251J3dxwImat1fdUj/E7o=@vger.kernel.org X-Gm-Message-State: AOJu0Yw4AK8+oEIjJ0LCbKQbGKcESijSokvmRr6jYqF5KKj9KqA0VOAw /Un8B1TZLHXzYGkQhdpho2Su0oVIzW47xPUeHY2Z6YmROUfVpjrB211B X-Gm-Gg: AY/fxX42jtkZ8764k1CGsLTlA1baamS4eSDc8Kc1tPOuyed5y1k4qCvETqKx+SIjE/D /tvutLe9fVv56LLeDiO2Ft1jGbwVmhUxjvj1ZrzOqgbOUiV/7iaBV4de5kdIvGxtc9zsCehLYIW c02ShoLDpbahmPIEizbfUH5O5eQixT41rZo4xRhWysaxZNux37S1OKkZo4j/uZgfX32TcGJ+xf8 RXyta08WZAyyR+jPm/5nxU95YZedEsqRT0zzjoIfYoHLVhw7QemG1SzxPphOUkA9XR7Vn3DkaLw j3A2Rbbp/aTpFlVV+fuuTp75MRnflDl9Z/qez9JLSazIatSI5yZ7J9COF9JNTWy6joU35Q3avHR B3UN1pzrDmfd/0eGiuqAMFIccTJ6ZKJxetHyXyTGeiRnvjRtMufB9B19FBCsZwLE542hctorWoq QJ2wqylmJSuBltyBM= X-Google-Smtp-Source: AGHT+IFiQda7vyrnxfvivqvCgO4e6qjL6oqGwmGim+3hpMHkIza8dH5snrsL7yqxi5m6n45jfh3bMQ== X-Received: by 2002:a17:907:9719:b0:b80:f4d:4aba with SMTP id a640c23a62f3a-b80371d6999mr2746322966b.47.1766858503444; Sat, 27 Dec 2025 10:01:43 -0800 (PST) Received: from builder.. ([2001:9e8:f10d:7316:be24:11ff:fe30:5d85]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-b8037de1421sm2794835666b.41.2025.12.27.10.01.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 27 Dec 2025 10:01:43 -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 v7 2/2] gpio: add gpio-line-mux driver Date: Sat, 27 Dec 2025 18:01:34 +0000 Message-ID: <20251227180134.1262138-3-jelonek.jonas@gmail.com> X-Mailer: git-send-email 2.48.1 In-Reply-To: <20251227180134.1262138-1-jelonek.jonas@gmail.com> References: <20251227180134.1262138-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 Reviewed-by: Linus Walleij --- MAINTAINERS | 6 ++ drivers/gpio/Kconfig | 9 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-line-mux.c | 126 +++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 drivers/gpio/gpio-line-mux.c diff --git a/MAINTAINERS b/MAINTAINERS index 5b11839cba9d..8056ef0ffbf0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10774,6 +10774,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 c33f9305ab97..2efa58f10781 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1994,6 +1994,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 2421a8fd3733..36fa7c52d240 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -90,6 +90,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..a4f384306218 --- /dev/null +++ b/drivers/gpio/gpio-line-mux.c @@ -0,0 +1,126 @@ +// 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 *muxed_gpio; + + u32 num_gpio_mux_states; + unsigned int gpio_mux_states[] __counted_by(num_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->muxed_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->muxed_gpio =3D devm_gpiod_get(dev, "muxed", GPIOD_IN); + if (IS_ERR(glm->muxed_gpio)) + return dev_err_probe(dev, PTR_ERR(glm->muxed_gpio), + "could not get muxed-gpio\n"); + + glm->num_gpio_mux_states =3D ngpio; + 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